1 /* 2 This is where the abstract matrix operations are defined 3 */ 4 5 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 6 #include <petsc/private/isimpl.h> 7 #include <petsc/private/vecimpl.h> 8 9 /* Logging support */ 10 PetscClassId MAT_CLASSID; 11 PetscClassId MAT_COLORING_CLASSID; 12 PetscClassId MAT_FDCOLORING_CLASSID; 13 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 14 15 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose; 16 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 17 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 18 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 19 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 20 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 21 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 22 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 23 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 24 PetscLogEvent MAT_TransposeColoringCreate; 25 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 26 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 27 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 28 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 29 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 30 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 31 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 32 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 33 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure; 34 PetscLogEvent MAT_GetMultiProcBlock; 35 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 36 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 37 PetscLogEvent MAT_SetValuesBatch; 38 PetscLogEvent MAT_ViennaCLCopyToGPU; 39 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 40 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 41 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 42 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 43 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 44 45 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 46 47 /*@ 48 MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 49 for sparse matrices that already have locations it fills the locations with random numbers 50 51 Logically Collective on mat 52 53 Input Parameters: 54 + x - the matrix 55 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and 56 it will create one internally. 57 58 Output Parameter: 59 . x - the matrix 60 61 Example of Usage: 62 .vb 63 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 64 MatSetRandom(x,rctx); 65 PetscRandomDestroy(rctx); 66 .ve 67 68 Level: intermediate 69 70 .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 71 @*/ 72 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) { 73 PetscRandom randObj = NULL; 74 75 PetscFunctionBegin; 76 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 77 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 78 PetscValidType(x, 1); 79 MatCheckPreallocated(x, 1); 80 81 if (!rctx) { 82 MPI_Comm comm; 83 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 84 PetscCall(PetscRandomCreate(comm, &randObj)); 85 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 86 PetscCall(PetscRandomSetFromOptions(randObj)); 87 rctx = randObj; 88 } 89 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 90 PetscUseTypeMethod(x, setrandom, rctx); 91 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 92 93 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 94 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 95 PetscCall(PetscRandomDestroy(&randObj)); 96 PetscFunctionReturn(0); 97 } 98 99 /*@ 100 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 101 102 Logically Collective on mat 103 104 Input Parameter: 105 . mat - the factored matrix 106 107 Output Parameters: 108 + pivot - the pivot value computed 109 - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes 110 the share the matrix 111 112 Level: advanced 113 114 Notes: 115 This routine does not work for factorizations done with external packages. 116 117 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 118 119 This can be called on non-factored matrices that come from, for example, matrices used in SOR. 120 121 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 122 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 123 @*/ 124 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) { 125 PetscFunctionBegin; 126 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 127 PetscValidRealPointer(pivot, 2); 128 PetscValidIntPointer(row, 3); 129 *pivot = mat->factorerror_zeropivot_value; 130 *row = mat->factorerror_zeropivot_row; 131 PetscFunctionReturn(0); 132 } 133 134 /*@ 135 MatFactorGetError - gets the error code from a factorization 136 137 Logically Collective on mat 138 139 Input Parameters: 140 . mat - the factored matrix 141 142 Output Parameter: 143 . err - the error code 144 145 Level: advanced 146 147 Note: 148 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 149 150 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 151 `MatFactorError` 152 @*/ 153 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) { 154 PetscFunctionBegin; 155 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 156 PetscValidPointer(err, 2); 157 *err = mat->factorerrortype; 158 PetscFunctionReturn(0); 159 } 160 161 /*@ 162 MatFactorClearError - clears the error code in a factorization 163 164 Logically Collective on mat 165 166 Input Parameter: 167 . mat - the factored matrix 168 169 Level: developer 170 171 Note: 172 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 173 174 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 175 `MatGetErrorCode()`, `MatFactorError` 176 @*/ 177 PetscErrorCode MatFactorClearError(Mat mat) { 178 PetscFunctionBegin; 179 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 180 mat->factorerrortype = MAT_FACTOR_NOERROR; 181 mat->factorerror_zeropivot_value = 0.0; 182 mat->factorerror_zeropivot_row = 0; 183 PetscFunctionReturn(0); 184 } 185 186 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) { 187 Vec r, l; 188 const PetscScalar *al; 189 PetscInt i, nz, gnz, N, n; 190 191 PetscFunctionBegin; 192 PetscCall(MatCreateVecs(mat, &r, &l)); 193 if (!cols) { /* nonzero rows */ 194 PetscCall(MatGetSize(mat, &N, NULL)); 195 PetscCall(MatGetLocalSize(mat, &n, NULL)); 196 PetscCall(VecSet(l, 0.0)); 197 PetscCall(VecSetRandom(r, NULL)); 198 PetscCall(MatMult(mat, r, l)); 199 PetscCall(VecGetArrayRead(l, &al)); 200 } else { /* nonzero columns */ 201 PetscCall(MatGetSize(mat, NULL, &N)); 202 PetscCall(MatGetLocalSize(mat, NULL, &n)); 203 PetscCall(VecSet(r, 0.0)); 204 PetscCall(VecSetRandom(l, NULL)); 205 PetscCall(MatMultTranspose(mat, l, r)); 206 PetscCall(VecGetArrayRead(r, &al)); 207 } 208 if (tol <= 0.0) { 209 for (i = 0, nz = 0; i < n; i++) 210 if (al[i] != 0.0) nz++; 211 } else { 212 for (i = 0, nz = 0; i < n; i++) 213 if (PetscAbsScalar(al[i]) > tol) nz++; 214 } 215 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 216 if (gnz != N) { 217 PetscInt *nzr; 218 PetscCall(PetscMalloc1(nz, &nzr)); 219 if (nz) { 220 if (tol < 0) { 221 for (i = 0, nz = 0; i < n; i++) 222 if (al[i] != 0.0) nzr[nz++] = i; 223 } else { 224 for (i = 0, nz = 0; i < n; i++) 225 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 226 } 227 } 228 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 229 } else *nonzero = NULL; 230 if (!cols) { /* nonzero rows */ 231 PetscCall(VecRestoreArrayRead(l, &al)); 232 } else { 233 PetscCall(VecRestoreArrayRead(r, &al)); 234 } 235 PetscCall(VecDestroy(&l)); 236 PetscCall(VecDestroy(&r)); 237 PetscFunctionReturn(0); 238 } 239 240 /*@ 241 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 242 243 Input Parameter: 244 . A - the matrix 245 246 Output Parameter: 247 . keptrows - the rows that are not completely zero 248 249 Note: 250 keptrows is set to NULL if all rows are nonzero. 251 252 Level: intermediate 253 254 .seealso: `Mat`, `MatFindZeroRows()` 255 @*/ 256 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) { 257 PetscFunctionBegin; 258 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 259 PetscValidType(mat, 1); 260 PetscValidPointer(keptrows, 2); 261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 262 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 263 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 264 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 265 PetscFunctionReturn(0); 266 } 267 268 /*@ 269 MatFindZeroRows - Locate all rows that are completely zero in the matrix 270 271 Input Parameter: 272 . A - the matrix 273 274 Output Parameter: 275 . zerorows - the rows that are completely zero 276 277 Note: 278 zerorows is set to NULL if no rows are zero. 279 280 Level: intermediate 281 282 .seealso: `Mat`, `MatFindNonzeroRows()` 283 @*/ 284 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) { 285 IS keptrows; 286 PetscInt m, n; 287 288 PetscFunctionBegin; 289 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 290 PetscValidType(mat, 1); 291 PetscValidPointer(zerorows, 2); 292 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 293 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 294 In keeping with this convention, we set zerorows to NULL if there are no zero 295 rows. */ 296 if (keptrows == NULL) { 297 *zerorows = NULL; 298 } else { 299 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 300 PetscCall(ISComplement(keptrows, m, n, zerorows)); 301 PetscCall(ISDestroy(&keptrows)); 302 } 303 PetscFunctionReturn(0); 304 } 305 306 /*@ 307 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 308 309 Not Collective 310 311 Input Parameters: 312 . A - the matrix 313 314 Output Parameters: 315 . a - the diagonal part (which is a SEQUENTIAL matrix) 316 317 Notes: 318 See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 319 320 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation. 321 322 Level: advanced 323 324 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 325 @*/ 326 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) { 327 PetscFunctionBegin; 328 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 329 PetscValidType(A, 1); 330 PetscValidPointer(a, 2); 331 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 332 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 333 else { 334 PetscMPIInt size; 335 336 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 337 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 338 *a = A; 339 } 340 PetscFunctionReturn(0); 341 } 342 343 /*@ 344 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 345 346 Collective on mat 347 348 Input Parameters: 349 . mat - the matrix 350 351 Output Parameter: 352 . trace - the sum of the diagonal entries 353 354 Level: advanced 355 356 .seealso: `Mat` 357 @*/ 358 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) { 359 Vec diag; 360 361 PetscFunctionBegin; 362 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 363 PetscValidScalarPointer(trace, 2); 364 PetscCall(MatCreateVecs(mat, &diag, NULL)); 365 PetscCall(MatGetDiagonal(mat, diag)); 366 PetscCall(VecSum(diag, trace)); 367 PetscCall(VecDestroy(&diag)); 368 PetscFunctionReturn(0); 369 } 370 371 /*@ 372 MatRealPart - Zeros out the imaginary part of the matrix 373 374 Logically Collective on mat 375 376 Input Parameters: 377 . mat - the matrix 378 379 Level: advanced 380 381 .seealso: `MatImaginaryPart()` 382 @*/ 383 PetscErrorCode MatRealPart(Mat mat) { 384 PetscFunctionBegin; 385 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 386 PetscValidType(mat, 1); 387 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 388 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 389 MatCheckPreallocated(mat, 1); 390 PetscUseTypeMethod(mat, realpart); 391 PetscFunctionReturn(0); 392 } 393 394 /*@C 395 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 396 397 Collective on mat 398 399 Input Parameter: 400 . mat - the matrix 401 402 Output Parameters: 403 + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 404 - ghosts - the global indices of the ghost points 405 406 Note: 407 the nghosts and ghosts are suitable to pass into `VecCreateGhost()` 408 409 Level: advanced 410 411 .seealso: `Mat`, `VecCreateGhost()` 412 @*/ 413 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) { 414 PetscFunctionBegin; 415 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 416 PetscValidType(mat, 1); 417 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 418 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 419 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 420 else { 421 if (nghosts) *nghosts = 0; 422 if (ghosts) *ghosts = NULL; 423 } 424 PetscFunctionReturn(0); 425 } 426 427 /*@ 428 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 429 430 Logically Collective on mat 431 432 Input Parameters: 433 . mat - the matrix 434 435 Level: advanced 436 437 .seealso: `MatRealPart()` 438 @*/ 439 PetscErrorCode MatImaginaryPart(Mat mat) { 440 PetscFunctionBegin; 441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 442 PetscValidType(mat, 1); 443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 444 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 445 MatCheckPreallocated(mat, 1); 446 PetscUseTypeMethod(mat, imaginarypart); 447 PetscFunctionReturn(0); 448 } 449 450 /*@ 451 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 452 453 Not Collective 454 455 Input Parameter: 456 . mat - the matrix 457 458 Output Parameters: 459 + missing - is any diagonal missing 460 - dd - first diagonal entry that is missing (optional) on this process 461 462 Level: advanced 463 464 .seealso: `Mat` 465 @*/ 466 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) { 467 PetscFunctionBegin; 468 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 469 PetscValidType(mat, 1); 470 PetscValidBoolPointer(missing, 2); 471 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 472 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 473 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 474 PetscFunctionReturn(0); 475 } 476 477 /*@C 478 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 479 for each row that you get to ensure that your application does 480 not bleed memory. 481 482 Not Collective 483 484 Input Parameters: 485 + mat - the matrix 486 - row - the row to get 487 488 Output Parameters: 489 + ncols - if not NULL, the number of nonzeros in the row 490 . cols - if not NULL, the column numbers 491 - vals - if not NULL, the values 492 493 Notes: 494 This routine is provided for people who need to have direct access 495 to the structure of a matrix. We hope that we provide enough 496 high-level matrix routines that few users will need it. 497 498 `MatGetRow()` always returns 0-based column indices, regardless of 499 whether the internal representation is 0-based (default) or 1-based. 500 501 For better efficiency, set cols and/or vals to NULL if you do 502 not wish to extract these quantities. 503 504 The user can only examine the values extracted with `MatGetRow()`; 505 the values cannot be altered. To change the matrix entries, one 506 must use `MatSetValues()`. 507 508 You can only have one call to `MatGetRow()` outstanding for a particular 509 matrix at a time, per processor. `MatGetRow()` can only obtain rows 510 associated with the given processor, it cannot get rows from the 511 other processors; for that we suggest using `MatCreateSubMatrices()`, then 512 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 513 is in the global number of rows. 514 515 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 516 517 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 518 519 Fortran Note: 520 The calling sequence from Fortran is 521 .vb 522 MatGetRow(matrix,row,ncols,cols,values,ierr) 523 Mat matrix (input) 524 integer row (input) 525 integer ncols (output) 526 integer cols(maxcols) (output) 527 double precision (or double complex) values(maxcols) output 528 .ve 529 where maxcols >= maximum nonzeros in any row of the matrix. 530 531 Caution: 532 Do not try to change the contents of the output arrays (cols and vals). 533 In some cases, this may corrupt the matrix. 534 535 Level: advanced 536 537 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 538 @*/ 539 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) { 540 PetscInt incols; 541 542 PetscFunctionBegin; 543 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 544 PetscValidType(mat, 1); 545 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 546 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 547 MatCheckPreallocated(mat, 1); 548 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); 549 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 550 PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals)); 551 if (ncols) *ncols = incols; 552 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 553 PetscFunctionReturn(0); 554 } 555 556 /*@ 557 MatConjugate - replaces the matrix values with their complex conjugates 558 559 Logically Collective on mat 560 561 Input Parameters: 562 . mat - the matrix 563 564 Level: advanced 565 566 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 567 @*/ 568 PetscErrorCode MatConjugate(Mat mat) { 569 PetscFunctionBegin; 570 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 571 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 572 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 573 PetscUseTypeMethod(mat, conjugate); 574 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 575 } 576 PetscFunctionReturn(0); 577 } 578 579 /*@C 580 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 581 582 Not Collective 583 584 Input Parameters: 585 + mat - the matrix 586 . row - the row to get 587 . ncols, cols - the number of nonzeros and their columns 588 - vals - if nonzero the column values 589 590 Notes: 591 This routine should be called after you have finished examining the entries. 592 593 This routine zeros out ncols, cols, and vals. This is to prevent accidental 594 us of the array after it has been restored. If you pass NULL, it will 595 not zero the pointers. Use of cols or vals after `MatRestoreRow()` is invalid. 596 597 Fortran Notes: 598 The calling sequence from Fortran is 599 .vb 600 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 601 Mat matrix (input) 602 integer row (input) 603 integer ncols (output) 604 integer cols(maxcols) (output) 605 double precision (or double complex) values(maxcols) output 606 .ve 607 Where maxcols >= maximum nonzeros in any row of the matrix. 608 609 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 610 before another call to `MatGetRow()` can be made. 611 612 Level: advanced 613 614 .seealso: `MatGetRow()` 615 @*/ 616 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) { 617 PetscFunctionBegin; 618 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 619 if (ncols) PetscValidIntPointer(ncols, 3); 620 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 621 if (!mat->ops->restorerow) PetscFunctionReturn(0); 622 PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals)); 623 if (ncols) *ncols = 0; 624 if (cols) *cols = NULL; 625 if (vals) *vals = NULL; 626 PetscFunctionReturn(0); 627 } 628 629 /*@ 630 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 631 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 632 633 Not Collective 634 635 Input Parameters: 636 . mat - the matrix 637 638 Note: 639 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. 640 641 Level: advanced 642 643 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 644 @*/ 645 PetscErrorCode MatGetRowUpperTriangular(Mat mat) { 646 PetscFunctionBegin; 647 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 648 PetscValidType(mat, 1); 649 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 650 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 651 MatCheckPreallocated(mat, 1); 652 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0); 653 PetscUseTypeMethod(mat, getrowuppertriangular); 654 PetscFunctionReturn(0); 655 } 656 657 /*@ 658 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 659 660 Not Collective 661 662 Input Parameters: 663 . mat - the matrix 664 665 Note: 666 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 667 668 Level: advanced 669 670 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()` 671 @*/ 672 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) { 673 PetscFunctionBegin; 674 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 675 PetscValidType(mat, 1); 676 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 677 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 678 MatCheckPreallocated(mat, 1); 679 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0); 680 PetscUseTypeMethod(mat, restorerowuppertriangular); 681 PetscFunctionReturn(0); 682 } 683 684 /*@C 685 MatSetOptionsPrefix - Sets the prefix used for searching for all 686 `Mat` options in the database. 687 688 Logically Collective on A 689 690 Input Parameters: 691 + A - the matrix 692 - prefix - the prefix to prepend to all option names 693 694 Notes: 695 A hyphen (-) must NOT be given at the beginning of the prefix name. 696 The first character of all runtime options is AUTOMATICALLY the hyphen. 697 698 This is NOT used for options for the factorization of the matrix. Normally the 699 prefix is automatically passed in from the PC calling the factorization. To set 700 it directly use `MatSetOptionsPrefixFactor()` 701 702 Level: advanced 703 704 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 705 @*/ 706 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) { 707 PetscFunctionBegin; 708 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 709 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 710 PetscFunctionReturn(0); 711 } 712 713 /*@C 714 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 715 for matrices created with `MatGetFactor()` 716 717 Logically Collective on A 718 719 Input Parameters: 720 + A - the matrix 721 - prefix - the prefix to prepend to all option names for the factored matrix 722 723 Notes: 724 A hyphen (-) must NOT be given at the beginning of the prefix name. 725 The first character of all runtime options is AUTOMATICALLY the hyphen. 726 727 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 728 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 729 730 Level: developer 731 732 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 733 @*/ 734 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) { 735 PetscFunctionBegin; 736 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 737 if (prefix) { 738 PetscValidCharPointer(prefix, 2); 739 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 740 if (prefix != A->factorprefix) { 741 PetscCall(PetscFree(A->factorprefix)); 742 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 743 } 744 } else PetscCall(PetscFree(A->factorprefix)); 745 PetscFunctionReturn(0); 746 } 747 748 /*@C 749 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 750 for matrices created with `MatGetFactor()` 751 752 Logically Collective on A 753 754 Input Parameters: 755 + A - the matrix 756 - prefix - the prefix to prepend to all option names for the factored matrix 757 758 Notes: 759 A hyphen (-) must NOT be given at the beginning of the prefix name. 760 The first character of all runtime options is AUTOMATICALLY the hyphen. 761 762 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 763 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 764 765 Level: developer 766 767 .seealso: `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 768 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 769 `MatSetOptionsPrefix()` 770 @*/ 771 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) { 772 char *buf = A->factorprefix; 773 size_t len1, len2; 774 775 PetscFunctionBegin; 776 PetscValidHeader(A, 1); 777 if (!prefix) PetscFunctionReturn(0); 778 if (!buf) { 779 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 780 PetscFunctionReturn(0); 781 } 782 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 783 784 PetscCall(PetscStrlen(prefix, &len1)); 785 PetscCall(PetscStrlen(buf, &len2)); 786 PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix)); 787 PetscCall(PetscStrcpy(A->factorprefix, buf)); 788 PetscCall(PetscStrcat(A->factorprefix, prefix)); 789 PetscCall(PetscFree(buf)); 790 PetscFunctionReturn(0); 791 } 792 793 /*@C 794 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 795 matrix options in the database. 796 797 Logically Collective on A 798 799 Input Parameters: 800 + A - the matrix 801 - prefix - the prefix to prepend to all option names 802 803 Note: 804 A hyphen (-) must NOT be given at the beginning of the prefix name. 805 The first character of all runtime options is AUTOMATICALLY the hyphen. 806 807 Level: advanced 808 809 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 810 @*/ 811 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) { 812 PetscFunctionBegin; 813 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 814 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 815 PetscFunctionReturn(0); 816 } 817 818 /*@C 819 MatGetOptionsPrefix - Gets the prefix used for searching for all 820 matrix options in the database. 821 822 Not Collective 823 824 Input Parameter: 825 . A - the matrix 826 827 Output Parameter: 828 . prefix - pointer to the prefix string used 829 830 Fortran Note: 831 On the fortran side, the user should pass in a string 'prefix' of 832 sufficient length to hold the prefix. 833 834 Level: advanced 835 836 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 837 @*/ 838 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) { 839 PetscFunctionBegin; 840 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 841 PetscValidPointer(prefix, 2); 842 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 843 PetscFunctionReturn(0); 844 } 845 846 /*@ 847 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 848 849 Collective on A 850 851 Input Parameters: 852 . A - the matrix 853 854 Notes: 855 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 856 857 Users can reset the preallocation to access the original memory. 858 859 Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices. 860 861 Level: beginner 862 863 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 864 @*/ 865 PetscErrorCode MatResetPreallocation(Mat A) { 866 PetscFunctionBegin; 867 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 868 PetscValidType(A, 1); 869 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 870 PetscFunctionReturn(0); 871 } 872 873 /*@ 874 MatSetUp - Sets up the internal matrix data structures for later use. 875 876 Collective on A 877 878 Input Parameters: 879 . A - the matrix 880 881 Notes: 882 If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used. 883 884 If a suitable preallocation routine is used, this function does not need to be called. 885 886 See the Performance chapter of the PETSc users manual for how to preallocate matrices 887 888 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 889 890 Level: intermediate 891 892 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()` 893 @*/ 894 PetscErrorCode MatSetUp(Mat A) { 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 897 if (!((PetscObject)A)->type_name) { 898 PetscMPIInt size; 899 900 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 901 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 902 } 903 if (!A->preallocated && A->ops->setup) { 904 PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n")); 905 PetscUseTypeMethod(A, setup); 906 } 907 PetscCall(PetscLayoutSetUp(A->rmap)); 908 PetscCall(PetscLayoutSetUp(A->cmap)); 909 A->preallocated = PETSC_TRUE; 910 PetscFunctionReturn(0); 911 } 912 913 #if defined(PETSC_HAVE_SAWS) 914 #include <petscviewersaws.h> 915 #endif 916 917 /*@C 918 MatViewFromOptions - View properties of the matrix from the options database 919 920 Collective on A 921 922 Input Parameters: 923 + A - the matrix 924 . obj - optional additional object that provides the options prefix to use 925 - name - command line option 926 927 Options Database: 928 . -mat_view [viewertype]:... - the viewer and its options 929 930 Notes: 931 .vb 932 If no value is provided ascii:stdout is used 933 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 934 for example ascii::ascii_info prints just the information about the object not all details 935 unless :append is given filename opens in write mode, overwriting what was already there 936 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 937 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 938 socket[:port] defaults to the standard output port 939 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 940 .ve 941 942 Level: intermediate 943 944 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 945 @*/ 946 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) { 947 PetscFunctionBegin; 948 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 949 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 950 PetscFunctionReturn(0); 951 } 952 953 /*@C 954 MatView - display information about a matrix in a variety ways 955 956 Collective on mat 957 958 Input Parameters: 959 + mat - the matrix 960 - viewer - visualization context 961 962 Notes: 963 The available visualization contexts include 964 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 965 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 966 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 967 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 968 969 The user can open alternative visualization contexts with 970 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 971 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 972 specified file; corresponding input uses MatLoad() 973 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 974 an X window display 975 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 976 Currently only the sequential dense and AIJ 977 matrix types support the Socket viewer. 978 979 The user can call `PetscViewerPushFormat()` to specify the output 980 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 981 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 982 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 983 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 984 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 985 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 986 format common among all matrix types 987 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 988 format (which is in many cases the same as the default) 989 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 990 size and structure (not the matrix entries) 991 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 992 the matrix structure 993 994 Options Database Keys: 995 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 996 . -mat_view ::ascii_info_detail - Prints more detailed info 997 . -mat_view - Prints matrix in ASCII format 998 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 999 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1000 . -display <name> - Sets display name (default is host) 1001 . -draw_pause <sec> - Sets number of seconds to pause after display 1002 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1003 . -viewer_socket_machine <machine> - 1004 . -viewer_socket_port <port> - 1005 . -mat_view binary - save matrix to file in binary format 1006 - -viewer_binary_filename <name> - 1007 1008 Level: beginner 1009 1010 Notes: 1011 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1012 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1013 1014 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1015 1016 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1017 viewer is used. 1018 1019 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1020 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1021 1022 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1023 and then use the following mouse functions. 1024 .vb 1025 left mouse: zoom in 1026 middle mouse: zoom out 1027 right mouse: continue with the simulation 1028 .ve 1029 1030 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`, 1031 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1032 @*/ 1033 PetscErrorCode MatView(Mat mat, PetscViewer viewer) { 1034 PetscInt rows, cols, rbs, cbs; 1035 PetscBool isascii, isstring, issaws; 1036 PetscViewerFormat format; 1037 PetscMPIInt size; 1038 1039 PetscFunctionBegin; 1040 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1041 PetscValidType(mat, 1); 1042 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1043 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1044 PetscCheckSameComm(mat, 1, viewer, 2); 1045 MatCheckPreallocated(mat, 1); 1046 1047 PetscCall(PetscViewerGetFormat(viewer, &format)); 1048 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1049 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0); 1050 1051 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1052 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1053 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1054 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"); 1055 1056 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1057 if (isascii) { 1058 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Must call MatAssemblyBegin/End() before viewing matrix"); 1059 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1060 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1061 MatNullSpace nullsp, transnullsp; 1062 1063 PetscCall(PetscViewerASCIIPushTab(viewer)); 1064 PetscCall(MatGetSize(mat, &rows, &cols)); 1065 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1066 if (rbs != 1 || cbs != 1) { 1067 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1068 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1069 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1070 if (mat->factortype) { 1071 MatSolverType solver; 1072 PetscCall(MatFactorGetSolverType(mat, &solver)); 1073 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1074 } 1075 if (mat->ops->getinfo) { 1076 MatInfo info; 1077 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1078 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1079 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1080 } 1081 PetscCall(MatGetNullSpace(mat, &nullsp)); 1082 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1083 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1084 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1085 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1086 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1087 PetscCall(PetscViewerASCIIPushTab(viewer)); 1088 PetscCall(MatProductView(mat, viewer)); 1089 PetscCall(PetscViewerASCIIPopTab(viewer)); 1090 } 1091 } else if (issaws) { 1092 #if defined(PETSC_HAVE_SAWS) 1093 PetscMPIInt rank; 1094 1095 PetscCall(PetscObjectName((PetscObject)mat)); 1096 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1097 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1098 #endif 1099 } else if (isstring) { 1100 const char *type; 1101 PetscCall(MatGetType(mat, &type)); 1102 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1103 PetscTryTypeMethod(mat, view, viewer); 1104 } 1105 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1106 PetscCall(PetscViewerASCIIPushTab(viewer)); 1107 PetscUseTypeMethod(mat, viewnative, viewer); 1108 PetscCall(PetscViewerASCIIPopTab(viewer)); 1109 } else if (mat->ops->view) { 1110 PetscCall(PetscViewerASCIIPushTab(viewer)); 1111 PetscUseTypeMethod(mat, view, viewer); 1112 PetscCall(PetscViewerASCIIPopTab(viewer)); 1113 } 1114 if (isascii) { 1115 PetscCall(PetscViewerGetFormat(viewer, &format)); 1116 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1117 } 1118 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1119 PetscFunctionReturn(0); 1120 } 1121 1122 #if defined(PETSC_USE_DEBUG) 1123 #include <../src/sys/totalview/tv_data_display.h> 1124 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) { 1125 TV_add_row("Local rows", "int", &mat->rmap->n); 1126 TV_add_row("Local columns", "int", &mat->cmap->n); 1127 TV_add_row("Global rows", "int", &mat->rmap->N); 1128 TV_add_row("Global columns", "int", &mat->cmap->N); 1129 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1130 return TV_format_OK; 1131 } 1132 #endif 1133 1134 /*@C 1135 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1136 with `MatView()`. The matrix format is determined from the options database. 1137 Generates a parallel MPI matrix if the communicator has more than one 1138 processor. The default matrix type is `MATAIJ`. 1139 1140 Collective on mat 1141 1142 Input Parameters: 1143 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1144 or some related function before a call to `MatLoad()` 1145 - viewer - binary/HDF5 file viewer 1146 1147 Options Database Keys: 1148 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1149 block size 1150 . -matload_block_size <bs> - set block size 1151 1152 Level: beginner 1153 1154 Notes: 1155 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1156 `Mat` before calling this routine if you wish to set it from the options database. 1157 1158 `MatLoad()` automatically loads into the options database any options 1159 given in the file filename.info where filename is the name of the file 1160 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1161 file will be ignored if you use the -viewer_binary_skip_info option. 1162 1163 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1164 sets the default matrix type AIJ and sets the local and global sizes. 1165 If type and/or size is already set, then the same are used. 1166 1167 In parallel, each processor can load a subset of rows (or the 1168 entire matrix). This routine is especially useful when a large 1169 matrix is stored on disk and only part of it is desired on each 1170 processor. For example, a parallel solver may access only some of 1171 the rows from each processor. The algorithm used here reads 1172 relatively small blocks of data rather than reading the entire 1173 matrix and then subsetting it. 1174 1175 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1176 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1177 or the sequence like 1178 .vb 1179 `PetscViewer` v; 1180 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1181 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1182 `PetscViewerSetFromOptions`(v); 1183 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1184 `PetscViewerFileSetName`(v,"datafile"); 1185 .ve 1186 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1187 $ -viewer_type {binary,hdf5} 1188 1189 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1190 and src/mat/tutorials/ex10.c with the second approach. 1191 1192 Notes about the PETSc binary format: 1193 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1194 is read onto rank 0 and then shipped to its destination rank, one after another. 1195 Multiple objects, both matrices and vectors, can be stored within the same file. 1196 Their PetscObject name is ignored; they are loaded in the order of their storage. 1197 1198 Most users should not need to know the details of the binary storage 1199 format, since `MatLoad()` and `MatView()` completely hide these details. 1200 But for anyone who's interested, the standard binary matrix storage 1201 format is 1202 1203 $ PetscInt MAT_FILE_CLASSID 1204 $ PetscInt number of rows 1205 $ PetscInt number of columns 1206 $ PetscInt total number of nonzeros 1207 $ PetscInt *number nonzeros in each row 1208 $ PetscInt *column indices of all nonzeros (starting index is zero) 1209 $ PetscScalar *values of all nonzeros 1210 1211 PETSc automatically does the byte swapping for 1212 machines that store the bytes reversed, e.g. DEC alpha, freebsd, 1213 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary 1214 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1215 and `PetscBinaryWrite()` to see how this may be done. 1216 1217 Notes about the HDF5 (MATLAB MAT-File Version 7.3) format: 1218 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1219 Each processor's chunk is loaded independently by its owning rank. 1220 Multiple objects, both matrices and vectors, can be stored within the same file. 1221 They are looked up by their PetscObject name. 1222 1223 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1224 by default the same structure and naming of the AIJ arrays and column count 1225 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1226 $ save example.mat A b -v7.3 1227 can be directly read by this routine (see Reference 1 for details). 1228 Note that depending on your MATLAB version, this format might be a default, 1229 otherwise you can set it as default in Preferences. 1230 1231 Unless -nocompression flag is used to save the file in MATLAB, 1232 PETSc must be configured with ZLIB package. 1233 1234 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1235 1236 Current HDF5 (MAT-File) limitations: 1237 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices. 1238 1239 Corresponding `MatView()` is not yet implemented. 1240 1241 The loaded matrix is actually a transpose of the original one in MATLAB, 1242 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1243 With this format, matrix is automatically transposed by PETSc, 1244 unless the matrix is marked as SPD or symmetric 1245 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1246 1247 References: 1248 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1249 1250 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1251 @*/ 1252 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) { 1253 PetscBool flg; 1254 1255 PetscFunctionBegin; 1256 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1257 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1258 1259 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1260 1261 flg = PETSC_FALSE; 1262 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1263 if (flg) { 1264 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1265 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1266 } 1267 flg = PETSC_FALSE; 1268 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1269 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1270 1271 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1272 PetscUseTypeMethod(mat, load, viewer); 1273 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1274 PetscFunctionReturn(0); 1275 } 1276 1277 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) { 1278 Mat_Redundant *redund = *redundant; 1279 1280 PetscFunctionBegin; 1281 if (redund) { 1282 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1283 PetscCall(ISDestroy(&redund->isrow)); 1284 PetscCall(ISDestroy(&redund->iscol)); 1285 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1286 } else { 1287 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1288 PetscCall(PetscFree(redund->sbuf_j)); 1289 PetscCall(PetscFree(redund->sbuf_a)); 1290 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1291 PetscCall(PetscFree(redund->rbuf_j[i])); 1292 PetscCall(PetscFree(redund->rbuf_a[i])); 1293 } 1294 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1295 } 1296 1297 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1298 PetscCall(PetscFree(redund)); 1299 } 1300 PetscFunctionReturn(0); 1301 } 1302 1303 /*@C 1304 MatDestroy - Frees space taken by a matrix. 1305 1306 Collective on A 1307 1308 Input Parameter: 1309 . A - the matrix 1310 1311 Level: beginner 1312 1313 Developer Note: 1314 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1315 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1316 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1317 if changes are needed here. 1318 1319 .seealso: `Mat`, `MatCreate()` 1320 @*/ 1321 PetscErrorCode MatDestroy(Mat *A) { 1322 PetscFunctionBegin; 1323 if (!*A) PetscFunctionReturn(0); 1324 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1325 if (--((PetscObject)(*A))->refct > 0) { 1326 *A = NULL; 1327 PetscFunctionReturn(0); 1328 } 1329 1330 /* if memory was published with SAWs then destroy it */ 1331 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1332 PetscTryTypeMethod((*A), destroy); 1333 1334 PetscCall(PetscFree((*A)->factorprefix)); 1335 PetscCall(PetscFree((*A)->defaultvectype)); 1336 PetscCall(PetscFree((*A)->defaultrandtype)); 1337 PetscCall(PetscFree((*A)->bsizes)); 1338 PetscCall(PetscFree((*A)->solvertype)); 1339 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1340 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1341 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1342 PetscCall(MatProductClear(*A)); 1343 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1344 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1345 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1346 PetscCall(MatDestroy(&(*A)->schur)); 1347 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1348 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1349 PetscCall(PetscHeaderDestroy(A)); 1350 PetscFunctionReturn(0); 1351 } 1352 1353 /*@C 1354 MatSetValues - Inserts or adds a block of values into a matrix. 1355 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1356 MUST be called after all calls to `MatSetValues()` have been completed. 1357 1358 Not Collective 1359 1360 Input Parameters: 1361 + mat - the matrix 1362 . v - a logically two-dimensional array of values 1363 . m, idxm - the number of rows and their global indices 1364 . n, idxn - the number of columns and their global indices 1365 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1366 1367 Notes: 1368 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1369 `MatSetUp()` before using this routine 1370 1371 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1372 1373 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1374 options cannot be mixed without intervening calls to the assembly 1375 routines. 1376 1377 `MatSetValues()` uses 0-based row and column numbers in Fortran 1378 as well as in C. 1379 1380 Negative indices may be passed in idxm and idxn, these rows and columns are 1381 simply ignored. This allows easily inserting element stiffness matrices 1382 with homogeneous Dirchlet boundary conditions that you don't want represented 1383 in the matrix. 1384 1385 Efficiency Alert: 1386 The routine `MatSetValuesBlocked()` may offer much better efficiency 1387 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1388 1389 Level: beginner 1390 1391 Developer Note: 1392 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1393 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1394 1395 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1396 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1397 @*/ 1398 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) { 1399 PetscFunctionBeginHot; 1400 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1401 PetscValidType(mat, 1); 1402 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1403 PetscValidIntPointer(idxm, 3); 1404 PetscValidIntPointer(idxn, 5); 1405 MatCheckPreallocated(mat, 1); 1406 1407 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1408 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1409 1410 if (PetscDefined(USE_DEBUG)) { 1411 PetscInt i, j; 1412 1413 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1414 for (i = 0; i < m; i++) { 1415 for (j = 0; j < n; j++) { 1416 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1417 #if defined(PETSC_USE_COMPLEX) 1418 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]); 1419 #else 1420 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]); 1421 #endif 1422 } 1423 } 1424 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); 1425 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); 1426 } 1427 1428 if (mat->assembled) { 1429 mat->was_assembled = PETSC_TRUE; 1430 mat->assembled = PETSC_FALSE; 1431 } 1432 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1433 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1434 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1435 PetscFunctionReturn(0); 1436 } 1437 1438 /*@C 1439 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1440 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1441 MUST be called after all calls to `MatSetValues()` have been completed. 1442 1443 Not Collective 1444 1445 Input Parameters: 1446 + mat - the matrix 1447 . v - a logically two-dimensional array of values 1448 . ism - the rows to provide 1449 . isn - the columns to provide 1450 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1451 1452 Notes: 1453 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1454 `MatSetUp()` before using this routine 1455 1456 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1457 1458 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1459 options cannot be mixed without intervening calls to the assembly 1460 routines. 1461 1462 MatSetValues() uses 0-based row and column numbers in Fortran 1463 as well as in C. 1464 1465 Negative indices may be passed in ism and isn, these rows and columns are 1466 simply ignored. This allows easily inserting element stiffness matrices 1467 with homogeneous Dirchlet boundary conditions that you don't want represented 1468 in the matrix. 1469 1470 Efficiency Alert: 1471 The routine `MatSetValuesBlocked()` may offer much better efficiency 1472 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1473 1474 Level: beginner 1475 1476 Developer Notes: 1477 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1478 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1479 1480 This is currently not optimized for any particular `ISType` 1481 1482 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1483 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1484 @*/ 1485 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) { 1486 PetscInt m, n; 1487 const PetscInt *rows, *cols; 1488 1489 PetscFunctionBeginHot; 1490 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1491 PetscCall(ISGetIndices(ism, &rows)); 1492 PetscCall(ISGetIndices(isn, &cols)); 1493 PetscCall(ISGetLocalSize(ism, &m)); 1494 PetscCall(ISGetLocalSize(isn, &n)); 1495 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1496 PetscCall(ISRestoreIndices(ism, &rows)); 1497 PetscCall(ISRestoreIndices(isn, &cols)); 1498 PetscFunctionReturn(0); 1499 } 1500 1501 /*@ 1502 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1503 values into a matrix 1504 1505 Not Collective 1506 1507 Input Parameters: 1508 + mat - the matrix 1509 . row - the (block) row to set 1510 - v - a logically two-dimensional array of values 1511 1512 Notes: 1513 By the values, v, are column-oriented (for the block version) and sorted 1514 1515 All the nonzeros in the row must be provided 1516 1517 The matrix must have previously had its column indices set 1518 1519 The row must belong to this process 1520 1521 Level: intermediate 1522 1523 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1524 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1525 @*/ 1526 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) { 1527 PetscInt globalrow; 1528 1529 PetscFunctionBegin; 1530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1531 PetscValidType(mat, 1); 1532 PetscValidScalarPointer(v, 3); 1533 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1534 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1535 PetscFunctionReturn(0); 1536 } 1537 1538 /*@ 1539 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1540 values into a matrix 1541 1542 Not Collective 1543 1544 Input Parameters: 1545 + mat - the matrix 1546 . row - the (block) row to set 1547 - 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 1548 1549 Notes: 1550 The values, v, are column-oriented for the block version. 1551 1552 All the nonzeros in the row must be provided 1553 1554 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1555 1556 The row must belong to this process 1557 1558 Level: advanced 1559 1560 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1561 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1562 @*/ 1563 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) { 1564 PetscFunctionBeginHot; 1565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1566 PetscValidType(mat, 1); 1567 MatCheckPreallocated(mat, 1); 1568 PetscValidScalarPointer(v, 3); 1569 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1570 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1571 mat->insertmode = INSERT_VALUES; 1572 1573 if (mat->assembled) { 1574 mat->was_assembled = PETSC_TRUE; 1575 mat->assembled = PETSC_FALSE; 1576 } 1577 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1578 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1579 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1580 PetscFunctionReturn(0); 1581 } 1582 1583 /*@ 1584 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1585 Using structured grid indexing 1586 1587 Not Collective 1588 1589 Input Parameters: 1590 + mat - the matrix 1591 . m - number of rows being entered 1592 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1593 . n - number of columns being entered 1594 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1595 . v - a logically two-dimensional array of values 1596 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1597 1598 Notes: 1599 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1600 1601 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1602 options cannot be mixed without intervening calls to the assembly 1603 routines. 1604 1605 The grid coordinates are across the entire grid, not just the local portion 1606 1607 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1608 as well as in C. 1609 1610 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1611 1612 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1613 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1614 1615 The columns and rows in the stencil passed in MUST be contained within the 1616 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1617 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1618 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1619 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1620 1621 In Fortran idxm and idxn should be declared as 1622 $ MatStencil idxm(4,m),idxn(4,n) 1623 and the values inserted using 1624 $ idxm(MatStencil_i,1) = i 1625 $ idxm(MatStencil_j,1) = j 1626 $ idxm(MatStencil_k,1) = k 1627 $ idxm(MatStencil_c,1) = c 1628 etc 1629 1630 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1631 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1632 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1633 `DM_BOUNDARY_PERIODIC` boundary type. 1634 1635 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 1636 a single value per point) you can skip filling those indices. 1637 1638 Inspired by the structured grid interface to the HYPRE package 1639 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1640 1641 Efficiency Alert: 1642 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1643 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1644 1645 Level: beginner 1646 1647 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1648 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1649 @*/ 1650 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) { 1651 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1652 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1653 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1654 1655 PetscFunctionBegin; 1656 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1657 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1658 PetscValidType(mat, 1); 1659 PetscValidPointer(idxm, 3); 1660 PetscValidPointer(idxn, 5); 1661 1662 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1663 jdxm = buf; 1664 jdxn = buf + m; 1665 } else { 1666 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1667 jdxm = bufm; 1668 jdxn = bufn; 1669 } 1670 for (i = 0; i < m; i++) { 1671 for (j = 0; j < 3 - sdim; j++) dxm++; 1672 tmp = *dxm++ - starts[0]; 1673 for (j = 0; j < dim - 1; j++) { 1674 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1675 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1676 } 1677 if (mat->stencil.noc) dxm++; 1678 jdxm[i] = tmp; 1679 } 1680 for (i = 0; i < n; i++) { 1681 for (j = 0; j < 3 - sdim; j++) dxn++; 1682 tmp = *dxn++ - starts[0]; 1683 for (j = 0; j < dim - 1; j++) { 1684 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1685 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1686 } 1687 if (mat->stencil.noc) dxn++; 1688 jdxn[i] = tmp; 1689 } 1690 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1691 PetscCall(PetscFree2(bufm, bufn)); 1692 PetscFunctionReturn(0); 1693 } 1694 1695 /*@ 1696 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1697 Using structured grid indexing 1698 1699 Not Collective 1700 1701 Input Parameters: 1702 + mat - the matrix 1703 . m - number of rows being entered 1704 . idxm - grid coordinates for matrix rows being entered 1705 . n - number of columns being entered 1706 . idxn - grid coordinates for matrix columns being entered 1707 . v - a logically two-dimensional array of values 1708 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1709 1710 Notes: 1711 By default the values, v, are row-oriented and unsorted. 1712 See `MatSetOption()` for other options. 1713 1714 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1715 options cannot be mixed without intervening calls to the assembly 1716 routines. 1717 1718 The grid coordinates are across the entire grid, not just the local portion 1719 1720 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1721 as well as in C. 1722 1723 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1724 1725 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1726 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1727 1728 The columns and rows in the stencil passed in MUST be contained within the 1729 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1730 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1731 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1732 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1733 1734 In Fortran idxm and idxn should be declared as 1735 $ MatStencil idxm(4,m),idxn(4,n) 1736 and the values inserted using 1737 $ idxm(MatStencil_i,1) = i 1738 $ idxm(MatStencil_j,1) = j 1739 $ idxm(MatStencil_k,1) = k 1740 etc 1741 1742 Negative indices may be passed in idxm and idxn, these rows and columns are 1743 simply ignored. This allows easily inserting element stiffness matrices 1744 with homogeneous Dirchlet boundary conditions that you don't want represented 1745 in the matrix. 1746 1747 Inspired by the structured grid interface to the HYPRE package 1748 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1749 1750 Level: beginner 1751 1752 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1753 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1754 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1755 @*/ 1756 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) { 1757 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1758 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1759 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1760 1761 PetscFunctionBegin; 1762 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1763 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1764 PetscValidType(mat, 1); 1765 PetscValidPointer(idxm, 3); 1766 PetscValidPointer(idxn, 5); 1767 PetscValidScalarPointer(v, 6); 1768 1769 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1770 jdxm = buf; 1771 jdxn = buf + m; 1772 } else { 1773 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1774 jdxm = bufm; 1775 jdxn = bufn; 1776 } 1777 for (i = 0; i < m; i++) { 1778 for (j = 0; j < 3 - sdim; j++) dxm++; 1779 tmp = *dxm++ - starts[0]; 1780 for (j = 0; j < sdim - 1; j++) { 1781 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1782 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1783 } 1784 dxm++; 1785 jdxm[i] = tmp; 1786 } 1787 for (i = 0; i < n; i++) { 1788 for (j = 0; j < 3 - sdim; j++) dxn++; 1789 tmp = *dxn++ - starts[0]; 1790 for (j = 0; j < sdim - 1; j++) { 1791 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1792 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1793 } 1794 dxn++; 1795 jdxn[i] = tmp; 1796 } 1797 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1798 PetscCall(PetscFree2(bufm, bufn)); 1799 PetscFunctionReturn(0); 1800 } 1801 1802 /*@ 1803 MatSetStencil - Sets the grid information for setting values into a matrix via 1804 `MatSetValuesStencil()` 1805 1806 Not Collective 1807 1808 Input Parameters: 1809 + mat - the matrix 1810 . dim - dimension of the grid 1, 2, or 3 1811 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1812 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1813 - dof - number of degrees of freedom per node 1814 1815 Notes: 1816 Inspired by the structured grid interface to the HYPRE package 1817 (www.llnl.gov/CASC/hyper) 1818 1819 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1820 user. 1821 1822 Level: beginner 1823 1824 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1825 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1826 @*/ 1827 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) { 1828 PetscFunctionBegin; 1829 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1830 PetscValidIntPointer(dims, 3); 1831 PetscValidIntPointer(starts, 4); 1832 1833 mat->stencil.dim = dim + (dof > 1); 1834 for (PetscInt i = 0; i < dim; i++) { 1835 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1836 mat->stencil.starts[i] = starts[dim - i - 1]; 1837 } 1838 mat->stencil.dims[dim] = dof; 1839 mat->stencil.starts[dim] = 0; 1840 mat->stencil.noc = (PetscBool)(dof == 1); 1841 PetscFunctionReturn(0); 1842 } 1843 1844 /*@C 1845 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1846 1847 Not Collective 1848 1849 Input Parameters: 1850 + mat - the matrix 1851 . v - a logically two-dimensional array of values 1852 . m, idxm - the number of block rows and their global block indices 1853 . n, idxn - the number of block columns and their global block indices 1854 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1855 1856 Notes: 1857 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1858 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1859 1860 The m and n count the NUMBER of blocks in the row direction and column direction, 1861 NOT the total number of rows/columns; for example, if the block size is 2 and 1862 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1863 The values in idxm would be 1 2; that is the first index for each block divided by 1864 the block size. 1865 1866 Note that you must call `MatSetBlockSize()` when constructing this matrix (before 1867 preallocating it). 1868 1869 By default the values, v, are row-oriented, so the layout of 1870 v is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1871 1872 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1873 options cannot be mixed without intervening calls to the assembly 1874 routines. 1875 1876 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1877 as well as in C. 1878 1879 Negative indices may be passed in idxm and idxn, these rows and columns are 1880 simply ignored. This allows easily inserting element stiffness matrices 1881 with homogeneous Dirchlet boundary conditions that you don't want represented 1882 in the matrix. 1883 1884 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1885 internal searching must be done to determine where to place the 1886 data in the matrix storage space. By instead inserting blocks of 1887 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1888 reduced. 1889 1890 Example: 1891 $ Suppose m=n=2 and block size(bs) = 2 The array is 1892 $ 1893 $ 1 2 | 3 4 1894 $ 5 6 | 7 8 1895 $ - - - | - - - 1896 $ 9 10 | 11 12 1897 $ 13 14 | 15 16 1898 $ 1899 $ v[] should be passed in like 1900 $ v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1901 $ 1902 $ If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1903 $ v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1904 1905 Level: intermediate 1906 1907 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1908 @*/ 1909 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) { 1910 PetscFunctionBeginHot; 1911 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1912 PetscValidType(mat, 1); 1913 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1914 PetscValidIntPointer(idxm, 3); 1915 PetscValidIntPointer(idxn, 5); 1916 MatCheckPreallocated(mat, 1); 1917 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1918 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1919 if (PetscDefined(USE_DEBUG)) { 1920 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1921 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1922 } 1923 if (PetscDefined(USE_DEBUG)) { 1924 PetscInt rbs, cbs, M, N, i; 1925 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1926 PetscCall(MatGetSize(mat, &M, &N)); 1927 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); 1928 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); 1929 } 1930 if (mat->assembled) { 1931 mat->was_assembled = PETSC_TRUE; 1932 mat->assembled = PETSC_FALSE; 1933 } 1934 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1935 if (mat->ops->setvaluesblocked) { 1936 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1937 } else { 1938 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1939 PetscInt i, j, bs, cbs; 1940 1941 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1942 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1943 iidxm = buf; 1944 iidxn = buf + m * bs; 1945 } else { 1946 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 1947 iidxm = bufr; 1948 iidxn = bufc; 1949 } 1950 for (i = 0; i < m; i++) { 1951 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 1952 } 1953 if (m != n || bs != cbs || idxm != idxn) { 1954 for (i = 0; i < n; i++) { 1955 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 1956 } 1957 } else iidxn = iidxm; 1958 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 1959 PetscCall(PetscFree2(bufr, bufc)); 1960 } 1961 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1962 PetscFunctionReturn(0); 1963 } 1964 1965 /*@C 1966 MatGetValues - Gets a block of local values from a matrix. 1967 1968 Not Collective; can only return values that are owned by the give process 1969 1970 Input Parameters: 1971 + mat - the matrix 1972 . v - a logically two-dimensional array for storing the values 1973 . m, idxm - the number of rows and their global indices 1974 - n, idxn - the number of columns and their global indices 1975 1976 Notes: 1977 The user must allocate space (m*n `PetscScalar`s) for the values, v. 1978 The values, v, are then returned in a row-oriented format, 1979 analogous to that used by default in `MatSetValues()`. 1980 1981 `MatGetValues()` uses 0-based row and column numbers in 1982 Fortran as well as in C. 1983 1984 `MatGetValues()` requires that the matrix has been assembled 1985 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 1986 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 1987 without intermediate matrix assembly. 1988 1989 Negative row or column indices will be ignored and those locations in v[] will be 1990 left unchanged. 1991 1992 For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank. 1993 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 1994 from `MatGetOwnershipRange`(mat,&rstart,&rend). 1995 1996 Level: advanced 1997 1998 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 1999 @*/ 2000 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) { 2001 PetscFunctionBegin; 2002 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2003 PetscValidType(mat, 1); 2004 if (!m || !n) PetscFunctionReturn(0); 2005 PetscValidIntPointer(idxm, 3); 2006 PetscValidIntPointer(idxn, 5); 2007 PetscValidScalarPointer(v, 6); 2008 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2009 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2010 MatCheckPreallocated(mat, 1); 2011 2012 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2013 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2014 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2015 PetscFunctionReturn(0); 2016 } 2017 2018 /*@C 2019 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2020 defined previously by `MatSetLocalToGlobalMapping()` 2021 2022 Not Collective 2023 2024 Input Parameters: 2025 + mat - the matrix 2026 . nrow, irow - number of rows and their local indices 2027 - ncol, icol - number of columns and their local indices 2028 2029 Output Parameter: 2030 . y - a logically two-dimensional array of values 2031 2032 Notes: 2033 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2034 2035 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, 2036 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2037 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2038 with `MatSetLocalToGlobalMapping()`. 2039 2040 Developer Note: 2041 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2042 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2043 2044 Level: advanced 2045 2046 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2047 `MatSetValuesLocal()`, `MatGetValues()` 2048 @*/ 2049 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) { 2050 PetscFunctionBeginHot; 2051 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2052 PetscValidType(mat, 1); 2053 MatCheckPreallocated(mat, 1); 2054 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */ 2055 PetscValidIntPointer(irow, 3); 2056 PetscValidIntPointer(icol, 5); 2057 if (PetscDefined(USE_DEBUG)) { 2058 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2059 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2060 } 2061 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2062 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2063 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2064 else { 2065 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2066 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2067 irowm = buf; 2068 icolm = buf + nrow; 2069 } else { 2070 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2071 irowm = bufr; 2072 icolm = bufc; 2073 } 2074 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2075 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2076 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2077 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2078 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2079 PetscCall(PetscFree2(bufr, bufc)); 2080 } 2081 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2082 PetscFunctionReturn(0); 2083 } 2084 2085 /*@ 2086 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2087 the same size. Currently, this can only be called once and creates the given matrix. 2088 2089 Not Collective 2090 2091 Input Parameters: 2092 + mat - the matrix 2093 . nb - the number of blocks 2094 . bs - the number of rows (and columns) in each block 2095 . rows - a concatenation of the rows for each block 2096 - v - a concatenation of logically two-dimensional arrays of values 2097 2098 Note: 2099 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2100 2101 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2102 2103 Level: advanced 2104 2105 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2106 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2107 @*/ 2108 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) { 2109 PetscFunctionBegin; 2110 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2111 PetscValidType(mat, 1); 2112 PetscValidIntPointer(rows, 4); 2113 PetscValidScalarPointer(v, 5); 2114 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2115 2116 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2117 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2118 else { 2119 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2120 } 2121 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2122 PetscFunctionReturn(0); 2123 } 2124 2125 /*@ 2126 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2127 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2128 using a local (per-processor) numbering. 2129 2130 Not Collective 2131 2132 Input Parameters: 2133 + x - the matrix 2134 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2135 - cmapping - column mapping 2136 2137 Level: intermediate 2138 2139 Note: 2140 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2141 2142 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2143 @*/ 2144 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) { 2145 PetscFunctionBegin; 2146 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2147 PetscValidType(x, 1); 2148 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2149 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2150 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2151 else { 2152 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2153 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2154 } 2155 PetscFunctionReturn(0); 2156 } 2157 2158 /*@ 2159 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2160 2161 Not Collective 2162 2163 Input Parameter: 2164 . A - the matrix 2165 2166 Output Parameters: 2167 + rmapping - row mapping 2168 - cmapping - column mapping 2169 2170 Level: advanced 2171 2172 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2173 @*/ 2174 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) { 2175 PetscFunctionBegin; 2176 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2177 PetscValidType(A, 1); 2178 if (rmapping) { 2179 PetscValidPointer(rmapping, 2); 2180 *rmapping = A->rmap->mapping; 2181 } 2182 if (cmapping) { 2183 PetscValidPointer(cmapping, 3); 2184 *cmapping = A->cmap->mapping; 2185 } 2186 PetscFunctionReturn(0); 2187 } 2188 2189 /*@ 2190 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2191 2192 Logically Collective on A 2193 2194 Input Parameters: 2195 + A - the matrix 2196 . rmap - row layout 2197 - cmap - column layout 2198 2199 Level: advanced 2200 2201 Note: 2202 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2203 2204 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2205 @*/ 2206 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) { 2207 PetscFunctionBegin; 2208 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2209 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2210 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2211 PetscFunctionReturn(0); 2212 } 2213 2214 /*@ 2215 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2216 2217 Not Collective 2218 2219 Input Parameter: 2220 . A - the matrix 2221 2222 Output Parameters: 2223 + rmap - row layout 2224 - cmap - column layout 2225 2226 Level: advanced 2227 2228 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2229 @*/ 2230 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) { 2231 PetscFunctionBegin; 2232 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2233 PetscValidType(A, 1); 2234 if (rmap) { 2235 PetscValidPointer(rmap, 2); 2236 *rmap = A->rmap; 2237 } 2238 if (cmap) { 2239 PetscValidPointer(cmap, 3); 2240 *cmap = A->cmap; 2241 } 2242 PetscFunctionReturn(0); 2243 } 2244 2245 /*@C 2246 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2247 using a local numbering of the nodes. 2248 2249 Not Collective 2250 2251 Input Parameters: 2252 + mat - the matrix 2253 . nrow, irow - number of rows and their local indices 2254 . ncol, icol - number of columns and their local indices 2255 . y - a logically two-dimensional array of values 2256 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2257 2258 Notes: 2259 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2260 `MatSetUp()` before using this routine 2261 2262 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2263 2264 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2265 options cannot be mixed without intervening calls to the assembly 2266 routines. 2267 2268 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2269 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2270 2271 Level: intermediate 2272 2273 Developer Note: 2274 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2275 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2276 2277 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2278 `MatGetValuesLocal()` 2279 @*/ 2280 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) { 2281 PetscFunctionBeginHot; 2282 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2283 PetscValidType(mat, 1); 2284 MatCheckPreallocated(mat, 1); 2285 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2286 PetscValidIntPointer(irow, 3); 2287 PetscValidIntPointer(icol, 5); 2288 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2289 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2290 if (PetscDefined(USE_DEBUG)) { 2291 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2292 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2293 } 2294 2295 if (mat->assembled) { 2296 mat->was_assembled = PETSC_TRUE; 2297 mat->assembled = PETSC_FALSE; 2298 } 2299 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2300 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2301 else { 2302 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2303 const PetscInt *irowm, *icolm; 2304 2305 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2306 bufr = buf; 2307 bufc = buf + nrow; 2308 irowm = bufr; 2309 icolm = bufc; 2310 } else { 2311 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2312 irowm = bufr; 2313 icolm = bufc; 2314 } 2315 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2316 else irowm = irow; 2317 if (mat->cmap->mapping) { 2318 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2319 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2320 } else icolm = irowm; 2321 } else icolm = icol; 2322 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2323 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2324 } 2325 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2326 PetscFunctionReturn(0); 2327 } 2328 2329 /*@C 2330 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2331 using a local ordering of the nodes a block at a time. 2332 2333 Not Collective 2334 2335 Input Parameters: 2336 + x - the matrix 2337 . nrow, irow - number of rows and their local indices 2338 . ncol, icol - number of columns and their local indices 2339 . y - a logically two-dimensional array of values 2340 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2341 2342 Notes: 2343 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2344 `MatSetUp()` before using this routine 2345 2346 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2347 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2348 2349 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2350 options cannot be mixed without intervening calls to the assembly 2351 routines. 2352 2353 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2354 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2355 2356 Level: intermediate 2357 2358 Developer Note: 2359 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2360 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2361 2362 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2363 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2364 @*/ 2365 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) { 2366 PetscFunctionBeginHot; 2367 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2368 PetscValidType(mat, 1); 2369 MatCheckPreallocated(mat, 1); 2370 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2371 PetscValidIntPointer(irow, 3); 2372 PetscValidIntPointer(icol, 5); 2373 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2374 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2375 if (PetscDefined(USE_DEBUG)) { 2376 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2377 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); 2378 } 2379 2380 if (mat->assembled) { 2381 mat->was_assembled = PETSC_TRUE; 2382 mat->assembled = PETSC_FALSE; 2383 } 2384 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2385 PetscInt irbs, rbs; 2386 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2387 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2388 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2389 } 2390 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2391 PetscInt icbs, cbs; 2392 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2393 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2394 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2395 } 2396 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2397 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2398 else { 2399 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2400 const PetscInt *irowm, *icolm; 2401 2402 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2403 bufr = buf; 2404 bufc = buf + nrow; 2405 irowm = bufr; 2406 icolm = bufc; 2407 } else { 2408 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2409 irowm = bufr; 2410 icolm = bufc; 2411 } 2412 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2413 else irowm = irow; 2414 if (mat->cmap->mapping) { 2415 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2416 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2417 } else icolm = irowm; 2418 } else icolm = icol; 2419 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2420 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2421 } 2422 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2423 PetscFunctionReturn(0); 2424 } 2425 2426 /*@ 2427 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2428 2429 Collective on mat 2430 2431 Input Parameters: 2432 + mat - the matrix 2433 - x - the vector to be multiplied 2434 2435 Output Parameters: 2436 . y - the result 2437 2438 Note: 2439 The vectors x and y cannot be the same. I.e., one cannot 2440 call `MatMultDiagonalBlock`(A,y,y). 2441 2442 Level: developer 2443 2444 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2445 @*/ 2446 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) { 2447 PetscFunctionBegin; 2448 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2449 PetscValidType(mat, 1); 2450 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2451 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2452 2453 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2454 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2455 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2456 MatCheckPreallocated(mat, 1); 2457 2458 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2459 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2460 PetscFunctionReturn(0); 2461 } 2462 2463 /* --------------------------------------------------------*/ 2464 /*@ 2465 MatMult - Computes the matrix-vector product, y = Ax. 2466 2467 Neighbor-wise Collective on mat 2468 2469 Input Parameters: 2470 + mat - the matrix 2471 - x - the vector to be multiplied 2472 2473 Output Parameters: 2474 . y - the result 2475 2476 Note: 2477 The vectors x and y cannot be the same. I.e., one cannot 2478 call `MatMult`(A,y,y). 2479 2480 Level: beginner 2481 2482 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2483 @*/ 2484 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) { 2485 PetscFunctionBegin; 2486 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2487 PetscValidType(mat, 1); 2488 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2489 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2492 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2493 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); 2494 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); 2495 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); 2496 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); 2497 PetscCall(VecSetErrorIfLocked(y, 3)); 2498 if (mat->erroriffailure) PetscCall(VecValidValues(x, 2, PETSC_TRUE)); 2499 MatCheckPreallocated(mat, 1); 2500 2501 PetscCall(VecLockReadPush(x)); 2502 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2503 PetscUseTypeMethod(mat, mult, x, y); 2504 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2505 if (mat->erroriffailure) PetscCall(VecValidValues(y, 3, PETSC_FALSE)); 2506 PetscCall(VecLockReadPop(x)); 2507 PetscFunctionReturn(0); 2508 } 2509 2510 /*@ 2511 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2512 2513 Neighbor-wise Collective on mat 2514 2515 Input Parameters: 2516 + mat - the matrix 2517 - x - the vector to be multiplied 2518 2519 Output Parameters: 2520 . y - the result 2521 2522 Notes: 2523 The vectors x and y cannot be the same. I.e., one cannot 2524 call `MatMultTranspose`(A,y,y). 2525 2526 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2527 use `MatMultHermitianTranspose()` 2528 2529 Level: beginner 2530 2531 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2532 @*/ 2533 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) { 2534 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2535 2536 PetscFunctionBegin; 2537 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2538 PetscValidType(mat, 1); 2539 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2540 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2541 2542 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2543 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2544 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2545 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); 2546 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); 2547 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); 2548 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); 2549 if (mat->erroriffailure) PetscCall(VecValidValues(x, 2, PETSC_TRUE)); 2550 MatCheckPreallocated(mat, 1); 2551 2552 if (!mat->ops->multtranspose) { 2553 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2554 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); 2555 } else op = mat->ops->multtranspose; 2556 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2557 PetscCall(VecLockReadPush(x)); 2558 PetscCall((*op)(mat, x, y)); 2559 PetscCall(VecLockReadPop(x)); 2560 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2561 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2562 if (mat->erroriffailure) PetscCall(VecValidValues(y, 3, PETSC_FALSE)); 2563 PetscFunctionReturn(0); 2564 } 2565 2566 /*@ 2567 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2568 2569 Neighbor-wise Collective on mat 2570 2571 Input Parameters: 2572 + mat - the matrix 2573 - x - the vector to be multilplied 2574 2575 Output Parameters: 2576 . y - the result 2577 2578 Notes: 2579 The vectors x and y cannot be the same. I.e., one cannot 2580 call `MatMultHermitianTranspose`(A,y,y). 2581 2582 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2583 2584 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2585 2586 Level: beginner 2587 2588 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2589 @*/ 2590 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) { 2591 PetscFunctionBegin; 2592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2593 PetscValidType(mat, 1); 2594 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2595 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2596 2597 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2598 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2599 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2600 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); 2601 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); 2602 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); 2603 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); 2604 MatCheckPreallocated(mat, 1); 2605 2606 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2607 #if defined(PETSC_USE_COMPLEX) 2608 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2609 PetscCall(VecLockReadPush(x)); 2610 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2611 else PetscUseTypeMethod(mat, mult, x, y); 2612 PetscCall(VecLockReadPop(x)); 2613 } else { 2614 Vec w; 2615 PetscCall(VecDuplicate(x, &w)); 2616 PetscCall(VecCopy(x, w)); 2617 PetscCall(VecConjugate(w)); 2618 PetscCall(MatMultTranspose(mat, w, y)); 2619 PetscCall(VecDestroy(&w)); 2620 PetscCall(VecConjugate(y)); 2621 } 2622 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2623 #else 2624 PetscCall(MatMultTranspose(mat, x, y)); 2625 #endif 2626 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2627 PetscFunctionReturn(0); 2628 } 2629 2630 /*@ 2631 MatMultAdd - Computes v3 = v2 + A * v1. 2632 2633 Neighbor-wise Collective on mat 2634 2635 Input Parameters: 2636 + mat - the matrix 2637 - v1, v2 - the vectors 2638 2639 Output Parameters: 2640 . v3 - the result 2641 2642 Note: 2643 The vectors v1 and v3 cannot be the same. I.e., one cannot 2644 call `MatMultAdd`(A,v1,v2,v1). 2645 2646 Level: beginner 2647 2648 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2649 @*/ 2650 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) { 2651 PetscFunctionBegin; 2652 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2653 PetscValidType(mat, 1); 2654 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2655 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2656 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2657 2658 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2659 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2660 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); 2661 /* 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); 2662 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); */ 2663 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); 2664 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); 2665 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2666 MatCheckPreallocated(mat, 1); 2667 2668 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2669 PetscCall(VecLockReadPush(v1)); 2670 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2671 PetscCall(VecLockReadPop(v1)); 2672 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2673 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2674 PetscFunctionReturn(0); 2675 } 2676 2677 /*@ 2678 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2679 2680 Neighbor-wise Collective on mat 2681 2682 Input Parameters: 2683 + mat - the matrix 2684 - v1, v2 - the vectors 2685 2686 Output Parameters: 2687 . v3 - the result 2688 2689 Note: 2690 The vectors v1 and v3 cannot be the same. I.e., one cannot 2691 call `MatMultTransposeAdd`(A,v1,v2,v1). 2692 2693 Level: beginner 2694 2695 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2696 @*/ 2697 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) { 2698 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2699 2700 PetscFunctionBegin; 2701 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2702 PetscValidType(mat, 1); 2703 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2704 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2705 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2706 2707 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2708 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2709 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); 2710 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); 2711 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); 2712 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2713 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2714 MatCheckPreallocated(mat, 1); 2715 2716 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2717 PetscCall(VecLockReadPush(v1)); 2718 PetscCall((*op)(mat, v1, v2, v3)); 2719 PetscCall(VecLockReadPop(v1)); 2720 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2721 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2722 PetscFunctionReturn(0); 2723 } 2724 2725 /*@ 2726 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2727 2728 Neighbor-wise Collective on mat 2729 2730 Input Parameters: 2731 + mat - the matrix 2732 - v1, v2 - the vectors 2733 2734 Output Parameters: 2735 . v3 - the result 2736 2737 Note: 2738 The vectors v1 and v3 cannot be the same. I.e., one cannot 2739 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2740 2741 Level: beginner 2742 2743 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2744 @*/ 2745 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) { 2746 PetscFunctionBegin; 2747 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2748 PetscValidType(mat, 1); 2749 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2750 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2751 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2752 2753 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2754 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2755 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2756 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); 2757 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); 2758 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); 2759 MatCheckPreallocated(mat, 1); 2760 2761 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2762 PetscCall(VecLockReadPush(v1)); 2763 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2764 else { 2765 Vec w, z; 2766 PetscCall(VecDuplicate(v1, &w)); 2767 PetscCall(VecCopy(v1, w)); 2768 PetscCall(VecConjugate(w)); 2769 PetscCall(VecDuplicate(v3, &z)); 2770 PetscCall(MatMultTranspose(mat, w, z)); 2771 PetscCall(VecDestroy(&w)); 2772 PetscCall(VecConjugate(z)); 2773 if (v2 != v3) { 2774 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2775 } else { 2776 PetscCall(VecAXPY(v3, 1.0, z)); 2777 } 2778 PetscCall(VecDestroy(&z)); 2779 } 2780 PetscCall(VecLockReadPop(v1)); 2781 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2782 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2783 PetscFunctionReturn(0); 2784 } 2785 2786 /*@C 2787 MatGetFactorType - gets the type of factorization it is 2788 2789 Not Collective 2790 2791 Input Parameters: 2792 . mat - the matrix 2793 2794 Output Parameters: 2795 . 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` 2796 2797 Level: intermediate 2798 2799 .seealso: `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2800 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2801 @*/ 2802 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) { 2803 PetscFunctionBegin; 2804 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2805 PetscValidType(mat, 1); 2806 PetscValidPointer(t, 2); 2807 *t = mat->factortype; 2808 PetscFunctionReturn(0); 2809 } 2810 2811 /*@C 2812 MatSetFactorType - sets the type of factorization it is 2813 2814 Logically Collective on mat 2815 2816 Input Parameters: 2817 + mat - the matrix 2818 - 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` 2819 2820 Level: intermediate 2821 2822 .seealso: `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2823 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2824 @*/ 2825 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) { 2826 PetscFunctionBegin; 2827 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2828 PetscValidType(mat, 1); 2829 mat->factortype = t; 2830 PetscFunctionReturn(0); 2831 } 2832 2833 /* ------------------------------------------------------------*/ 2834 /*@C 2835 MatGetInfo - Returns information about matrix storage (number of 2836 nonzeros, memory, etc.). 2837 2838 Collective on mat if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2839 2840 Input Parameter: 2841 . mat - the matrix 2842 2843 Output Parameters: 2844 + flag - flag indicating the type of parameters to be returned 2845 (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, 2846 MAT_GLOBAL_SUM - sum over all processors) 2847 - info - matrix information context 2848 2849 Notes: 2850 The `MatInfo` context contains a variety of matrix data, including 2851 number of nonzeros allocated and used, number of mallocs during 2852 matrix assembly, etc. Additional information for factored matrices 2853 is provided (such as the fill ratio, number of mallocs during 2854 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2855 when using the runtime options 2856 $ -info -mat_view ::ascii_info 2857 2858 Example for C/C++ Users: 2859 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2860 data within the MatInfo context. For example, 2861 .vb 2862 MatInfo info; 2863 Mat A; 2864 double mal, nz_a, nz_u; 2865 2866 MatGetInfo(A,MAT_LOCAL,&info); 2867 mal = info.mallocs; 2868 nz_a = info.nz_allocated; 2869 .ve 2870 2871 Example for Fortran Users: 2872 Fortran users should declare info as a double precision 2873 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2874 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2875 a complete list of parameter names. 2876 .vb 2877 double precision info(MAT_INFO_SIZE) 2878 double precision mal, nz_a 2879 Mat A 2880 integer ierr 2881 2882 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2883 mal = info(MAT_INFO_MALLOCS) 2884 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2885 .ve 2886 2887 Level: intermediate 2888 2889 Developer Note: fortran interface is not autogenerated as the f90 2890 interface definition cannot be generated correctly [due to MatInfo] 2891 2892 .seealso: `MatInfo`, `MatStashGetInfo()` 2893 @*/ 2894 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) { 2895 PetscFunctionBegin; 2896 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2897 PetscValidType(mat, 1); 2898 PetscValidPointer(info, 3); 2899 MatCheckPreallocated(mat, 1); 2900 PetscUseTypeMethod(mat, getinfo, flag, info); 2901 PetscFunctionReturn(0); 2902 } 2903 2904 /* 2905 This is used by external packages where it is not easy to get the info from the actual 2906 matrix factorization. 2907 */ 2908 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) { 2909 PetscFunctionBegin; 2910 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2911 PetscFunctionReturn(0); 2912 } 2913 2914 /* ----------------------------------------------------------*/ 2915 2916 /*@C 2917 MatLUFactor - Performs in-place LU factorization of matrix. 2918 2919 Collective on mat 2920 2921 Input Parameters: 2922 + mat - the matrix 2923 . row - row permutation 2924 . col - column permutation 2925 - info - options for factorization, includes 2926 $ fill - expected fill as ratio of original fill. 2927 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 2928 $ Run with the option -info to determine an optimal value to use 2929 2930 Notes: 2931 Most users should employ the `KSP` interface for linear solvers 2932 instead of working directly with matrix algebra routines such as this. 2933 See, e.g., `KSPCreate()`. 2934 2935 This changes the state of the matrix to a factored matrix; it cannot be used 2936 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 2937 2938 This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 2939 when not using `KSP`. 2940 2941 Level: developer 2942 2943 Developer Note: 2944 The Fortran interface is not autogenerated as the f90 2945 interface definition cannot be generated correctly [due to `MatFactorInfo`] 2946 2947 .seealso: `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 2948 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 2949 @*/ 2950 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) { 2951 MatFactorInfo tinfo; 2952 2953 PetscFunctionBegin; 2954 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2955 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 2956 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 2957 if (info) PetscValidPointer(info, 4); 2958 PetscValidType(mat, 1); 2959 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2960 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2961 MatCheckPreallocated(mat, 1); 2962 if (!info) { 2963 PetscCall(MatFactorInfoInitialize(&tinfo)); 2964 info = &tinfo; 2965 } 2966 2967 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 2968 PetscUseTypeMethod(mat, lufactor, row, col, info); 2969 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 2970 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 2971 PetscFunctionReturn(0); 2972 } 2973 2974 /*@C 2975 MatILUFactor - Performs in-place ILU factorization of matrix. 2976 2977 Collective on mat 2978 2979 Input Parameters: 2980 + mat - the matrix 2981 . row - row permutation 2982 . col - column permutation 2983 - info - structure containing 2984 $ levels - number of levels of fill. 2985 $ expected fill - as ratio of original fill. 2986 $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 2987 missing diagonal entries) 2988 2989 Notes: 2990 Most users should employ the `KSP` interface for linear solvers 2991 instead of working directly with matrix algebra routines such as this. 2992 See, e.g., `KSPCreate()`. 2993 2994 Probably really in-place only when level of fill is zero, otherwise allocates 2995 new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 2996 when not using `KSP`. 2997 2998 Level: developer 2999 3000 Developer Note: 3001 The Fortran interface is not autogenerated as the f90 3002 interface definition cannot be generated correctly [due to MatFactorInfo] 3003 3004 .seealso: `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3005 @*/ 3006 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) { 3007 PetscFunctionBegin; 3008 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3009 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3010 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3011 PetscValidPointer(info, 4); 3012 PetscValidType(mat, 1); 3013 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3014 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3015 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3016 MatCheckPreallocated(mat, 1); 3017 3018 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3019 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3020 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3021 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3022 PetscFunctionReturn(0); 3023 } 3024 3025 /*@C 3026 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3027 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3028 3029 Collective on fact 3030 3031 Input Parameters: 3032 + fact - the factor matrix obtained with `MatGetFactor()` 3033 . mat - the matrix 3034 . row, col - row and column permutations 3035 - info - options for factorization, includes 3036 $ fill - expected fill as ratio of original fill. 3037 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3038 $ Run with the option -info to determine an optimal value to use 3039 3040 Notes: 3041 See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency. 3042 3043 Most users should employ the simplified `KSP` interface for linear solvers 3044 instead of working directly with matrix algebra routines such as this. 3045 See, e.g., `KSPCreate()`. 3046 3047 Level: developer 3048 3049 Developer Note: 3050 The Fortran interface is not autogenerated as the f90 3051 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3052 3053 .seealso: `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3054 @*/ 3055 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) { 3056 MatFactorInfo tinfo; 3057 3058 PetscFunctionBegin; 3059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3060 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3061 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3062 if (info) PetscValidPointer(info, 5); 3063 PetscValidType(mat, 2); 3064 PetscValidPointer(fact, 1); 3065 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3066 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3067 if (!(fact)->ops->lufactorsymbolic) { 3068 MatSolverType stype; 3069 PetscCall(MatFactorGetSolverType(fact, &stype)); 3070 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype); 3071 } 3072 MatCheckPreallocated(mat, 2); 3073 if (!info) { 3074 PetscCall(MatFactorInfoInitialize(&tinfo)); 3075 info = &tinfo; 3076 } 3077 3078 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3079 PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info)); 3080 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3081 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3082 PetscFunctionReturn(0); 3083 } 3084 3085 /*@C 3086 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3087 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3088 3089 Collective on fact 3090 3091 Input Parameters: 3092 + fact - the factor matrix obtained with `MatGetFactor()` 3093 . mat - the matrix 3094 - info - options for factorization 3095 3096 Notes: 3097 See `MatLUFactor()` for in-place factorization. See 3098 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3099 3100 Most users should employ the `KSP` interface for linear solvers 3101 instead of working directly with matrix algebra routines such as this. 3102 See, e.g., `KSPCreate()`. 3103 3104 Level: developer 3105 3106 Developer Note: 3107 The Fortran interface is not autogenerated as the f90 3108 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3109 3110 .seealso: `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3111 @*/ 3112 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) { 3113 MatFactorInfo tinfo; 3114 3115 PetscFunctionBegin; 3116 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3117 PetscValidType(mat, 2); 3118 PetscValidPointer(fact, 1); 3119 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3120 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3121 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, 3122 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3123 3124 PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name); 3125 MatCheckPreallocated(mat, 2); 3126 if (!info) { 3127 PetscCall(MatFactorInfoInitialize(&tinfo)); 3128 info = &tinfo; 3129 } 3130 3131 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3132 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3133 PetscCall((fact->ops->lufactornumeric)(fact, mat, info)); 3134 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3135 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3136 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3137 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3138 PetscFunctionReturn(0); 3139 } 3140 3141 /*@C 3142 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3143 symmetric matrix. 3144 3145 Collective on mat 3146 3147 Input Parameters: 3148 + mat - the matrix 3149 . perm - row and column permutations 3150 - f - expected fill as ratio of original fill 3151 3152 Notes: 3153 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3154 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3155 3156 Most users should employ the `KSP` interface for linear solvers 3157 instead of working directly with matrix algebra routines such as this. 3158 See, e.g., `KSPCreate()`. 3159 3160 Level: developer 3161 3162 Developer Note: 3163 The Fortran interface is not autogenerated as the f90 3164 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3165 3166 .seealso: `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3167 `MatGetOrdering()` 3168 @*/ 3169 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) { 3170 MatFactorInfo tinfo; 3171 3172 PetscFunctionBegin; 3173 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3174 PetscValidType(mat, 1); 3175 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3176 if (info) PetscValidPointer(info, 3); 3177 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3178 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3179 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3180 MatCheckPreallocated(mat, 1); 3181 if (!info) { 3182 PetscCall(MatFactorInfoInitialize(&tinfo)); 3183 info = &tinfo; 3184 } 3185 3186 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3187 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3188 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3189 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3190 PetscFunctionReturn(0); 3191 } 3192 3193 /*@C 3194 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3195 of a symmetric matrix. 3196 3197 Collective on fact 3198 3199 Input Parameters: 3200 + fact - the factor matrix obtained with `MatGetFactor()` 3201 . mat - the matrix 3202 . perm - row and column permutations 3203 - info - options for factorization, includes 3204 $ fill - expected fill as ratio of original fill. 3205 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3206 $ Run with the option -info to determine an optimal value to use 3207 3208 Notes: 3209 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3210 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3211 3212 Most users should employ the `KSP` interface for linear solvers 3213 instead of working directly with matrix algebra routines such as this. 3214 See, e.g., `KSPCreate()`. 3215 3216 Level: developer 3217 3218 Developer Note: 3219 The Fortran interface is not autogenerated as the f90 3220 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3221 3222 .seealso: `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3223 `MatGetOrdering()` 3224 @*/ 3225 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) { 3226 MatFactorInfo tinfo; 3227 3228 PetscFunctionBegin; 3229 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3230 PetscValidType(mat, 2); 3231 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3232 if (info) PetscValidPointer(info, 4); 3233 PetscValidPointer(fact, 1); 3234 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3235 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3236 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3237 if (!(fact)->ops->choleskyfactorsymbolic) { 3238 MatSolverType stype; 3239 PetscCall(MatFactorGetSolverType(fact, &stype)); 3240 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype); 3241 } 3242 MatCheckPreallocated(mat, 2); 3243 if (!info) { 3244 PetscCall(MatFactorInfoInitialize(&tinfo)); 3245 info = &tinfo; 3246 } 3247 3248 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3249 PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info)); 3250 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3251 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3252 PetscFunctionReturn(0); 3253 } 3254 3255 /*@C 3256 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3257 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3258 `MatCholeskyFactorSymbolic()`. 3259 3260 Collective on fact 3261 3262 Input Parameters: 3263 + fact - the factor matrix obtained with `MatGetFactor()` 3264 . mat - the initial matrix 3265 . info - options for factorization 3266 - fact - the symbolic factor of mat 3267 3268 Note: 3269 Most users should employ the `KSP` interface for linear solvers 3270 instead of working directly with matrix algebra routines such as this. 3271 See, e.g., `KSPCreate()`. 3272 3273 Level: developer 3274 3275 Developer Note: 3276 The Fortran interface is not autogenerated as the f90 3277 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3278 3279 .seealso: `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3280 @*/ 3281 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) { 3282 MatFactorInfo tinfo; 3283 3284 PetscFunctionBegin; 3285 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3286 PetscValidType(mat, 2); 3287 PetscValidPointer(fact, 1); 3288 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3289 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3290 PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name); 3291 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, 3292 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3293 MatCheckPreallocated(mat, 2); 3294 if (!info) { 3295 PetscCall(MatFactorInfoInitialize(&tinfo)); 3296 info = &tinfo; 3297 } 3298 3299 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3300 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3301 PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info)); 3302 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3303 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3304 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3305 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3306 PetscFunctionReturn(0); 3307 } 3308 3309 /*@ 3310 MatQRFactor - Performs in-place QR factorization of matrix. 3311 3312 Collective on mat 3313 3314 Input Parameters: 3315 + mat - the matrix 3316 . col - column permutation 3317 - info - options for factorization, includes 3318 $ fill - expected fill as ratio of original fill. 3319 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3320 $ Run with the option -info to determine an optimal value to use 3321 3322 Notes: 3323 Most users should employ the `KSP` interface for linear solvers 3324 instead of working directly with matrix algebra routines such as this. 3325 See, e.g., `KSPCreate()`. 3326 3327 This changes the state of the matrix to a factored matrix; it cannot be used 3328 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3329 3330 Level: developer 3331 3332 Developer Note: 3333 The Fortran interface is not autogenerated as the f90 3334 interface definition cannot be generated correctly [due to MatFactorInfo] 3335 3336 .seealso: `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3337 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3338 @*/ 3339 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) { 3340 PetscFunctionBegin; 3341 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3342 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3343 if (info) PetscValidPointer(info, 3); 3344 PetscValidType(mat, 1); 3345 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3346 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3347 MatCheckPreallocated(mat, 1); 3348 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3349 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3350 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3351 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3352 PetscFunctionReturn(0); 3353 } 3354 3355 /*@ 3356 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3357 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3358 3359 Collective on fact 3360 3361 Input Parameters: 3362 + fact - the factor matrix obtained with `MatGetFactor()` 3363 . mat - the matrix 3364 . col - column permutation 3365 - info - options for factorization, includes 3366 $ fill - expected fill as ratio of original fill. 3367 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3368 $ Run with the option -info to determine an optimal value to use 3369 3370 Most users should employ the `KSP` interface for linear solvers 3371 instead of working directly with matrix algebra routines such as this. 3372 See, e.g., `KSPCreate()`. 3373 3374 Level: developer 3375 3376 Developer Note: 3377 The Fortran interface is not autogenerated as the f90 3378 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3379 3380 .seealso: `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3381 @*/ 3382 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) { 3383 MatFactorInfo tinfo; 3384 3385 PetscFunctionBegin; 3386 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3387 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3388 if (info) PetscValidPointer(info, 4); 3389 PetscValidType(mat, 2); 3390 PetscValidPointer(fact, 1); 3391 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3392 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3393 MatCheckPreallocated(mat, 2); 3394 if (!info) { 3395 PetscCall(MatFactorInfoInitialize(&tinfo)); 3396 info = &tinfo; 3397 } 3398 3399 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3400 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3401 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3402 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3403 PetscFunctionReturn(0); 3404 } 3405 3406 /*@ 3407 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3408 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3409 3410 Collective on fact 3411 3412 Input Parameters: 3413 + fact - the factor matrix obtained with `MatGetFactor()` 3414 . mat - the matrix 3415 - info - options for factorization 3416 3417 Notes: 3418 See `MatQRFactor()` for in-place factorization. 3419 3420 Most users should employ the `KSP` interface for linear solvers 3421 instead of working directly with matrix algebra routines such as this. 3422 See, e.g., `KSPCreate()`. 3423 3424 Level: developer 3425 3426 Developer Note: 3427 The Fortran interface is not autogenerated as the f90 3428 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3429 3430 .seealso: `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3431 @*/ 3432 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) { 3433 MatFactorInfo tinfo; 3434 3435 PetscFunctionBegin; 3436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3437 PetscValidType(mat, 2); 3438 PetscValidPointer(fact, 1); 3439 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3440 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3441 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, 3442 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3443 3444 MatCheckPreallocated(mat, 2); 3445 if (!info) { 3446 PetscCall(MatFactorInfoInitialize(&tinfo)); 3447 info = &tinfo; 3448 } 3449 3450 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3451 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3452 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3453 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3454 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3455 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3456 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3457 PetscFunctionReturn(0); 3458 } 3459 3460 /* ----------------------------------------------------------------*/ 3461 /*@ 3462 MatSolve - Solves A x = b, given a factored matrix. 3463 3464 Neighbor-wise Collective on mat 3465 3466 Input Parameters: 3467 + mat - the factored matrix 3468 - b - the right-hand-side vector 3469 3470 Output Parameter: 3471 . x - the result vector 3472 3473 Notes: 3474 The vectors b and x cannot be the same. I.e., one cannot 3475 call `MatSolve`(A,x,x). 3476 3477 Most users should employ the `KSP` interface for linear solvers 3478 instead of working directly with matrix algebra routines such as this. 3479 See, e.g., `KSPCreate()`. 3480 3481 Level: developer 3482 3483 .seealso: `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3484 @*/ 3485 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) { 3486 PetscFunctionBegin; 3487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3488 PetscValidType(mat, 1); 3489 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3490 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3491 PetscCheckSameComm(mat, 1, b, 2); 3492 PetscCheckSameComm(mat, 1, x, 3); 3493 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3494 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); 3495 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); 3496 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); 3497 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3498 MatCheckPreallocated(mat, 1); 3499 3500 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3501 if (mat->factorerrortype) { 3502 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3503 PetscCall(VecSetInf(x)); 3504 } else PetscUseTypeMethod(mat, solve, b, x); 3505 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3506 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3507 PetscFunctionReturn(0); 3508 } 3509 3510 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) { 3511 Vec b, x; 3512 PetscInt N, i; 3513 PetscErrorCode (*f)(Mat, Vec, Vec); 3514 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3515 3516 PetscFunctionBegin; 3517 if (A->factorerrortype) { 3518 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3519 PetscCall(MatSetInf(X)); 3520 PetscFunctionReturn(0); 3521 } 3522 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3523 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3524 PetscCall(MatBoundToCPU(A, &Abound)); 3525 if (!Abound) { 3526 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3527 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3528 } 3529 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3530 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3531 PetscCall(MatGetSize(B, NULL, &N)); 3532 for (i = 0; i < N; i++) { 3533 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3534 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3535 PetscCall((*f)(A, b, x)); 3536 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3537 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3538 } 3539 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3540 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3541 PetscFunctionReturn(0); 3542 } 3543 3544 /*@ 3545 MatMatSolve - Solves A X = B, given a factored matrix. 3546 3547 Neighbor-wise Collective on A 3548 3549 Input Parameters: 3550 + A - the factored matrix 3551 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3552 3553 Output Parameter: 3554 . X - the result matrix (dense matrix) 3555 3556 Note: 3557 If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO; 3558 otherwise, B and X cannot be the same. 3559 3560 Level: developer 3561 3562 .seealso: `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3563 @*/ 3564 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) { 3565 PetscFunctionBegin; 3566 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3567 PetscValidType(A, 1); 3568 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3569 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3570 PetscCheckSameComm(A, 1, B, 2); 3571 PetscCheckSameComm(A, 1, X, 3); 3572 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); 3573 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); 3574 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"); 3575 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3576 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3577 MatCheckPreallocated(A, 1); 3578 3579 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3580 if (!A->ops->matsolve) { 3581 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3582 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3583 } else PetscUseTypeMethod(A, matsolve, B, X); 3584 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3585 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3586 PetscFunctionReturn(0); 3587 } 3588 3589 /*@ 3590 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3591 3592 Neighbor-wise Collective on A 3593 3594 Input Parameters: 3595 + A - the factored matrix 3596 - B - the right-hand-side matrix (`MATDENSE` matrix) 3597 3598 Output Parameter: 3599 . X - the result matrix (dense matrix) 3600 3601 Note: 3602 The matrices B and X cannot be the same. I.e., one cannot 3603 call `MatMatSolveTranspose`(A,X,X). 3604 3605 Level: developer 3606 3607 .seealso: `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3608 @*/ 3609 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) { 3610 PetscFunctionBegin; 3611 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3612 PetscValidType(A, 1); 3613 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3614 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3615 PetscCheckSameComm(A, 1, B, 2); 3616 PetscCheckSameComm(A, 1, X, 3); 3617 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3618 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); 3619 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); 3620 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); 3621 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"); 3622 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3623 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3624 MatCheckPreallocated(A, 1); 3625 3626 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3627 if (!A->ops->matsolvetranspose) { 3628 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3629 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3630 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3631 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3632 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3633 PetscFunctionReturn(0); 3634 } 3635 3636 /*@ 3637 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3638 3639 Neighbor-wise Collective on A 3640 3641 Input Parameters: 3642 + A - the factored matrix 3643 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3644 3645 Output Parameter: 3646 . X - the result matrix (dense matrix) 3647 3648 Note: 3649 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 3650 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3651 3652 Level: developer 3653 3654 .seealso: `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3655 @*/ 3656 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) { 3657 PetscFunctionBegin; 3658 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3659 PetscValidType(A, 1); 3660 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3661 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3662 PetscCheckSameComm(A, 1, Bt, 2); 3663 PetscCheckSameComm(A, 1, X, 3); 3664 3665 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3666 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); 3667 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); 3668 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"); 3669 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3670 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3671 MatCheckPreallocated(A, 1); 3672 3673 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3674 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3675 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3676 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3677 PetscFunctionReturn(0); 3678 } 3679 3680 /*@ 3681 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3682 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3683 3684 Neighbor-wise Collective on mat 3685 3686 Input Parameters: 3687 + mat - the factored matrix 3688 - b - the right-hand-side vector 3689 3690 Output Parameter: 3691 . x - the result vector 3692 3693 Notes: 3694 `MatSolve()` should be used for most applications, as it performs 3695 a forward solve followed by a backward solve. 3696 3697 The vectors b and x cannot be the same, i.e., one cannot 3698 call `MatForwardSolve`(A,x,x). 3699 3700 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3701 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3702 `MatForwardSolve()` solves U^T*D y = b, and 3703 `MatBackwardSolve()` solves U x = y. 3704 Thus they do not provide a symmetric preconditioner. 3705 3706 Level: developer 3707 3708 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3709 @*/ 3710 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) { 3711 PetscFunctionBegin; 3712 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3713 PetscValidType(mat, 1); 3714 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3715 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3716 PetscCheckSameComm(mat, 1, b, 2); 3717 PetscCheckSameComm(mat, 1, x, 3); 3718 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3719 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); 3720 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); 3721 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); 3722 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3723 MatCheckPreallocated(mat, 1); 3724 3725 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3726 PetscUseTypeMethod(mat, forwardsolve, b, x); 3727 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3728 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3729 PetscFunctionReturn(0); 3730 } 3731 3732 /*@ 3733 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3734 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3735 3736 Neighbor-wise Collective on mat 3737 3738 Input Parameters: 3739 + mat - the factored matrix 3740 - b - the right-hand-side vector 3741 3742 Output Parameter: 3743 . x - the result vector 3744 3745 Notes: 3746 `MatSolve()` should be used for most applications, as it performs 3747 a forward solve followed by a backward solve. 3748 3749 The vectors b and x cannot be the same. I.e., one cannot 3750 call `MatBackwardSolve`(A,x,x). 3751 3752 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3753 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3754 `MatForwardSolve()` solves U^T*D y = b, and 3755 `MatBackwardSolve()` solves U x = y. 3756 Thus they do not provide a symmetric preconditioner. 3757 3758 Level: developer 3759 3760 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3761 @*/ 3762 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) { 3763 PetscFunctionBegin; 3764 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3765 PetscValidType(mat, 1); 3766 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3767 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3768 PetscCheckSameComm(mat, 1, b, 2); 3769 PetscCheckSameComm(mat, 1, x, 3); 3770 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3771 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); 3772 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); 3773 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); 3774 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3775 MatCheckPreallocated(mat, 1); 3776 3777 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3778 PetscUseTypeMethod(mat, backwardsolve, b, x); 3779 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3780 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3781 PetscFunctionReturn(0); 3782 } 3783 3784 /*@ 3785 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3786 3787 Neighbor-wise Collective on mat 3788 3789 Input Parameters: 3790 + mat - the factored matrix 3791 . b - the right-hand-side vector 3792 - y - the vector to be added to 3793 3794 Output Parameter: 3795 . x - the result vector 3796 3797 Note: 3798 The vectors b and x cannot be the same. I.e., one cannot 3799 call `MatSolveAdd`(A,x,y,x). 3800 3801 Level: developer 3802 3803 .seealso: `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3804 @*/ 3805 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) { 3806 PetscScalar one = 1.0; 3807 Vec tmp; 3808 3809 PetscFunctionBegin; 3810 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3811 PetscValidType(mat, 1); 3812 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3813 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3814 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3815 PetscCheckSameComm(mat, 1, b, 2); 3816 PetscCheckSameComm(mat, 1, y, 3); 3817 PetscCheckSameComm(mat, 1, x, 4); 3818 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3819 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); 3820 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); 3821 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); 3822 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3823 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); 3824 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3825 MatCheckPreallocated(mat, 1); 3826 3827 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3828 if (mat->factorerrortype) { 3829 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3830 PetscCall(VecSetInf(x)); 3831 } else if (mat->ops->solveadd) { 3832 PetscUseTypeMethod(mat, solveadd, b, y, x); 3833 } else { 3834 /* do the solve then the add manually */ 3835 if (x != y) { 3836 PetscCall(MatSolve(mat, b, x)); 3837 PetscCall(VecAXPY(x, one, y)); 3838 } else { 3839 PetscCall(VecDuplicate(x, &tmp)); 3840 PetscCall(PetscLogObjectParent((PetscObject)mat, (PetscObject)tmp)); 3841 PetscCall(VecCopy(x, tmp)); 3842 PetscCall(MatSolve(mat, b, x)); 3843 PetscCall(VecAXPY(x, one, tmp)); 3844 PetscCall(VecDestroy(&tmp)); 3845 } 3846 } 3847 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3848 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3849 PetscFunctionReturn(0); 3850 } 3851 3852 /*@ 3853 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3854 3855 Neighbor-wise Collective on mat 3856 3857 Input Parameters: 3858 + mat - the factored matrix 3859 - b - the right-hand-side vector 3860 3861 Output Parameter: 3862 . x - the result vector 3863 3864 Notes: 3865 The vectors b and x cannot be the same. I.e., one cannot 3866 call `MatSolveTranspose`(A,x,x). 3867 3868 Most users should employ the `KSP` interface for linear solvers 3869 instead of working directly with matrix algebra routines such as this. 3870 See, e.g., `KSPCreate()`. 3871 3872 Level: developer 3873 3874 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3875 @*/ 3876 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) { 3877 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3878 3879 PetscFunctionBegin; 3880 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3881 PetscValidType(mat, 1); 3882 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3883 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3884 PetscCheckSameComm(mat, 1, b, 2); 3885 PetscCheckSameComm(mat, 1, x, 3); 3886 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3887 PetscCheck(mat->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); 3888 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); 3889 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3890 MatCheckPreallocated(mat, 1); 3891 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 3892 if (mat->factorerrortype) { 3893 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3894 PetscCall(VecSetInf(x)); 3895 } else { 3896 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 3897 PetscCall((*f)(mat, b, x)); 3898 } 3899 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 3900 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3901 PetscFunctionReturn(0); 3902 } 3903 3904 /*@ 3905 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 3906 factored matrix. 3907 3908 Neighbor-wise Collective on mat 3909 3910 Input Parameters: 3911 + mat - the factored matrix 3912 . b - the right-hand-side vector 3913 - y - the vector to be added to 3914 3915 Output Parameter: 3916 . x - the result vector 3917 3918 Note: 3919 The vectors b and x cannot be the same. I.e., one cannot 3920 call `MatSolveTransposeAdd`(A,x,y,x). 3921 3922 Level: developer 3923 3924 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 3925 @*/ 3926 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) { 3927 PetscScalar one = 1.0; 3928 Vec tmp; 3929 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 3930 3931 PetscFunctionBegin; 3932 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3933 PetscValidType(mat, 1); 3934 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3935 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3936 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3937 PetscCheckSameComm(mat, 1, b, 2); 3938 PetscCheckSameComm(mat, 1, y, 3); 3939 PetscCheckSameComm(mat, 1, x, 4); 3940 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3941 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); 3942 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); 3943 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); 3944 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); 3945 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3946 MatCheckPreallocated(mat, 1); 3947 3948 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 3949 if (mat->factorerrortype) { 3950 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3951 PetscCall(VecSetInf(x)); 3952 } else if (f) { 3953 PetscCall((*f)(mat, b, y, x)); 3954 } else { 3955 /* do the solve then the add manually */ 3956 if (x != y) { 3957 PetscCall(MatSolveTranspose(mat, b, x)); 3958 PetscCall(VecAXPY(x, one, y)); 3959 } else { 3960 PetscCall(VecDuplicate(x, &tmp)); 3961 PetscCall(PetscLogObjectParent((PetscObject)mat, (PetscObject)tmp)); 3962 PetscCall(VecCopy(x, tmp)); 3963 PetscCall(MatSolveTranspose(mat, b, x)); 3964 PetscCall(VecAXPY(x, one, tmp)); 3965 PetscCall(VecDestroy(&tmp)); 3966 } 3967 } 3968 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 3969 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3970 PetscFunctionReturn(0); 3971 } 3972 /* ----------------------------------------------------------------*/ 3973 3974 /*@ 3975 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 3976 3977 Neighbor-wise Collective on mat 3978 3979 Input Parameters: 3980 + mat - the matrix 3981 . b - the right hand side 3982 . omega - the relaxation factor 3983 . flag - flag indicating the type of SOR (see below) 3984 . shift - diagonal shift 3985 . its - the number of iterations 3986 - lits - the number of local iterations 3987 3988 Output Parameter: 3989 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 3990 3991 SOR Flags: 3992 + `SOR_FORWARD_SWEEP` - forward SOR 3993 . `SOR_BACKWARD_SWEEP` - backward SOR 3994 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 3995 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 3996 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 3997 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 3998 . `SOR_EISENSTAT` - SOR with Eisenstat trick 3999 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4000 upper/lower triangular part of matrix to 4001 vector (with omega) 4002 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4003 4004 Notes: 4005 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4006 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4007 on each processor. 4008 4009 Application programmers will not generally use `MatSOR()` directly, 4010 but instead will employ the `KSP`/`PC` interface. 4011 4012 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4013 4014 Most users should employ the `KSP` interface for linear solvers 4015 instead of working directly with matrix algebra routines such as this. 4016 See, e.g., `KSPCreate()`. 4017 4018 Vectors x and b CANNOT be the same 4019 4020 Notes for Advanced Users: 4021 The flags are implemented as bitwise inclusive or operations. 4022 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4023 to specify a zero initial guess for SSOR. 4024 4025 Developer Note: 4026 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4027 4028 Level: developer 4029 4030 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4031 @*/ 4032 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) { 4033 PetscFunctionBegin; 4034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4035 PetscValidType(mat, 1); 4036 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4037 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4038 PetscCheckSameComm(mat, 1, b, 2); 4039 PetscCheckSameComm(mat, 1, x, 8); 4040 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4041 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4042 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); 4043 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); 4044 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); 4045 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4046 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4047 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4048 4049 MatCheckPreallocated(mat, 1); 4050 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4051 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4052 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4053 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4054 PetscFunctionReturn(0); 4055 } 4056 4057 /* 4058 Default matrix copy routine. 4059 */ 4060 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) { 4061 PetscInt i, rstart = 0, rend = 0, nz; 4062 const PetscInt *cwork; 4063 const PetscScalar *vwork; 4064 4065 PetscFunctionBegin; 4066 if (B->assembled) PetscCall(MatZeroEntries(B)); 4067 if (str == SAME_NONZERO_PATTERN) { 4068 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4069 for (i = rstart; i < rend; i++) { 4070 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4071 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4072 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4073 } 4074 } else { 4075 PetscCall(MatAYPX(B, 0.0, A, str)); 4076 } 4077 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4078 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4079 PetscFunctionReturn(0); 4080 } 4081 4082 /*@ 4083 MatCopy - Copies a matrix to another matrix. 4084 4085 Collective on A 4086 4087 Input Parameters: 4088 + A - the matrix 4089 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4090 4091 Output Parameter: 4092 . B - where the copy is put 4093 4094 Notes: 4095 If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash. 4096 4097 `MatCopy()` copies the matrix entries of a matrix to another existing 4098 matrix (after first zeroing the second matrix). A related routine is 4099 `MatConvert()`, which first creates a new matrix and then copies the data. 4100 4101 Level: intermediate 4102 4103 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()` 4104 @*/ 4105 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) { 4106 PetscInt i; 4107 4108 PetscFunctionBegin; 4109 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4110 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4111 PetscValidType(A, 1); 4112 PetscValidType(B, 2); 4113 PetscCheckSameComm(A, 1, B, 2); 4114 MatCheckPreallocated(B, 2); 4115 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4116 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4117 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, 4118 A->cmap->N, B->cmap->N); 4119 MatCheckPreallocated(A, 1); 4120 if (A == B) PetscFunctionReturn(0); 4121 4122 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4123 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4124 else PetscCall(MatCopy_Basic(A, B, str)); 4125 4126 B->stencil.dim = A->stencil.dim; 4127 B->stencil.noc = A->stencil.noc; 4128 for (i = 0; i <= A->stencil.dim; i++) { 4129 B->stencil.dims[i] = A->stencil.dims[i]; 4130 B->stencil.starts[i] = A->stencil.starts[i]; 4131 } 4132 4133 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4134 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4135 PetscFunctionReturn(0); 4136 } 4137 4138 /*@C 4139 MatConvert - Converts a matrix to another matrix, either of the same 4140 or different type. 4141 4142 Collective on mat 4143 4144 Input Parameters: 4145 + mat - the matrix 4146 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4147 same type as the original matrix. 4148 - reuse - denotes if the destination matrix is to be created or reused. 4149 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 4150 `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). 4151 4152 Output Parameter: 4153 . M - pointer to place new matrix 4154 4155 Notes: 4156 `MatConvert()` first creates a new matrix and then copies the data from 4157 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4158 entries of one matrix to another already existing matrix context. 4159 4160 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4161 the MPI communicator of the generated matrix is always the same as the communicator 4162 of the input matrix. 4163 4164 Level: intermediate 4165 4166 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4167 @*/ 4168 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) { 4169 PetscBool sametype, issame, flg; 4170 PetscBool3 issymmetric, ishermitian; 4171 char convname[256], mtype[256]; 4172 Mat B; 4173 4174 PetscFunctionBegin; 4175 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4176 PetscValidType(mat, 1); 4177 PetscValidPointer(M, 4); 4178 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4179 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4180 MatCheckPreallocated(mat, 1); 4181 4182 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4183 if (flg) newtype = mtype; 4184 4185 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4186 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4187 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4188 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"); 4189 4190 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4191 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4192 PetscFunctionReturn(0); 4193 } 4194 4195 /* Cache Mat options because some converters use MatHeaderReplace */ 4196 issymmetric = mat->symmetric; 4197 ishermitian = mat->hermitian; 4198 4199 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4200 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4201 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4202 } else { 4203 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4204 const char *prefix[3] = {"seq", "mpi", ""}; 4205 PetscInt i; 4206 /* 4207 Order of precedence: 4208 0) See if newtype is a superclass of the current matrix. 4209 1) See if a specialized converter is known to the current matrix. 4210 2) See if a specialized converter is known to the desired matrix class. 4211 3) See if a good general converter is registered for the desired class 4212 (as of 6/27/03 only MATMPIADJ falls into this category). 4213 4) See if a good general converter is known for the current matrix. 4214 5) Use a really basic converter. 4215 */ 4216 4217 /* 0) See if newtype is a superclass of the current matrix. 4218 i.e mat is mpiaij and newtype is aij */ 4219 for (i = 0; i < 2; i++) { 4220 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4221 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4222 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4223 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4224 if (flg) { 4225 if (reuse == MAT_INPLACE_MATRIX) { 4226 PetscCall(PetscInfo(mat, "Early return\n")); 4227 PetscFunctionReturn(0); 4228 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4229 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4230 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4231 PetscFunctionReturn(0); 4232 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4233 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4234 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4235 PetscFunctionReturn(0); 4236 } 4237 } 4238 } 4239 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4240 for (i = 0; i < 3; i++) { 4241 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4242 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4243 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4244 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4245 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4246 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4247 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4248 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4249 if (conv) goto foundconv; 4250 } 4251 4252 /* 2) See if a specialized converter is known to the desired matrix class. */ 4253 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4254 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4255 PetscCall(MatSetType(B, newtype)); 4256 for (i = 0; i < 3; i++) { 4257 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4258 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4259 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4260 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4261 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4262 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4263 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4264 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4265 if (conv) { 4266 PetscCall(MatDestroy(&B)); 4267 goto foundconv; 4268 } 4269 } 4270 4271 /* 3) See if a good general converter is registered for the desired class */ 4272 conv = B->ops->convertfrom; 4273 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4274 PetscCall(MatDestroy(&B)); 4275 if (conv) goto foundconv; 4276 4277 /* 4) See if a good general converter is known for the current matrix */ 4278 if (mat->ops->convert) conv = mat->ops->convert; 4279 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4280 if (conv) goto foundconv; 4281 4282 /* 5) Use a really basic converter. */ 4283 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4284 conv = MatConvert_Basic; 4285 4286 foundconv: 4287 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4288 PetscCall((*conv)(mat, newtype, reuse, M)); 4289 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4290 /* the block sizes must be same if the mappings are copied over */ 4291 (*M)->rmap->bs = mat->rmap->bs; 4292 (*M)->cmap->bs = mat->cmap->bs; 4293 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4294 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4295 (*M)->rmap->mapping = mat->rmap->mapping; 4296 (*M)->cmap->mapping = mat->cmap->mapping; 4297 } 4298 (*M)->stencil.dim = mat->stencil.dim; 4299 (*M)->stencil.noc = mat->stencil.noc; 4300 for (i = 0; i <= mat->stencil.dim; i++) { 4301 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4302 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4303 } 4304 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4305 } 4306 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4307 4308 /* Copy Mat options */ 4309 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4310 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4311 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4312 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4313 PetscFunctionReturn(0); 4314 } 4315 4316 /*@C 4317 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4318 4319 Not Collective 4320 4321 Input Parameter: 4322 . mat - the matrix, must be a factored matrix 4323 4324 Output Parameter: 4325 . type - the string name of the package (do not free this string) 4326 4327 Note: 4328 In Fortran you pass in a empty string and the package name will be copied into it. 4329 (Make sure the string is long enough) 4330 4331 Level: intermediate 4332 4333 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4334 @*/ 4335 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) { 4336 PetscErrorCode (*conv)(Mat, MatSolverType *); 4337 4338 PetscFunctionBegin; 4339 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4340 PetscValidType(mat, 1); 4341 PetscValidPointer(type, 2); 4342 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4343 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4344 if (conv) PetscCall((*conv)(mat, type)); 4345 else *type = MATSOLVERPETSC; 4346 PetscFunctionReturn(0); 4347 } 4348 4349 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4350 struct _MatSolverTypeForSpecifcType { 4351 MatType mtype; 4352 /* no entry for MAT_FACTOR_NONE */ 4353 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4354 MatSolverTypeForSpecifcType next; 4355 }; 4356 4357 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4358 struct _MatSolverTypeHolder { 4359 char *name; 4360 MatSolverTypeForSpecifcType handlers; 4361 MatSolverTypeHolder next; 4362 }; 4363 4364 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4365 4366 /*@C 4367 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4368 4369 Input Parameters: 4370 + package - name of the package, for example petsc or superlu 4371 . mtype - the matrix type that works with this package 4372 . ftype - the type of factorization supported by the package 4373 - createfactor - routine that will create the factored matrix ready to be used 4374 4375 Level: developer 4376 4377 .seealso: `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4378 @*/ 4379 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) { 4380 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4381 PetscBool flg; 4382 MatSolverTypeForSpecifcType inext, iprev = NULL; 4383 4384 PetscFunctionBegin; 4385 PetscCall(MatInitializePackage()); 4386 if (!next) { 4387 PetscCall(PetscNew(&MatSolverTypeHolders)); 4388 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4389 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4390 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4391 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4392 PetscFunctionReturn(0); 4393 } 4394 while (next) { 4395 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4396 if (flg) { 4397 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4398 inext = next->handlers; 4399 while (inext) { 4400 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4401 if (flg) { 4402 inext->createfactor[(int)ftype - 1] = createfactor; 4403 PetscFunctionReturn(0); 4404 } 4405 iprev = inext; 4406 inext = inext->next; 4407 } 4408 PetscCall(PetscNew(&iprev->next)); 4409 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4410 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4411 PetscFunctionReturn(0); 4412 } 4413 prev = next; 4414 next = next->next; 4415 } 4416 PetscCall(PetscNew(&prev->next)); 4417 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4418 PetscCall(PetscNew(&prev->next->handlers)); 4419 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4420 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4421 PetscFunctionReturn(0); 4422 } 4423 4424 /*@C 4425 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4426 4427 Input Parameters: 4428 + type - name of the package, for example petsc or superlu 4429 . ftype - the type of factorization supported by the type 4430 - mtype - the matrix type that works with this type 4431 4432 Output Parameters: 4433 + foundtype - `PETSC_TRUE` if the type was registered 4434 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4435 - createfactor - routine that will create the factored matrix ready to be used or NULL if not found 4436 4437 Level: developer 4438 4439 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4440 @*/ 4441 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) { 4442 MatSolverTypeHolder next = MatSolverTypeHolders; 4443 PetscBool flg; 4444 MatSolverTypeForSpecifcType inext; 4445 4446 PetscFunctionBegin; 4447 if (foundtype) *foundtype = PETSC_FALSE; 4448 if (foundmtype) *foundmtype = PETSC_FALSE; 4449 if (createfactor) *createfactor = NULL; 4450 4451 if (type) { 4452 while (next) { 4453 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4454 if (flg) { 4455 if (foundtype) *foundtype = PETSC_TRUE; 4456 inext = next->handlers; 4457 while (inext) { 4458 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4459 if (flg) { 4460 if (foundmtype) *foundmtype = PETSC_TRUE; 4461 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4462 PetscFunctionReturn(0); 4463 } 4464 inext = inext->next; 4465 } 4466 } 4467 next = next->next; 4468 } 4469 } else { 4470 while (next) { 4471 inext = next->handlers; 4472 while (inext) { 4473 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4474 if (flg && inext->createfactor[(int)ftype - 1]) { 4475 if (foundtype) *foundtype = PETSC_TRUE; 4476 if (foundmtype) *foundmtype = PETSC_TRUE; 4477 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4478 PetscFunctionReturn(0); 4479 } 4480 inext = inext->next; 4481 } 4482 next = next->next; 4483 } 4484 /* try with base classes inext->mtype */ 4485 next = MatSolverTypeHolders; 4486 while (next) { 4487 inext = next->handlers; 4488 while (inext) { 4489 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4490 if (flg && inext->createfactor[(int)ftype - 1]) { 4491 if (foundtype) *foundtype = PETSC_TRUE; 4492 if (foundmtype) *foundmtype = PETSC_TRUE; 4493 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4494 PetscFunctionReturn(0); 4495 } 4496 inext = inext->next; 4497 } 4498 next = next->next; 4499 } 4500 } 4501 PetscFunctionReturn(0); 4502 } 4503 4504 PetscErrorCode MatSolverTypeDestroy(void) { 4505 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4506 MatSolverTypeForSpecifcType inext, iprev; 4507 4508 PetscFunctionBegin; 4509 while (next) { 4510 PetscCall(PetscFree(next->name)); 4511 inext = next->handlers; 4512 while (inext) { 4513 PetscCall(PetscFree(inext->mtype)); 4514 iprev = inext; 4515 inext = inext->next; 4516 PetscCall(PetscFree(iprev)); 4517 } 4518 prev = next; 4519 next = next->next; 4520 PetscCall(PetscFree(prev)); 4521 } 4522 MatSolverTypeHolders = NULL; 4523 PetscFunctionReturn(0); 4524 } 4525 4526 /*@C 4527 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4528 4529 Logically Collective on mat 4530 4531 Input Parameters: 4532 . mat - the matrix 4533 4534 Output Parameters: 4535 . flg - `PETSC_TRUE` if uses the ordering 4536 4537 Note: 4538 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4539 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4540 4541 Level: developer 4542 4543 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4544 @*/ 4545 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) { 4546 PetscFunctionBegin; 4547 *flg = mat->canuseordering; 4548 PetscFunctionReturn(0); 4549 } 4550 4551 /*@C 4552 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4553 4554 Logically Collective on mat 4555 4556 Input Parameters: 4557 . mat - the matrix obtained with `MatGetFactor()` 4558 4559 Output Parameters: 4560 . otype - the preferred type 4561 4562 Level: developer 4563 4564 .seealso: `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4565 @*/ 4566 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) { 4567 PetscFunctionBegin; 4568 *otype = mat->preferredordering[ftype]; 4569 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4570 PetscFunctionReturn(0); 4571 } 4572 4573 /*@C 4574 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4575 4576 Collective on mat 4577 4578 Input Parameters: 4579 + mat - the matrix 4580 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4581 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4582 4583 Output Parameters: 4584 . f - the factor matrix used with MatXXFactorSymbolic() calls 4585 4586 Options Database Key: 4587 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4588 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4589 4590 Notes: 4591 Users usually access the factorization solvers via `KSP` 4592 4593 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4594 such as pastix, superlu, mumps etc. 4595 4596 PETSc must have been ./configure to use the external solver, using the option --download-package 4597 4598 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4599 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4600 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4601 4602 Developer Note: 4603 This should actually be called `MatCreateFactor()` since it creates a new factor object 4604 4605 Level: intermediate 4606 4607 .seealso: `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4608 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4609 @*/ 4610 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) { 4611 PetscBool foundtype, foundmtype; 4612 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4613 4614 PetscFunctionBegin; 4615 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4616 PetscValidType(mat, 1); 4617 4618 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4619 MatCheckPreallocated(mat, 1); 4620 4621 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4622 if (!foundtype) { 4623 if (type) { 4624 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], 4625 ((PetscObject)mat)->type_name, type); 4626 } else { 4627 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); 4628 } 4629 } 4630 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4631 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); 4632 4633 PetscCall((*conv)(mat, ftype, f)); 4634 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4635 PetscFunctionReturn(0); 4636 } 4637 4638 /*@C 4639 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4640 4641 Not Collective 4642 4643 Input Parameters: 4644 + mat - the matrix 4645 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4646 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4647 4648 Output Parameter: 4649 . flg - PETSC_TRUE if the factorization is available 4650 4651 Notes: 4652 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4653 such as pastix, superlu, mumps etc. 4654 4655 PETSc must have been ./configure to use the external solver, using the option --download-package 4656 4657 Developer Note: 4658 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4659 4660 Level: intermediate 4661 4662 .seealso: `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4663 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4664 @*/ 4665 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) { 4666 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4667 4668 PetscFunctionBegin; 4669 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4670 PetscValidType(mat, 1); 4671 PetscValidBoolPointer(flg, 4); 4672 4673 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4674 MatCheckPreallocated(mat, 1); 4675 4676 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4677 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4678 PetscFunctionReturn(0); 4679 } 4680 4681 /*@ 4682 MatDuplicate - Duplicates a matrix including the non-zero structure. 4683 4684 Collective on mat 4685 4686 Input Parameters: 4687 + mat - the matrix 4688 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4689 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4690 4691 Output Parameter: 4692 . M - pointer to place new matrix 4693 4694 Level: intermediate 4695 4696 Notes: 4697 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4698 4699 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. 4700 4701 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 4702 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4703 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4704 4705 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4706 @*/ 4707 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) { 4708 Mat B; 4709 VecType vtype; 4710 PetscInt i; 4711 PetscObject dm; 4712 void (*viewf)(void); 4713 4714 PetscFunctionBegin; 4715 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4716 PetscValidType(mat, 1); 4717 PetscValidPointer(M, 3); 4718 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4719 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4720 MatCheckPreallocated(mat, 1); 4721 4722 *M = NULL; 4723 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4724 PetscUseTypeMethod(mat, duplicate, op, M); 4725 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4726 B = *M; 4727 4728 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4729 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4730 PetscCall(MatGetVecType(mat, &vtype)); 4731 PetscCall(MatSetVecType(B, vtype)); 4732 4733 B->stencil.dim = mat->stencil.dim; 4734 B->stencil.noc = mat->stencil.noc; 4735 for (i = 0; i <= mat->stencil.dim; i++) { 4736 B->stencil.dims[i] = mat->stencil.dims[i]; 4737 B->stencil.starts[i] = mat->stencil.starts[i]; 4738 } 4739 4740 B->nooffproczerorows = mat->nooffproczerorows; 4741 B->nooffprocentries = mat->nooffprocentries; 4742 4743 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4744 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4745 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4746 PetscFunctionReturn(0); 4747 } 4748 4749 /*@ 4750 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4751 4752 Logically Collective on mat 4753 4754 Input Parameters: 4755 + mat - the matrix 4756 - v - the vector for storing the diagonal 4757 4758 Output Parameter: 4759 . v - the diagonal of the matrix 4760 4761 Level: intermediate 4762 4763 Note: 4764 Currently only correct in parallel for square matrices. 4765 4766 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4767 @*/ 4768 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) { 4769 PetscFunctionBegin; 4770 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4771 PetscValidType(mat, 1); 4772 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4773 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4774 MatCheckPreallocated(mat, 1); 4775 4776 PetscUseTypeMethod(mat, getdiagonal, v); 4777 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4778 PetscFunctionReturn(0); 4779 } 4780 4781 /*@C 4782 MatGetRowMin - Gets the minimum value (of the real part) of each 4783 row of the matrix 4784 4785 Logically Collective on mat 4786 4787 Input Parameter: 4788 . mat - the matrix 4789 4790 Output Parameters: 4791 + v - the vector for storing the maximums 4792 - idx - the indices of the column found for each row (optional) 4793 4794 Level: intermediate 4795 4796 Note: 4797 The result of this call are the same as if one converted the matrix to dense format 4798 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4799 4800 This code is only implemented for a couple of matrix formats. 4801 4802 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4803 `MatGetRowMax()` 4804 @*/ 4805 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) { 4806 PetscFunctionBegin; 4807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4808 PetscValidType(mat, 1); 4809 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4810 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4811 4812 if (!mat->cmap->N) { 4813 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4814 if (idx) { 4815 PetscInt i, m = mat->rmap->n; 4816 for (i = 0; i < m; i++) idx[i] = -1; 4817 } 4818 } else { 4819 MatCheckPreallocated(mat, 1); 4820 } 4821 PetscUseTypeMethod(mat, getrowmin, v, idx); 4822 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4823 PetscFunctionReturn(0); 4824 } 4825 4826 /*@C 4827 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4828 row of the matrix 4829 4830 Logically Collective on mat 4831 4832 Input Parameter: 4833 . mat - the matrix 4834 4835 Output Parameters: 4836 + v - the vector for storing the minimums 4837 - idx - the indices of the column found for each row (or NULL if not needed) 4838 4839 Level: intermediate 4840 4841 Notes: 4842 if a row is completely empty or has only 0.0 values then the idx[] value for that 4843 row is 0 (the first column). 4844 4845 This code is only implemented for a couple of matrix formats. 4846 4847 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4848 @*/ 4849 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) { 4850 PetscFunctionBegin; 4851 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4852 PetscValidType(mat, 1); 4853 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4854 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4855 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4856 4857 if (!mat->cmap->N) { 4858 PetscCall(VecSet(v, 0.0)); 4859 if (idx) { 4860 PetscInt i, m = mat->rmap->n; 4861 for (i = 0; i < m; i++) idx[i] = -1; 4862 } 4863 } else { 4864 MatCheckPreallocated(mat, 1); 4865 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4866 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4867 } 4868 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4869 PetscFunctionReturn(0); 4870 } 4871 4872 /*@C 4873 MatGetRowMax - Gets the maximum value (of the real part) of each 4874 row of the matrix 4875 4876 Logically Collective on mat 4877 4878 Input Parameter: 4879 . mat - the matrix 4880 4881 Output Parameters: 4882 + v - the vector for storing the maximums 4883 - idx - the indices of the column found for each row (optional) 4884 4885 Level: intermediate 4886 4887 Notes: 4888 The result of this call are the same as if one converted the matrix to dense format 4889 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4890 4891 This code is only implemented for a couple of matrix formats. 4892 4893 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 4894 @*/ 4895 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) { 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 4902 if (!mat->cmap->N) { 4903 PetscCall(VecSet(v, PETSC_MIN_REAL)); 4904 if (idx) { 4905 PetscInt i, m = mat->rmap->n; 4906 for (i = 0; i < m; i++) idx[i] = -1; 4907 } 4908 } else { 4909 MatCheckPreallocated(mat, 1); 4910 PetscUseTypeMethod(mat, getrowmax, v, idx); 4911 } 4912 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4913 PetscFunctionReturn(0); 4914 } 4915 4916 /*@C 4917 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 4918 row of the matrix 4919 4920 Logically Collective on mat 4921 4922 Input Parameter: 4923 . mat - the matrix 4924 4925 Output Parameters: 4926 + v - the vector for storing the maximums 4927 - idx - the indices of the column found for each row (or NULL if not needed) 4928 4929 Level: intermediate 4930 4931 Notes: 4932 if a row is completely empty or has only 0.0 values then the idx[] value for that 4933 row is 0 (the first column). 4934 4935 This code is only implemented for a couple of matrix formats. 4936 4937 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 4938 @*/ 4939 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) { 4940 PetscFunctionBegin; 4941 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4942 PetscValidType(mat, 1); 4943 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4944 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4945 4946 if (!mat->cmap->N) { 4947 PetscCall(VecSet(v, 0.0)); 4948 if (idx) { 4949 PetscInt i, m = mat->rmap->n; 4950 for (i = 0; i < m; i++) idx[i] = -1; 4951 } 4952 } else { 4953 MatCheckPreallocated(mat, 1); 4954 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4955 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 4956 } 4957 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4958 PetscFunctionReturn(0); 4959 } 4960 4961 /*@ 4962 MatGetRowSum - Gets the sum of each row of the matrix 4963 4964 Logically or Neighborhood Collective on mat 4965 4966 Input Parameters: 4967 . mat - the matrix 4968 4969 Output Parameter: 4970 . v - the vector for storing the sum of rows 4971 4972 Level: intermediate 4973 4974 Notes: 4975 This code is slow since it is not currently specialized for different formats 4976 4977 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 4978 @*/ 4979 PetscErrorCode MatGetRowSum(Mat mat, Vec v) { 4980 Vec ones; 4981 4982 PetscFunctionBegin; 4983 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4984 PetscValidType(mat, 1); 4985 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4986 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4987 MatCheckPreallocated(mat, 1); 4988 PetscCall(MatCreateVecs(mat, &ones, NULL)); 4989 PetscCall(VecSet(ones, 1.)); 4990 PetscCall(MatMult(mat, ones, v)); 4991 PetscCall(VecDestroy(&ones)); 4992 PetscFunctionReturn(0); 4993 } 4994 4995 /*@ 4996 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 4997 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 4998 4999 Collective on mat 5000 5001 Input Parameter: 5002 . mat - the matrix to provide the transpose 5003 5004 Output Parameter: 5005 . 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 5006 5007 Level: advanced 5008 5009 Note: 5010 Normally he use of `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) requires that B was obtained with a call to `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B). This 5011 routine allows bypassing that call. 5012 5013 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5014 @*/ 5015 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) { 5016 PetscContainer rB = NULL; 5017 MatParentState *rb = NULL; 5018 5019 PetscFunctionBegin; 5020 PetscCall(PetscNew(&rb)); 5021 rb->id = ((PetscObject)mat)->id; 5022 rb->state = 0; 5023 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5024 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5025 PetscCall(PetscContainerSetPointer(rB, rb)); 5026 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5027 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5028 PetscCall(PetscObjectDereference((PetscObject)rB)); 5029 PetscFunctionReturn(0); 5030 } 5031 5032 /*@ 5033 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5034 5035 Collective on mat 5036 5037 Input Parameters: 5038 + mat - the matrix to transpose 5039 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5040 5041 Output Parameter: 5042 . B - the transpose 5043 5044 Notes: 5045 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5046 5047 `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 5048 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5049 5050 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. 5051 5052 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5053 5054 If mat is unchanged from the last call this function returns immediately without recomputing the result 5055 5056 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5057 5058 Level: intermediate 5059 5060 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5061 `MatTransposeSymbolic()` 5062 @*/ 5063 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) { 5064 PetscContainer rB = NULL; 5065 MatParentState *rb = NULL; 5066 5067 PetscFunctionBegin; 5068 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5069 PetscValidType(mat, 1); 5070 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5071 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5072 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5073 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5074 MatCheckPreallocated(mat, 1); 5075 if (reuse == MAT_REUSE_MATRIX) { 5076 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5077 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5078 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5079 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5080 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0); 5081 } 5082 5083 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5084 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5085 PetscUseTypeMethod(mat, transpose, reuse, B); 5086 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5087 } 5088 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5089 5090 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5091 if (reuse != MAT_INPLACE_MATRIX) { 5092 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5093 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5094 rb->state = ((PetscObject)mat)->state; 5095 rb->nonzerostate = mat->nonzerostate; 5096 } 5097 PetscFunctionReturn(0); 5098 } 5099 5100 /*@ 5101 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5102 5103 Collective on A 5104 5105 Input Parameters: 5106 . A - the matrix to transpose 5107 5108 Output Parameter: 5109 . 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 5110 numerical portion. 5111 5112 Level: intermediate 5113 5114 Note: 5115 This is not supported for many matrix types, use `MatTranspose()` in those cases 5116 5117 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5118 @*/ 5119 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) { 5120 PetscFunctionBegin; 5121 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5122 PetscValidType(A, 1); 5123 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5124 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5125 PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 5126 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5127 PetscCall((*A->ops->transposesymbolic)(A, B)); 5128 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5129 5130 PetscCall(MatTransposeSetPrecursor(A, *B)); 5131 PetscFunctionReturn(0); 5132 } 5133 5134 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) { 5135 PetscContainer rB; 5136 MatParentState *rb; 5137 5138 PetscFunctionBegin; 5139 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5140 PetscValidType(A, 1); 5141 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5142 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5143 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5144 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5145 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5146 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5147 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5148 PetscFunctionReturn(0); 5149 } 5150 5151 /*@ 5152 MatIsTranspose - Test whether a matrix is another one's transpose, 5153 or its own, in which case it tests symmetry. 5154 5155 Collective on A 5156 5157 Input Parameters: 5158 + A - the matrix to test 5159 - B - the matrix to test against, this can equal the first parameter 5160 5161 Output Parameters: 5162 . flg - the result 5163 5164 Notes: 5165 Only available for `MATAIJ` matrices. 5166 5167 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5168 test involves parallel copies of the block-offdiagonal parts of the matrix. 5169 5170 Level: intermediate 5171 5172 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5173 @*/ 5174 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) { 5175 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5176 5177 PetscFunctionBegin; 5178 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5179 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5180 PetscValidBoolPointer(flg, 4); 5181 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5182 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5183 *flg = PETSC_FALSE; 5184 if (f && g) { 5185 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5186 PetscCall((*f)(A, B, tol, flg)); 5187 } else { 5188 MatType mattype; 5189 5190 PetscCall(MatGetType(f ? B : A, &mattype)); 5191 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5192 } 5193 PetscFunctionReturn(0); 5194 } 5195 5196 /*@ 5197 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5198 5199 Collective on mat 5200 5201 Input Parameters: 5202 + mat - the matrix to transpose and complex conjugate 5203 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5204 5205 Output Parameter: 5206 . B - the Hermitian transpose 5207 5208 Level: intermediate 5209 5210 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5211 @*/ 5212 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) { 5213 PetscFunctionBegin; 5214 PetscCall(MatTranspose(mat, reuse, B)); 5215 #if defined(PETSC_USE_COMPLEX) 5216 PetscCall(MatConjugate(*B)); 5217 #endif 5218 PetscFunctionReturn(0); 5219 } 5220 5221 /*@ 5222 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5223 5224 Collective on A 5225 5226 Input Parameters: 5227 + A - the matrix to test 5228 - B - the matrix to test against, this can equal the first parameter 5229 5230 Output Parameters: 5231 . flg - the result 5232 5233 Notes: 5234 Only available for `MATAIJ` matrices. 5235 5236 The sequential algorithm 5237 has a running time of the order of the number of nonzeros; the parallel 5238 test involves parallel copies of the block-offdiagonal parts of the matrix. 5239 5240 Level: intermediate 5241 5242 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5243 @*/ 5244 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) { 5245 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5246 5247 PetscFunctionBegin; 5248 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5249 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5250 PetscValidBoolPointer(flg, 4); 5251 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5252 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5253 if (f && g) { 5254 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5255 PetscCall((*f)(A, B, tol, flg)); 5256 } 5257 PetscFunctionReturn(0); 5258 } 5259 5260 /*@ 5261 MatPermute - Creates a new matrix with rows and columns permuted from the 5262 original. 5263 5264 Collective on mat 5265 5266 Input Parameters: 5267 + mat - the matrix to permute 5268 . row - row permutation, each processor supplies only the permutation for its rows 5269 - col - column permutation, each processor supplies only the permutation for its columns 5270 5271 Output Parameters: 5272 . B - the permuted matrix 5273 5274 Level: advanced 5275 5276 Note: 5277 The index sets map from row/col of permuted matrix to row/col of original matrix. 5278 The index sets should be on the same communicator as mat and have the same local sizes. 5279 5280 Developer Note: 5281 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5282 exploit the fact that row and col are permutations, consider implementing the 5283 more general `MatCreateSubMatrix()` instead. 5284 5285 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5286 @*/ 5287 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) { 5288 PetscFunctionBegin; 5289 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5290 PetscValidType(mat, 1); 5291 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5292 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5293 PetscValidPointer(B, 4); 5294 PetscCheckSameComm(mat, 1, row, 2); 5295 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5296 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5297 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5298 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5299 MatCheckPreallocated(mat, 1); 5300 5301 if (mat->ops->permute) { 5302 PetscUseTypeMethod(mat, permute, row, col, B); 5303 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5304 } else { 5305 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5306 } 5307 PetscFunctionReturn(0); 5308 } 5309 5310 /*@ 5311 MatEqual - Compares two matrices. 5312 5313 Collective on A 5314 5315 Input Parameters: 5316 + A - the first matrix 5317 - B - the second matrix 5318 5319 Output Parameter: 5320 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5321 5322 Level: intermediate 5323 5324 .seealso: `Mat` 5325 @*/ 5326 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) { 5327 PetscFunctionBegin; 5328 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5329 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5330 PetscValidType(A, 1); 5331 PetscValidType(B, 2); 5332 PetscValidBoolPointer(flg, 3); 5333 PetscCheckSameComm(A, 1, B, 2); 5334 MatCheckPreallocated(A, 1); 5335 MatCheckPreallocated(B, 2); 5336 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5337 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5338 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, 5339 B->cmap->N); 5340 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5341 PetscUseTypeMethod(A, equal, B, flg); 5342 } else { 5343 PetscCall(MatMultEqual(A, B, 10, flg)); 5344 } 5345 PetscFunctionReturn(0); 5346 } 5347 5348 /*@ 5349 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5350 matrices that are stored as vectors. Either of the two scaling 5351 matrices can be NULL. 5352 5353 Collective on mat 5354 5355 Input Parameters: 5356 + mat - the matrix to be scaled 5357 . l - the left scaling vector (or NULL) 5358 - r - the right scaling vector (or NULL) 5359 5360 Note: 5361 `MatDiagonalScale()` computes A = LAR, where 5362 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5363 The L scales the rows of the matrix, the R scales the columns of the matrix. 5364 5365 Level: intermediate 5366 5367 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5368 @*/ 5369 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) { 5370 PetscFunctionBegin; 5371 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5372 PetscValidType(mat, 1); 5373 if (l) { 5374 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5375 PetscCheckSameComm(mat, 1, l, 2); 5376 } 5377 if (r) { 5378 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5379 PetscCheckSameComm(mat, 1, r, 3); 5380 } 5381 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5382 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5383 MatCheckPreallocated(mat, 1); 5384 if (!l && !r) PetscFunctionReturn(0); 5385 5386 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5387 PetscUseTypeMethod(mat, diagonalscale, l, r); 5388 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5389 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5390 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5391 PetscFunctionReturn(0); 5392 } 5393 5394 /*@ 5395 MatScale - Scales all elements of a matrix by a given number. 5396 5397 Logically Collective on mat 5398 5399 Input Parameters: 5400 + mat - the matrix to be scaled 5401 - a - the scaling value 5402 5403 Output Parameter: 5404 . mat - the scaled matrix 5405 5406 Level: intermediate 5407 5408 .seealso: `Mat`, `MatDiagonalScale()` 5409 @*/ 5410 PetscErrorCode MatScale(Mat mat, PetscScalar a) { 5411 PetscFunctionBegin; 5412 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5413 PetscValidType(mat, 1); 5414 PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 5415 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5416 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5417 PetscValidLogicalCollectiveScalar(mat, a, 2); 5418 MatCheckPreallocated(mat, 1); 5419 5420 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5421 if (a != (PetscScalar)1.0) { 5422 PetscUseTypeMethod(mat, scale, a); 5423 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5424 } 5425 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5426 PetscFunctionReturn(0); 5427 } 5428 5429 /*@ 5430 MatNorm - Calculates various norms of a matrix. 5431 5432 Collective on mat 5433 5434 Input Parameters: 5435 + mat - the matrix 5436 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5437 5438 Output Parameter: 5439 . nrm - the resulting norm 5440 5441 Level: intermediate 5442 5443 .seealso: `Mat` 5444 @*/ 5445 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) { 5446 PetscFunctionBegin; 5447 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5448 PetscValidType(mat, 1); 5449 PetscValidRealPointer(nrm, 3); 5450 5451 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5452 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5453 MatCheckPreallocated(mat, 1); 5454 5455 PetscUseTypeMethod(mat, norm, type, nrm); 5456 PetscFunctionReturn(0); 5457 } 5458 5459 /* 5460 This variable is used to prevent counting of MatAssemblyBegin() that 5461 are called from within a MatAssemblyEnd(). 5462 */ 5463 static PetscInt MatAssemblyEnd_InUse = 0; 5464 /*@ 5465 MatAssemblyBegin - Begins assembling the matrix. This routine should 5466 be called after completing all calls to `MatSetValues()`. 5467 5468 Collective on mat 5469 5470 Input Parameters: 5471 + mat - the matrix 5472 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5473 5474 Notes: 5475 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5476 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5477 5478 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5479 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5480 using the matrix. 5481 5482 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5483 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 5484 a global collective operation requring all processes that share the matrix. 5485 5486 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5487 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5488 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5489 5490 Level: beginner 5491 5492 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5493 @*/ 5494 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) { 5495 PetscFunctionBegin; 5496 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5497 PetscValidType(mat, 1); 5498 MatCheckPreallocated(mat, 1); 5499 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5500 if (mat->assembled) { 5501 mat->was_assembled = PETSC_TRUE; 5502 mat->assembled = PETSC_FALSE; 5503 } 5504 5505 if (!MatAssemblyEnd_InUse) { 5506 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5507 PetscTryTypeMethod(mat, assemblybegin, type); 5508 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5509 } else PetscTryTypeMethod(mat, assemblybegin, type); 5510 PetscFunctionReturn(0); 5511 } 5512 5513 /*@ 5514 MatAssembled - Indicates if a matrix has been assembled and is ready for 5515 use; for example, in matrix-vector product. 5516 5517 Not Collective 5518 5519 Input Parameter: 5520 . mat - the matrix 5521 5522 Output Parameter: 5523 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5524 5525 Level: advanced 5526 5527 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5528 @*/ 5529 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) { 5530 PetscFunctionBegin; 5531 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5532 PetscValidBoolPointer(assembled, 2); 5533 *assembled = mat->assembled; 5534 PetscFunctionReturn(0); 5535 } 5536 5537 /*@ 5538 MatAssemblyEnd - Completes assembling the matrix. This routine should 5539 be called after `MatAssemblyBegin()`. 5540 5541 Collective on Mat 5542 5543 Input Parameters: 5544 + mat - the matrix 5545 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5546 5547 Options Database Keys: 5548 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5549 . -mat_view ::ascii_info_detail - Prints more detailed info 5550 . -mat_view - Prints matrix in ASCII format 5551 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5552 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5553 . -display <name> - Sets display name (default is host) 5554 . -draw_pause <sec> - Sets number of seconds to pause after display 5555 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See Users-Manual: ch_matlab) 5556 . -viewer_socket_machine <machine> - Machine to use for socket 5557 . -viewer_socket_port <port> - Port number to use for socket 5558 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5559 5560 Level: beginner 5561 5562 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5563 @*/ 5564 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) { 5565 static PetscInt inassm = 0; 5566 PetscBool flg = PETSC_FALSE; 5567 5568 PetscFunctionBegin; 5569 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5570 PetscValidType(mat, 1); 5571 5572 inassm++; 5573 MatAssemblyEnd_InUse++; 5574 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5575 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5576 PetscTryTypeMethod(mat, assemblyend, type); 5577 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5578 } else PetscTryTypeMethod(mat, assemblyend, type); 5579 5580 /* Flush assembly is not a true assembly */ 5581 if (type != MAT_FLUSH_ASSEMBLY) { 5582 if (mat->num_ass) { 5583 if (!mat->symmetry_eternal) { 5584 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5585 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5586 } 5587 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5588 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5589 } 5590 mat->num_ass++; 5591 mat->assembled = PETSC_TRUE; 5592 mat->ass_nonzerostate = mat->nonzerostate; 5593 } 5594 5595 mat->insertmode = NOT_SET_VALUES; 5596 MatAssemblyEnd_InUse--; 5597 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5598 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5599 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5600 5601 if (mat->checksymmetryonassembly) { 5602 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5603 if (flg) { 5604 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5605 } else { 5606 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5607 } 5608 } 5609 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5610 } 5611 inassm--; 5612 PetscFunctionReturn(0); 5613 } 5614 5615 /*@ 5616 MatSetOption - Sets a parameter option for a matrix. Some options 5617 may be specific to certain storage formats. Some options 5618 determine how values will be inserted (or added). Sorted, 5619 row-oriented input will generally assemble the fastest. The default 5620 is row-oriented. 5621 5622 Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5623 5624 Input Parameters: 5625 + mat - the matrix 5626 . option - the option, one of those listed below (and possibly others), 5627 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5628 5629 Options Describing Matrix Structure: 5630 + `MAT_SPD` - symmetric positive definite 5631 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5632 . `MAT_HERMITIAN` - transpose is the complex conjugation 5633 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5634 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5635 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5636 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5637 5638 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5639 do not need to be computed (usually at a high cost) 5640 5641 Options For Use with `MatSetValues()`: 5642 Insert a logically dense subblock, which can be 5643 . `MAT_ROW_ORIENTED` - row-oriented (default) 5644 5645 Note these options reflect the data you pass in with `MatSetValues()`; it has 5646 nothing to do with how the data is stored internally in the matrix 5647 data structure. 5648 5649 When (re)assembling a matrix, we can restrict the input for 5650 efficiency/debugging purposes. These options include 5651 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5652 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5653 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5654 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5655 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5656 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5657 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5658 performance for very large process counts. 5659 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5660 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5661 functions, instead sending only neighbor messages. 5662 5663 Notes: 5664 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5665 5666 Some options are relevant only for particular matrix types and 5667 are thus ignored by others. Other options are not supported by 5668 certain matrix types and will generate an error message if set. 5669 5670 If using a Fortran 77 module to compute a matrix, one may need to 5671 use the column-oriented option (or convert to the row-oriented 5672 format). 5673 5674 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5675 that would generate a new entry in the nonzero structure is instead 5676 ignored. Thus, if memory has not alredy been allocated for this particular 5677 data, then the insertion is ignored. For dense matrices, in which 5678 the entire array is allocated, no entries are ever ignored. 5679 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5680 5681 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5682 that would generate a new entry in the nonzero structure instead produces 5683 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 5684 5685 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5686 that would generate a new entry that has not been preallocated will 5687 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5688 only.) This is a useful flag when debugging matrix memory preallocation. 5689 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5690 5691 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5692 other processors should be dropped, rather than stashed. 5693 This is useful if you know that the "owning" processor is also 5694 always generating the correct matrix entries, so that PETSc need 5695 not transfer duplicate entries generated on another processor. 5696 5697 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5698 searches during matrix assembly. When this flag is set, the hash table 5699 is created during the first matrix assembly. This hash table is 5700 used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()` 5701 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5702 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5703 supported by` MATMPIBAIJ` format only. 5704 5705 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5706 are kept in the nonzero structure 5707 5708 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5709 a zero location in the matrix 5710 5711 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5712 5713 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5714 zero row routines and thus improves performance for very large process counts. 5715 5716 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5717 part of the matrix (since they should match the upper triangular part). 5718 5719 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5720 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5721 with finite difference schemes with non-periodic boundary conditions. 5722 5723 Developer Note: 5724 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5725 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5726 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5727 not changed. 5728 5729 Level: intermediate 5730 5731 .seealso: `MatOption`, `Mat`, `MatGetOption()` 5732 @*/ 5733 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) { 5734 PetscFunctionBegin; 5735 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5736 if (op > 0) { 5737 PetscValidLogicalCollectiveEnum(mat, op, 2); 5738 PetscValidLogicalCollectiveBool(mat, flg, 3); 5739 } 5740 5741 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); 5742 5743 switch (op) { 5744 case MAT_FORCE_DIAGONAL_ENTRIES: mat->force_diagonals = flg; PetscFunctionReturn(0); 5745 case MAT_NO_OFF_PROC_ENTRIES: mat->nooffprocentries = flg; PetscFunctionReturn(0); 5746 case MAT_SUBSET_OFF_PROC_ENTRIES: 5747 mat->assembly_subset = flg; 5748 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5749 #if !defined(PETSC_HAVE_MPIUNI) 5750 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5751 #endif 5752 mat->stash.first_assembly_done = PETSC_FALSE; 5753 } 5754 PetscFunctionReturn(0); 5755 case MAT_NO_OFF_PROC_ZERO_ROWS: mat->nooffproczerorows = flg; PetscFunctionReturn(0); 5756 case MAT_SPD: 5757 if (flg) { 5758 mat->spd = PETSC_BOOL3_TRUE; 5759 mat->symmetric = PETSC_BOOL3_TRUE; 5760 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5761 } else { 5762 mat->spd = PETSC_BOOL3_FALSE; 5763 } 5764 break; 5765 case MAT_SYMMETRIC: 5766 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5767 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5768 #if !defined(PETSC_USE_COMPLEX) 5769 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5770 #endif 5771 break; 5772 case MAT_HERMITIAN: 5773 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5774 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5775 #if !defined(PETSC_USE_COMPLEX) 5776 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5777 #endif 5778 break; 5779 case MAT_STRUCTURALLY_SYMMETRIC: mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; break; 5780 case MAT_SYMMETRY_ETERNAL: 5781 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"); 5782 mat->symmetry_eternal = flg; 5783 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5784 break; 5785 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5786 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"); 5787 mat->structural_symmetry_eternal = flg; 5788 break; 5789 case MAT_SPD_ETERNAL: 5790 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"); 5791 mat->spd_eternal = flg; 5792 if (flg) { 5793 mat->structural_symmetry_eternal = PETSC_TRUE; 5794 mat->symmetry_eternal = PETSC_TRUE; 5795 } 5796 break; 5797 case MAT_STRUCTURE_ONLY: mat->structure_only = flg; break; 5798 case MAT_SORTED_FULL: mat->sortedfull = flg; break; 5799 default: break; 5800 } 5801 PetscTryTypeMethod(mat, setoption, op, flg); 5802 PetscFunctionReturn(0); 5803 } 5804 5805 /*@ 5806 MatGetOption - Gets a parameter option that has been set for a matrix. 5807 5808 Logically Collective on mat 5809 5810 Input Parameters: 5811 + mat - the matrix 5812 - option - the option, this only responds to certain options, check the code for which ones 5813 5814 Output Parameter: 5815 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5816 5817 Notes: 5818 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5819 5820 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5821 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5822 5823 Level: intermediate 5824 5825 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5826 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5827 @*/ 5828 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) { 5829 PetscFunctionBegin; 5830 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5831 PetscValidType(mat, 1); 5832 5833 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); 5834 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()"); 5835 5836 switch (op) { 5837 case MAT_NO_OFF_PROC_ENTRIES: *flg = mat->nooffprocentries; break; 5838 case MAT_NO_OFF_PROC_ZERO_ROWS: *flg = mat->nooffproczerorows; break; 5839 case MAT_SYMMETRIC: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); break; 5840 case MAT_HERMITIAN: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); break; 5841 case MAT_STRUCTURALLY_SYMMETRIC: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); break; 5842 case MAT_SPD: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); break; 5843 case MAT_SYMMETRY_ETERNAL: *flg = mat->symmetry_eternal; break; 5844 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: *flg = mat->symmetry_eternal; break; 5845 default: break; 5846 } 5847 PetscFunctionReturn(0); 5848 } 5849 5850 /*@ 5851 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 5852 this routine retains the old nonzero structure. 5853 5854 Logically Collective on mat 5855 5856 Input Parameters: 5857 . mat - the matrix 5858 5859 Level: intermediate 5860 5861 Note: 5862 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. 5863 See the Performance chapter of the users manual for information on preallocating matrices. 5864 5865 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 5866 @*/ 5867 PetscErrorCode MatZeroEntries(Mat mat) { 5868 PetscFunctionBegin; 5869 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5870 PetscValidType(mat, 1); 5871 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5872 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"); 5873 MatCheckPreallocated(mat, 1); 5874 5875 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 5876 PetscUseTypeMethod(mat, zeroentries); 5877 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 5878 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5879 PetscFunctionReturn(0); 5880 } 5881 5882 /*@ 5883 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 5884 of a set of rows and columns of a matrix. 5885 5886 Collective on mat 5887 5888 Input Parameters: 5889 + mat - the matrix 5890 . numRows - the number of rows to remove 5891 . rows - the global row indices 5892 . diag - value put in the diagonal of the eliminated rows 5893 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 5894 - b - optional vector of right hand side, that will be adjusted by provided solution 5895 5896 Notes: 5897 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 5898 5899 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 5900 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 5901 5902 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 5903 Krylov method to take advantage of the known solution on the zeroed rows. 5904 5905 For the parallel case, all processes that share the matrix (i.e., 5906 those in the communicator used for matrix creation) MUST call this 5907 routine, regardless of whether any rows being zeroed are owned by 5908 them. 5909 5910 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 5911 5912 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 5913 list only rows local to itself). 5914 5915 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 5916 5917 Level: intermediate 5918 5919 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 5920 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 5921 @*/ 5922 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 5923 PetscFunctionBegin; 5924 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5925 PetscValidType(mat, 1); 5926 if (numRows) PetscValidIntPointer(rows, 3); 5927 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5928 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5929 MatCheckPreallocated(mat, 1); 5930 5931 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 5932 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5933 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5934 PetscFunctionReturn(0); 5935 } 5936 5937 /*@ 5938 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 5939 of a set of rows and columns of a matrix. 5940 5941 Collective on mat 5942 5943 Input Parameters: 5944 + mat - the matrix 5945 . is - the rows to zero 5946 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 5947 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 5948 - b - optional vector of right hand side, that will be adjusted by provided solution 5949 5950 Note: 5951 See `MatZeroRowsColumns()` for details on how this routine operates. 5952 5953 Level: intermediate 5954 5955 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 5956 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 5957 @*/ 5958 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) { 5959 PetscInt numRows; 5960 const PetscInt *rows; 5961 5962 PetscFunctionBegin; 5963 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5964 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 5965 PetscValidType(mat, 1); 5966 PetscValidType(is, 2); 5967 PetscCall(ISGetLocalSize(is, &numRows)); 5968 PetscCall(ISGetIndices(is, &rows)); 5969 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 5970 PetscCall(ISRestoreIndices(is, &rows)); 5971 PetscFunctionReturn(0); 5972 } 5973 5974 /*@ 5975 MatZeroRows - Zeros all entries (except possibly the main diagonal) 5976 of a set of rows of a matrix. 5977 5978 Collective on mat 5979 5980 Input Parameters: 5981 + mat - the matrix 5982 . numRows - the number of rows to remove 5983 . rows - the global row indices 5984 . diag - value put in the diagonal of the eliminated rows 5985 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 5986 - b - optional vector of right hand side, that will be adjusted by provided solution 5987 5988 Notes: 5989 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 5990 5991 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 5992 5993 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 5994 Krylov method to take advantage of the known solution on the zeroed rows. 5995 5996 May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns) 5997 from the matrix. 5998 5999 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6000 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 6001 formats this does not alter the nonzero structure. 6002 6003 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6004 of the matrix is not changed the values are 6005 merely zeroed. 6006 6007 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6008 formats can optionally remove the main diagonal entry from the 6009 nonzero structure as well, by passing 0.0 as the final argument). 6010 6011 For the parallel case, all processes that share the matrix (i.e., 6012 those in the communicator used for matrix creation) MUST call this 6013 routine, regardless of whether any rows being zeroed are owned by 6014 them. 6015 6016 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6017 list only rows local to itself). 6018 6019 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6020 owns that are to be zeroed. This saves a global synchronization in the implementation. 6021 6022 Level: intermediate 6023 6024 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6025 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6026 @*/ 6027 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 6028 PetscFunctionBegin; 6029 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6030 PetscValidType(mat, 1); 6031 if (numRows) PetscValidIntPointer(rows, 3); 6032 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6033 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6034 MatCheckPreallocated(mat, 1); 6035 6036 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6037 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6038 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6039 PetscFunctionReturn(0); 6040 } 6041 6042 /*@ 6043 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6044 of a set of rows of a matrix. 6045 6046 Collective on Mat 6047 6048 Input Parameters: 6049 + mat - the matrix 6050 . is - index set of rows to remove (if NULL then no row is removed) 6051 . diag - value put in all diagonals of eliminated rows 6052 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6053 - b - optional vector of right hand side, that will be adjusted by provided solution 6054 6055 Note: 6056 See `MatZeroRows()` for details on how this routine operates. 6057 6058 Level: intermediate 6059 6060 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6061 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6062 @*/ 6063 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) { 6064 PetscInt numRows = 0; 6065 const PetscInt *rows = NULL; 6066 6067 PetscFunctionBegin; 6068 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6069 PetscValidType(mat, 1); 6070 if (is) { 6071 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6072 PetscCall(ISGetLocalSize(is, &numRows)); 6073 PetscCall(ISGetIndices(is, &rows)); 6074 } 6075 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6076 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6077 PetscFunctionReturn(0); 6078 } 6079 6080 /*@ 6081 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6082 of a set of rows of a matrix. These rows must be local to the process. 6083 6084 Collective on mat 6085 6086 Input Parameters: 6087 + mat - the matrix 6088 . numRows - the number of rows to remove 6089 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6090 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6091 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6092 - b - optional vector of right hand side, that will be adjusted by provided solution 6093 6094 Notes: 6095 See `MatZeroRows()` for details on how this routine operates. 6096 6097 The grid coordinates are across the entire grid, not just the local portion 6098 6099 In Fortran idxm and idxn should be declared as 6100 $ MatStencil idxm(4,m) 6101 and the values inserted using 6102 $ idxm(MatStencil_i,1) = i 6103 $ idxm(MatStencil_j,1) = j 6104 $ idxm(MatStencil_k,1) = k 6105 $ idxm(MatStencil_c,1) = c 6106 etc 6107 6108 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6109 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6110 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6111 `DM_BOUNDARY_PERIODIC` boundary type. 6112 6113 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 6114 a single value per point) you can skip filling those indices. 6115 6116 Level: intermediate 6117 6118 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6119 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6120 @*/ 6121 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) { 6122 PetscInt dim = mat->stencil.dim; 6123 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6124 PetscInt *dims = mat->stencil.dims + 1; 6125 PetscInt *starts = mat->stencil.starts; 6126 PetscInt *dxm = (PetscInt *)rows; 6127 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6128 6129 PetscFunctionBegin; 6130 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6131 PetscValidType(mat, 1); 6132 if (numRows) PetscValidPointer(rows, 3); 6133 6134 PetscCall(PetscMalloc1(numRows, &jdxm)); 6135 for (i = 0; i < numRows; ++i) { 6136 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6137 for (j = 0; j < 3 - sdim; ++j) dxm++; 6138 /* Local index in X dir */ 6139 tmp = *dxm++ - starts[0]; 6140 /* Loop over remaining dimensions */ 6141 for (j = 0; j < dim - 1; ++j) { 6142 /* If nonlocal, set index to be negative */ 6143 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6144 /* Update local index */ 6145 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6146 } 6147 /* Skip component slot if necessary */ 6148 if (mat->stencil.noc) dxm++; 6149 /* Local row number */ 6150 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6151 } 6152 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6153 PetscCall(PetscFree(jdxm)); 6154 PetscFunctionReturn(0); 6155 } 6156 6157 /*@ 6158 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6159 of a set of rows and columns of a matrix. 6160 6161 Collective on mat 6162 6163 Input Parameters: 6164 + mat - the matrix 6165 . numRows - the number of rows/columns to remove 6166 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6167 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6168 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6169 - b - optional vector of right hand side, that will be adjusted by provided solution 6170 6171 Notes: 6172 See `MatZeroRowsColumns()` for details on how this routine operates. 6173 6174 The grid coordinates are across the entire grid, not just the local portion 6175 6176 In Fortran idxm and idxn should be declared as 6177 $ MatStencil idxm(4,m) 6178 and the values inserted using 6179 $ idxm(MatStencil_i,1) = i 6180 $ idxm(MatStencil_j,1) = j 6181 $ idxm(MatStencil_k,1) = k 6182 $ idxm(MatStencil_c,1) = c 6183 etc 6184 6185 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6186 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6187 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6188 `DM_BOUNDARY_PERIODIC` boundary type. 6189 6190 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 6191 a single value per point) you can skip filling those indices. 6192 6193 Level: intermediate 6194 6195 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6196 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6197 @*/ 6198 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) { 6199 PetscInt dim = mat->stencil.dim; 6200 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6201 PetscInt *dims = mat->stencil.dims + 1; 6202 PetscInt *starts = mat->stencil.starts; 6203 PetscInt *dxm = (PetscInt *)rows; 6204 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6205 6206 PetscFunctionBegin; 6207 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6208 PetscValidType(mat, 1); 6209 if (numRows) PetscValidPointer(rows, 3); 6210 6211 PetscCall(PetscMalloc1(numRows, &jdxm)); 6212 for (i = 0; i < numRows; ++i) { 6213 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6214 for (j = 0; j < 3 - sdim; ++j) dxm++; 6215 /* Local index in X dir */ 6216 tmp = *dxm++ - starts[0]; 6217 /* Loop over remaining dimensions */ 6218 for (j = 0; j < dim - 1; ++j) { 6219 /* If nonlocal, set index to be negative */ 6220 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6221 /* Update local index */ 6222 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6223 } 6224 /* Skip component slot if necessary */ 6225 if (mat->stencil.noc) dxm++; 6226 /* Local row number */ 6227 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6228 } 6229 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6230 PetscCall(PetscFree(jdxm)); 6231 PetscFunctionReturn(0); 6232 } 6233 6234 /*@C 6235 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6236 of a set of rows of a matrix; using local numbering of rows. 6237 6238 Collective on mat 6239 6240 Input Parameters: 6241 + mat - the matrix 6242 . numRows - the number of rows to remove 6243 . rows - the local row indices 6244 . diag - value put in all diagonals of eliminated rows 6245 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6246 - b - optional vector of right hand side, that will be adjusted by provided solution 6247 6248 Notes: 6249 Before calling `MatZeroRowsLocal()`, the user must first set the 6250 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6251 6252 See `MatZeroRows()` for details on how this routine operates. 6253 6254 Level: intermediate 6255 6256 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6257 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6258 @*/ 6259 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 6260 PetscFunctionBegin; 6261 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6262 PetscValidType(mat, 1); 6263 if (numRows) PetscValidIntPointer(rows, 3); 6264 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6265 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6266 MatCheckPreallocated(mat, 1); 6267 6268 if (mat->ops->zerorowslocal) { 6269 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6270 } else { 6271 IS is, newis; 6272 const PetscInt *newRows; 6273 6274 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6275 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6276 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6277 PetscCall(ISGetIndices(newis, &newRows)); 6278 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6279 PetscCall(ISRestoreIndices(newis, &newRows)); 6280 PetscCall(ISDestroy(&newis)); 6281 PetscCall(ISDestroy(&is)); 6282 } 6283 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6284 PetscFunctionReturn(0); 6285 } 6286 6287 /*@ 6288 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6289 of a set of rows of a matrix; using local numbering of rows. 6290 6291 Collective on mat 6292 6293 Input Parameters: 6294 + mat - the matrix 6295 . is - index set of rows to remove 6296 . diag - value put in all diagonals of eliminated rows 6297 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6298 - b - optional vector of right hand side, that will be adjusted by provided solution 6299 6300 Notes: 6301 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6302 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6303 6304 See `MatZeroRows()` for details on how this routine operates. 6305 6306 Level: intermediate 6307 6308 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6309 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6310 @*/ 6311 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) { 6312 PetscInt numRows; 6313 const PetscInt *rows; 6314 6315 PetscFunctionBegin; 6316 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6317 PetscValidType(mat, 1); 6318 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6319 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6320 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6321 MatCheckPreallocated(mat, 1); 6322 6323 PetscCall(ISGetLocalSize(is, &numRows)); 6324 PetscCall(ISGetIndices(is, &rows)); 6325 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6326 PetscCall(ISRestoreIndices(is, &rows)); 6327 PetscFunctionReturn(0); 6328 } 6329 6330 /*@ 6331 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6332 of a set of rows and columns of a matrix; using local numbering of rows. 6333 6334 Collective on mat 6335 6336 Input Parameters: 6337 + mat - the matrix 6338 . numRows - the number of rows to remove 6339 . rows - the global row indices 6340 . diag - value put in all diagonals of eliminated rows 6341 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6342 - b - optional vector of right hand side, that will be adjusted by provided solution 6343 6344 Notes: 6345 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6346 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6347 6348 See `MatZeroRowsColumns()` for details on how this routine operates. 6349 6350 Level: intermediate 6351 6352 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6353 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6354 @*/ 6355 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 6356 IS is, newis; 6357 const PetscInt *newRows; 6358 6359 PetscFunctionBegin; 6360 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6361 PetscValidType(mat, 1); 6362 if (numRows) PetscValidIntPointer(rows, 3); 6363 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6364 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6365 MatCheckPreallocated(mat, 1); 6366 6367 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6368 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6369 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6370 PetscCall(ISGetIndices(newis, &newRows)); 6371 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6372 PetscCall(ISRestoreIndices(newis, &newRows)); 6373 PetscCall(ISDestroy(&newis)); 6374 PetscCall(ISDestroy(&is)); 6375 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6376 PetscFunctionReturn(0); 6377 } 6378 6379 /*@ 6380 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6381 of a set of rows and columns of a matrix; using local numbering of rows. 6382 6383 Collective on Mat 6384 6385 Input Parameters: 6386 + mat - the matrix 6387 . is - index set of rows to remove 6388 . diag - value put in all diagonals of eliminated rows 6389 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6390 - b - optional vector of right hand side, that will be adjusted by provided solution 6391 6392 Notes: 6393 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6394 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6395 6396 See `MatZeroRowsColumns()` for details on how this routine operates. 6397 6398 Level: intermediate 6399 6400 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6401 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6402 @*/ 6403 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) { 6404 PetscInt numRows; 6405 const PetscInt *rows; 6406 6407 PetscFunctionBegin; 6408 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6409 PetscValidType(mat, 1); 6410 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6411 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6412 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6413 MatCheckPreallocated(mat, 1); 6414 6415 PetscCall(ISGetLocalSize(is, &numRows)); 6416 PetscCall(ISGetIndices(is, &rows)); 6417 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6418 PetscCall(ISRestoreIndices(is, &rows)); 6419 PetscFunctionReturn(0); 6420 } 6421 6422 /*@C 6423 MatGetSize - Returns the numbers of rows and columns in a matrix. 6424 6425 Not Collective 6426 6427 Input Parameter: 6428 . mat - the matrix 6429 6430 Output Parameters: 6431 + m - the number of global rows 6432 - n - the number of global columns 6433 6434 Note: both output parameters can be NULL on input. 6435 6436 Level: beginner 6437 6438 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6439 @*/ 6440 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) { 6441 PetscFunctionBegin; 6442 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6443 if (m) *m = mat->rmap->N; 6444 if (n) *n = mat->cmap->N; 6445 PetscFunctionReturn(0); 6446 } 6447 6448 /*@C 6449 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6450 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6451 6452 Not Collective 6453 6454 Input Parameter: 6455 . mat - the matrix 6456 6457 Output Parameters: 6458 + m - the number of local rows, use `NULL` to not obtain this value 6459 - n - the number of local columns, use `NULL` to not obtain this value 6460 6461 Level: beginner 6462 6463 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()` 6464 @*/ 6465 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) { 6466 PetscFunctionBegin; 6467 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6468 if (m) PetscValidIntPointer(m, 2); 6469 if (n) PetscValidIntPointer(n, 3); 6470 if (m) *m = mat->rmap->n; 6471 if (n) *n = mat->cmap->n; 6472 PetscFunctionReturn(0); 6473 } 6474 6475 /*@C 6476 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6477 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6478 6479 Not Collective, unless matrix has not been allocated, then collective on mat 6480 6481 Input Parameter: 6482 . mat - the matrix 6483 6484 Output Parameters: 6485 + m - the global index of the first local column, use `NULL` to not obtain this value 6486 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6487 6488 Level: developer 6489 6490 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6491 @*/ 6492 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) { 6493 PetscFunctionBegin; 6494 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6495 PetscValidType(mat, 1); 6496 if (m) PetscValidIntPointer(m, 2); 6497 if (n) PetscValidIntPointer(n, 3); 6498 MatCheckPreallocated(mat, 1); 6499 if (m) *m = mat->cmap->rstart; 6500 if (n) *n = mat->cmap->rend; 6501 PetscFunctionReturn(0); 6502 } 6503 6504 /*@C 6505 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6506 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 6507 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6508 6509 Not Collective 6510 6511 Input Parameter: 6512 . mat - the matrix 6513 6514 Output Parameters: 6515 + m - the global index of the first local row, use `NULL` to not obtain this value 6516 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6517 6518 Note: 6519 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6520 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6521 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6522 6523 Level: beginner 6524 6525 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6526 `PetscLayout` 6527 @*/ 6528 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) { 6529 PetscFunctionBegin; 6530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6531 PetscValidType(mat, 1); 6532 if (m) PetscValidIntPointer(m, 2); 6533 if (n) PetscValidIntPointer(n, 3); 6534 MatCheckPreallocated(mat, 1); 6535 if (m) *m = mat->rmap->rstart; 6536 if (n) *n = mat->rmap->rend; 6537 PetscFunctionReturn(0); 6538 } 6539 6540 /*@C 6541 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6542 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 6543 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6544 6545 Not Collective, unless matrix has not been allocated, then collective on mat 6546 6547 Input Parameters: 6548 . mat - the matrix 6549 6550 Output Parameters: 6551 . ranges - start of each processors portion plus one more than the total length at the end 6552 6553 Level: beginner 6554 6555 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6556 @*/ 6557 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) { 6558 PetscFunctionBegin; 6559 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6560 PetscValidType(mat, 1); 6561 MatCheckPreallocated(mat, 1); 6562 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6563 PetscFunctionReturn(0); 6564 } 6565 6566 /*@C 6567 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6568 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6569 6570 Not Collective, unless matrix has not been allocated, then collective on Mat 6571 6572 Input Parameters: 6573 . mat - the matrix 6574 6575 Output Parameters: 6576 . ranges - start of each processors portion plus one more then the total length at the end 6577 6578 Level: beginner 6579 6580 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6581 @*/ 6582 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) { 6583 PetscFunctionBegin; 6584 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6585 PetscValidType(mat, 1); 6586 MatCheckPreallocated(mat, 1); 6587 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6588 PetscFunctionReturn(0); 6589 } 6590 6591 /*@C 6592 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6593 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6594 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6595 6596 Not Collective 6597 6598 Input Parameter: 6599 . A - matrix 6600 6601 Output Parameters: 6602 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6603 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6604 6605 Level: intermediate 6606 6607 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6608 @*/ 6609 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) { 6610 PetscErrorCode (*f)(Mat, IS *, IS *); 6611 6612 PetscFunctionBegin; 6613 MatCheckPreallocated(A, 1); 6614 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6615 if (f) { 6616 PetscCall((*f)(A, rows, cols)); 6617 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6618 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6619 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6620 } 6621 PetscFunctionReturn(0); 6622 } 6623 6624 /*@C 6625 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6626 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6627 to complete the factorization. 6628 6629 Collective on fact 6630 6631 Input Parameters: 6632 + fact - the factorized matrix obtained with `MatGetFactor()` 6633 . mat - the matrix 6634 . row - row permutation 6635 . column - column permutation 6636 - info - structure containing 6637 $ levels - number of levels of fill. 6638 $ expected fill - as ratio of original fill. 6639 $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6640 missing diagonal entries) 6641 6642 Output Parameters: 6643 . fact - new matrix that has been symbolically factored 6644 6645 Level: developer 6646 6647 Notes: 6648 See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency. 6649 6650 Most users should employ the `KSP` interface for linear solvers 6651 instead of working directly with matrix algebra routines such as this. 6652 See, e.g., `KSPCreate()`. 6653 6654 Uses the definition of level of fill as in Y. Saad, 2003 6655 6656 Developer Note: 6657 The Fortran interface is not autogenerated as the f90 6658 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6659 6660 References: 6661 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6662 6663 .seealso: `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6664 `MatGetOrdering()`, `MatFactorInfo` 6665 @*/ 6666 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) { 6667 PetscFunctionBegin; 6668 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6669 PetscValidType(mat, 2); 6670 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6671 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6672 PetscValidPointer(info, 5); 6673 PetscValidPointer(fact, 1); 6674 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6675 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6676 if (!fact->ops->ilufactorsymbolic) { 6677 MatSolverType stype; 6678 PetscCall(MatFactorGetSolverType(fact, &stype)); 6679 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype); 6680 } 6681 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6682 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6683 MatCheckPreallocated(mat, 2); 6684 6685 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6686 PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info)); 6687 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6688 PetscFunctionReturn(0); 6689 } 6690 6691 /*@C 6692 MatICCFactorSymbolic - Performs symbolic incomplete 6693 Cholesky factorization for a symmetric matrix. Use 6694 `MatCholeskyFactorNumeric()` to complete the factorization. 6695 6696 Collective on fact 6697 6698 Input Parameters: 6699 + fact - the factorized matrix obtained with `MatGetFactor()` 6700 . mat - the matrix to be factored 6701 . perm - row and column permutation 6702 - info - structure containing 6703 $ levels - number of levels of fill. 6704 $ expected fill - as ratio of original fill. 6705 6706 Output Parameter: 6707 . fact - the factored matrix 6708 6709 Level: developer 6710 6711 Notes: 6712 Most users should employ the `KSP` interface for linear solvers 6713 instead of working directly with matrix algebra routines such as this. 6714 See, e.g., `KSPCreate()`. 6715 6716 This uses the definition of level of fill as in Y. Saad, 2003 6717 6718 Developer Note: 6719 The Fortran interface is not autogenerated as the f90 6720 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6721 6722 References: 6723 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6724 6725 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6726 @*/ 6727 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) { 6728 PetscFunctionBegin; 6729 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6730 PetscValidType(mat, 2); 6731 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6732 PetscValidPointer(info, 4); 6733 PetscValidPointer(fact, 1); 6734 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6735 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6736 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6737 if (!(fact)->ops->iccfactorsymbolic) { 6738 MatSolverType stype; 6739 PetscCall(MatFactorGetSolverType(fact, &stype)); 6740 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype); 6741 } 6742 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6743 MatCheckPreallocated(mat, 2); 6744 6745 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6746 PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info)); 6747 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6748 PetscFunctionReturn(0); 6749 } 6750 6751 /*@C 6752 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6753 points to an array of valid matrices, they may be reused to store the new 6754 submatrices. 6755 6756 Collective on mat 6757 6758 Input Parameters: 6759 + mat - the matrix 6760 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6761 . irow, icol - index sets of rows and columns to extract 6762 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6763 6764 Output Parameter: 6765 . submat - the array of submatrices 6766 6767 Notes: 6768 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6769 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6770 to extract a parallel submatrix. 6771 6772 Some matrix types place restrictions on the row and column 6773 indices, such as that they be sorted or that they be equal to each other. 6774 6775 The index sets may not have duplicate entries. 6776 6777 When extracting submatrices from a parallel matrix, each processor can 6778 form a different submatrix by setting the rows and columns of its 6779 individual index sets according to the local submatrix desired. 6780 6781 When finished using the submatrices, the user should destroy 6782 them with `MatDestroySubMatrices()`. 6783 6784 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6785 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6786 6787 This routine creates the matrices in submat; you should NOT create them before 6788 calling it. It also allocates the array of matrix pointers submat. 6789 6790 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6791 request one row/column in a block, they must request all rows/columns that are in 6792 that block. For example, if the block size is 2 you cannot request just row 0 and 6793 column 0. 6794 6795 Fortran Note: 6796 The Fortran interface is slightly different from that given below; it 6797 requires one to pass in as submat a `Mat` (integer) array of size at least n+1. 6798 6799 Level: advanced 6800 6801 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6802 @*/ 6803 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) { 6804 PetscInt i; 6805 PetscBool eq; 6806 6807 PetscFunctionBegin; 6808 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6809 PetscValidType(mat, 1); 6810 if (n) { 6811 PetscValidPointer(irow, 3); 6812 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 6813 PetscValidPointer(icol, 4); 6814 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 6815 } 6816 PetscValidPointer(submat, 6); 6817 if (n && scall == MAT_REUSE_MATRIX) { 6818 PetscValidPointer(*submat, 6); 6819 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 6820 } 6821 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6822 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6823 MatCheckPreallocated(mat, 1); 6824 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 6825 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 6826 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 6827 for (i = 0; i < n; i++) { 6828 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 6829 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 6830 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 6831 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 6832 if (mat->boundtocpu && mat->bindingpropagates) { 6833 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 6834 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 6835 } 6836 #endif 6837 } 6838 PetscFunctionReturn(0); 6839 } 6840 6841 /*@C 6842 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 6843 6844 Collective on mat 6845 6846 Input Parameters: 6847 + mat - the matrix 6848 . n - the number of submatrixes to be extracted 6849 . irow, icol - index sets of rows and columns to extract 6850 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6851 6852 Output Parameter: 6853 . submat - the array of submatrices 6854 6855 Level: advanced 6856 6857 Note: 6858 This is used by `PCGASM` 6859 6860 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6861 @*/ 6862 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) { 6863 PetscInt i; 6864 PetscBool eq; 6865 6866 PetscFunctionBegin; 6867 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6868 PetscValidType(mat, 1); 6869 if (n) { 6870 PetscValidPointer(irow, 3); 6871 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 6872 PetscValidPointer(icol, 4); 6873 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 6874 } 6875 PetscValidPointer(submat, 6); 6876 if (n && scall == MAT_REUSE_MATRIX) { 6877 PetscValidPointer(*submat, 6); 6878 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 6879 } 6880 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6881 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6882 MatCheckPreallocated(mat, 1); 6883 6884 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 6885 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 6886 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 6887 for (i = 0; i < n; i++) { 6888 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 6889 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 6890 } 6891 PetscFunctionReturn(0); 6892 } 6893 6894 /*@C 6895 MatDestroyMatrices - Destroys an array of matrices. 6896 6897 Collective on mat 6898 6899 Input Parameters: 6900 + n - the number of local matrices 6901 - mat - the matrices (note that this is a pointer to the array of matrices) 6902 6903 Level: advanced 6904 6905 Note: 6906 Frees not only the matrices, but also the array that contains the matrices 6907 In Fortran will not free the array. 6908 6909 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 6910 @*/ 6911 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) { 6912 PetscInt i; 6913 6914 PetscFunctionBegin; 6915 if (!*mat) PetscFunctionReturn(0); 6916 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 6917 PetscValidPointer(mat, 2); 6918 6919 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 6920 6921 /* memory is allocated even if n = 0 */ 6922 PetscCall(PetscFree(*mat)); 6923 PetscFunctionReturn(0); 6924 } 6925 6926 /*@C 6927 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 6928 6929 Collective on mat 6930 6931 Input Parameters: 6932 + n - the number of local matrices 6933 - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling 6934 sequence of MatCreateSubMatrices()) 6935 6936 Level: advanced 6937 6938 Note: 6939 Frees not only the matrices, but also the array that contains the matrices 6940 In Fortran will not free the array. 6941 6942 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()` 6943 @*/ 6944 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) { 6945 Mat mat0; 6946 6947 PetscFunctionBegin; 6948 if (!*mat) PetscFunctionReturn(0); 6949 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 6950 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 6951 PetscValidPointer(mat, 2); 6952 6953 mat0 = (*mat)[0]; 6954 if (mat0 && mat0->ops->destroysubmatrices) { 6955 PetscCall((mat0->ops->destroysubmatrices)(n, mat)); 6956 } else { 6957 PetscCall(MatDestroyMatrices(n, mat)); 6958 } 6959 PetscFunctionReturn(0); 6960 } 6961 6962 /*@C 6963 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 6964 6965 Collective on mat 6966 6967 Input Parameters: 6968 . mat - the matrix 6969 6970 Output Parameter: 6971 . matstruct - the sequential matrix with the nonzero structure of mat 6972 6973 Level: developer 6974 6975 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 6976 @*/ 6977 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) { 6978 PetscFunctionBegin; 6979 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6980 PetscValidPointer(matstruct, 2); 6981 6982 PetscValidType(mat, 1); 6983 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6984 MatCheckPreallocated(mat, 1); 6985 6986 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 6987 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 6988 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 6989 PetscFunctionReturn(0); 6990 } 6991 6992 /*@C 6993 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 6994 6995 Collective on mat 6996 6997 Input Parameters: 6998 . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling 6999 sequence of `MatGetSequentialNonzeroStructure()`) 7000 7001 Level: advanced 7002 7003 Note: 7004 Frees not only the matrices, but also the array that contains the matrices 7005 7006 .seealso: `Mat`, `MatGetSeqNonzeroStructure()` 7007 @*/ 7008 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) { 7009 PetscFunctionBegin; 7010 PetscValidPointer(mat, 1); 7011 PetscCall(MatDestroy(mat)); 7012 PetscFunctionReturn(0); 7013 } 7014 7015 /*@ 7016 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7017 replaces the index sets by larger ones that represent submatrices with 7018 additional overlap. 7019 7020 Collective on mat 7021 7022 Input Parameters: 7023 + mat - the matrix 7024 . n - the number of index sets 7025 . is - the array of index sets (these index sets will changed during the call) 7026 - ov - the additional overlap requested 7027 7028 Options Database: 7029 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7030 7031 Level: developer 7032 7033 Developer Note: 7034 Any implementation must preserve block sizes. That is: if the row block size and the column block size of mat are equal to bs, then the output index sets must be compatible with bs. 7035 7036 .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7037 @*/ 7038 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) { 7039 PetscInt i, bs, cbs; 7040 7041 PetscFunctionBegin; 7042 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7043 PetscValidType(mat, 1); 7044 PetscValidLogicalCollectiveInt(mat, n, 2); 7045 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7046 if (n) { 7047 PetscValidPointer(is, 3); 7048 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7049 } 7050 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7051 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7052 MatCheckPreallocated(mat, 1); 7053 7054 if (!ov || !n) PetscFunctionReturn(0); 7055 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7056 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7057 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7058 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7059 if (bs == cbs) { 7060 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7061 } 7062 PetscFunctionReturn(0); 7063 } 7064 7065 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7066 7067 /*@ 7068 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7069 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7070 additional overlap. 7071 7072 Collective on mat 7073 7074 Input Parameters: 7075 + mat - the matrix 7076 . n - the number of index sets 7077 . is - the array of index sets (these index sets will changed during the call) 7078 - ov - the additional overlap requested 7079 7080 ` Options Database: 7081 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7082 7083 Level: developer 7084 7085 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7086 @*/ 7087 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) { 7088 PetscInt i; 7089 7090 PetscFunctionBegin; 7091 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7092 PetscValidType(mat, 1); 7093 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7094 if (n) { 7095 PetscValidPointer(is, 3); 7096 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7097 } 7098 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7099 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7100 MatCheckPreallocated(mat, 1); 7101 if (!ov) PetscFunctionReturn(0); 7102 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7103 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7104 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7105 PetscFunctionReturn(0); 7106 } 7107 7108 /*@ 7109 MatGetBlockSize - Returns the matrix block size. 7110 7111 Not Collective 7112 7113 Input Parameter: 7114 . mat - the matrix 7115 7116 Output Parameter: 7117 . bs - block size 7118 7119 Notes: 7120 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7121 7122 If the block size has not been set yet this routine returns 1. 7123 7124 Level: intermediate 7125 7126 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7127 @*/ 7128 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) { 7129 PetscFunctionBegin; 7130 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7131 PetscValidIntPointer(bs, 2); 7132 *bs = PetscAbs(mat->rmap->bs); 7133 PetscFunctionReturn(0); 7134 } 7135 7136 /*@ 7137 MatGetBlockSizes - Returns the matrix block row and column sizes. 7138 7139 Not Collective 7140 7141 Input Parameter: 7142 . mat - the matrix 7143 7144 Output Parameters: 7145 + rbs - row block size 7146 - cbs - column block size 7147 7148 Notes: 7149 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7150 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7151 7152 If a block size has not been set yet this routine returns 1. 7153 7154 Level: intermediate 7155 7156 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7157 @*/ 7158 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) { 7159 PetscFunctionBegin; 7160 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7161 if (rbs) PetscValidIntPointer(rbs, 2); 7162 if (cbs) PetscValidIntPointer(cbs, 3); 7163 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7164 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7165 PetscFunctionReturn(0); 7166 } 7167 7168 /*@ 7169 MatSetBlockSize - Sets the matrix block size. 7170 7171 Logically Collective on mat 7172 7173 Input Parameters: 7174 + mat - the matrix 7175 - bs - block size 7176 7177 Notes: 7178 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7179 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7180 7181 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7182 is compatible with the matrix local sizes. 7183 7184 Level: intermediate 7185 7186 .seealso: `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7187 @*/ 7188 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) { 7189 PetscFunctionBegin; 7190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7191 PetscValidLogicalCollectiveInt(mat, bs, 2); 7192 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7193 PetscFunctionReturn(0); 7194 } 7195 7196 typedef struct { 7197 PetscInt n; 7198 IS *is; 7199 Mat *mat; 7200 PetscObjectState nonzerostate; 7201 Mat C; 7202 } EnvelopeData; 7203 7204 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) { 7205 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7206 PetscCall(PetscFree(edata->is)); 7207 PetscCall(PetscFree(edata)); 7208 return 0; 7209 } 7210 7211 /* 7212 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7213 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7214 7215 Collective on mat 7216 7217 Input Parameter: 7218 . mat - the matrix 7219 7220 Notes: 7221 There can be zeros within the blocks 7222 7223 The blocks can overlap between processes, including laying on more than two processes 7224 7225 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7226 */ 7227 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) { 7228 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7229 PetscInt *diag, *odiag, sc; 7230 VecScatter scatter; 7231 PetscScalar *seqv; 7232 const PetscScalar *parv; 7233 const PetscInt *ia, *ja; 7234 PetscBool set, flag, done; 7235 Mat AA = mat, A; 7236 MPI_Comm comm; 7237 PetscMPIInt rank, size, tag; 7238 MPI_Status status; 7239 PetscContainer container; 7240 EnvelopeData *edata; 7241 Vec seq, par; 7242 IS isglobal; 7243 7244 PetscFunctionBegin; 7245 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7246 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7247 if (!set || !flag) { 7248 /* TOO: only needs nonzero structure of transpose */ 7249 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7250 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7251 } 7252 PetscCall(MatAIJGetLocalMat(AA, &A)); 7253 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7254 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7255 7256 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7257 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7258 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7259 PetscCallMPI(MPI_Comm_size(comm, &size)); 7260 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7261 7262 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7263 7264 if (rank > 0) { 7265 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7266 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7267 } 7268 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7269 for (i = 0; i < n; i++) { 7270 env = PetscMax(env, ja[ia[i + 1] - 1]); 7271 II = rstart + i; 7272 if (env == II) { 7273 starts[lblocks] = tbs; 7274 sizes[lblocks++] = 1 + II - tbs; 7275 tbs = 1 + II; 7276 } 7277 } 7278 if (rank < size - 1) { 7279 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7280 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7281 } 7282 7283 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7284 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7285 PetscCall(MatDestroy(&A)); 7286 7287 PetscCall(PetscNew(&edata)); 7288 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7289 edata->n = lblocks; 7290 /* create IS needed for extracting blocks from the original matrix */ 7291 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7292 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7293 7294 /* Create the resulting inverse matrix structure with preallocation information */ 7295 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7296 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7297 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7298 PetscCall(MatSetType(edata->C, MATAIJ)); 7299 7300 /* Communicate the start and end of each row, from each block to the correct rank */ 7301 /* TODO: Use PetscSF instead of VecScatter */ 7302 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7303 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7304 PetscCall(VecGetArrayWrite(seq, &seqv)); 7305 for (PetscInt i = 0; i < lblocks; i++) { 7306 for (PetscInt j = 0; j < sizes[i]; j++) { 7307 seqv[cnt] = starts[i]; 7308 seqv[cnt + 1] = starts[i] + sizes[i]; 7309 cnt += 2; 7310 } 7311 } 7312 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7313 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7314 sc -= cnt; 7315 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7316 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7317 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7318 PetscCall(ISDestroy(&isglobal)); 7319 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7320 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7321 PetscCall(VecScatterDestroy(&scatter)); 7322 PetscCall(VecDestroy(&seq)); 7323 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7324 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7325 PetscCall(VecGetArrayRead(par, &parv)); 7326 cnt = 0; 7327 PetscCall(MatGetSize(mat, NULL, &n)); 7328 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7329 PetscInt start, end, d = 0, od = 0; 7330 7331 start = (PetscInt)PetscRealPart(parv[cnt]); 7332 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7333 cnt += 2; 7334 7335 if (start < cstart) { 7336 od += cstart - start + n - cend; 7337 d += cend - cstart; 7338 } else if (start < cend) { 7339 od += n - cend; 7340 d += cend - start; 7341 } else od += n - start; 7342 if (end <= cstart) { 7343 od -= cstart - end + n - cend; 7344 d -= cend - cstart; 7345 } else if (end < cend) { 7346 od -= n - cend; 7347 d -= cend - end; 7348 } else od -= n - end; 7349 7350 odiag[i] = od; 7351 diag[i] = d; 7352 } 7353 PetscCall(VecRestoreArrayRead(par, &parv)); 7354 PetscCall(VecDestroy(&par)); 7355 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7356 PetscCall(PetscFree2(diag, odiag)); 7357 PetscCall(PetscFree2(sizes, starts)); 7358 7359 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7360 PetscCall(PetscContainerSetPointer(container, edata)); 7361 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7362 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7363 PetscCall(PetscObjectDereference((PetscObject)container)); 7364 PetscFunctionReturn(0); 7365 } 7366 7367 /*@ 7368 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7369 7370 Collective on A 7371 7372 Input Parameters: 7373 . A - the matrix 7374 7375 Output Parameters: 7376 . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 7377 7378 Note: 7379 For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal. 7380 7381 Level: advanced 7382 7383 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7384 @*/ 7385 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) { 7386 PetscContainer container; 7387 EnvelopeData *edata; 7388 PetscObjectState nonzerostate; 7389 7390 PetscFunctionBegin; 7391 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7392 if (!container) { 7393 PetscCall(MatComputeVariableBlockEnvelope(A)); 7394 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7395 } 7396 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7397 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7398 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7399 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7400 7401 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7402 *C = edata->C; 7403 7404 for (PetscInt i = 0; i < edata->n; i++) { 7405 Mat D; 7406 PetscScalar *dvalues; 7407 7408 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7409 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7410 PetscCall(MatSeqDenseInvert(D)); 7411 PetscCall(MatDenseGetArray(D, &dvalues)); 7412 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7413 PetscCall(MatDestroy(&D)); 7414 } 7415 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7416 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7417 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7418 PetscFunctionReturn(0); 7419 } 7420 7421 /*@ 7422 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7423 7424 Logically Collective on mat 7425 7426 Input Parameters: 7427 + mat - the matrix 7428 . nblocks - the number of blocks on this process, each block can only exist on a single process 7429 - bsizes - the block sizes 7430 7431 Notes: 7432 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7433 7434 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. 7435 7436 Level: intermediate 7437 7438 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7439 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7440 @*/ 7441 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) { 7442 PetscInt i, ncnt = 0, nlocal; 7443 7444 PetscFunctionBegin; 7445 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7446 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7447 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7448 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7449 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); 7450 PetscCall(PetscFree(mat->bsizes)); 7451 mat->nblocks = nblocks; 7452 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7453 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7454 PetscFunctionReturn(0); 7455 } 7456 7457 /*@C 7458 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7459 7460 Logically Collective on mat 7461 7462 Input Parameter: 7463 . mat - the matrix 7464 7465 Output Parameters: 7466 + nblocks - the number of blocks on this process 7467 - bsizes - the block sizes 7468 7469 Fortran Note: 7470 Currently not supported from Fortran 7471 7472 Level: intermediate 7473 7474 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7475 @*/ 7476 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) { 7477 PetscFunctionBegin; 7478 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7479 *nblocks = mat->nblocks; 7480 *bsizes = mat->bsizes; 7481 PetscFunctionReturn(0); 7482 } 7483 7484 /*@ 7485 MatSetBlockSizes - Sets the matrix block row and column sizes. 7486 7487 Logically Collective on mat 7488 7489 Input Parameters: 7490 + mat - the matrix 7491 . rbs - row block size 7492 - cbs - column block size 7493 7494 Notes: 7495 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7496 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7497 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7498 7499 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7500 are compatible with the matrix local sizes. 7501 7502 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7503 7504 Level: intermediate 7505 7506 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7507 @*/ 7508 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) { 7509 PetscFunctionBegin; 7510 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7511 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7512 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7513 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7514 if (mat->rmap->refcnt) { 7515 ISLocalToGlobalMapping l2g = NULL; 7516 PetscLayout nmap = NULL; 7517 7518 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7519 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7520 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7521 mat->rmap = nmap; 7522 mat->rmap->mapping = l2g; 7523 } 7524 if (mat->cmap->refcnt) { 7525 ISLocalToGlobalMapping l2g = NULL; 7526 PetscLayout nmap = NULL; 7527 7528 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7529 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7530 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7531 mat->cmap = nmap; 7532 mat->cmap->mapping = l2g; 7533 } 7534 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7535 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7536 PetscFunctionReturn(0); 7537 } 7538 7539 /*@ 7540 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7541 7542 Logically Collective on mat 7543 7544 Input Parameters: 7545 + mat - the matrix 7546 . fromRow - matrix from which to copy row block size 7547 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7548 7549 Level: developer 7550 7551 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7552 @*/ 7553 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) { 7554 PetscFunctionBegin; 7555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7556 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7557 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7558 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7559 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7560 PetscFunctionReturn(0); 7561 } 7562 7563 /*@ 7564 MatResidual - Default routine to calculate the residual r = b - Ax 7565 7566 Collective on mat 7567 7568 Input Parameters: 7569 + mat - the matrix 7570 . b - the right-hand-side 7571 - x - the approximate solution 7572 7573 Output Parameter: 7574 . r - location to store the residual 7575 7576 Level: developer 7577 7578 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7579 @*/ 7580 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) { 7581 PetscFunctionBegin; 7582 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7583 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7584 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7585 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7586 PetscValidType(mat, 1); 7587 MatCheckPreallocated(mat, 1); 7588 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7589 if (!mat->ops->residual) { 7590 PetscCall(MatMult(mat, x, r)); 7591 PetscCall(VecAYPX(r, -1.0, b)); 7592 } else { 7593 PetscUseTypeMethod(mat, residual, b, x, r); 7594 } 7595 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7596 PetscFunctionReturn(0); 7597 } 7598 7599 /*@C 7600 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7601 7602 Collective on mat 7603 7604 Input Parameters: 7605 + mat - the matrix 7606 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7607 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7608 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7609 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7610 always used. 7611 7612 Output Parameters: 7613 + n - number of local rows in the (possibly compressed) matrix 7614 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7615 . ja - the column indices 7616 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7617 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7618 7619 Level: developer 7620 7621 Notes: 7622 You CANNOT change any of the ia[] or ja[] values. 7623 7624 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7625 7626 Fortran Notes: 7627 In Fortran use 7628 $ 7629 $ PetscInt ia(1), ja(1) 7630 $ PetscOffset iia, jja 7631 $ call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr) 7632 $ ! Access the ith and jth entries via ia(iia + i) and ja(jja + j) 7633 7634 or 7635 $ 7636 $ PetscInt, pointer :: ia(:),ja(:) 7637 $ call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7638 $ ! Access the ith and jth entries via ia(i) and ja(j) 7639 7640 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7641 @*/ 7642 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 7643 PetscFunctionBegin; 7644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7645 PetscValidType(mat, 1); 7646 if (n) PetscValidIntPointer(n, 5); 7647 if (ia) PetscValidPointer(ia, 6); 7648 if (ja) PetscValidPointer(ja, 7); 7649 if (done) PetscValidBoolPointer(done, 8); 7650 MatCheckPreallocated(mat, 1); 7651 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7652 else { 7653 if (done) *done = PETSC_TRUE; 7654 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7655 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7656 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7657 } 7658 PetscFunctionReturn(0); 7659 } 7660 7661 /*@C 7662 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7663 7664 Collective on mat 7665 7666 Input Parameters: 7667 + mat - the matrix 7668 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7669 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7670 symmetrized 7671 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7672 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7673 always used. 7674 . n - number of columns in the (possibly compressed) matrix 7675 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7676 - ja - the row indices 7677 7678 Output Parameters: 7679 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7680 7681 Level: developer 7682 7683 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7684 @*/ 7685 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 7686 PetscFunctionBegin; 7687 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7688 PetscValidType(mat, 1); 7689 PetscValidIntPointer(n, 5); 7690 if (ia) PetscValidPointer(ia, 6); 7691 if (ja) PetscValidPointer(ja, 7); 7692 PetscValidBoolPointer(done, 8); 7693 MatCheckPreallocated(mat, 1); 7694 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7695 else { 7696 *done = PETSC_TRUE; 7697 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7698 } 7699 PetscFunctionReturn(0); 7700 } 7701 7702 /*@C 7703 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7704 7705 Collective on mat 7706 7707 Input Parameters: 7708 + mat - the matrix 7709 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7710 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7711 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7712 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7713 always used. 7714 . n - size of (possibly compressed) matrix 7715 . ia - the row pointers 7716 - ja - the column indices 7717 7718 Output Parameters: 7719 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7720 7721 Note: 7722 This routine zeros out n, ia, and ja. This is to prevent accidental 7723 us of the array after it has been restored. If you pass NULL, it will 7724 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7725 7726 Level: developer 7727 7728 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7729 @*/ 7730 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 7731 PetscFunctionBegin; 7732 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7733 PetscValidType(mat, 1); 7734 if (ia) PetscValidPointer(ia, 6); 7735 if (ja) PetscValidPointer(ja, 7); 7736 if (done) PetscValidBoolPointer(done, 8); 7737 MatCheckPreallocated(mat, 1); 7738 7739 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 7740 else { 7741 if (done) *done = PETSC_TRUE; 7742 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7743 if (n) *n = 0; 7744 if (ia) *ia = NULL; 7745 if (ja) *ja = NULL; 7746 } 7747 PetscFunctionReturn(0); 7748 } 7749 7750 /*@C 7751 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 7752 7753 Collective on Mat 7754 7755 Input Parameters: 7756 + mat - the matrix 7757 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7758 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7759 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7760 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7761 always used. 7762 7763 Output Parameters: 7764 + n - size of (possibly compressed) matrix 7765 . ia - the column pointers 7766 . ja - the row indices 7767 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7768 7769 Level: developer 7770 7771 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()` 7772 @*/ 7773 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) { 7774 PetscFunctionBegin; 7775 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7776 PetscValidType(mat, 1); 7777 if (ia) PetscValidPointer(ia, 6); 7778 if (ja) PetscValidPointer(ja, 7); 7779 PetscValidBoolPointer(done, 8); 7780 MatCheckPreallocated(mat, 1); 7781 7782 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 7783 else { 7784 *done = PETSC_TRUE; 7785 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7786 if (n) *n = 0; 7787 if (ia) *ia = NULL; 7788 if (ja) *ja = NULL; 7789 } 7790 PetscFunctionReturn(0); 7791 } 7792 7793 /*@C 7794 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 7795 7796 Collective on mat 7797 7798 Input Parameters: 7799 + mat - the matrix 7800 . ncolors - max color value 7801 . n - number of entries in colorarray 7802 - colorarray - array indicating color for each column 7803 7804 Output Parameters: 7805 . iscoloring - coloring generated using colorarray information 7806 7807 Level: developer 7808 7809 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()` 7810 @*/ 7811 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) { 7812 PetscFunctionBegin; 7813 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7814 PetscValidType(mat, 1); 7815 PetscValidIntPointer(colorarray, 4); 7816 PetscValidPointer(iscoloring, 5); 7817 MatCheckPreallocated(mat, 1); 7818 7819 if (!mat->ops->coloringpatch) { 7820 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 7821 } else { 7822 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 7823 } 7824 PetscFunctionReturn(0); 7825 } 7826 7827 /*@ 7828 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 7829 7830 Logically Collective on mat 7831 7832 Input Parameter: 7833 . mat - the factored matrix to be reset 7834 7835 Notes: 7836 This routine should be used only with factored matrices formed by in-place 7837 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 7838 format). This option can save memory, for example, when solving nonlinear 7839 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 7840 ILU(0) preconditioner. 7841 7842 Note that one can specify in-place ILU(0) factorization by calling 7843 .vb 7844 PCType(pc,PCILU); 7845 PCFactorSeUseInPlace(pc); 7846 .ve 7847 or by using the options -pc_type ilu -pc_factor_in_place 7848 7849 In-place factorization ILU(0) can also be used as a local 7850 solver for the blocks within the block Jacobi or additive Schwarz 7851 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 7852 for details on setting local solver options. 7853 7854 Most users should employ the `KSP` interface for linear solvers 7855 instead of working directly with matrix algebra routines such as this. 7856 See, e.g., `KSPCreate()`. 7857 7858 Level: developer 7859 7860 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 7861 @*/ 7862 PetscErrorCode MatSetUnfactored(Mat mat) { 7863 PetscFunctionBegin; 7864 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7865 PetscValidType(mat, 1); 7866 MatCheckPreallocated(mat, 1); 7867 mat->factortype = MAT_FACTOR_NONE; 7868 if (!mat->ops->setunfactored) PetscFunctionReturn(0); 7869 PetscUseTypeMethod(mat, setunfactored); 7870 PetscFunctionReturn(0); 7871 } 7872 7873 /*MC 7874 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 7875 7876 Synopsis: 7877 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 7878 7879 Not collective 7880 7881 Input Parameter: 7882 . x - matrix 7883 7884 Output Parameters: 7885 + xx_v - the Fortran pointer to the array 7886 - ierr - error code 7887 7888 Example of Usage: 7889 .vb 7890 PetscScalar, pointer xx_v(:,:) 7891 .... 7892 call MatDenseGetArrayF90(x,xx_v,ierr) 7893 a = xx_v(3) 7894 call MatDenseRestoreArrayF90(x,xx_v,ierr) 7895 .ve 7896 7897 Level: advanced 7898 7899 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 7900 7901 M*/ 7902 7903 /*MC 7904 MatDenseRestoreArrayF90 - Restores a matrix array that has been 7905 accessed with `MatDenseGetArrayF90()`. 7906 7907 Synopsis: 7908 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 7909 7910 Not collective 7911 7912 Input Parameters: 7913 + x - matrix 7914 - xx_v - the Fortran90 pointer to the array 7915 7916 Output Parameter: 7917 . ierr - error code 7918 7919 Example of Usage: 7920 .vb 7921 PetscScalar, pointer xx_v(:,:) 7922 .... 7923 call MatDenseGetArrayF90(x,xx_v,ierr) 7924 a = xx_v(3) 7925 call MatDenseRestoreArrayF90(x,xx_v,ierr) 7926 .ve 7927 7928 Level: advanced 7929 7930 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 7931 7932 M*/ 7933 7934 /*MC 7935 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 7936 7937 Synopsis: 7938 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 7939 7940 Not collective 7941 7942 Input Parameter: 7943 . x - matrix 7944 7945 Output Parameters: 7946 + xx_v - the Fortran pointer to the array 7947 - ierr - error code 7948 7949 Example of Usage: 7950 .vb 7951 PetscScalar, pointer xx_v(:) 7952 .... 7953 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 7954 a = xx_v(3) 7955 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 7956 .ve 7957 7958 Level: advanced 7959 7960 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 7961 7962 M*/ 7963 7964 /*MC 7965 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 7966 accessed with `MatSeqAIJGetArrayF90()`. 7967 7968 Synopsis: 7969 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 7970 7971 Not collective 7972 7973 Input Parameters: 7974 + x - matrix 7975 - xx_v - the Fortran90 pointer to the array 7976 7977 Output Parameter: 7978 . ierr - error code 7979 7980 Example of Usage: 7981 .vb 7982 PetscScalar, pointer xx_v(:) 7983 .... 7984 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 7985 a = xx_v(3) 7986 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 7987 .ve 7988 7989 Level: advanced 7990 7991 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 7992 7993 M*/ 7994 7995 /*@ 7996 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 7997 as the original matrix. 7998 7999 Collective on mat 8000 8001 Input Parameters: 8002 + mat - the original matrix 8003 . isrow - parallel IS containing the rows this processor should obtain 8004 . 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. 8005 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8006 8007 Output Parameter: 8008 . newmat - the new submatrix, of the same type as the old 8009 8010 Level: advanced 8011 8012 Notes: 8013 The submatrix will be able to be multiplied with vectors using the same layout as iscol. 8014 8015 Some matrix types place restrictions on the row and column indices, such 8016 as that they be sorted or that they be equal to each other. 8017 8018 The index sets may not have duplicate entries. 8019 8020 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8021 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8022 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8023 will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when 8024 you are finished using it. 8025 8026 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8027 the input matrix. 8028 8029 If iscol is NULL then all columns are obtained (not supported in Fortran). 8030 8031 Example usage: 8032 Consider the following 8x8 matrix with 34 non-zero values, that is 8033 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8034 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8035 as follows: 8036 8037 .vb 8038 1 2 0 | 0 3 0 | 0 4 8039 Proc0 0 5 6 | 7 0 0 | 8 0 8040 9 0 10 | 11 0 0 | 12 0 8041 ------------------------------------- 8042 13 0 14 | 15 16 17 | 0 0 8043 Proc1 0 18 0 | 19 20 21 | 0 0 8044 0 0 0 | 22 23 0 | 24 0 8045 ------------------------------------- 8046 Proc2 25 26 27 | 0 0 28 | 29 0 8047 30 0 0 | 31 32 33 | 0 34 8048 .ve 8049 8050 Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8051 8052 .vb 8053 2 0 | 0 3 0 | 0 8054 Proc0 5 6 | 7 0 0 | 8 8055 ------------------------------- 8056 Proc1 18 0 | 19 20 21 | 0 8057 ------------------------------- 8058 Proc2 26 27 | 0 0 28 | 29 8059 0 0 | 31 32 33 | 0 8060 .ve 8061 8062 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8063 @*/ 8064 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) { 8065 PetscMPIInt size; 8066 Mat *local; 8067 IS iscoltmp; 8068 PetscBool flg; 8069 8070 PetscFunctionBegin; 8071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8072 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8073 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8074 PetscValidPointer(newmat, 5); 8075 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8076 PetscValidType(mat, 1); 8077 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8078 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8079 8080 MatCheckPreallocated(mat, 1); 8081 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8082 8083 if (!iscol || isrow == iscol) { 8084 PetscBool stride; 8085 PetscMPIInt grabentirematrix = 0, grab; 8086 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8087 if (stride) { 8088 PetscInt first, step, n, rstart, rend; 8089 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8090 if (step == 1) { 8091 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8092 if (rstart == first) { 8093 PetscCall(ISGetLocalSize(isrow, &n)); 8094 if (n == rend - rstart) grabentirematrix = 1; 8095 } 8096 } 8097 } 8098 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8099 if (grab) { 8100 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8101 if (cll == MAT_INITIAL_MATRIX) { 8102 *newmat = mat; 8103 PetscCall(PetscObjectReference((PetscObject)mat)); 8104 } 8105 PetscFunctionReturn(0); 8106 } 8107 } 8108 8109 if (!iscol) { 8110 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8111 } else { 8112 iscoltmp = iscol; 8113 } 8114 8115 /* if original matrix is on just one processor then use submatrix generated */ 8116 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8117 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8118 goto setproperties; 8119 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8120 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8121 *newmat = *local; 8122 PetscCall(PetscFree(local)); 8123 goto setproperties; 8124 } else if (!mat->ops->createsubmatrix) { 8125 /* Create a new matrix type that implements the operation using the full matrix */ 8126 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8127 switch (cll) { 8128 case MAT_INITIAL_MATRIX: PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); break; 8129 case MAT_REUSE_MATRIX: PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); break; 8130 default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8131 } 8132 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8133 goto setproperties; 8134 } 8135 8136 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8137 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8138 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8139 8140 setproperties: 8141 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8142 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8143 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8144 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8145 PetscFunctionReturn(0); 8146 } 8147 8148 /*@ 8149 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8150 8151 Not Collective 8152 8153 Input Parameters: 8154 + A - the matrix we wish to propagate options from 8155 - B - the matrix we wish to propagate options to 8156 8157 Level: beginner 8158 8159 Note: 8160 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8161 8162 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8163 @*/ 8164 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) { 8165 PetscFunctionBegin; 8166 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8167 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8168 B->symmetry_eternal = A->symmetry_eternal; 8169 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8170 B->symmetric = A->symmetric; 8171 B->structurally_symmetric = A->structurally_symmetric; 8172 B->spd = A->spd; 8173 B->hermitian = A->hermitian; 8174 PetscFunctionReturn(0); 8175 } 8176 8177 /*@ 8178 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8179 used during the assembly process to store values that belong to 8180 other processors. 8181 8182 Not Collective 8183 8184 Input Parameters: 8185 + mat - the matrix 8186 . size - the initial size of the stash. 8187 - bsize - the initial size of the block-stash(if used). 8188 8189 Options Database Keys: 8190 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8191 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8192 8193 Level: intermediate 8194 8195 Notes: 8196 The block-stash is used for values set with `MatSetValuesBlocked()` while 8197 the stash is used for values set with `MatSetValues()` 8198 8199 Run with the option -info and look for output of the form 8200 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8201 to determine the appropriate value, MM, to use for size and 8202 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8203 to determine the value, BMM to use for bsize 8204 8205 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8206 @*/ 8207 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) { 8208 PetscFunctionBegin; 8209 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8210 PetscValidType(mat, 1); 8211 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8212 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8213 PetscFunctionReturn(0); 8214 } 8215 8216 /*@ 8217 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8218 the matrix 8219 8220 Neighbor-wise Collective on mat 8221 8222 Input Parameters: 8223 + mat - the matrix 8224 . x,y - the vectors 8225 - w - where the result is stored 8226 8227 Level: intermediate 8228 8229 Notes: 8230 w may be the same vector as y. 8231 8232 This allows one to use either the restriction or interpolation (its transpose) 8233 matrix to do the interpolation 8234 8235 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8236 @*/ 8237 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) { 8238 PetscInt M, N, Ny; 8239 8240 PetscFunctionBegin; 8241 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8242 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8243 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8244 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8245 PetscCall(MatGetSize(A, &M, &N)); 8246 PetscCall(VecGetSize(y, &Ny)); 8247 if (M == Ny) { 8248 PetscCall(MatMultAdd(A, x, y, w)); 8249 } else { 8250 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8251 } 8252 PetscFunctionReturn(0); 8253 } 8254 8255 /*@ 8256 MatInterpolate - y = A*x or A'*x depending on the shape of 8257 the matrix 8258 8259 Neighbor-wise Collective on mat 8260 8261 Input Parameters: 8262 + mat - the matrix 8263 - x,y - the vectors 8264 8265 Level: intermediate 8266 8267 Note: 8268 This allows one to use either the restriction or interpolation (its transpose) 8269 matrix to do the interpolation 8270 8271 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8272 @*/ 8273 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) { 8274 PetscInt M, N, Ny; 8275 8276 PetscFunctionBegin; 8277 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8278 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8279 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8280 PetscCall(MatGetSize(A, &M, &N)); 8281 PetscCall(VecGetSize(y, &Ny)); 8282 if (M == Ny) { 8283 PetscCall(MatMult(A, x, y)); 8284 } else { 8285 PetscCall(MatMultTranspose(A, x, y)); 8286 } 8287 PetscFunctionReturn(0); 8288 } 8289 8290 /*@ 8291 MatRestrict - y = A*x or A'*x 8292 8293 Neighbor-wise Collective on Mat 8294 8295 Input Parameters: 8296 + mat - the matrix 8297 - x,y - the vectors 8298 8299 Level: intermediate 8300 8301 Note: 8302 This allows one to use either the restriction or interpolation (its transpose) 8303 matrix to do the restriction 8304 8305 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8306 @*/ 8307 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) { 8308 PetscInt M, N, Ny; 8309 8310 PetscFunctionBegin; 8311 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8312 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8313 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8314 PetscCall(MatGetSize(A, &M, &N)); 8315 PetscCall(VecGetSize(y, &Ny)); 8316 if (M == Ny) { 8317 PetscCall(MatMult(A, x, y)); 8318 } else { 8319 PetscCall(MatMultTranspose(A, x, y)); 8320 } 8321 PetscFunctionReturn(0); 8322 } 8323 8324 /*@ 8325 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8326 8327 Neighbor-wise Collective on Mat 8328 8329 Input Parameters: 8330 + mat - the matrix 8331 - w, x - the input dense matrices 8332 8333 Output Parameters: 8334 . y - the output dense matrix 8335 8336 Level: intermediate 8337 8338 Note: 8339 This allows one to use either the restriction or interpolation (its transpose) 8340 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8341 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8342 8343 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8344 @*/ 8345 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) { 8346 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8347 PetscBool trans = PETSC_TRUE; 8348 MatReuse reuse = MAT_INITIAL_MATRIX; 8349 8350 PetscFunctionBegin; 8351 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8352 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8353 PetscValidType(x, 2); 8354 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8355 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8356 PetscCall(MatGetSize(A, &M, &N)); 8357 PetscCall(MatGetSize(x, &Mx, &Nx)); 8358 if (N == Mx) trans = PETSC_FALSE; 8359 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); 8360 Mo = trans ? N : M; 8361 if (*y) { 8362 PetscCall(MatGetSize(*y, &My, &Ny)); 8363 if (Mo == My && Nx == Ny) { 8364 reuse = MAT_REUSE_MATRIX; 8365 } else { 8366 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); 8367 PetscCall(MatDestroy(y)); 8368 } 8369 } 8370 8371 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8372 PetscBool flg; 8373 8374 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8375 if (w) { 8376 PetscInt My, Ny, Mw, Nw; 8377 8378 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8379 PetscCall(MatGetSize(*y, &My, &Ny)); 8380 PetscCall(MatGetSize(w, &Mw, &Nw)); 8381 if (!flg || My != Mw || Ny != Nw) w = NULL; 8382 } 8383 if (!w) { 8384 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8385 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8386 PetscCall(PetscLogObjectParent((PetscObject)*y, (PetscObject)w)); 8387 PetscCall(PetscObjectDereference((PetscObject)w)); 8388 } else { 8389 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8390 } 8391 } 8392 if (!trans) { 8393 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8394 } else { 8395 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8396 } 8397 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8398 PetscFunctionReturn(0); 8399 } 8400 8401 /*@ 8402 MatMatInterpolate - Y = A*X or A'*X 8403 8404 Neighbor-wise Collective on Mat 8405 8406 Input Parameters: 8407 + mat - the matrix 8408 - x - the input dense matrix 8409 8410 Output Parameters: 8411 . y - the output dense matrix 8412 8413 Level: intermediate 8414 8415 Note: 8416 This allows one to use either the restriction or interpolation (its transpose) 8417 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8418 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8419 8420 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8421 @*/ 8422 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) { 8423 PetscFunctionBegin; 8424 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8425 PetscFunctionReturn(0); 8426 } 8427 8428 /*@ 8429 MatMatRestrict - Y = A*X or A'*X 8430 8431 Neighbor-wise Collective on Mat 8432 8433 Input Parameters: 8434 + mat - the matrix 8435 - x - the input dense matrix 8436 8437 Output Parameters: 8438 . y - the output dense matrix 8439 8440 Level: intermediate 8441 8442 Note: 8443 This allows one to use either the restriction or interpolation (its transpose) 8444 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8445 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8446 8447 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8448 @*/ 8449 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) { 8450 PetscFunctionBegin; 8451 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8452 PetscFunctionReturn(0); 8453 } 8454 8455 /*@ 8456 MatGetNullSpace - retrieves the null space of a matrix. 8457 8458 Logically Collective on mat 8459 8460 Input Parameters: 8461 + mat - the matrix 8462 - nullsp - the null space object 8463 8464 Level: developer 8465 8466 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8467 @*/ 8468 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) { 8469 PetscFunctionBegin; 8470 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8471 PetscValidPointer(nullsp, 2); 8472 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8473 PetscFunctionReturn(0); 8474 } 8475 8476 /*@ 8477 MatSetNullSpace - attaches a null space to a matrix. 8478 8479 Logically Collective on mat 8480 8481 Input Parameters: 8482 + mat - the matrix 8483 - nullsp - the null space object 8484 8485 Level: advanced 8486 8487 Notes: 8488 This null space is used by the `KSP` linear solvers to solve singular systems. 8489 8490 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 8491 8492 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 8493 to zero but the linear system will still be solved in a least squares sense. 8494 8495 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8496 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). 8497 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 8498 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 8499 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). 8500 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8501 8502 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8503 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8504 routine also automatically calls `MatSetTransposeNullSpace()`. 8505 8506 The user should call `MatNullSpaceDestroy()`. 8507 8508 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8509 `KSPSetPCSide()` 8510 @*/ 8511 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) { 8512 PetscFunctionBegin; 8513 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8514 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8515 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8516 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8517 mat->nullsp = nullsp; 8518 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8519 PetscFunctionReturn(0); 8520 } 8521 8522 /*@ 8523 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8524 8525 Logically Collective on mat 8526 8527 Input Parameters: 8528 + mat - the matrix 8529 - nullsp - the null space object 8530 8531 Level: developer 8532 8533 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8534 @*/ 8535 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) { 8536 PetscFunctionBegin; 8537 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8538 PetscValidType(mat, 1); 8539 PetscValidPointer(nullsp, 2); 8540 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8541 PetscFunctionReturn(0); 8542 } 8543 8544 /*@ 8545 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8546 8547 Logically Collective on mat 8548 8549 Input Parameters: 8550 + mat - the matrix 8551 - nullsp - the null space object 8552 8553 Level: advanced 8554 8555 Notes: 8556 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8557 8558 See `MatSetNullSpace()` 8559 8560 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8561 @*/ 8562 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) { 8563 PetscFunctionBegin; 8564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8565 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8566 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8567 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8568 mat->transnullsp = nullsp; 8569 PetscFunctionReturn(0); 8570 } 8571 8572 /*@ 8573 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8574 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8575 8576 Logically Collective on mat 8577 8578 Input Parameters: 8579 + mat - the matrix 8580 - nullsp - the null space object 8581 8582 Level: advanced 8583 8584 Notes: 8585 Overwrites any previous near null space that may have been attached 8586 8587 You can remove the null space by calling this routine with an nullsp of NULL 8588 8589 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8590 @*/ 8591 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) { 8592 PetscFunctionBegin; 8593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8594 PetscValidType(mat, 1); 8595 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8596 MatCheckPreallocated(mat, 1); 8597 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8598 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8599 mat->nearnullsp = nullsp; 8600 PetscFunctionReturn(0); 8601 } 8602 8603 /*@ 8604 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8605 8606 Not Collective 8607 8608 Input Parameter: 8609 . mat - the matrix 8610 8611 Output Parameter: 8612 . nullsp - the null space object, NULL if not set 8613 8614 Level: advanced 8615 8616 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8617 @*/ 8618 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) { 8619 PetscFunctionBegin; 8620 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8621 PetscValidType(mat, 1); 8622 PetscValidPointer(nullsp, 2); 8623 MatCheckPreallocated(mat, 1); 8624 *nullsp = mat->nearnullsp; 8625 PetscFunctionReturn(0); 8626 } 8627 8628 /*@C 8629 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8630 8631 Collective on mat 8632 8633 Input Parameters: 8634 + mat - the matrix 8635 . row - row/column permutation 8636 . fill - expected fill factor >= 1.0 8637 - level - level of fill, for ICC(k) 8638 8639 Notes: 8640 Probably really in-place only when level of fill is zero, otherwise allocates 8641 new space to store factored matrix and deletes previous memory. 8642 8643 Most users should employ the `KSP` interface for linear solvers 8644 instead of working directly with matrix algebra routines such as this. 8645 See, e.g., `KSPCreate()`. 8646 8647 Level: developer 8648 8649 Developer Note: 8650 The Fortran interface is not autogenerated as the f90 8651 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8652 8653 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8654 @*/ 8655 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) { 8656 PetscFunctionBegin; 8657 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8658 PetscValidType(mat, 1); 8659 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8660 PetscValidPointer(info, 3); 8661 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8662 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8663 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8664 MatCheckPreallocated(mat, 1); 8665 PetscUseTypeMethod(mat, iccfactor, row, info); 8666 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8667 PetscFunctionReturn(0); 8668 } 8669 8670 /*@ 8671 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8672 ghosted ones. 8673 8674 Not Collective 8675 8676 Input Parameters: 8677 + mat - the matrix 8678 - diag - the diagonal values, including ghost ones 8679 8680 Level: developer 8681 8682 Notes: 8683 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8684 8685 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8686 8687 .seealso: `MatDiagonalScale()` 8688 @*/ 8689 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) { 8690 PetscMPIInt size; 8691 8692 PetscFunctionBegin; 8693 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8694 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8695 PetscValidType(mat, 1); 8696 8697 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8698 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8699 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8700 if (size == 1) { 8701 PetscInt n, m; 8702 PetscCall(VecGetSize(diag, &n)); 8703 PetscCall(MatGetSize(mat, NULL, &m)); 8704 if (m == n) { 8705 PetscCall(MatDiagonalScale(mat, NULL, diag)); 8706 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 8707 } else { 8708 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 8709 } 8710 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 8711 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8712 PetscFunctionReturn(0); 8713 } 8714 8715 /*@ 8716 MatGetInertia - Gets the inertia from a factored matrix 8717 8718 Collective on mat 8719 8720 Input Parameter: 8721 . mat - the matrix 8722 8723 Output Parameters: 8724 + nneg - number of negative eigenvalues 8725 . nzero - number of zero eigenvalues 8726 - npos - number of positive eigenvalues 8727 8728 Level: advanced 8729 8730 Note: 8731 Matrix must have been factored by `MatCholeskyFactor()` 8732 8733 .seealso: `MatGetFactor()`, `MatCholeskyFactor()` 8734 @*/ 8735 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) { 8736 PetscFunctionBegin; 8737 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8738 PetscValidType(mat, 1); 8739 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 8740 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 8741 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 8742 PetscFunctionReturn(0); 8743 } 8744 8745 /* ----------------------------------------------------------------*/ 8746 /*@C 8747 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 8748 8749 Neighbor-wise Collective on mat 8750 8751 Input Parameters: 8752 + mat - the factored matrix obtained with `MatGetFactor()` 8753 - b - the right-hand-side vectors 8754 8755 Output Parameter: 8756 . x - the result vectors 8757 8758 Note: 8759 The vectors b and x cannot be the same. I.e., one cannot 8760 call `MatSolves`(A,x,x). 8761 8762 Level: developer 8763 8764 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 8765 @*/ 8766 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) { 8767 PetscFunctionBegin; 8768 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8769 PetscValidType(mat, 1); 8770 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 8771 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 8772 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 8773 8774 MatCheckPreallocated(mat, 1); 8775 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 8776 PetscUseTypeMethod(mat, solves, b, x); 8777 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 8778 PetscFunctionReturn(0); 8779 } 8780 8781 /*@ 8782 MatIsSymmetric - Test whether a matrix is symmetric 8783 8784 Collective on mat 8785 8786 Input Parameters: 8787 + A - the matrix to test 8788 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 8789 8790 Output Parameters: 8791 . flg - the result 8792 8793 Notes: 8794 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 8795 8796 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 8797 8798 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 8799 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 8800 8801 Level: intermediate 8802 8803 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 8804 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 8805 @*/ 8806 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) { 8807 PetscFunctionBegin; 8808 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8809 PetscValidBoolPointer(flg, 3); 8810 8811 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 8812 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 8813 else { 8814 if (!A->ops->issymmetric) { 8815 MatType mattype; 8816 PetscCall(MatGetType(A, &mattype)); 8817 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype); 8818 } 8819 PetscUseTypeMethod(A, issymmetric, tol, flg); 8820 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 8821 } 8822 PetscFunctionReturn(0); 8823 } 8824 8825 /*@ 8826 MatIsHermitian - Test whether a matrix is Hermitian 8827 8828 Collective on Mat 8829 8830 Input Parameters: 8831 + A - the matrix to test 8832 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 8833 8834 Output Parameters: 8835 . flg - the result 8836 8837 Level: intermediate 8838 8839 Notes: 8840 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 8841 8842 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 8843 8844 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 8845 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 8846 8847 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 8848 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 8849 @*/ 8850 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) { 8851 PetscFunctionBegin; 8852 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8853 PetscValidBoolPointer(flg, 3); 8854 8855 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 8856 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 8857 else { 8858 if (!A->ops->ishermitian) { 8859 MatType mattype; 8860 PetscCall(MatGetType(A, &mattype)); 8861 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype); 8862 } 8863 PetscUseTypeMethod(A, ishermitian, tol, flg); 8864 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 8865 } 8866 PetscFunctionReturn(0); 8867 } 8868 8869 /*@ 8870 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 8871 8872 Not Collective 8873 8874 Input Parameter: 8875 . A - the matrix to check 8876 8877 Output Parameters: 8878 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 8879 - flg - the result (only valid if set is `PETSC_TRUE`) 8880 8881 Level: advanced 8882 8883 Notes: 8884 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 8885 if you want it explicitly checked 8886 8887 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 8888 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 8889 8890 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 8891 @*/ 8892 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) { 8893 PetscFunctionBegin; 8894 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8895 PetscValidBoolPointer(set, 2); 8896 PetscValidBoolPointer(flg, 3); 8897 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 8898 *set = PETSC_TRUE; 8899 *flg = PetscBool3ToBool(A->symmetric); 8900 } else { 8901 *set = PETSC_FALSE; 8902 } 8903 PetscFunctionReturn(0); 8904 } 8905 8906 /*@ 8907 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 8908 8909 Not Collective 8910 8911 Input Parameter: 8912 . A - the matrix to check 8913 8914 Output Parameters: 8915 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 8916 - flg - the result (only valid if set is `PETSC_TRUE`) 8917 8918 Level: advanced 8919 8920 Notes: 8921 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 8922 8923 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 8924 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 8925 8926 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 8927 @*/ 8928 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) { 8929 PetscFunctionBegin; 8930 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8931 PetscValidBoolPointer(set, 2); 8932 PetscValidBoolPointer(flg, 3); 8933 if (A->spd != PETSC_BOOL3_UNKNOWN) { 8934 *set = PETSC_TRUE; 8935 *flg = PetscBool3ToBool(A->spd); 8936 } else { 8937 *set = PETSC_FALSE; 8938 } 8939 PetscFunctionReturn(0); 8940 } 8941 8942 /*@ 8943 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 8944 8945 Not Collective 8946 8947 Input Parameter: 8948 . A - the matrix to check 8949 8950 Output Parameters: 8951 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 8952 - flg - the result (only valid if set is `PETSC_TRUE`) 8953 8954 Level: advanced 8955 8956 Notes: 8957 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 8958 if you want it explicitly checked 8959 8960 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 8961 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 8962 8963 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 8964 @*/ 8965 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) { 8966 PetscFunctionBegin; 8967 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8968 PetscValidBoolPointer(set, 2); 8969 PetscValidBoolPointer(flg, 3); 8970 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 8971 *set = PETSC_TRUE; 8972 *flg = PetscBool3ToBool(A->hermitian); 8973 } else { 8974 *set = PETSC_FALSE; 8975 } 8976 PetscFunctionReturn(0); 8977 } 8978 8979 /*@ 8980 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 8981 8982 Collective on Mat 8983 8984 Input Parameter: 8985 . A - the matrix to test 8986 8987 Output Parameters: 8988 . flg - the result 8989 8990 Notes: 8991 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 8992 8993 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 8994 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 8995 8996 Level: intermediate 8997 8998 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 8999 @*/ 9000 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) { 9001 PetscFunctionBegin; 9002 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9003 PetscValidBoolPointer(flg, 2); 9004 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9005 *flg = PetscBool3ToBool(A->structurally_symmetric); 9006 } else { 9007 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9008 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9009 } 9010 PetscFunctionReturn(0); 9011 } 9012 9013 /*@ 9014 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9015 9016 Not Collective 9017 9018 Input Parameter: 9019 . A - the matrix to check 9020 9021 Output Parameters: 9022 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9023 - flg - the result (only valid if set is PETSC_TRUE) 9024 9025 Level: advanced 9026 9027 Notes: 9028 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 9029 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9030 9031 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9032 9033 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9034 @*/ 9035 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) { 9036 PetscFunctionBegin; 9037 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9038 PetscValidBoolPointer(set, 2); 9039 PetscValidBoolPointer(flg, 3); 9040 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9041 *set = PETSC_TRUE; 9042 *flg = PetscBool3ToBool(A->structurally_symmetric); 9043 } else { 9044 *set = PETSC_FALSE; 9045 } 9046 PetscFunctionReturn(0); 9047 } 9048 9049 /*@ 9050 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9051 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9052 9053 Not collective 9054 9055 Input Parameter: 9056 . mat - the matrix 9057 9058 Output Parameters: 9059 + nstash - the size of the stash 9060 . reallocs - the number of additional mallocs incurred. 9061 . bnstash - the size of the block stash 9062 - breallocs - the number of additional mallocs incurred.in the block stash 9063 9064 Level: advanced 9065 9066 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9067 @*/ 9068 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) { 9069 PetscFunctionBegin; 9070 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9071 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9072 PetscFunctionReturn(0); 9073 } 9074 9075 /*@C 9076 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9077 parallel layout, `PetscLayout` for rows and columns 9078 9079 Collective on mat 9080 9081 Input Parameter: 9082 . mat - the matrix 9083 9084 Output Parameters: 9085 + right - (optional) vector that the matrix can be multiplied against 9086 - left - (optional) vector that the matrix vector product can be stored in 9087 9088 Notes: 9089 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()`. 9090 9091 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9092 9093 Level: advanced 9094 9095 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9096 @*/ 9097 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) { 9098 PetscFunctionBegin; 9099 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9100 PetscValidType(mat, 1); 9101 if (mat->ops->getvecs) { 9102 PetscUseTypeMethod(mat, getvecs, right, left); 9103 } else { 9104 PetscInt rbs, cbs; 9105 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9106 if (right) { 9107 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9108 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9109 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9110 PetscCall(VecSetBlockSize(*right, cbs)); 9111 PetscCall(VecSetType(*right, mat->defaultvectype)); 9112 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 9113 if (mat->boundtocpu && mat->bindingpropagates) { 9114 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9115 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9116 } 9117 #endif 9118 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9119 } 9120 if (left) { 9121 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9122 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9123 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9124 PetscCall(VecSetBlockSize(*left, rbs)); 9125 PetscCall(VecSetType(*left, mat->defaultvectype)); 9126 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 9127 if (mat->boundtocpu && mat->bindingpropagates) { 9128 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9129 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9130 } 9131 #endif 9132 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9133 } 9134 } 9135 PetscFunctionReturn(0); 9136 } 9137 9138 /*@C 9139 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9140 with default values. 9141 9142 Not Collective 9143 9144 Input Parameters: 9145 . info - the `MatFactorInfo` data structure 9146 9147 Notes: 9148 The solvers are generally used through the `KSP` and `PC` objects, for example 9149 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9150 9151 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9152 9153 Level: developer 9154 9155 Developer Note: 9156 The Fortran interface is not autogenerated as the f90 9157 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9158 9159 .seealso: `MatGetFactor()`, `MatFactorInfo` 9160 @*/ 9161 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) { 9162 PetscFunctionBegin; 9163 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9164 PetscFunctionReturn(0); 9165 } 9166 9167 /*@ 9168 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9169 9170 Collective on mat 9171 9172 Input Parameters: 9173 + mat - the factored matrix 9174 - is - the index set defining the Schur indices (0-based) 9175 9176 Notes: 9177 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9178 9179 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9180 9181 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9182 9183 Level: advanced 9184 9185 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9186 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9187 9188 @*/ 9189 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) { 9190 PetscErrorCode (*f)(Mat, IS); 9191 9192 PetscFunctionBegin; 9193 PetscValidType(mat, 1); 9194 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9195 PetscValidType(is, 2); 9196 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9197 PetscCheckSameComm(mat, 1, is, 2); 9198 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9199 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9200 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9201 PetscCall(MatDestroy(&mat->schur)); 9202 PetscCall((*f)(mat, is)); 9203 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9204 PetscFunctionReturn(0); 9205 } 9206 9207 /*@ 9208 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9209 9210 Logically Collective on mat 9211 9212 Input Parameters: 9213 + F - the factored matrix obtained by calling `MatGetFactor()` 9214 . S - location where to return the Schur complement, can be NULL 9215 - status - the status of the Schur complement matrix, can be NULL 9216 9217 Notes: 9218 You must call `MatFactorSetSchurIS()` before calling this routine. 9219 9220 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9221 9222 The routine provides a copy of the Schur matrix stored within the solver data structures. 9223 The caller must destroy the object when it is no longer needed. 9224 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9225 9226 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) 9227 9228 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9229 9230 Developer Note: 9231 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9232 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9233 9234 Level: advanced 9235 9236 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9237 @*/ 9238 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) { 9239 PetscFunctionBegin; 9240 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9241 if (S) PetscValidPointer(S, 2); 9242 if (status) PetscValidPointer(status, 3); 9243 if (S) { 9244 PetscErrorCode (*f)(Mat, Mat *); 9245 9246 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9247 if (f) { 9248 PetscCall((*f)(F, S)); 9249 } else { 9250 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9251 } 9252 } 9253 if (status) *status = F->schur_status; 9254 PetscFunctionReturn(0); 9255 } 9256 9257 /*@ 9258 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9259 9260 Logically Collective on mat 9261 9262 Input Parameters: 9263 + F - the factored matrix obtained by calling `MatGetFactor()` 9264 . *S - location where to return the Schur complement, can be NULL 9265 - status - the status of the Schur complement matrix, can be NULL 9266 9267 Notes: 9268 You must call `MatFactorSetSchurIS()` before calling this routine. 9269 9270 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9271 9272 The routine returns a the Schur Complement stored within the data strutures of the solver. 9273 9274 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9275 9276 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9277 9278 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9279 9280 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9281 9282 Level: advanced 9283 9284 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9285 @*/ 9286 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) { 9287 PetscFunctionBegin; 9288 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9289 if (S) PetscValidPointer(S, 2); 9290 if (status) PetscValidPointer(status, 3); 9291 if (S) *S = F->schur; 9292 if (status) *status = F->schur_status; 9293 PetscFunctionReturn(0); 9294 } 9295 9296 /*@ 9297 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9298 9299 Logically Collective on mat 9300 9301 Input Parameters: 9302 + F - the factored matrix obtained by calling `MatGetFactor()` 9303 . *S - location where the Schur complement is stored 9304 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9305 9306 Level: advanced 9307 9308 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9309 @*/ 9310 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) { 9311 PetscFunctionBegin; 9312 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9313 if (S) { 9314 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9315 *S = NULL; 9316 } 9317 F->schur_status = status; 9318 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9319 PetscFunctionReturn(0); 9320 } 9321 9322 /*@ 9323 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9324 9325 Logically Collective on mat 9326 9327 Input Parameters: 9328 + F - the factored matrix obtained by calling `MatGetFactor()` 9329 . rhs - location where the right hand side of the Schur complement system is stored 9330 - sol - location where the solution of the Schur complement system has to be returned 9331 9332 Notes: 9333 The sizes of the vectors should match the size of the Schur complement 9334 9335 Must be called after `MatFactorSetSchurIS()` 9336 9337 Level: advanced 9338 9339 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9340 @*/ 9341 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) { 9342 PetscFunctionBegin; 9343 PetscValidType(F, 1); 9344 PetscValidType(rhs, 2); 9345 PetscValidType(sol, 3); 9346 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9347 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9348 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9349 PetscCheckSameComm(F, 1, rhs, 2); 9350 PetscCheckSameComm(F, 1, sol, 3); 9351 PetscCall(MatFactorFactorizeSchurComplement(F)); 9352 switch (F->schur_status) { 9353 case MAT_FACTOR_SCHUR_FACTORED: PetscCall(MatSolveTranspose(F->schur, rhs, sol)); break; 9354 case MAT_FACTOR_SCHUR_INVERTED: PetscCall(MatMultTranspose(F->schur, rhs, sol)); break; 9355 default: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9356 } 9357 PetscFunctionReturn(0); 9358 } 9359 9360 /*@ 9361 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9362 9363 Logically Collective on mat 9364 9365 Input Parameters: 9366 + F - the factored matrix obtained by calling `MatGetFactor()` 9367 . rhs - location where the right hand side of the Schur complement system is stored 9368 - sol - location where the solution of the Schur complement system has to be returned 9369 9370 Notes: 9371 The sizes of the vectors should match the size of the Schur complement 9372 9373 Must be called after `MatFactorSetSchurIS()` 9374 9375 Level: advanced 9376 9377 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9378 @*/ 9379 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) { 9380 PetscFunctionBegin; 9381 PetscValidType(F, 1); 9382 PetscValidType(rhs, 2); 9383 PetscValidType(sol, 3); 9384 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9385 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9386 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9387 PetscCheckSameComm(F, 1, rhs, 2); 9388 PetscCheckSameComm(F, 1, sol, 3); 9389 PetscCall(MatFactorFactorizeSchurComplement(F)); 9390 switch (F->schur_status) { 9391 case MAT_FACTOR_SCHUR_FACTORED: PetscCall(MatSolve(F->schur, rhs, sol)); break; 9392 case MAT_FACTOR_SCHUR_INVERTED: PetscCall(MatMult(F->schur, rhs, sol)); break; 9393 default: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9394 } 9395 PetscFunctionReturn(0); 9396 } 9397 9398 /*@ 9399 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9400 9401 Logically Collective on F 9402 9403 Input Parameters: 9404 . F - the factored matrix obtained by calling `MatGetFactor()` 9405 9406 Notes: 9407 Must be called after `MatFactorSetSchurIS()`. 9408 9409 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9410 9411 Level: advanced 9412 9413 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9414 @*/ 9415 PetscErrorCode MatFactorInvertSchurComplement(Mat F) { 9416 PetscFunctionBegin; 9417 PetscValidType(F, 1); 9418 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9419 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0); 9420 PetscCall(MatFactorFactorizeSchurComplement(F)); 9421 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9422 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9423 PetscFunctionReturn(0); 9424 } 9425 9426 /*@ 9427 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9428 9429 Logically Collective on mat 9430 9431 Input Parameters: 9432 . F - the factored matrix obtained by calling `MatGetFactor()` 9433 9434 Note: 9435 Must be called after `MatFactorSetSchurIS()` 9436 9437 Level: advanced 9438 9439 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9440 @*/ 9441 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) { 9442 PetscFunctionBegin; 9443 PetscValidType(F, 1); 9444 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9445 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0); 9446 PetscCall(MatFactorFactorizeSchurComplement_Private(F)); 9447 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9448 PetscFunctionReturn(0); 9449 } 9450 9451 /*@ 9452 MatPtAP - Creates the matrix product C = P^T * A * P 9453 9454 Neighbor-wise Collective on A 9455 9456 Input Parameters: 9457 + A - the matrix 9458 . P - the projection matrix 9459 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9460 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9461 if the result is a dense matrix this is irrelevant 9462 9463 Output Parameters: 9464 . C - the product matrix 9465 9466 Notes: 9467 C will be created and must be destroyed by the user with `MatDestroy()`. 9468 9469 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9470 9471 Developer Note: 9472 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9473 9474 Level: intermediate 9475 9476 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9477 @*/ 9478 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) { 9479 PetscFunctionBegin; 9480 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9481 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9482 9483 if (scall == MAT_INITIAL_MATRIX) { 9484 PetscCall(MatProductCreate(A, P, NULL, C)); 9485 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9486 PetscCall(MatProductSetAlgorithm(*C, "default")); 9487 PetscCall(MatProductSetFill(*C, fill)); 9488 9489 (*C)->product->api_user = PETSC_TRUE; 9490 PetscCall(MatProductSetFromOptions(*C)); 9491 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); 9492 PetscCall(MatProductSymbolic(*C)); 9493 } else { /* scall == MAT_REUSE_MATRIX */ 9494 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9495 } 9496 9497 PetscCall(MatProductNumeric(*C)); 9498 (*C)->symmetric = A->symmetric; 9499 (*C)->spd = A->spd; 9500 PetscFunctionReturn(0); 9501 } 9502 9503 /*@ 9504 MatRARt - Creates the matrix product C = R * A * R^T 9505 9506 Neighbor-wise Collective on A 9507 9508 Input Parameters: 9509 + A - the matrix 9510 . R - the projection matrix 9511 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9512 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9513 if the result is a dense matrix this is irrelevant 9514 9515 Output Parameters: 9516 . C - the product matrix 9517 9518 Notes: 9519 C will be created and must be destroyed by the user with `MatDestroy()`. 9520 9521 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9522 9523 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9524 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9525 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9526 We recommend using MatPtAP(). 9527 9528 Level: intermediate 9529 9530 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9531 @*/ 9532 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) { 9533 PetscFunctionBegin; 9534 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9535 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9536 9537 if (scall == MAT_INITIAL_MATRIX) { 9538 PetscCall(MatProductCreate(A, R, NULL, C)); 9539 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9540 PetscCall(MatProductSetAlgorithm(*C, "default")); 9541 PetscCall(MatProductSetFill(*C, fill)); 9542 9543 (*C)->product->api_user = PETSC_TRUE; 9544 PetscCall(MatProductSetFromOptions(*C)); 9545 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); 9546 PetscCall(MatProductSymbolic(*C)); 9547 } else { /* scall == MAT_REUSE_MATRIX */ 9548 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9549 } 9550 9551 PetscCall(MatProductNumeric(*C)); 9552 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9553 PetscFunctionReturn(0); 9554 } 9555 9556 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) { 9557 PetscFunctionBegin; 9558 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9559 9560 if (scall == MAT_INITIAL_MATRIX) { 9561 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9562 PetscCall(MatProductCreate(A, B, NULL, C)); 9563 PetscCall(MatProductSetType(*C, ptype)); 9564 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9565 PetscCall(MatProductSetFill(*C, fill)); 9566 9567 (*C)->product->api_user = PETSC_TRUE; 9568 PetscCall(MatProductSetFromOptions(*C)); 9569 PetscCall(MatProductSymbolic(*C)); 9570 } else { /* scall == MAT_REUSE_MATRIX */ 9571 Mat_Product *product = (*C)->product; 9572 PetscBool isdense; 9573 9574 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9575 if (isdense && product && product->type != ptype) { 9576 PetscCall(MatProductClear(*C)); 9577 product = NULL; 9578 } 9579 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9580 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9581 if (isdense) { 9582 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9583 product = (*C)->product; 9584 product->fill = fill; 9585 product->api_user = PETSC_TRUE; 9586 product->clear = PETSC_TRUE; 9587 9588 PetscCall(MatProductSetType(*C, ptype)); 9589 PetscCall(MatProductSetFromOptions(*C)); 9590 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); 9591 PetscCall(MatProductSymbolic(*C)); 9592 } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9593 } else { /* user may change input matrices A or B when REUSE */ 9594 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9595 } 9596 } 9597 PetscCall(MatProductNumeric(*C)); 9598 PetscFunctionReturn(0); 9599 } 9600 9601 /*@ 9602 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9603 9604 Neighbor-wise Collective on A 9605 9606 Input Parameters: 9607 + A - the left matrix 9608 . B - the right matrix 9609 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9610 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9611 if the result is a dense matrix this is irrelevant 9612 9613 Output Parameters: 9614 . C - the product matrix 9615 9616 Notes: 9617 Unless scall is `MAT_REUSE_MATRIX` C will be created. 9618 9619 `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 9620 call to this function with `MAT_INITIAL_MATRIX`. 9621 9622 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 9623 9624 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`, 9625 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 9626 9627 Example of Usage: 9628 .vb 9629 MatProductCreate(A,B,NULL,&C); 9630 MatProductSetType(C,MATPRODUCT_AB); 9631 MatProductSymbolic(C); 9632 MatProductNumeric(C); // compute C=A * B 9633 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 9634 MatProductNumeric(C); 9635 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 9636 MatProductNumeric(C); 9637 .ve 9638 9639 Level: intermediate 9640 9641 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 9642 @*/ 9643 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) { 9644 PetscFunctionBegin; 9645 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 9646 PetscFunctionReturn(0); 9647 } 9648 9649 /*@ 9650 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 9651 9652 Neighbor-wise Collective on A 9653 9654 Input Parameters: 9655 + A - the left matrix 9656 . B - the right matrix 9657 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9658 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9659 9660 Output Parameters: 9661 . C - the product matrix 9662 9663 Notes: 9664 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 9665 9666 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 9667 9668 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9669 actually needed. 9670 9671 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 9672 and for pairs of `MATMPIDENSE` matrices. 9673 9674 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 9675 9676 Options Database Keys: 9677 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 9678 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 9679 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 9680 9681 Level: intermediate 9682 9683 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 9684 @*/ 9685 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) { 9686 PetscFunctionBegin; 9687 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 9688 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9689 PetscFunctionReturn(0); 9690 } 9691 9692 /*@ 9693 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 9694 9695 Neighbor-wise Collective on A 9696 9697 Input Parameters: 9698 + A - the left matrix 9699 . B - the right matrix 9700 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9701 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9702 9703 Output Parameters: 9704 . C - the product matrix 9705 9706 Notes: 9707 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 9708 9709 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 9710 9711 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 9712 9713 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9714 actually needed. 9715 9716 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 9717 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 9718 9719 Level: intermediate 9720 9721 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 9722 @*/ 9723 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) { 9724 PetscFunctionBegin; 9725 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 9726 PetscFunctionReturn(0); 9727 } 9728 9729 /*@ 9730 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 9731 9732 Neighbor-wise Collective on A 9733 9734 Input Parameters: 9735 + A - the left matrix 9736 . B - the middle matrix 9737 . C - the right matrix 9738 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9739 - 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 9740 if the result is a dense matrix this is irrelevant 9741 9742 Output Parameters: 9743 . D - the product matrix 9744 9745 Notes: 9746 Unless scall is `MAT_REUSE_MATRIX` D will be created. 9747 9748 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 9749 9750 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 9751 9752 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9753 actually needed. 9754 9755 If you have many matrices with the same non-zero structure to multiply, you 9756 should use `MAT_REUSE_MATRIX` in all calls but the first 9757 9758 Level: intermediate 9759 9760 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 9761 @*/ 9762 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) { 9763 PetscFunctionBegin; 9764 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 9765 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9766 9767 if (scall == MAT_INITIAL_MATRIX) { 9768 PetscCall(MatProductCreate(A, B, C, D)); 9769 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 9770 PetscCall(MatProductSetAlgorithm(*D, "default")); 9771 PetscCall(MatProductSetFill(*D, fill)); 9772 9773 (*D)->product->api_user = PETSC_TRUE; 9774 PetscCall(MatProductSetFromOptions(*D)); 9775 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, 9776 ((PetscObject)C)->type_name); 9777 PetscCall(MatProductSymbolic(*D)); 9778 } else { /* user may change input matrices when REUSE */ 9779 PetscCall(MatProductReplaceMats(A, B, C, *D)); 9780 } 9781 PetscCall(MatProductNumeric(*D)); 9782 PetscFunctionReturn(0); 9783 } 9784 9785 /*@ 9786 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 9787 9788 Collective on mat 9789 9790 Input Parameters: 9791 + mat - the matrix 9792 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 9793 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 9794 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9795 9796 Output Parameter: 9797 . matredundant - redundant matrix 9798 9799 Notes: 9800 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 9801 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 9802 9803 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 9804 calling it. 9805 9806 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 9807 9808 Level: advanced 9809 9810 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 9811 @*/ 9812 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) { 9813 MPI_Comm comm; 9814 PetscMPIInt size; 9815 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 9816 Mat_Redundant *redund = NULL; 9817 PetscSubcomm psubcomm = NULL; 9818 MPI_Comm subcomm_in = subcomm; 9819 Mat *matseq; 9820 IS isrow, iscol; 9821 PetscBool newsubcomm = PETSC_FALSE; 9822 9823 PetscFunctionBegin; 9824 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9825 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 9826 PetscValidPointer(*matredundant, 5); 9827 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 9828 } 9829 9830 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9831 if (size == 1 || nsubcomm == 1) { 9832 if (reuse == MAT_INITIAL_MATRIX) { 9833 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 9834 } else { 9835 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"); 9836 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 9837 } 9838 PetscFunctionReturn(0); 9839 } 9840 9841 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9842 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9843 MatCheckPreallocated(mat, 1); 9844 9845 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 9846 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 9847 /* create psubcomm, then get subcomm */ 9848 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 9849 PetscCallMPI(MPI_Comm_size(comm, &size)); 9850 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 9851 9852 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 9853 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 9854 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 9855 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 9856 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 9857 newsubcomm = PETSC_TRUE; 9858 PetscCall(PetscSubcommDestroy(&psubcomm)); 9859 } 9860 9861 /* get isrow, iscol and a local sequential matrix matseq[0] */ 9862 if (reuse == MAT_INITIAL_MATRIX) { 9863 mloc_sub = PETSC_DECIDE; 9864 nloc_sub = PETSC_DECIDE; 9865 if (bs < 1) { 9866 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 9867 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 9868 } else { 9869 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 9870 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 9871 } 9872 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 9873 rstart = rend - mloc_sub; 9874 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 9875 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 9876 } else { /* reuse == MAT_REUSE_MATRIX */ 9877 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"); 9878 /* retrieve subcomm */ 9879 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 9880 redund = (*matredundant)->redundant; 9881 isrow = redund->isrow; 9882 iscol = redund->iscol; 9883 matseq = redund->matseq; 9884 } 9885 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 9886 9887 /* get matredundant over subcomm */ 9888 if (reuse == MAT_INITIAL_MATRIX) { 9889 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 9890 9891 /* create a supporting struct and attach it to C for reuse */ 9892 PetscCall(PetscNewLog(*matredundant, &redund)); 9893 (*matredundant)->redundant = redund; 9894 redund->isrow = isrow; 9895 redund->iscol = iscol; 9896 redund->matseq = matseq; 9897 if (newsubcomm) { 9898 redund->subcomm = subcomm; 9899 } else { 9900 redund->subcomm = MPI_COMM_NULL; 9901 } 9902 } else { 9903 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 9904 } 9905 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 9906 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 9907 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 9908 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 9909 } 9910 #endif 9911 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 9912 PetscFunctionReturn(0); 9913 } 9914 9915 /*@C 9916 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 9917 a given `Mat`. Each submatrix can span multiple procs. 9918 9919 Collective on mat 9920 9921 Input Parameters: 9922 + mat - the matrix 9923 . subcomm - the subcommunicator obtained by MPI_Com_split(comm) 9924 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9925 9926 Output Parameter: 9927 . subMat - 'parallel submatrices each spans a given subcomm 9928 9929 Notes: 9930 The submatrix partition across processors is dictated by 'subComm' a 9931 communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm 9932 is not restriced to be grouped with consecutive original ranks. 9933 9934 Due the MPI_Comm_split() usage, the parallel layout of the submatrices 9935 map directly to the layout of the original matrix [wrt the local 9936 row,col partitioning]. So the original 'DiagonalMat' naturally maps 9937 into the 'DiagonalMat' of the subMat, hence it is used directly from 9938 the subMat. However the offDiagMat looses some columns - and this is 9939 reconstructed with `MatSetValues()` 9940 9941 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 9942 9943 Level: advanced 9944 9945 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 9946 @*/ 9947 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) { 9948 PetscMPIInt commsize, subCommSize; 9949 9950 PetscFunctionBegin; 9951 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 9952 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 9953 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 9954 9955 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"); 9956 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 9957 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 9958 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 9959 PetscFunctionReturn(0); 9960 } 9961 9962 /*@ 9963 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 9964 9965 Not Collective 9966 9967 Input Parameters: 9968 + mat - matrix to extract local submatrix from 9969 . isrow - local row indices for submatrix 9970 - iscol - local column indices for submatrix 9971 9972 Output Parameter: 9973 . submat - the submatrix 9974 9975 Level: intermediate 9976 9977 Notes: 9978 The submat should be returned with `MatRestoreLocalSubMatrix()`. 9979 9980 Depending on the format of mat, the returned submat may not implement `MatMult()`. Its communicator may be 9981 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's. 9982 9983 The submat always implements `MatSetValuesLocal()`. If isrow and iscol have the same block size, then 9984 `MatSetValuesBlockedLocal()` will also be implemented. 9985 9986 The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 9987 Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided. 9988 9989 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 9990 @*/ 9991 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) { 9992 PetscFunctionBegin; 9993 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9994 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 9995 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 9996 PetscCheckSameComm(isrow, 2, iscol, 3); 9997 PetscValidPointer(submat, 4); 9998 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 9999 10000 if (mat->ops->getlocalsubmatrix) { 10001 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10002 } else { 10003 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10004 } 10005 PetscFunctionReturn(0); 10006 } 10007 10008 /*@ 10009 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10010 10011 Not Collective 10012 10013 Input Parameters: 10014 + mat - matrix to extract local submatrix from 10015 . isrow - local row indices for submatrix 10016 . iscol - local column indices for submatrix 10017 - submat - the submatrix 10018 10019 Level: intermediate 10020 10021 .seealso: `MatGetLocalSubMatrix()` 10022 @*/ 10023 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) { 10024 PetscFunctionBegin; 10025 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10026 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10027 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10028 PetscCheckSameComm(isrow, 2, iscol, 3); 10029 PetscValidPointer(submat, 4); 10030 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10031 10032 if (mat->ops->restorelocalsubmatrix) { 10033 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10034 } else { 10035 PetscCall(MatDestroy(submat)); 10036 } 10037 *submat = NULL; 10038 PetscFunctionReturn(0); 10039 } 10040 10041 /* --------------------------------------------------------*/ 10042 /*@ 10043 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10044 10045 Collective on mat 10046 10047 Input Parameter: 10048 . mat - the matrix 10049 10050 Output Parameter: 10051 . is - if any rows have zero diagonals this contains the list of them 10052 10053 Level: developer 10054 10055 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10056 @*/ 10057 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) { 10058 PetscFunctionBegin; 10059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10060 PetscValidType(mat, 1); 10061 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10062 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10063 10064 if (!mat->ops->findzerodiagonals) { 10065 Vec diag; 10066 const PetscScalar *a; 10067 PetscInt *rows; 10068 PetscInt rStart, rEnd, r, nrow = 0; 10069 10070 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10071 PetscCall(MatGetDiagonal(mat, diag)); 10072 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10073 PetscCall(VecGetArrayRead(diag, &a)); 10074 for (r = 0; r < rEnd - rStart; ++r) 10075 if (a[r] == 0.0) ++nrow; 10076 PetscCall(PetscMalloc1(nrow, &rows)); 10077 nrow = 0; 10078 for (r = 0; r < rEnd - rStart; ++r) 10079 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10080 PetscCall(VecRestoreArrayRead(diag, &a)); 10081 PetscCall(VecDestroy(&diag)); 10082 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10083 } else { 10084 PetscUseTypeMethod(mat, findzerodiagonals, is); 10085 } 10086 PetscFunctionReturn(0); 10087 } 10088 10089 /*@ 10090 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10091 10092 Collective on mat 10093 10094 Input Parameter: 10095 . mat - the matrix 10096 10097 Output Parameter: 10098 . is - contains the list of rows with off block diagonal entries 10099 10100 Level: developer 10101 10102 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10103 @*/ 10104 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) { 10105 PetscFunctionBegin; 10106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10107 PetscValidType(mat, 1); 10108 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10109 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10110 10111 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10112 PetscFunctionReturn(0); 10113 } 10114 10115 /*@C 10116 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10117 10118 Collective on mat 10119 10120 Input Parameters: 10121 . mat - the matrix 10122 10123 Output Parameters: 10124 . values - the block inverses in column major order (FORTRAN-like) 10125 10126 Notes: 10127 The size of the blocks is determined by the block size of the matrix. 10128 10129 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10130 10131 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10132 10133 Fortran Note: 10134 This routine is not available from Fortran. 10135 10136 Level: advanced 10137 10138 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10139 @*/ 10140 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) { 10141 PetscFunctionBegin; 10142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10143 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10144 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10145 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10146 PetscFunctionReturn(0); 10147 } 10148 10149 /*@C 10150 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10151 10152 Collective on mat 10153 10154 Input Parameters: 10155 + mat - the matrix 10156 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10157 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10158 10159 Output Parameters: 10160 . values - the block inverses in column major order (FORTRAN-like) 10161 10162 Notes: 10163 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10164 10165 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10166 10167 Fortran Note: 10168 This routine is not available from Fortran. 10169 10170 Level: advanced 10171 10172 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10173 @*/ 10174 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) { 10175 PetscFunctionBegin; 10176 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10177 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10178 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10179 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10180 PetscFunctionReturn(0); 10181 } 10182 10183 /*@ 10184 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10185 10186 Collective on Mat 10187 10188 Input Parameters: 10189 + A - the matrix 10190 - C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 10191 10192 Note: 10193 The blocksize of the matrix is used to determine the blocks on the diagonal of C 10194 10195 Level: advanced 10196 10197 .seealso: `MatInvertBlockDiagonal()` 10198 @*/ 10199 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) { 10200 const PetscScalar *vals; 10201 PetscInt *dnnz; 10202 PetscInt m, rstart, rend, bs, i, j; 10203 10204 PetscFunctionBegin; 10205 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10206 PetscCall(MatGetBlockSize(A, &bs)); 10207 PetscCall(MatGetLocalSize(A, &m, NULL)); 10208 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10209 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10210 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10211 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10212 PetscCall(PetscFree(dnnz)); 10213 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10214 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10215 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10216 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10217 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10218 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10219 PetscFunctionReturn(0); 10220 } 10221 10222 /*@C 10223 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10224 via `MatTransposeColoringCreate()`. 10225 10226 Collective on c 10227 10228 Input Parameter: 10229 . c - coloring context 10230 10231 Level: intermediate 10232 10233 .seealso: `MatTransposeColoringCreate()` 10234 @*/ 10235 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) { 10236 MatTransposeColoring matcolor = *c; 10237 10238 PetscFunctionBegin; 10239 if (!matcolor) PetscFunctionReturn(0); 10240 if (--((PetscObject)matcolor)->refct > 0) { 10241 matcolor = NULL; 10242 PetscFunctionReturn(0); 10243 } 10244 10245 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10246 PetscCall(PetscFree(matcolor->rows)); 10247 PetscCall(PetscFree(matcolor->den2sp)); 10248 PetscCall(PetscFree(matcolor->colorforcol)); 10249 PetscCall(PetscFree(matcolor->columns)); 10250 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10251 PetscCall(PetscHeaderDestroy(c)); 10252 PetscFunctionReturn(0); 10253 } 10254 10255 /*@C 10256 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10257 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10258 `MatTransposeColoring` to sparse B. 10259 10260 Collective on coloring 10261 10262 Input Parameters: 10263 + B - sparse matrix B 10264 . Btdense - symbolic dense matrix B^T 10265 - coloring - coloring context created with `MatTransposeColoringCreate()` 10266 10267 Output Parameter: 10268 . Btdense - dense matrix B^T 10269 10270 Level: developer 10271 10272 Note: 10273 These are used internally for some implementations of `MatRARt()` 10274 10275 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10276 10277 @*/ 10278 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) { 10279 PetscFunctionBegin; 10280 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10281 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10282 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10283 10284 PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10285 PetscFunctionReturn(0); 10286 } 10287 10288 /*@C 10289 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10290 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10291 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10292 Csp from Cden. 10293 10294 Collective on matcoloring 10295 10296 Input Parameters: 10297 + coloring - coloring context created with `MatTransposeColoringCreate()` 10298 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10299 10300 Output Parameter: 10301 . Csp - sparse matrix 10302 10303 Level: developer 10304 10305 Note: 10306 These are used internally for some implementations of `MatRARt()` 10307 10308 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10309 10310 @*/ 10311 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) { 10312 PetscFunctionBegin; 10313 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10314 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10315 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10316 10317 PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10318 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10319 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10320 PetscFunctionReturn(0); 10321 } 10322 10323 /*@C 10324 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10325 10326 Collective on mat 10327 10328 Input Parameters: 10329 + mat - the matrix product C 10330 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10331 10332 Output Parameter: 10333 . color - the new coloring context 10334 10335 Level: intermediate 10336 10337 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10338 `MatTransColoringApplyDenToSp()` 10339 @*/ 10340 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) { 10341 MatTransposeColoring c; 10342 MPI_Comm comm; 10343 10344 PetscFunctionBegin; 10345 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10346 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10347 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10348 10349 c->ctype = iscoloring->ctype; 10350 if (mat->ops->transposecoloringcreate) { 10351 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10352 } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name); 10353 10354 *color = c; 10355 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10356 PetscFunctionReturn(0); 10357 } 10358 10359 /*@ 10360 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10361 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10362 same, otherwise it will be larger 10363 10364 Not Collective 10365 10366 Input Parameter: 10367 . A - the matrix 10368 10369 Output Parameter: 10370 . state - the current state 10371 10372 Notes: 10373 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10374 different matrices 10375 10376 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10377 10378 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10379 10380 Level: intermediate 10381 10382 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()` 10383 @*/ 10384 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) { 10385 PetscFunctionBegin; 10386 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10387 *state = mat->nonzerostate; 10388 PetscFunctionReturn(0); 10389 } 10390 10391 /*@ 10392 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10393 matrices from each processor 10394 10395 Collective 10396 10397 Input Parameters: 10398 + comm - the communicators the parallel matrix will live on 10399 . seqmat - the input sequential matrices 10400 . n - number of local columns (or `PETSC_DECIDE`) 10401 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10402 10403 Output Parameter: 10404 . mpimat - the parallel matrix generated 10405 10406 Level: developer 10407 10408 Note: 10409 The number of columns of the matrix in EACH processor MUST be the same. 10410 10411 .seealso: `Mat` 10412 @*/ 10413 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) { 10414 PetscMPIInt size; 10415 10416 PetscFunctionBegin; 10417 PetscCallMPI(MPI_Comm_size(comm, &size)); 10418 if (size == 1) { 10419 if (reuse == MAT_INITIAL_MATRIX) { 10420 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10421 } else { 10422 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10423 } 10424 PetscFunctionReturn(0); 10425 } 10426 10427 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"); 10428 10429 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10430 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10431 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10432 PetscFunctionReturn(0); 10433 } 10434 10435 /*@ 10436 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10437 10438 Collective on A 10439 10440 Input Parameters: 10441 + A - the matrix to create subdomains from 10442 - N - requested number of subdomains 10443 10444 Output Parameters: 10445 + n - number of subdomains resulting on this rank 10446 - iss - `IS` list with indices of subdomains on this rank 10447 10448 Level: advanced 10449 10450 Note: 10451 The number of subdomains must be smaller than the communicator size 10452 10453 .seealso: `Mat`, `IS` 10454 @*/ 10455 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) { 10456 MPI_Comm comm, subcomm; 10457 PetscMPIInt size, rank, color; 10458 PetscInt rstart, rend, k; 10459 10460 PetscFunctionBegin; 10461 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10462 PetscCallMPI(MPI_Comm_size(comm, &size)); 10463 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10464 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); 10465 *n = 1; 10466 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10467 color = rank / k; 10468 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10469 PetscCall(PetscMalloc1(1, iss)); 10470 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10471 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10472 PetscCallMPI(MPI_Comm_free(&subcomm)); 10473 PetscFunctionReturn(0); 10474 } 10475 10476 /*@ 10477 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10478 10479 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10480 If they are not the same, uses `MatMatMatMult()`. 10481 10482 Once the coarse grid problem is constructed, correct for interpolation operators 10483 that are not of full rank, which can legitimately happen in the case of non-nested 10484 geometric multigrid. 10485 10486 Input Parameters: 10487 + restrct - restriction operator 10488 . dA - fine grid matrix 10489 . interpolate - interpolation operator 10490 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10491 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10492 10493 Output Parameters: 10494 . A - the Galerkin coarse matrix 10495 10496 Options Database Key: 10497 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10498 10499 Level: developer 10500 10501 .seealso: `MatPtAP()`, `MatMatMatMult()` 10502 @*/ 10503 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) { 10504 IS zerorows; 10505 Vec diag; 10506 10507 PetscFunctionBegin; 10508 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10509 /* Construct the coarse grid matrix */ 10510 if (interpolate == restrct) { 10511 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10512 } else { 10513 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10514 } 10515 10516 /* If the interpolation matrix is not of full rank, A will have zero rows. 10517 This can legitimately happen in the case of non-nested geometric multigrid. 10518 In that event, we set the rows of the matrix to the rows of the identity, 10519 ignoring the equations (as the RHS will also be zero). */ 10520 10521 PetscCall(MatFindZeroRows(*A, &zerorows)); 10522 10523 if (zerorows != NULL) { /* if there are any zero rows */ 10524 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10525 PetscCall(MatGetDiagonal(*A, diag)); 10526 PetscCall(VecISSet(diag, zerorows, 1.0)); 10527 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10528 PetscCall(VecDestroy(&diag)); 10529 PetscCall(ISDestroy(&zerorows)); 10530 } 10531 PetscFunctionReturn(0); 10532 } 10533 10534 /*@C 10535 MatSetOperation - Allows user to set a matrix operation for any matrix type 10536 10537 Logically Collective on mat 10538 10539 Input Parameters: 10540 + mat - the matrix 10541 . op - the name of the operation 10542 - f - the function that provides the operation 10543 10544 Level: developer 10545 10546 Usage: 10547 $ extern PetscErrorCode usermult(Mat,Vec,Vec); 10548 $ PetscCall(MatCreateXXX(comm,...&A); 10549 $ PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult); 10550 10551 Notes: 10552 See the file include/petscmat.h for a complete list of matrix 10553 operations, which all have the form MATOP_<OPERATION>, where 10554 <OPERATION> is the name (in all capital letters) of the 10555 user interface routine (e.g., MatMult() -> MATOP_MULT). 10556 10557 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10558 sequence as the usual matrix interface routines, since they 10559 are intended to be accessed via the usual matrix interface 10560 routines, e.g., 10561 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 10562 10563 In particular each function MUST return an error code of 0 on success and 10564 nonzero on failure. 10565 10566 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10567 10568 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10569 @*/ 10570 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) { 10571 PetscFunctionBegin; 10572 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10573 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10574 (((void (**)(void))mat->ops)[op]) = f; 10575 PetscFunctionReturn(0); 10576 } 10577 10578 /*@C 10579 MatGetOperation - Gets a matrix operation for any matrix type. 10580 10581 Not Collective 10582 10583 Input Parameters: 10584 + mat - the matrix 10585 - op - the name of the operation 10586 10587 Output Parameter: 10588 . f - the function that provides the operation 10589 10590 Level: developer 10591 10592 Usage: 10593 $ PetscErrorCode (*usermult)(Mat,Vec,Vec); 10594 $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult); 10595 10596 Notes: 10597 See the file include/petscmat.h for a complete list of matrix 10598 operations, which all have the form MATOP_<OPERATION>, where 10599 <OPERATION> is the name (in all capital letters) of the 10600 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10601 10602 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 10603 10604 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 10605 @*/ 10606 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) { 10607 PetscFunctionBegin; 10608 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10609 *f = (((void (**)(void))mat->ops)[op]); 10610 PetscFunctionReturn(0); 10611 } 10612 10613 /*@ 10614 MatHasOperation - Determines whether the given matrix supports the particular operation. 10615 10616 Not Collective 10617 10618 Input Parameters: 10619 + mat - the matrix 10620 - op - the operation, for example, `MATOP_GET_DIAGONAL` 10621 10622 Output Parameter: 10623 . has - either `PETSC_TRUE` or `PETSC_FALSE` 10624 10625 Level: advanced 10626 10627 Note: 10628 See the file include/petscmat.h for a complete list of matrix 10629 operations, which all have the form MATOP_<OPERATION>, where 10630 <OPERATION> is the name (in all capital letters) of the 10631 user-level routine. E.g., `MatNorm()` -> `MATOP_NORM`. 10632 10633 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 10634 @*/ 10635 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) { 10636 PetscFunctionBegin; 10637 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10638 PetscValidBoolPointer(has, 3); 10639 if (mat->ops->hasoperation) { 10640 PetscUseTypeMethod(mat, hasoperation, op, has); 10641 } else { 10642 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 10643 else { 10644 *has = PETSC_FALSE; 10645 if (op == MATOP_CREATE_SUBMATRIX) { 10646 PetscMPIInt size; 10647 10648 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10649 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 10650 } 10651 } 10652 } 10653 PetscFunctionReturn(0); 10654 } 10655 10656 /*@ 10657 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 10658 10659 Collective on mat 10660 10661 Input Parameters: 10662 . mat - the matrix 10663 10664 Output Parameter: 10665 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 10666 10667 Level: beginner 10668 10669 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout` 10670 @*/ 10671 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) { 10672 PetscFunctionBegin; 10673 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10674 PetscValidType(mat, 1); 10675 PetscValidBoolPointer(cong, 2); 10676 if (!mat->rmap || !mat->cmap) { 10677 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 10678 PetscFunctionReturn(0); 10679 } 10680 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 10681 PetscCall(PetscLayoutSetUp(mat->rmap)); 10682 PetscCall(PetscLayoutSetUp(mat->cmap)); 10683 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 10684 if (*cong) mat->congruentlayouts = 1; 10685 else mat->congruentlayouts = 0; 10686 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 10687 PetscFunctionReturn(0); 10688 } 10689 10690 PetscErrorCode MatSetInf(Mat A) { 10691 PetscFunctionBegin; 10692 PetscUseTypeMethod(A, setinf); 10693 PetscFunctionReturn(0); 10694 } 10695 10696 /*C 10697 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 10698 10699 Collective on mat 10700 10701 Input Parameters: 10702 + A - the matrix 10703 - sym - `PETSC_TRUE` indicates that the graph will be symmetrized 10704 . scale - `PETSC_TRUE` indicates that the graph will be scaled with the diagonal 10705 10706 Output Parameter: 10707 . graph - the resulting graph 10708 10709 Level: advanced 10710 10711 .seealso: `MatCreate()`, `MatFilter()` 10712 */ 10713 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, Mat *graph) { 10714 PetscFunctionBegin; 10715 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 10716 PetscValidType(A, 1); 10717 PetscValidPointer(graph, 3); 10718 PetscUseTypeMethod(A, creategraph, sym, scale, graph); 10719 PetscFunctionReturn(0); 10720 } 10721 10722 /*C 10723 MatFilter - filters a matrices values with an absolut value equal to or below a give threshold 10724 10725 Collective on mat 10726 10727 Input Parameter: 10728 . value - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries <= value 10729 10730 Input/Output Parameter: 10731 . A - the `Mat` to filter in place 10732 10733 Level: developer 10734 10735 Note: 10736 This is called before graph coarsers are called in `PCGAMG` 10737 10738 .seealso: `MatCreate()`, `MatCreateGraph()` 10739 */ 10740 PETSC_EXTERN PetscErrorCode MatFilter(Mat G, PetscReal value, Mat *F) { 10741 PetscFunctionBegin; 10742 PetscValidHeaderSpecific(G, MAT_CLASSID, 1); 10743 PetscValidType(G, 1); 10744 PetscValidPointer(F, 3); 10745 if (value >= 0.0) PetscCall((G->ops->filter)(G, value, F)); 10746 PetscFunctionReturn(0); 10747 } 10748