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 { 74 PetscRandom randObj = NULL; 75 76 PetscFunctionBegin; 77 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 78 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 79 PetscValidType(x, 1); 80 MatCheckPreallocated(x, 1); 81 82 if (!rctx) { 83 MPI_Comm comm; 84 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 85 PetscCall(PetscRandomCreate(comm, &randObj)); 86 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 87 PetscCall(PetscRandomSetFromOptions(randObj)); 88 rctx = randObj; 89 } 90 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 91 PetscUseTypeMethod(x, setrandom, rctx); 92 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 93 94 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 95 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 96 PetscCall(PetscRandomDestroy(&randObj)); 97 PetscFunctionReturn(0); 98 } 99 100 /*@ 101 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 102 103 Logically Collective on mat 104 105 Input Parameter: 106 . mat - the factored matrix 107 108 Output Parameters: 109 + pivot - the pivot value computed 110 - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes 111 the share the matrix 112 113 Level: advanced 114 115 Notes: 116 This routine does not work for factorizations done with external packages. 117 118 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 119 120 This can be called on non-factored matrices that come from, for example, matrices used in SOR. 121 122 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 123 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 124 @*/ 125 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 126 { 127 PetscFunctionBegin; 128 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 129 PetscValidRealPointer(pivot, 2); 130 PetscValidIntPointer(row, 3); 131 *pivot = mat->factorerror_zeropivot_value; 132 *row = mat->factorerror_zeropivot_row; 133 PetscFunctionReturn(0); 134 } 135 136 /*@ 137 MatFactorGetError - gets the error code from a factorization 138 139 Logically Collective on mat 140 141 Input Parameters: 142 . mat - the factored matrix 143 144 Output Parameter: 145 . err - the error code 146 147 Level: advanced 148 149 Note: 150 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 151 152 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 153 `MatFactorError` 154 @*/ 155 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 156 { 157 PetscFunctionBegin; 158 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 159 PetscValidPointer(err, 2); 160 *err = mat->factorerrortype; 161 PetscFunctionReturn(0); 162 } 163 164 /*@ 165 MatFactorClearError - clears the error code in a factorization 166 167 Logically Collective on mat 168 169 Input Parameter: 170 . mat - the factored matrix 171 172 Level: developer 173 174 Note: 175 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 176 177 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 178 `MatGetErrorCode()`, `MatFactorError` 179 @*/ 180 PetscErrorCode MatFactorClearError(Mat mat) 181 { 182 PetscFunctionBegin; 183 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 184 mat->factorerrortype = MAT_FACTOR_NOERROR; 185 mat->factorerror_zeropivot_value = 0.0; 186 mat->factorerror_zeropivot_row = 0; 187 PetscFunctionReturn(0); 188 } 189 190 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 191 { 192 Vec r, l; 193 const PetscScalar *al; 194 PetscInt i, nz, gnz, N, n; 195 196 PetscFunctionBegin; 197 PetscCall(MatCreateVecs(mat, &r, &l)); 198 if (!cols) { /* nonzero rows */ 199 PetscCall(MatGetSize(mat, &N, NULL)); 200 PetscCall(MatGetLocalSize(mat, &n, NULL)); 201 PetscCall(VecSet(l, 0.0)); 202 PetscCall(VecSetRandom(r, NULL)); 203 PetscCall(MatMult(mat, r, l)); 204 PetscCall(VecGetArrayRead(l, &al)); 205 } else { /* nonzero columns */ 206 PetscCall(MatGetSize(mat, NULL, &N)); 207 PetscCall(MatGetLocalSize(mat, NULL, &n)); 208 PetscCall(VecSet(r, 0.0)); 209 PetscCall(VecSetRandom(l, NULL)); 210 PetscCall(MatMultTranspose(mat, l, r)); 211 PetscCall(VecGetArrayRead(r, &al)); 212 } 213 if (tol <= 0.0) { 214 for (i = 0, nz = 0; i < n; i++) 215 if (al[i] != 0.0) nz++; 216 } else { 217 for (i = 0, nz = 0; i < n; i++) 218 if (PetscAbsScalar(al[i]) > tol) nz++; 219 } 220 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 221 if (gnz != N) { 222 PetscInt *nzr; 223 PetscCall(PetscMalloc1(nz, &nzr)); 224 if (nz) { 225 if (tol < 0) { 226 for (i = 0, nz = 0; i < n; i++) 227 if (al[i] != 0.0) nzr[nz++] = i; 228 } else { 229 for (i = 0, nz = 0; i < n; i++) 230 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 231 } 232 } 233 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 234 } else *nonzero = NULL; 235 if (!cols) { /* nonzero rows */ 236 PetscCall(VecRestoreArrayRead(l, &al)); 237 } else { 238 PetscCall(VecRestoreArrayRead(r, &al)); 239 } 240 PetscCall(VecDestroy(&l)); 241 PetscCall(VecDestroy(&r)); 242 PetscFunctionReturn(0); 243 } 244 245 /*@ 246 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 247 248 Input Parameter: 249 . A - the matrix 250 251 Output Parameter: 252 . keptrows - the rows that are not completely zero 253 254 Note: 255 keptrows is set to NULL if all rows are nonzero. 256 257 Level: intermediate 258 259 .seealso: `Mat`, `MatFindZeroRows()` 260 @*/ 261 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 262 { 263 PetscFunctionBegin; 264 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 265 PetscValidType(mat, 1); 266 PetscValidPointer(keptrows, 2); 267 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 268 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 269 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 270 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 271 PetscFunctionReturn(0); 272 } 273 274 /*@ 275 MatFindZeroRows - Locate all rows that are completely zero in the matrix 276 277 Input Parameter: 278 . A - the matrix 279 280 Output Parameter: 281 . zerorows - the rows that are completely zero 282 283 Note: 284 zerorows is set to NULL if no rows are zero. 285 286 Level: intermediate 287 288 .seealso: `Mat`, `MatFindNonzeroRows()` 289 @*/ 290 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 291 { 292 IS keptrows; 293 PetscInt m, n; 294 295 PetscFunctionBegin; 296 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 297 PetscValidType(mat, 1); 298 PetscValidPointer(zerorows, 2); 299 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 300 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 301 In keeping with this convention, we set zerorows to NULL if there are no zero 302 rows. */ 303 if (keptrows == NULL) { 304 *zerorows = NULL; 305 } else { 306 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 307 PetscCall(ISComplement(keptrows, m, n, zerorows)); 308 PetscCall(ISDestroy(&keptrows)); 309 } 310 PetscFunctionReturn(0); 311 } 312 313 /*@ 314 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 315 316 Not Collective 317 318 Input Parameters: 319 . A - the matrix 320 321 Output Parameters: 322 . a - the diagonal part (which is a SEQUENTIAL matrix) 323 324 Notes: 325 See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 326 327 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. 328 329 Level: advanced 330 331 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 332 @*/ 333 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 334 { 335 PetscFunctionBegin; 336 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 337 PetscValidType(A, 1); 338 PetscValidPointer(a, 2); 339 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 340 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 341 else { 342 PetscMPIInt size; 343 344 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 345 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 346 *a = A; 347 } 348 PetscFunctionReturn(0); 349 } 350 351 /*@ 352 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 353 354 Collective on mat 355 356 Input Parameters: 357 . mat - the matrix 358 359 Output Parameter: 360 . trace - the sum of the diagonal entries 361 362 Level: advanced 363 364 .seealso: `Mat` 365 @*/ 366 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 367 { 368 Vec diag; 369 370 PetscFunctionBegin; 371 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 372 PetscValidScalarPointer(trace, 2); 373 PetscCall(MatCreateVecs(mat, &diag, NULL)); 374 PetscCall(MatGetDiagonal(mat, diag)); 375 PetscCall(VecSum(diag, trace)); 376 PetscCall(VecDestroy(&diag)); 377 PetscFunctionReturn(0); 378 } 379 380 /*@ 381 MatRealPart - Zeros out the imaginary part of the matrix 382 383 Logically Collective on mat 384 385 Input Parameters: 386 . mat - the matrix 387 388 Level: advanced 389 390 .seealso: `MatImaginaryPart()` 391 @*/ 392 PetscErrorCode MatRealPart(Mat mat) 393 { 394 PetscFunctionBegin; 395 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 396 PetscValidType(mat, 1); 397 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 398 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 399 MatCheckPreallocated(mat, 1); 400 PetscUseTypeMethod(mat, realpart); 401 PetscFunctionReturn(0); 402 } 403 404 /*@C 405 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 406 407 Collective on mat 408 409 Input Parameter: 410 . mat - the matrix 411 412 Output Parameters: 413 + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 414 - ghosts - the global indices of the ghost points 415 416 Note: 417 the nghosts and ghosts are suitable to pass into `VecCreateGhost()` 418 419 Level: advanced 420 421 .seealso: `Mat`, `VecCreateGhost()` 422 @*/ 423 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 424 { 425 PetscFunctionBegin; 426 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 427 PetscValidType(mat, 1); 428 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 429 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 430 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 431 else { 432 if (nghosts) *nghosts = 0; 433 if (ghosts) *ghosts = NULL; 434 } 435 PetscFunctionReturn(0); 436 } 437 438 /*@ 439 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 440 441 Logically Collective on mat 442 443 Input Parameters: 444 . mat - the matrix 445 446 Level: advanced 447 448 .seealso: `MatRealPart()` 449 @*/ 450 PetscErrorCode MatImaginaryPart(Mat mat) 451 { 452 PetscFunctionBegin; 453 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 454 PetscValidType(mat, 1); 455 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 456 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 457 MatCheckPreallocated(mat, 1); 458 PetscUseTypeMethod(mat, imaginarypart); 459 PetscFunctionReturn(0); 460 } 461 462 /*@ 463 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 464 465 Not Collective 466 467 Input Parameter: 468 . mat - the matrix 469 470 Output Parameters: 471 + missing - is any diagonal missing 472 - dd - first diagonal entry that is missing (optional) on this process 473 474 Level: advanced 475 476 .seealso: `Mat` 477 @*/ 478 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 479 { 480 PetscFunctionBegin; 481 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 482 PetscValidType(mat, 1); 483 PetscValidBoolPointer(missing, 2); 484 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 485 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 486 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 487 PetscFunctionReturn(0); 488 } 489 490 /*@C 491 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 492 for each row that you get to ensure that your application does 493 not bleed memory. 494 495 Not Collective 496 497 Input Parameters: 498 + mat - the matrix 499 - row - the row to get 500 501 Output Parameters: 502 + ncols - if not NULL, the number of nonzeros in the row 503 . cols - if not NULL, the column numbers 504 - vals - if not NULL, the values 505 506 Notes: 507 This routine is provided for people who need to have direct access 508 to the structure of a matrix. We hope that we provide enough 509 high-level matrix routines that few users will need it. 510 511 `MatGetRow()` always returns 0-based column indices, regardless of 512 whether the internal representation is 0-based (default) or 1-based. 513 514 For better efficiency, set cols and/or vals to NULL if you do 515 not wish to extract these quantities. 516 517 The user can only examine the values extracted with `MatGetRow()`; 518 the values cannot be altered. To change the matrix entries, one 519 must use `MatSetValues()`. 520 521 You can only have one call to `MatGetRow()` outstanding for a particular 522 matrix at a time, per processor. `MatGetRow()` can only obtain rows 523 associated with the given processor, it cannot get rows from the 524 other processors; for that we suggest using `MatCreateSubMatrices()`, then 525 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 526 is in the global number of rows. 527 528 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 529 530 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 531 532 Fortran Note: 533 The calling sequence from Fortran is 534 .vb 535 MatGetRow(matrix,row,ncols,cols,values,ierr) 536 Mat matrix (input) 537 integer row (input) 538 integer ncols (output) 539 integer cols(maxcols) (output) 540 double precision (or double complex) values(maxcols) output 541 .ve 542 where maxcols >= maximum nonzeros in any row of the matrix. 543 544 Caution: 545 Do not try to change the contents of the output arrays (cols and vals). 546 In some cases, this may corrupt the matrix. 547 548 Level: advanced 549 550 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 551 @*/ 552 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 553 { 554 PetscInt incols; 555 556 PetscFunctionBegin; 557 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 558 PetscValidType(mat, 1); 559 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 560 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 561 MatCheckPreallocated(mat, 1); 562 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); 563 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 564 PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals)); 565 if (ncols) *ncols = incols; 566 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 567 PetscFunctionReturn(0); 568 } 569 570 /*@ 571 MatConjugate - replaces the matrix values with their complex conjugates 572 573 Logically Collective on mat 574 575 Input Parameters: 576 . mat - the matrix 577 578 Level: advanced 579 580 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 581 @*/ 582 PetscErrorCode MatConjugate(Mat mat) 583 { 584 PetscFunctionBegin; 585 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 586 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 587 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 588 PetscUseTypeMethod(mat, conjugate); 589 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 590 } 591 PetscFunctionReturn(0); 592 } 593 594 /*@C 595 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 596 597 Not Collective 598 599 Input Parameters: 600 + mat - the matrix 601 . row - the row to get 602 . ncols, cols - the number of nonzeros and their columns 603 - vals - if nonzero the column values 604 605 Notes: 606 This routine should be called after you have finished examining the entries. 607 608 This routine zeros out ncols, cols, and vals. This is to prevent accidental 609 us of the array after it has been restored. If you pass NULL, it will 610 not zero the pointers. Use of cols or vals after `MatRestoreRow()` is invalid. 611 612 Fortran Notes: 613 The calling sequence from Fortran is 614 .vb 615 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 616 Mat matrix (input) 617 integer row (input) 618 integer ncols (output) 619 integer cols(maxcols) (output) 620 double precision (or double complex) values(maxcols) output 621 .ve 622 Where maxcols >= maximum nonzeros in any row of the matrix. 623 624 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 625 before another call to `MatGetRow()` can be made. 626 627 Level: advanced 628 629 .seealso: `MatGetRow()` 630 @*/ 631 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 632 { 633 PetscFunctionBegin; 634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 635 if (ncols) PetscValidIntPointer(ncols, 3); 636 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 637 if (!mat->ops->restorerow) PetscFunctionReturn(0); 638 PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals)); 639 if (ncols) *ncols = 0; 640 if (cols) *cols = NULL; 641 if (vals) *vals = NULL; 642 PetscFunctionReturn(0); 643 } 644 645 /*@ 646 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 647 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 648 649 Not Collective 650 651 Input Parameters: 652 . mat - the matrix 653 654 Note: 655 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. 656 657 Level: advanced 658 659 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 660 @*/ 661 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 662 { 663 PetscFunctionBegin; 664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 665 PetscValidType(mat, 1); 666 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 667 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 668 MatCheckPreallocated(mat, 1); 669 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0); 670 PetscUseTypeMethod(mat, getrowuppertriangular); 671 PetscFunctionReturn(0); 672 } 673 674 /*@ 675 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 676 677 Not Collective 678 679 Input Parameters: 680 . mat - the matrix 681 682 Note: 683 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 684 685 Level: advanced 686 687 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()` 688 @*/ 689 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 690 { 691 PetscFunctionBegin; 692 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 693 PetscValidType(mat, 1); 694 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 695 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 696 MatCheckPreallocated(mat, 1); 697 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0); 698 PetscUseTypeMethod(mat, restorerowuppertriangular); 699 PetscFunctionReturn(0); 700 } 701 702 /*@C 703 MatSetOptionsPrefix - Sets the prefix used for searching for all 704 `Mat` options in the database. 705 706 Logically Collective on A 707 708 Input Parameters: 709 + A - the matrix 710 - prefix - the prefix to prepend to all option names 711 712 Notes: 713 A hyphen (-) must NOT be given at the beginning of the prefix name. 714 The first character of all runtime options is AUTOMATICALLY the hyphen. 715 716 This is NOT used for options for the factorization of the matrix. Normally the 717 prefix is automatically passed in from the PC calling the factorization. To set 718 it directly use `MatSetOptionsPrefixFactor()` 719 720 Level: advanced 721 722 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 723 @*/ 724 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 725 { 726 PetscFunctionBegin; 727 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 728 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 729 PetscFunctionReturn(0); 730 } 731 732 /*@C 733 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 734 for matrices created with `MatGetFactor()` 735 736 Logically Collective on A 737 738 Input Parameters: 739 + A - the matrix 740 - prefix - the prefix to prepend to all option names for the factored matrix 741 742 Notes: 743 A hyphen (-) must NOT be given at the beginning of the prefix name. 744 The first character of all runtime options is AUTOMATICALLY the hyphen. 745 746 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 747 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 748 749 Level: developer 750 751 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 752 @*/ 753 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 754 { 755 PetscFunctionBegin; 756 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 757 if (prefix) { 758 PetscValidCharPointer(prefix, 2); 759 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 760 if (prefix != A->factorprefix) { 761 PetscCall(PetscFree(A->factorprefix)); 762 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 763 } 764 } else PetscCall(PetscFree(A->factorprefix)); 765 PetscFunctionReturn(0); 766 } 767 768 /*@C 769 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 770 for matrices created with `MatGetFactor()` 771 772 Logically Collective on A 773 774 Input Parameters: 775 + A - the matrix 776 - prefix - the prefix to prepend to all option names for the factored matrix 777 778 Notes: 779 A hyphen (-) must NOT be given at the beginning of the prefix name. 780 The first character of all runtime options is AUTOMATICALLY the hyphen. 781 782 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 783 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 784 785 Level: developer 786 787 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 788 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 789 `MatSetOptionsPrefix()` 790 @*/ 791 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 792 { 793 char *buf = A->factorprefix; 794 size_t len1, len2; 795 796 PetscFunctionBegin; 797 PetscValidHeader(A, 1); 798 if (!prefix) PetscFunctionReturn(0); 799 if (!buf) { 800 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 801 PetscFunctionReturn(0); 802 } 803 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 804 805 PetscCall(PetscStrlen(prefix, &len1)); 806 PetscCall(PetscStrlen(buf, &len2)); 807 PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix)); 808 PetscCall(PetscStrcpy(A->factorprefix, buf)); 809 PetscCall(PetscStrcat(A->factorprefix, prefix)); 810 PetscCall(PetscFree(buf)); 811 PetscFunctionReturn(0); 812 } 813 814 /*@C 815 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 816 matrix options in the database. 817 818 Logically Collective on A 819 820 Input Parameters: 821 + A - the matrix 822 - prefix - the prefix to prepend to all option names 823 824 Note: 825 A hyphen (-) must NOT be given at the beginning of the prefix name. 826 The first character of all runtime options is AUTOMATICALLY the hyphen. 827 828 Level: advanced 829 830 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 831 @*/ 832 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 833 { 834 PetscFunctionBegin; 835 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 836 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 837 PetscFunctionReturn(0); 838 } 839 840 /*@C 841 MatGetOptionsPrefix - Gets the prefix used for searching for all 842 matrix options in the database. 843 844 Not Collective 845 846 Input Parameter: 847 . A - the matrix 848 849 Output Parameter: 850 . prefix - pointer to the prefix string used 851 852 Fortran Note: 853 On the fortran side, the user should pass in a string 'prefix' of 854 sufficient length to hold the prefix. 855 856 Level: advanced 857 858 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 859 @*/ 860 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 861 { 862 PetscFunctionBegin; 863 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 864 PetscValidPointer(prefix, 2); 865 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 866 PetscFunctionReturn(0); 867 } 868 869 /*@ 870 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 871 872 Collective on A 873 874 Input Parameters: 875 . A - the matrix 876 877 Notes: 878 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 879 880 Users can reset the preallocation to access the original memory. 881 882 Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices. 883 884 Level: beginner 885 886 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 887 @*/ 888 PetscErrorCode MatResetPreallocation(Mat A) 889 { 890 PetscFunctionBegin; 891 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 892 PetscValidType(A, 1); 893 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 894 PetscFunctionReturn(0); 895 } 896 897 /*@ 898 MatSetUp - Sets up the internal matrix data structures for later use. 899 900 Collective on A 901 902 Input Parameters: 903 . A - the matrix 904 905 Notes: 906 If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used. 907 908 If a suitable preallocation routine is used, this function does not need to be called. 909 910 See the Performance chapter of the PETSc users manual for how to preallocate matrices 911 912 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 913 914 Level: intermediate 915 916 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()` 917 @*/ 918 PetscErrorCode MatSetUp(Mat A) 919 { 920 PetscFunctionBegin; 921 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 922 if (!((PetscObject)A)->type_name) { 923 PetscMPIInt size; 924 925 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 926 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 927 } 928 if (!A->preallocated && A->ops->setup) { 929 PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n")); 930 PetscUseTypeMethod(A, setup); 931 } 932 PetscCall(PetscLayoutSetUp(A->rmap)); 933 PetscCall(PetscLayoutSetUp(A->cmap)); 934 A->preallocated = PETSC_TRUE; 935 PetscFunctionReturn(0); 936 } 937 938 #if defined(PETSC_HAVE_SAWS) 939 #include <petscviewersaws.h> 940 #endif 941 942 /*@C 943 MatViewFromOptions - View properties of the matrix from the options database 944 945 Collective on A 946 947 Input Parameters: 948 + A - the matrix 949 . obj - optional additional object that provides the options prefix to use 950 - name - command line option 951 952 Options Database: 953 . -mat_view [viewertype]:... - the viewer and its options 954 955 Notes: 956 .vb 957 If no value is provided ascii:stdout is used 958 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 959 for example ascii::ascii_info prints just the information about the object not all details 960 unless :append is given filename opens in write mode, overwriting what was already there 961 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 962 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 963 socket[:port] defaults to the standard output port 964 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 965 .ve 966 967 Level: intermediate 968 969 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 970 @*/ 971 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 972 { 973 PetscFunctionBegin; 974 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 975 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 976 PetscFunctionReturn(0); 977 } 978 979 /*@C 980 MatView - display information about a matrix in a variety ways 981 982 Collective on mat 983 984 Input Parameters: 985 + mat - the matrix 986 - viewer - visualization context 987 988 Notes: 989 The available visualization contexts include 990 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 991 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 992 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 993 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 994 995 The user can open alternative visualization contexts with 996 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 997 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 998 specified file; corresponding input uses MatLoad() 999 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1000 an X window display 1001 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1002 Currently only the sequential dense and AIJ 1003 matrix types support the Socket viewer. 1004 1005 The user can call `PetscViewerPushFormat()` to specify the output 1006 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1007 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1008 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1009 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1010 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1011 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1012 format common among all matrix types 1013 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1014 format (which is in many cases the same as the default) 1015 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1016 size and structure (not the matrix entries) 1017 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1018 the matrix structure 1019 1020 Options Database Keys: 1021 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1022 . -mat_view ::ascii_info_detail - Prints more detailed info 1023 . -mat_view - Prints matrix in ASCII format 1024 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1025 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1026 . -display <name> - Sets display name (default is host) 1027 . -draw_pause <sec> - Sets number of seconds to pause after display 1028 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1029 . -viewer_socket_machine <machine> - 1030 . -viewer_socket_port <port> - 1031 . -mat_view binary - save matrix to file in binary format 1032 - -viewer_binary_filename <name> - 1033 1034 Level: beginner 1035 1036 Notes: 1037 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1038 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1039 1040 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1041 1042 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1043 viewer is used. 1044 1045 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1046 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1047 1048 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1049 and then use the following mouse functions. 1050 .vb 1051 left mouse: zoom in 1052 middle mouse: zoom out 1053 right mouse: continue with the simulation 1054 .ve 1055 1056 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`, 1057 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1058 @*/ 1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1060 { 1061 PetscInt rows, cols, rbs, cbs; 1062 PetscBool isascii, isstring, issaws; 1063 PetscViewerFormat format; 1064 PetscMPIInt size; 1065 1066 PetscFunctionBegin; 1067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1068 PetscValidType(mat, 1); 1069 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1070 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1071 PetscCheckSameComm(mat, 1, viewer, 2); 1072 MatCheckPreallocated(mat, 1); 1073 1074 PetscCall(PetscViewerGetFormat(viewer, &format)); 1075 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1076 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0); 1077 1078 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1079 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1080 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1081 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"); 1082 1083 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1084 if (isascii) { 1085 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Must call MatAssemblyBegin/End() before viewing matrix"); 1086 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1087 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1088 MatNullSpace nullsp, transnullsp; 1089 1090 PetscCall(PetscViewerASCIIPushTab(viewer)); 1091 PetscCall(MatGetSize(mat, &rows, &cols)); 1092 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1093 if (rbs != 1 || cbs != 1) { 1094 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1095 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1096 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1097 if (mat->factortype) { 1098 MatSolverType solver; 1099 PetscCall(MatFactorGetSolverType(mat, &solver)); 1100 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1101 } 1102 if (mat->ops->getinfo) { 1103 MatInfo info; 1104 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1105 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1106 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1107 } 1108 PetscCall(MatGetNullSpace(mat, &nullsp)); 1109 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1110 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1111 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1112 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1113 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1114 PetscCall(PetscViewerASCIIPushTab(viewer)); 1115 PetscCall(MatProductView(mat, viewer)); 1116 PetscCall(PetscViewerASCIIPopTab(viewer)); 1117 } 1118 } else if (issaws) { 1119 #if defined(PETSC_HAVE_SAWS) 1120 PetscMPIInt rank; 1121 1122 PetscCall(PetscObjectName((PetscObject)mat)); 1123 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1124 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1125 #endif 1126 } else if (isstring) { 1127 const char *type; 1128 PetscCall(MatGetType(mat, &type)); 1129 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1130 PetscTryTypeMethod(mat, view, viewer); 1131 } 1132 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1133 PetscCall(PetscViewerASCIIPushTab(viewer)); 1134 PetscUseTypeMethod(mat, viewnative, viewer); 1135 PetscCall(PetscViewerASCIIPopTab(viewer)); 1136 } else if (mat->ops->view) { 1137 PetscCall(PetscViewerASCIIPushTab(viewer)); 1138 PetscUseTypeMethod(mat, view, viewer); 1139 PetscCall(PetscViewerASCIIPopTab(viewer)); 1140 } 1141 if (isascii) { 1142 PetscCall(PetscViewerGetFormat(viewer, &format)); 1143 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1144 } 1145 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1146 PetscFunctionReturn(0); 1147 } 1148 1149 #if defined(PETSC_USE_DEBUG) 1150 #include <../src/sys/totalview/tv_data_display.h> 1151 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1152 { 1153 TV_add_row("Local rows", "int", &mat->rmap->n); 1154 TV_add_row("Local columns", "int", &mat->cmap->n); 1155 TV_add_row("Global rows", "int", &mat->rmap->N); 1156 TV_add_row("Global columns", "int", &mat->cmap->N); 1157 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1158 return TV_format_OK; 1159 } 1160 #endif 1161 1162 /*@C 1163 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1164 with `MatView()`. The matrix format is determined from the options database. 1165 Generates a parallel MPI matrix if the communicator has more than one 1166 processor. The default matrix type is `MATAIJ`. 1167 1168 Collective on mat 1169 1170 Input Parameters: 1171 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1172 or some related function before a call to `MatLoad()` 1173 - viewer - binary/HDF5 file viewer 1174 1175 Options Database Keys: 1176 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1177 block size 1178 . -matload_block_size <bs> - set block size 1179 1180 Level: beginner 1181 1182 Notes: 1183 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1184 `Mat` before calling this routine if you wish to set it from the options database. 1185 1186 `MatLoad()` automatically loads into the options database any options 1187 given in the file filename.info where filename is the name of the file 1188 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1189 file will be ignored if you use the -viewer_binary_skip_info option. 1190 1191 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1192 sets the default matrix type AIJ and sets the local and global sizes. 1193 If type and/or size is already set, then the same are used. 1194 1195 In parallel, each processor can load a subset of rows (or the 1196 entire matrix). This routine is especially useful when a large 1197 matrix is stored on disk and only part of it is desired on each 1198 processor. For example, a parallel solver may access only some of 1199 the rows from each processor. The algorithm used here reads 1200 relatively small blocks of data rather than reading the entire 1201 matrix and then subsetting it. 1202 1203 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1204 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1205 or the sequence like 1206 .vb 1207 `PetscViewer` v; 1208 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1209 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1210 `PetscViewerSetFromOptions`(v); 1211 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1212 `PetscViewerFileSetName`(v,"datafile"); 1213 .ve 1214 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1215 $ -viewer_type {binary,hdf5} 1216 1217 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1218 and src/mat/tutorials/ex10.c with the second approach. 1219 1220 Notes about the PETSc binary format: 1221 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1222 is read onto rank 0 and then shipped to its destination rank, one after another. 1223 Multiple objects, both matrices and vectors, can be stored within the same file. 1224 Their PetscObject name is ignored; they are loaded in the order of their storage. 1225 1226 Most users should not need to know the details of the binary storage 1227 format, since `MatLoad()` and `MatView()` completely hide these details. 1228 But for anyone who's interested, the standard binary matrix storage 1229 format is 1230 1231 $ PetscInt MAT_FILE_CLASSID 1232 $ PetscInt number of rows 1233 $ PetscInt number of columns 1234 $ PetscInt total number of nonzeros 1235 $ PetscInt *number nonzeros in each row 1236 $ PetscInt *column indices of all nonzeros (starting index is zero) 1237 $ PetscScalar *values of all nonzeros 1238 1239 PETSc automatically does the byte swapping for 1240 machines that store the bytes reversed, e.g. DEC alpha, freebsd, 1241 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary 1242 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1243 and `PetscBinaryWrite()` to see how this may be done. 1244 1245 Notes about the HDF5 (MATLAB MAT-File Version 7.3) format: 1246 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1247 Each processor's chunk is loaded independently by its owning rank. 1248 Multiple objects, both matrices and vectors, can be stored within the same file. 1249 They are looked up by their PetscObject name. 1250 1251 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1252 by default the same structure and naming of the AIJ arrays and column count 1253 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1254 $ save example.mat A b -v7.3 1255 can be directly read by this routine (see Reference 1 for details). 1256 Note that depending on your MATLAB version, this format might be a default, 1257 otherwise you can set it as default in Preferences. 1258 1259 Unless -nocompression flag is used to save the file in MATLAB, 1260 PETSc must be configured with ZLIB package. 1261 1262 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1263 1264 Current HDF5 (MAT-File) limitations: 1265 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices. 1266 1267 Corresponding `MatView()` is not yet implemented. 1268 1269 The loaded matrix is actually a transpose of the original one in MATLAB, 1270 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1271 With this format, matrix is automatically transposed by PETSc, 1272 unless the matrix is marked as SPD or symmetric 1273 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1274 1275 References: 1276 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1277 1278 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1279 @*/ 1280 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1281 { 1282 PetscBool flg; 1283 1284 PetscFunctionBegin; 1285 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1286 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1287 1288 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1289 1290 flg = PETSC_FALSE; 1291 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1292 if (flg) { 1293 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1294 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1295 } 1296 flg = PETSC_FALSE; 1297 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1298 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1299 1300 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1301 PetscUseTypeMethod(mat, load, viewer); 1302 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1303 PetscFunctionReturn(0); 1304 } 1305 1306 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1307 { 1308 Mat_Redundant *redund = *redundant; 1309 1310 PetscFunctionBegin; 1311 if (redund) { 1312 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1313 PetscCall(ISDestroy(&redund->isrow)); 1314 PetscCall(ISDestroy(&redund->iscol)); 1315 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1316 } else { 1317 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1318 PetscCall(PetscFree(redund->sbuf_j)); 1319 PetscCall(PetscFree(redund->sbuf_a)); 1320 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1321 PetscCall(PetscFree(redund->rbuf_j[i])); 1322 PetscCall(PetscFree(redund->rbuf_a[i])); 1323 } 1324 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1325 } 1326 1327 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1328 PetscCall(PetscFree(redund)); 1329 } 1330 PetscFunctionReturn(0); 1331 } 1332 1333 /*@C 1334 MatDestroy - Frees space taken by a matrix. 1335 1336 Collective on A 1337 1338 Input Parameter: 1339 . A - the matrix 1340 1341 Level: beginner 1342 1343 Developer Note: 1344 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1345 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1346 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1347 if changes are needed here. 1348 1349 .seealso: `Mat`, `MatCreate()` 1350 @*/ 1351 PetscErrorCode MatDestroy(Mat *A) 1352 { 1353 PetscFunctionBegin; 1354 if (!*A) PetscFunctionReturn(0); 1355 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1356 if (--((PetscObject)(*A))->refct > 0) { 1357 *A = NULL; 1358 PetscFunctionReturn(0); 1359 } 1360 1361 /* if memory was published with SAWs then destroy it */ 1362 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1363 PetscTryTypeMethod((*A), destroy); 1364 1365 PetscCall(PetscFree((*A)->factorprefix)); 1366 PetscCall(PetscFree((*A)->defaultvectype)); 1367 PetscCall(PetscFree((*A)->defaultrandtype)); 1368 PetscCall(PetscFree((*A)->bsizes)); 1369 PetscCall(PetscFree((*A)->solvertype)); 1370 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1371 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1372 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1373 PetscCall(MatProductClear(*A)); 1374 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1375 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1376 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1377 PetscCall(MatDestroy(&(*A)->schur)); 1378 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1379 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1380 PetscCall(PetscHeaderDestroy(A)); 1381 PetscFunctionReturn(0); 1382 } 1383 1384 /*@C 1385 MatSetValues - Inserts or adds a block of values into a matrix. 1386 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1387 MUST be called after all calls to `MatSetValues()` have been completed. 1388 1389 Not Collective 1390 1391 Input Parameters: 1392 + mat - the matrix 1393 . v - a logically two-dimensional array of values 1394 . m, idxm - the number of rows and their global indices 1395 . n, idxn - the number of columns and their global indices 1396 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1397 1398 Notes: 1399 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1400 `MatSetUp()` before using this routine 1401 1402 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1403 1404 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1405 options cannot be mixed without intervening calls to the assembly 1406 routines. 1407 1408 `MatSetValues()` uses 0-based row and column numbers in Fortran 1409 as well as in C. 1410 1411 Negative indices may be passed in idxm and idxn, these rows and columns are 1412 simply ignored. This allows easily inserting element stiffness matrices 1413 with homogeneous Dirchlet boundary conditions that you don't want represented 1414 in the matrix. 1415 1416 Efficiency Alert: 1417 The routine `MatSetValuesBlocked()` may offer much better efficiency 1418 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1419 1420 Level: beginner 1421 1422 Developer Note: 1423 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1424 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1425 1426 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1427 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1428 @*/ 1429 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1430 { 1431 PetscFunctionBeginHot; 1432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1433 PetscValidType(mat, 1); 1434 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1435 PetscValidIntPointer(idxm, 3); 1436 PetscValidIntPointer(idxn, 5); 1437 MatCheckPreallocated(mat, 1); 1438 1439 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1440 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1441 1442 if (PetscDefined(USE_DEBUG)) { 1443 PetscInt i, j; 1444 1445 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1446 for (i = 0; i < m; i++) { 1447 for (j = 0; j < n; j++) { 1448 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1449 #if defined(PETSC_USE_COMPLEX) 1450 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]); 1451 #else 1452 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]); 1453 #endif 1454 } 1455 } 1456 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); 1457 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); 1458 } 1459 1460 if (mat->assembled) { 1461 mat->was_assembled = PETSC_TRUE; 1462 mat->assembled = PETSC_FALSE; 1463 } 1464 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1465 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1466 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1467 PetscFunctionReturn(0); 1468 } 1469 1470 /*@C 1471 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1472 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1473 MUST be called after all calls to `MatSetValues()` have been completed. 1474 1475 Not Collective 1476 1477 Input Parameters: 1478 + mat - the matrix 1479 . v - a logically two-dimensional array of values 1480 . ism - the rows to provide 1481 . isn - the columns to provide 1482 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1483 1484 Notes: 1485 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1486 `MatSetUp()` before using this routine 1487 1488 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1489 1490 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1491 options cannot be mixed without intervening calls to the assembly 1492 routines. 1493 1494 MatSetValues() uses 0-based row and column numbers in Fortran 1495 as well as in C. 1496 1497 Negative indices may be passed in ism and isn, these rows and columns are 1498 simply ignored. This allows easily inserting element stiffness matrices 1499 with homogeneous Dirchlet boundary conditions that you don't want represented 1500 in the matrix. 1501 1502 Efficiency Alert: 1503 The routine `MatSetValuesBlocked()` may offer much better efficiency 1504 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1505 1506 Level: beginner 1507 1508 Developer Notes: 1509 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1510 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1511 1512 This is currently not optimized for any particular `ISType` 1513 1514 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1515 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1516 @*/ 1517 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1518 { 1519 PetscInt m, n; 1520 const PetscInt *rows, *cols; 1521 1522 PetscFunctionBeginHot; 1523 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1524 PetscCall(ISGetIndices(ism, &rows)); 1525 PetscCall(ISGetIndices(isn, &cols)); 1526 PetscCall(ISGetLocalSize(ism, &m)); 1527 PetscCall(ISGetLocalSize(isn, &n)); 1528 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1529 PetscCall(ISRestoreIndices(ism, &rows)); 1530 PetscCall(ISRestoreIndices(isn, &cols)); 1531 PetscFunctionReturn(0); 1532 } 1533 1534 /*@ 1535 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1536 values into a matrix 1537 1538 Not Collective 1539 1540 Input Parameters: 1541 + mat - the matrix 1542 . row - the (block) row to set 1543 - v - a logically two-dimensional array of values 1544 1545 Notes: 1546 By the values, v, are column-oriented (for the block version) and sorted 1547 1548 All the nonzeros in the row must be provided 1549 1550 The matrix must have previously had its column indices set 1551 1552 The row must belong to this process 1553 1554 Level: intermediate 1555 1556 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1557 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1558 @*/ 1559 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1560 { 1561 PetscInt globalrow; 1562 1563 PetscFunctionBegin; 1564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1565 PetscValidType(mat, 1); 1566 PetscValidScalarPointer(v, 3); 1567 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1568 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1569 PetscFunctionReturn(0); 1570 } 1571 1572 /*@ 1573 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1574 values into a matrix 1575 1576 Not Collective 1577 1578 Input Parameters: 1579 + mat - the matrix 1580 . row - the (block) row to set 1581 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1582 1583 Notes: 1584 The values, v, are column-oriented for the block version. 1585 1586 All the nonzeros in the row must be provided 1587 1588 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1589 1590 The row must belong to this process 1591 1592 Level: advanced 1593 1594 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1595 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1596 @*/ 1597 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1598 { 1599 PetscFunctionBeginHot; 1600 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1601 PetscValidType(mat, 1); 1602 MatCheckPreallocated(mat, 1); 1603 PetscValidScalarPointer(v, 3); 1604 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1605 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1606 mat->insertmode = INSERT_VALUES; 1607 1608 if (mat->assembled) { 1609 mat->was_assembled = PETSC_TRUE; 1610 mat->assembled = PETSC_FALSE; 1611 } 1612 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1613 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1614 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1615 PetscFunctionReturn(0); 1616 } 1617 1618 /*@ 1619 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1620 Using structured grid indexing 1621 1622 Not Collective 1623 1624 Input Parameters: 1625 + mat - the matrix 1626 . m - number of rows being entered 1627 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1628 . n - number of columns being entered 1629 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1630 . v - a logically two-dimensional array of values 1631 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1632 1633 Notes: 1634 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1635 1636 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1637 options cannot be mixed without intervening calls to the assembly 1638 routines. 1639 1640 The grid coordinates are across the entire grid, not just the local portion 1641 1642 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1643 as well as in C. 1644 1645 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1646 1647 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1648 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1649 1650 The columns and rows in the stencil passed in MUST be contained within the 1651 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1652 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1653 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1654 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1655 1656 In Fortran idxm and idxn should be declared as 1657 $ MatStencil idxm(4,m),idxn(4,n) 1658 and the values inserted using 1659 $ idxm(MatStencil_i,1) = i 1660 $ idxm(MatStencil_j,1) = j 1661 $ idxm(MatStencil_k,1) = k 1662 $ idxm(MatStencil_c,1) = c 1663 etc 1664 1665 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1666 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1667 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1668 `DM_BOUNDARY_PERIODIC` boundary type. 1669 1670 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 1671 a single value per point) you can skip filling those indices. 1672 1673 Inspired by the structured grid interface to the HYPRE package 1674 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1675 1676 Efficiency Alert: 1677 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1678 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1679 1680 Level: beginner 1681 1682 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1683 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1684 @*/ 1685 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1686 { 1687 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1688 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1689 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1690 1691 PetscFunctionBegin; 1692 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1693 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1694 PetscValidType(mat, 1); 1695 PetscValidPointer(idxm, 3); 1696 PetscValidPointer(idxn, 5); 1697 1698 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1699 jdxm = buf; 1700 jdxn = buf + m; 1701 } else { 1702 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1703 jdxm = bufm; 1704 jdxn = bufn; 1705 } 1706 for (i = 0; i < m; i++) { 1707 for (j = 0; j < 3 - sdim; j++) dxm++; 1708 tmp = *dxm++ - starts[0]; 1709 for (j = 0; j < dim - 1; j++) { 1710 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1711 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1712 } 1713 if (mat->stencil.noc) dxm++; 1714 jdxm[i] = tmp; 1715 } 1716 for (i = 0; i < n; i++) { 1717 for (j = 0; j < 3 - sdim; j++) dxn++; 1718 tmp = *dxn++ - starts[0]; 1719 for (j = 0; j < dim - 1; j++) { 1720 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1721 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1722 } 1723 if (mat->stencil.noc) dxn++; 1724 jdxn[i] = tmp; 1725 } 1726 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1727 PetscCall(PetscFree2(bufm, bufn)); 1728 PetscFunctionReturn(0); 1729 } 1730 1731 /*@ 1732 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1733 Using structured grid indexing 1734 1735 Not Collective 1736 1737 Input Parameters: 1738 + mat - the matrix 1739 . m - number of rows being entered 1740 . idxm - grid coordinates for matrix rows being entered 1741 . n - number of columns being entered 1742 . idxn - grid coordinates for matrix columns being entered 1743 . v - a logically two-dimensional array of values 1744 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1745 1746 Notes: 1747 By default the values, v, are row-oriented and unsorted. 1748 See `MatSetOption()` for other options. 1749 1750 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1751 options cannot be mixed without intervening calls to the assembly 1752 routines. 1753 1754 The grid coordinates are across the entire grid, not just the local portion 1755 1756 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1757 as well as in C. 1758 1759 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1760 1761 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1762 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1763 1764 The columns and rows in the stencil passed in MUST be contained within the 1765 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1766 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1767 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1768 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1769 1770 In Fortran idxm and idxn should be declared as 1771 $ MatStencil idxm(4,m),idxn(4,n) 1772 and the values inserted using 1773 $ idxm(MatStencil_i,1) = i 1774 $ idxm(MatStencil_j,1) = j 1775 $ idxm(MatStencil_k,1) = k 1776 etc 1777 1778 Negative indices may be passed in idxm and idxn, these rows and columns are 1779 simply ignored. This allows easily inserting element stiffness matrices 1780 with homogeneous Dirchlet boundary conditions that you don't want represented 1781 in the matrix. 1782 1783 Inspired by the structured grid interface to the HYPRE package 1784 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1785 1786 Level: beginner 1787 1788 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1789 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1790 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1791 @*/ 1792 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1793 { 1794 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1795 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1796 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1797 1798 PetscFunctionBegin; 1799 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1800 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1801 PetscValidType(mat, 1); 1802 PetscValidPointer(idxm, 3); 1803 PetscValidPointer(idxn, 5); 1804 PetscValidScalarPointer(v, 6); 1805 1806 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1807 jdxm = buf; 1808 jdxn = buf + m; 1809 } else { 1810 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1811 jdxm = bufm; 1812 jdxn = bufn; 1813 } 1814 for (i = 0; i < m; i++) { 1815 for (j = 0; j < 3 - sdim; j++) dxm++; 1816 tmp = *dxm++ - starts[0]; 1817 for (j = 0; j < sdim - 1; j++) { 1818 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1819 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1820 } 1821 dxm++; 1822 jdxm[i] = tmp; 1823 } 1824 for (i = 0; i < n; i++) { 1825 for (j = 0; j < 3 - sdim; j++) dxn++; 1826 tmp = *dxn++ - starts[0]; 1827 for (j = 0; j < sdim - 1; j++) { 1828 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1829 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1830 } 1831 dxn++; 1832 jdxn[i] = tmp; 1833 } 1834 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1835 PetscCall(PetscFree2(bufm, bufn)); 1836 PetscFunctionReturn(0); 1837 } 1838 1839 /*@ 1840 MatSetStencil - Sets the grid information for setting values into a matrix via 1841 `MatSetValuesStencil()` 1842 1843 Not Collective 1844 1845 Input Parameters: 1846 + mat - the matrix 1847 . dim - dimension of the grid 1, 2, or 3 1848 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1849 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1850 - dof - number of degrees of freedom per node 1851 1852 Notes: 1853 Inspired by the structured grid interface to the HYPRE package 1854 (www.llnl.gov/CASC/hyper) 1855 1856 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1857 user. 1858 1859 Level: beginner 1860 1861 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1862 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1863 @*/ 1864 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1865 { 1866 PetscFunctionBegin; 1867 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1868 PetscValidIntPointer(dims, 3); 1869 PetscValidIntPointer(starts, 4); 1870 1871 mat->stencil.dim = dim + (dof > 1); 1872 for (PetscInt i = 0; i < dim; i++) { 1873 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1874 mat->stencil.starts[i] = starts[dim - i - 1]; 1875 } 1876 mat->stencil.dims[dim] = dof; 1877 mat->stencil.starts[dim] = 0; 1878 mat->stencil.noc = (PetscBool)(dof == 1); 1879 PetscFunctionReturn(0); 1880 } 1881 1882 /*@C 1883 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1884 1885 Not Collective 1886 1887 Input Parameters: 1888 + mat - the matrix 1889 . v - a logically two-dimensional array of values 1890 . m, idxm - the number of block rows and their global block indices 1891 . n, idxn - the number of block columns and their global block indices 1892 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1893 1894 Notes: 1895 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1896 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1897 1898 The m and n count the NUMBER of blocks in the row direction and column direction, 1899 NOT the total number of rows/columns; for example, if the block size is 2 and 1900 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1901 The values in idxm would be 1 2; that is the first index for each block divided by 1902 the block size. 1903 1904 Note that you must call `MatSetBlockSize()` when constructing this matrix (before 1905 preallocating it). 1906 1907 By default the values, v, are row-oriented, so the layout of 1908 v is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1909 1910 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1911 options cannot be mixed without intervening calls to the assembly 1912 routines. 1913 1914 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1915 as well as in C. 1916 1917 Negative indices may be passed in idxm and idxn, these rows and columns are 1918 simply ignored. This allows easily inserting element stiffness matrices 1919 with homogeneous Dirchlet boundary conditions that you don't want represented 1920 in the matrix. 1921 1922 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1923 internal searching must be done to determine where to place the 1924 data in the matrix storage space. By instead inserting blocks of 1925 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1926 reduced. 1927 1928 Example: 1929 $ Suppose m=n=2 and block size(bs) = 2 The array is 1930 $ 1931 $ 1 2 | 3 4 1932 $ 5 6 | 7 8 1933 $ - - - | - - - 1934 $ 9 10 | 11 12 1935 $ 13 14 | 15 16 1936 $ 1937 $ v[] should be passed in like 1938 $ v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1939 $ 1940 $ If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1941 $ v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1942 1943 Level: intermediate 1944 1945 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1946 @*/ 1947 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1948 { 1949 PetscFunctionBeginHot; 1950 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1951 PetscValidType(mat, 1); 1952 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1953 PetscValidIntPointer(idxm, 3); 1954 PetscValidIntPointer(idxn, 5); 1955 MatCheckPreallocated(mat, 1); 1956 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1957 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1958 if (PetscDefined(USE_DEBUG)) { 1959 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1960 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1961 } 1962 if (PetscDefined(USE_DEBUG)) { 1963 PetscInt rbs, cbs, M, N, i; 1964 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1965 PetscCall(MatGetSize(mat, &M, &N)); 1966 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); 1967 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); 1968 } 1969 if (mat->assembled) { 1970 mat->was_assembled = PETSC_TRUE; 1971 mat->assembled = PETSC_FALSE; 1972 } 1973 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1974 if (mat->ops->setvaluesblocked) { 1975 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1976 } else { 1977 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1978 PetscInt i, j, bs, cbs; 1979 1980 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1981 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1982 iidxm = buf; 1983 iidxn = buf + m * bs; 1984 } else { 1985 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 1986 iidxm = bufr; 1987 iidxn = bufc; 1988 } 1989 for (i = 0; i < m; i++) { 1990 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 1991 } 1992 if (m != n || bs != cbs || idxm != idxn) { 1993 for (i = 0; i < n; i++) { 1994 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 1995 } 1996 } else iidxn = iidxm; 1997 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 1998 PetscCall(PetscFree2(bufr, bufc)); 1999 } 2000 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2001 PetscFunctionReturn(0); 2002 } 2003 2004 /*@C 2005 MatGetValues - Gets a block of local values from a matrix. 2006 2007 Not Collective; can only return values that are owned by the give process 2008 2009 Input Parameters: 2010 + mat - the matrix 2011 . v - a logically two-dimensional array for storing the values 2012 . m, idxm - the number of rows and their global indices 2013 - n, idxn - the number of columns and their global indices 2014 2015 Notes: 2016 The user must allocate space (m*n `PetscScalar`s) for the values, v. 2017 The values, v, are then returned in a row-oriented format, 2018 analogous to that used by default in `MatSetValues()`. 2019 2020 `MatGetValues()` uses 0-based row and column numbers in 2021 Fortran as well as in C. 2022 2023 `MatGetValues()` requires that the matrix has been assembled 2024 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2025 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2026 without intermediate matrix assembly. 2027 2028 Negative row or column indices will be ignored and those locations in v[] will be 2029 left unchanged. 2030 2031 For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank. 2032 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2033 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2034 2035 Level: advanced 2036 2037 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2038 @*/ 2039 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2040 { 2041 PetscFunctionBegin; 2042 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2043 PetscValidType(mat, 1); 2044 if (!m || !n) PetscFunctionReturn(0); 2045 PetscValidIntPointer(idxm, 3); 2046 PetscValidIntPointer(idxn, 5); 2047 PetscValidScalarPointer(v, 6); 2048 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2049 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2050 MatCheckPreallocated(mat, 1); 2051 2052 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2053 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2054 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2055 PetscFunctionReturn(0); 2056 } 2057 2058 /*@C 2059 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2060 defined previously by `MatSetLocalToGlobalMapping()` 2061 2062 Not Collective 2063 2064 Input Parameters: 2065 + mat - the matrix 2066 . nrow, irow - number of rows and their local indices 2067 - ncol, icol - number of columns and their local indices 2068 2069 Output Parameter: 2070 . y - a logically two-dimensional array of values 2071 2072 Notes: 2073 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2074 2075 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, 2076 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2077 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2078 with `MatSetLocalToGlobalMapping()`. 2079 2080 Developer Note: 2081 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2082 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2083 2084 Level: advanced 2085 2086 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2087 `MatSetValuesLocal()`, `MatGetValues()` 2088 @*/ 2089 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2090 { 2091 PetscFunctionBeginHot; 2092 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2093 PetscValidType(mat, 1); 2094 MatCheckPreallocated(mat, 1); 2095 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */ 2096 PetscValidIntPointer(irow, 3); 2097 PetscValidIntPointer(icol, 5); 2098 if (PetscDefined(USE_DEBUG)) { 2099 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2100 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2101 } 2102 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2103 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2104 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2105 else { 2106 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2107 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2108 irowm = buf; 2109 icolm = buf + nrow; 2110 } else { 2111 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2112 irowm = bufr; 2113 icolm = bufc; 2114 } 2115 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2116 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2117 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2118 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2119 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2120 PetscCall(PetscFree2(bufr, bufc)); 2121 } 2122 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2123 PetscFunctionReturn(0); 2124 } 2125 2126 /*@ 2127 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2128 the same size. Currently, this can only be called once and creates the given matrix. 2129 2130 Not Collective 2131 2132 Input Parameters: 2133 + mat - the matrix 2134 . nb - the number of blocks 2135 . bs - the number of rows (and columns) in each block 2136 . rows - a concatenation of the rows for each block 2137 - v - a concatenation of logically two-dimensional arrays of values 2138 2139 Note: 2140 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2141 2142 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2143 2144 Level: advanced 2145 2146 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2147 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2148 @*/ 2149 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2150 { 2151 PetscFunctionBegin; 2152 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2153 PetscValidType(mat, 1); 2154 PetscValidIntPointer(rows, 4); 2155 PetscValidScalarPointer(v, 5); 2156 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2157 2158 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2159 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2160 else { 2161 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2162 } 2163 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2164 PetscFunctionReturn(0); 2165 } 2166 2167 /*@ 2168 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2169 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2170 using a local (per-processor) numbering. 2171 2172 Not Collective 2173 2174 Input Parameters: 2175 + x - the matrix 2176 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2177 - cmapping - column mapping 2178 2179 Level: intermediate 2180 2181 Note: 2182 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2183 2184 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2185 @*/ 2186 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2187 { 2188 PetscFunctionBegin; 2189 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2190 PetscValidType(x, 1); 2191 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2192 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2193 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2194 else { 2195 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2196 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2197 } 2198 PetscFunctionReturn(0); 2199 } 2200 2201 /*@ 2202 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2203 2204 Not Collective 2205 2206 Input Parameter: 2207 . A - the matrix 2208 2209 Output Parameters: 2210 + rmapping - row mapping 2211 - cmapping - column mapping 2212 2213 Level: advanced 2214 2215 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2216 @*/ 2217 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2218 { 2219 PetscFunctionBegin; 2220 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2221 PetscValidType(A, 1); 2222 if (rmapping) { 2223 PetscValidPointer(rmapping, 2); 2224 *rmapping = A->rmap->mapping; 2225 } 2226 if (cmapping) { 2227 PetscValidPointer(cmapping, 3); 2228 *cmapping = A->cmap->mapping; 2229 } 2230 PetscFunctionReturn(0); 2231 } 2232 2233 /*@ 2234 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2235 2236 Logically Collective on A 2237 2238 Input Parameters: 2239 + A - the matrix 2240 . rmap - row layout 2241 - cmap - column layout 2242 2243 Level: advanced 2244 2245 Note: 2246 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2247 2248 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2249 @*/ 2250 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2251 { 2252 PetscFunctionBegin; 2253 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2254 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2255 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2256 PetscFunctionReturn(0); 2257 } 2258 2259 /*@ 2260 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2261 2262 Not Collective 2263 2264 Input Parameter: 2265 . A - the matrix 2266 2267 Output Parameters: 2268 + rmap - row layout 2269 - cmap - column layout 2270 2271 Level: advanced 2272 2273 .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2274 @*/ 2275 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2276 { 2277 PetscFunctionBegin; 2278 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2279 PetscValidType(A, 1); 2280 if (rmap) { 2281 PetscValidPointer(rmap, 2); 2282 *rmap = A->rmap; 2283 } 2284 if (cmap) { 2285 PetscValidPointer(cmap, 3); 2286 *cmap = A->cmap; 2287 } 2288 PetscFunctionReturn(0); 2289 } 2290 2291 /*@C 2292 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2293 using a local numbering of the nodes. 2294 2295 Not Collective 2296 2297 Input Parameters: 2298 + mat - the matrix 2299 . nrow, irow - number of rows and their local indices 2300 . ncol, icol - number of columns and their local indices 2301 . y - a logically two-dimensional array of values 2302 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2303 2304 Notes: 2305 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2306 `MatSetUp()` before using this routine 2307 2308 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2309 2310 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2311 options cannot be mixed without intervening calls to the assembly 2312 routines. 2313 2314 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2315 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2316 2317 Level: intermediate 2318 2319 Developer Note: 2320 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2321 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2322 2323 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2324 `MatGetValuesLocal()` 2325 @*/ 2326 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2327 { 2328 PetscFunctionBeginHot; 2329 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2330 PetscValidType(mat, 1); 2331 MatCheckPreallocated(mat, 1); 2332 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2333 PetscValidIntPointer(irow, 3); 2334 PetscValidIntPointer(icol, 5); 2335 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2336 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2337 if (PetscDefined(USE_DEBUG)) { 2338 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2339 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2340 } 2341 2342 if (mat->assembled) { 2343 mat->was_assembled = PETSC_TRUE; 2344 mat->assembled = PETSC_FALSE; 2345 } 2346 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2347 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2348 else { 2349 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2350 const PetscInt *irowm, *icolm; 2351 2352 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2353 bufr = buf; 2354 bufc = buf + nrow; 2355 irowm = bufr; 2356 icolm = bufc; 2357 } else { 2358 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2359 irowm = bufr; 2360 icolm = bufc; 2361 } 2362 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2363 else irowm = irow; 2364 if (mat->cmap->mapping) { 2365 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2366 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2367 } else icolm = irowm; 2368 } else icolm = icol; 2369 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2370 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2371 } 2372 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2373 PetscFunctionReturn(0); 2374 } 2375 2376 /*@C 2377 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2378 using a local ordering of the nodes a block at a time. 2379 2380 Not Collective 2381 2382 Input Parameters: 2383 + x - the matrix 2384 . nrow, irow - number of rows and their local indices 2385 . ncol, icol - number of columns and their local indices 2386 . y - a logically two-dimensional array of values 2387 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2388 2389 Notes: 2390 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2391 `MatSetUp()` before using this routine 2392 2393 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2394 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2395 2396 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2397 options cannot be mixed without intervening calls to the assembly 2398 routines. 2399 2400 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2401 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2402 2403 Level: intermediate 2404 2405 Developer Note: 2406 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2407 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2408 2409 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2410 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2411 @*/ 2412 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2413 { 2414 PetscFunctionBeginHot; 2415 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2416 PetscValidType(mat, 1); 2417 MatCheckPreallocated(mat, 1); 2418 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2419 PetscValidIntPointer(irow, 3); 2420 PetscValidIntPointer(icol, 5); 2421 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2422 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2423 if (PetscDefined(USE_DEBUG)) { 2424 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2425 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); 2426 } 2427 2428 if (mat->assembled) { 2429 mat->was_assembled = PETSC_TRUE; 2430 mat->assembled = PETSC_FALSE; 2431 } 2432 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2433 PetscInt irbs, rbs; 2434 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2435 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2436 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2437 } 2438 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2439 PetscInt icbs, cbs; 2440 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2441 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2442 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2443 } 2444 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2445 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2446 else { 2447 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2448 const PetscInt *irowm, *icolm; 2449 2450 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2451 bufr = buf; 2452 bufc = buf + nrow; 2453 irowm = bufr; 2454 icolm = bufc; 2455 } else { 2456 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2457 irowm = bufr; 2458 icolm = bufc; 2459 } 2460 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2461 else irowm = irow; 2462 if (mat->cmap->mapping) { 2463 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2464 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2465 } else icolm = irowm; 2466 } else icolm = icol; 2467 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2468 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2469 } 2470 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2471 PetscFunctionReturn(0); 2472 } 2473 2474 /*@ 2475 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2476 2477 Collective on mat 2478 2479 Input Parameters: 2480 + mat - the matrix 2481 - x - the vector to be multiplied 2482 2483 Output Parameters: 2484 . y - the result 2485 2486 Note: 2487 The vectors x and y cannot be the same. I.e., one cannot 2488 call `MatMultDiagonalBlock`(A,y,y). 2489 2490 Level: developer 2491 2492 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2493 @*/ 2494 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2495 { 2496 PetscFunctionBegin; 2497 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2498 PetscValidType(mat, 1); 2499 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2500 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2501 2502 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2503 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2504 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2505 MatCheckPreallocated(mat, 1); 2506 2507 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2508 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2509 PetscFunctionReturn(0); 2510 } 2511 2512 /* --------------------------------------------------------*/ 2513 /*@ 2514 MatMult - Computes the matrix-vector product, y = Ax. 2515 2516 Neighbor-wise Collective on mat 2517 2518 Input Parameters: 2519 + mat - the matrix 2520 - x - the vector to be multiplied 2521 2522 Output Parameters: 2523 . y - the result 2524 2525 Note: 2526 The vectors x and y cannot be the same. I.e., one cannot 2527 call `MatMult`(A,y,y). 2528 2529 Level: beginner 2530 2531 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2532 @*/ 2533 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2534 { 2535 PetscFunctionBegin; 2536 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2537 PetscValidType(mat, 1); 2538 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2539 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2540 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2541 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2542 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2543 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); 2544 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); 2545 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); 2546 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); 2547 PetscCall(VecSetErrorIfLocked(y, 3)); 2548 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2549 MatCheckPreallocated(mat, 1); 2550 2551 PetscCall(VecLockReadPush(x)); 2552 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2553 PetscUseTypeMethod(mat, mult, x, y); 2554 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2555 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2556 PetscCall(VecLockReadPop(x)); 2557 PetscFunctionReturn(0); 2558 } 2559 2560 /*@ 2561 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2562 2563 Neighbor-wise Collective on mat 2564 2565 Input Parameters: 2566 + mat - the matrix 2567 - x - the vector to be multiplied 2568 2569 Output Parameters: 2570 . y - the result 2571 2572 Notes: 2573 The vectors x and y cannot be the same. I.e., one cannot 2574 call `MatMultTranspose`(A,y,y). 2575 2576 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2577 use `MatMultHermitianTranspose()` 2578 2579 Level: beginner 2580 2581 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2582 @*/ 2583 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2584 { 2585 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2586 2587 PetscFunctionBegin; 2588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2589 PetscValidType(mat, 1); 2590 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2591 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2592 2593 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2594 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2595 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2596 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); 2597 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); 2598 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); 2599 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); 2600 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2601 MatCheckPreallocated(mat, 1); 2602 2603 if (!mat->ops->multtranspose) { 2604 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2605 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); 2606 } else op = mat->ops->multtranspose; 2607 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2608 PetscCall(VecLockReadPush(x)); 2609 PetscCall((*op)(mat, x, y)); 2610 PetscCall(VecLockReadPop(x)); 2611 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2612 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2613 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2614 PetscFunctionReturn(0); 2615 } 2616 2617 /*@ 2618 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2619 2620 Neighbor-wise Collective on mat 2621 2622 Input Parameters: 2623 + mat - the matrix 2624 - x - the vector to be multilplied 2625 2626 Output Parameters: 2627 . y - the result 2628 2629 Notes: 2630 The vectors x and y cannot be the same. I.e., one cannot 2631 call `MatMultHermitianTranspose`(A,y,y). 2632 2633 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2634 2635 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2636 2637 Level: beginner 2638 2639 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2640 @*/ 2641 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2642 { 2643 PetscFunctionBegin; 2644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2645 PetscValidType(mat, 1); 2646 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2647 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2648 2649 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2650 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2651 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2652 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); 2653 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); 2654 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); 2655 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); 2656 MatCheckPreallocated(mat, 1); 2657 2658 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2659 #if defined(PETSC_USE_COMPLEX) 2660 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2661 PetscCall(VecLockReadPush(x)); 2662 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2663 else PetscUseTypeMethod(mat, mult, x, y); 2664 PetscCall(VecLockReadPop(x)); 2665 } else { 2666 Vec w; 2667 PetscCall(VecDuplicate(x, &w)); 2668 PetscCall(VecCopy(x, w)); 2669 PetscCall(VecConjugate(w)); 2670 PetscCall(MatMultTranspose(mat, w, y)); 2671 PetscCall(VecDestroy(&w)); 2672 PetscCall(VecConjugate(y)); 2673 } 2674 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2675 #else 2676 PetscCall(MatMultTranspose(mat, x, y)); 2677 #endif 2678 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2679 PetscFunctionReturn(0); 2680 } 2681 2682 /*@ 2683 MatMultAdd - Computes v3 = v2 + A * v1. 2684 2685 Neighbor-wise Collective on mat 2686 2687 Input Parameters: 2688 + mat - the matrix 2689 - v1, v2 - the vectors 2690 2691 Output Parameters: 2692 . v3 - the result 2693 2694 Note: 2695 The vectors v1 and v3 cannot be the same. I.e., one cannot 2696 call `MatMultAdd`(A,v1,v2,v1). 2697 2698 Level: beginner 2699 2700 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2701 @*/ 2702 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2703 { 2704 PetscFunctionBegin; 2705 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2706 PetscValidType(mat, 1); 2707 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2708 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2709 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2710 2711 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2712 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2713 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); 2714 /* 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); 2715 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); */ 2716 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); 2717 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); 2718 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2719 MatCheckPreallocated(mat, 1); 2720 2721 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2722 PetscCall(VecLockReadPush(v1)); 2723 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2724 PetscCall(VecLockReadPop(v1)); 2725 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2726 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2727 PetscFunctionReturn(0); 2728 } 2729 2730 /*@ 2731 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2732 2733 Neighbor-wise Collective on mat 2734 2735 Input Parameters: 2736 + mat - the matrix 2737 - v1, v2 - the vectors 2738 2739 Output Parameters: 2740 . v3 - the result 2741 2742 Note: 2743 The vectors v1 and v3 cannot be the same. I.e., one cannot 2744 call `MatMultTransposeAdd`(A,v1,v2,v1). 2745 2746 Level: beginner 2747 2748 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2749 @*/ 2750 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2751 { 2752 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2753 2754 PetscFunctionBegin; 2755 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2756 PetscValidType(mat, 1); 2757 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2758 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2759 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2760 2761 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2762 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2763 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); 2764 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); 2765 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); 2766 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2767 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2768 MatCheckPreallocated(mat, 1); 2769 2770 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2771 PetscCall(VecLockReadPush(v1)); 2772 PetscCall((*op)(mat, v1, v2, v3)); 2773 PetscCall(VecLockReadPop(v1)); 2774 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2775 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2776 PetscFunctionReturn(0); 2777 } 2778 2779 /*@ 2780 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2781 2782 Neighbor-wise Collective on mat 2783 2784 Input Parameters: 2785 + mat - the matrix 2786 - v1, v2 - the vectors 2787 2788 Output Parameters: 2789 . v3 - the result 2790 2791 Note: 2792 The vectors v1 and v3 cannot be the same. I.e., one cannot 2793 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2794 2795 Level: beginner 2796 2797 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2798 @*/ 2799 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2800 { 2801 PetscFunctionBegin; 2802 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2803 PetscValidType(mat, 1); 2804 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2805 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2806 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2807 2808 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2809 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2810 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2811 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); 2812 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); 2813 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); 2814 MatCheckPreallocated(mat, 1); 2815 2816 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2817 PetscCall(VecLockReadPush(v1)); 2818 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2819 else { 2820 Vec w, z; 2821 PetscCall(VecDuplicate(v1, &w)); 2822 PetscCall(VecCopy(v1, w)); 2823 PetscCall(VecConjugate(w)); 2824 PetscCall(VecDuplicate(v3, &z)); 2825 PetscCall(MatMultTranspose(mat, w, z)); 2826 PetscCall(VecDestroy(&w)); 2827 PetscCall(VecConjugate(z)); 2828 if (v2 != v3) { 2829 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2830 } else { 2831 PetscCall(VecAXPY(v3, 1.0, z)); 2832 } 2833 PetscCall(VecDestroy(&z)); 2834 } 2835 PetscCall(VecLockReadPop(v1)); 2836 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2837 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2838 PetscFunctionReturn(0); 2839 } 2840 2841 /*@C 2842 MatGetFactorType - gets the type of factorization it is 2843 2844 Not Collective 2845 2846 Input Parameters: 2847 . mat - the matrix 2848 2849 Output Parameters: 2850 . 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` 2851 2852 Level: intermediate 2853 2854 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2855 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2856 @*/ 2857 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2858 { 2859 PetscFunctionBegin; 2860 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2861 PetscValidType(mat, 1); 2862 PetscValidPointer(t, 2); 2863 *t = mat->factortype; 2864 PetscFunctionReturn(0); 2865 } 2866 2867 /*@C 2868 MatSetFactorType - sets the type of factorization it is 2869 2870 Logically Collective on mat 2871 2872 Input Parameters: 2873 + mat - the matrix 2874 - 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` 2875 2876 Level: intermediate 2877 2878 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2879 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2880 @*/ 2881 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2882 { 2883 PetscFunctionBegin; 2884 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2885 PetscValidType(mat, 1); 2886 mat->factortype = t; 2887 PetscFunctionReturn(0); 2888 } 2889 2890 /* ------------------------------------------------------------*/ 2891 /*@C 2892 MatGetInfo - Returns information about matrix storage (number of 2893 nonzeros, memory, etc.). 2894 2895 Collective on mat if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2896 2897 Input Parameter: 2898 . mat - the matrix 2899 2900 Output Parameters: 2901 + flag - flag indicating the type of parameters to be returned 2902 (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, 2903 MAT_GLOBAL_SUM - sum over all processors) 2904 - info - matrix information context 2905 2906 Notes: 2907 The `MatInfo` context contains a variety of matrix data, including 2908 number of nonzeros allocated and used, number of mallocs during 2909 matrix assembly, etc. Additional information for factored matrices 2910 is provided (such as the fill ratio, number of mallocs during 2911 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2912 when using the runtime options 2913 $ -info -mat_view ::ascii_info 2914 2915 Example for C/C++ Users: 2916 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2917 data within the MatInfo context. For example, 2918 .vb 2919 MatInfo info; 2920 Mat A; 2921 double mal, nz_a, nz_u; 2922 2923 MatGetInfo(A,MAT_LOCAL,&info); 2924 mal = info.mallocs; 2925 nz_a = info.nz_allocated; 2926 .ve 2927 2928 Example for Fortran Users: 2929 Fortran users should declare info as a double precision 2930 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2931 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2932 a complete list of parameter names. 2933 .vb 2934 double precision info(MAT_INFO_SIZE) 2935 double precision mal, nz_a 2936 Mat A 2937 integer ierr 2938 2939 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2940 mal = info(MAT_INFO_MALLOCS) 2941 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2942 .ve 2943 2944 Level: intermediate 2945 2946 Developer Note: fortran interface is not autogenerated as the f90 2947 interface definition cannot be generated correctly [due to MatInfo] 2948 2949 .seealso: `MatInfo`, `MatStashGetInfo()` 2950 @*/ 2951 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2952 { 2953 PetscFunctionBegin; 2954 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2955 PetscValidType(mat, 1); 2956 PetscValidPointer(info, 3); 2957 MatCheckPreallocated(mat, 1); 2958 PetscUseTypeMethod(mat, getinfo, flag, info); 2959 PetscFunctionReturn(0); 2960 } 2961 2962 /* 2963 This is used by external packages where it is not easy to get the info from the actual 2964 matrix factorization. 2965 */ 2966 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2967 { 2968 PetscFunctionBegin; 2969 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2970 PetscFunctionReturn(0); 2971 } 2972 2973 /* ----------------------------------------------------------*/ 2974 2975 /*@C 2976 MatLUFactor - Performs in-place LU factorization of matrix. 2977 2978 Collective on mat 2979 2980 Input Parameters: 2981 + mat - the matrix 2982 . row - row permutation 2983 . col - column permutation 2984 - info - options for factorization, includes 2985 $ fill - expected fill as ratio of original fill. 2986 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 2987 $ Run with the option -info to determine an optimal value to use 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 This changes the state of the matrix to a factored matrix; it cannot be used 2995 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 2996 2997 This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 2998 when not using `KSP`. 2999 3000 Level: developer 3001 3002 Developer Note: 3003 The Fortran interface is not autogenerated as the f90 3004 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3005 3006 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3007 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3008 @*/ 3009 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3010 { 3011 MatFactorInfo tinfo; 3012 3013 PetscFunctionBegin; 3014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3015 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3016 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3017 if (info) PetscValidPointer(info, 4); 3018 PetscValidType(mat, 1); 3019 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3020 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3021 MatCheckPreallocated(mat, 1); 3022 if (!info) { 3023 PetscCall(MatFactorInfoInitialize(&tinfo)); 3024 info = &tinfo; 3025 } 3026 3027 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3028 PetscUseTypeMethod(mat, lufactor, row, col, info); 3029 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3030 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3031 PetscFunctionReturn(0); 3032 } 3033 3034 /*@C 3035 MatILUFactor - Performs in-place ILU factorization of matrix. 3036 3037 Collective on mat 3038 3039 Input Parameters: 3040 + mat - the matrix 3041 . row - row permutation 3042 . col - column permutation 3043 - info - structure containing 3044 $ levels - number of levels of fill. 3045 $ expected fill - as ratio of original fill. 3046 $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3047 missing diagonal entries) 3048 3049 Notes: 3050 Most users should employ the `KSP` interface for linear solvers 3051 instead of working directly with matrix algebra routines such as this. 3052 See, e.g., `KSPCreate()`. 3053 3054 Probably really in-place only when level of fill is zero, otherwise allocates 3055 new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3056 when not using `KSP`. 3057 3058 Level: developer 3059 3060 Developer Note: 3061 The Fortran interface is not autogenerated as the f90 3062 interface definition cannot be generated correctly [due to MatFactorInfo] 3063 3064 .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3065 @*/ 3066 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3067 { 3068 PetscFunctionBegin; 3069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3070 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3071 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3072 PetscValidPointer(info, 4); 3073 PetscValidType(mat, 1); 3074 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3075 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3076 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3077 MatCheckPreallocated(mat, 1); 3078 3079 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3080 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3081 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3082 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3083 PetscFunctionReturn(0); 3084 } 3085 3086 /*@C 3087 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3088 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3089 3090 Collective on fact 3091 3092 Input Parameters: 3093 + fact - the factor matrix obtained with `MatGetFactor()` 3094 . mat - the matrix 3095 . row, col - row and column permutations 3096 - info - options for factorization, includes 3097 .vb 3098 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3099 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3100 .ve 3101 3102 Notes: 3103 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3104 3105 Most users should employ the simplified `KSP` interface for linear solvers 3106 instead of working directly with matrix algebra routines such as this. 3107 See, e.g., `KSPCreate()`. 3108 3109 Level: developer 3110 3111 Developer Note: 3112 The Fortran interface is not autogenerated as the f90 3113 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3114 3115 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3116 @*/ 3117 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3118 { 3119 MatFactorInfo tinfo; 3120 3121 PetscFunctionBegin; 3122 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3123 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3124 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3125 if (info) PetscValidPointer(info, 5); 3126 PetscValidType(mat, 2); 3127 PetscValidPointer(fact, 1); 3128 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3129 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3130 if (!(fact)->ops->lufactorsymbolic) { 3131 MatSolverType stype; 3132 PetscCall(MatFactorGetSolverType(fact, &stype)); 3133 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype); 3134 } 3135 MatCheckPreallocated(mat, 2); 3136 if (!info) { 3137 PetscCall(MatFactorInfoInitialize(&tinfo)); 3138 info = &tinfo; 3139 } 3140 3141 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3142 PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info)); 3143 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3144 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3145 PetscFunctionReturn(0); 3146 } 3147 3148 /*@C 3149 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3150 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3151 3152 Collective on fact 3153 3154 Input Parameters: 3155 + fact - the factor matrix obtained with `MatGetFactor()` 3156 . mat - the matrix 3157 - info - options for factorization 3158 3159 Notes: 3160 See `MatLUFactor()` for in-place factorization. See 3161 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3162 3163 Most users should employ the `KSP` interface for linear solvers 3164 instead of working directly with matrix algebra routines such as this. 3165 See, e.g., `KSPCreate()`. 3166 3167 Level: developer 3168 3169 Developer Note: 3170 The Fortran interface is not autogenerated as the f90 3171 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3172 3173 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3174 @*/ 3175 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3176 { 3177 MatFactorInfo tinfo; 3178 3179 PetscFunctionBegin; 3180 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3181 PetscValidType(mat, 2); 3182 PetscValidPointer(fact, 1); 3183 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3184 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3185 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, 3186 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3187 3188 PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name); 3189 MatCheckPreallocated(mat, 2); 3190 if (!info) { 3191 PetscCall(MatFactorInfoInitialize(&tinfo)); 3192 info = &tinfo; 3193 } 3194 3195 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3196 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3197 PetscCall((fact->ops->lufactornumeric)(fact, mat, info)); 3198 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3199 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3200 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3201 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3202 PetscFunctionReturn(0); 3203 } 3204 3205 /*@C 3206 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3207 symmetric matrix. 3208 3209 Collective on mat 3210 3211 Input Parameters: 3212 + mat - the matrix 3213 . perm - row and column permutations 3214 - f - expected fill as ratio of original fill 3215 3216 Notes: 3217 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3218 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3219 3220 Most users should employ the `KSP` interface for linear solvers 3221 instead of working directly with matrix algebra routines such as this. 3222 See, e.g., `KSPCreate()`. 3223 3224 Level: developer 3225 3226 Developer Note: 3227 The Fortran interface is not autogenerated as the f90 3228 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3229 3230 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3231 `MatGetOrdering()` 3232 @*/ 3233 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3234 { 3235 MatFactorInfo tinfo; 3236 3237 PetscFunctionBegin; 3238 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3239 PetscValidType(mat, 1); 3240 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3241 if (info) PetscValidPointer(info, 3); 3242 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3243 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3244 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3245 MatCheckPreallocated(mat, 1); 3246 if (!info) { 3247 PetscCall(MatFactorInfoInitialize(&tinfo)); 3248 info = &tinfo; 3249 } 3250 3251 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3252 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3253 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3254 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3255 PetscFunctionReturn(0); 3256 } 3257 3258 /*@C 3259 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3260 of a symmetric matrix. 3261 3262 Collective on fact 3263 3264 Input Parameters: 3265 + fact - the factor matrix obtained with `MatGetFactor()` 3266 . mat - the matrix 3267 . perm - row and column permutations 3268 - info - options for factorization, includes 3269 $ fill - expected fill as ratio of original fill. 3270 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3271 $ Run with the option -info to determine an optimal value to use 3272 3273 Notes: 3274 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3275 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3276 3277 Most users should employ the `KSP` interface for linear solvers 3278 instead of working directly with matrix algebra routines such as this. 3279 See, e.g., `KSPCreate()`. 3280 3281 Level: developer 3282 3283 Developer Note: 3284 The Fortran interface is not autogenerated as the f90 3285 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3286 3287 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3288 `MatGetOrdering()` 3289 @*/ 3290 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3291 { 3292 MatFactorInfo tinfo; 3293 3294 PetscFunctionBegin; 3295 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3296 PetscValidType(mat, 2); 3297 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3298 if (info) PetscValidPointer(info, 4); 3299 PetscValidPointer(fact, 1); 3300 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3301 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3302 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3303 if (!(fact)->ops->choleskyfactorsymbolic) { 3304 MatSolverType stype; 3305 PetscCall(MatFactorGetSolverType(fact, &stype)); 3306 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype); 3307 } 3308 MatCheckPreallocated(mat, 2); 3309 if (!info) { 3310 PetscCall(MatFactorInfoInitialize(&tinfo)); 3311 info = &tinfo; 3312 } 3313 3314 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3315 PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info)); 3316 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3317 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3318 PetscFunctionReturn(0); 3319 } 3320 3321 /*@C 3322 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3323 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3324 `MatCholeskyFactorSymbolic()`. 3325 3326 Collective on fact 3327 3328 Input Parameters: 3329 + fact - the factor matrix obtained with `MatGetFactor()` 3330 . mat - the initial matrix 3331 . info - options for factorization 3332 - fact - the symbolic factor of mat 3333 3334 Note: 3335 Most users should employ the `KSP` interface for linear solvers 3336 instead of working directly with matrix algebra routines such as this. 3337 See, e.g., `KSPCreate()`. 3338 3339 Level: developer 3340 3341 Developer Note: 3342 The Fortran interface is not autogenerated as the f90 3343 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3344 3345 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3346 @*/ 3347 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3348 { 3349 MatFactorInfo tinfo; 3350 3351 PetscFunctionBegin; 3352 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3353 PetscValidType(mat, 2); 3354 PetscValidPointer(fact, 1); 3355 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3356 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3357 PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name); 3358 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, 3359 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3360 MatCheckPreallocated(mat, 2); 3361 if (!info) { 3362 PetscCall(MatFactorInfoInitialize(&tinfo)); 3363 info = &tinfo; 3364 } 3365 3366 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3367 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3368 PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info)); 3369 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3370 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3371 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3372 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3373 PetscFunctionReturn(0); 3374 } 3375 3376 /*@ 3377 MatQRFactor - Performs in-place QR factorization of matrix. 3378 3379 Collective on mat 3380 3381 Input Parameters: 3382 + mat - the matrix 3383 . col - column permutation 3384 - info - options for factorization, includes 3385 $ fill - expected fill as ratio of original fill. 3386 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3387 $ Run with the option -info to determine an optimal value to use 3388 3389 Notes: 3390 Most users should employ the `KSP` interface for linear solvers 3391 instead of working directly with matrix algebra routines such as this. 3392 See, e.g., `KSPCreate()`. 3393 3394 This changes the state of the matrix to a factored matrix; it cannot be used 3395 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3396 3397 Level: developer 3398 3399 Developer Note: 3400 The Fortran interface is not autogenerated as the f90 3401 interface definition cannot be generated correctly [due to MatFactorInfo] 3402 3403 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3404 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3405 @*/ 3406 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3407 { 3408 PetscFunctionBegin; 3409 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3410 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3411 if (info) PetscValidPointer(info, 3); 3412 PetscValidType(mat, 1); 3413 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3414 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3415 MatCheckPreallocated(mat, 1); 3416 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3417 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3418 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3419 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3420 PetscFunctionReturn(0); 3421 } 3422 3423 /*@ 3424 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3425 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3426 3427 Collective on fact 3428 3429 Input Parameters: 3430 + fact - the factor matrix obtained with `MatGetFactor()` 3431 . mat - the matrix 3432 . col - column permutation 3433 - info - options for factorization, includes 3434 $ fill - expected fill as ratio of original fill. 3435 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3436 $ Run with the option -info to determine an optimal value to use 3437 3438 Most users should employ the `KSP` interface for linear solvers 3439 instead of working directly with matrix algebra routines such as this. 3440 See, e.g., `KSPCreate()`. 3441 3442 Level: developer 3443 3444 Developer Note: 3445 The Fortran interface is not autogenerated as the f90 3446 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3447 3448 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3449 @*/ 3450 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3451 { 3452 MatFactorInfo tinfo; 3453 3454 PetscFunctionBegin; 3455 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3456 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3457 if (info) PetscValidPointer(info, 4); 3458 PetscValidType(mat, 2); 3459 PetscValidPointer(fact, 1); 3460 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3461 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3462 MatCheckPreallocated(mat, 2); 3463 if (!info) { 3464 PetscCall(MatFactorInfoInitialize(&tinfo)); 3465 info = &tinfo; 3466 } 3467 3468 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3469 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3470 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3471 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3472 PetscFunctionReturn(0); 3473 } 3474 3475 /*@ 3476 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3477 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3478 3479 Collective on fact 3480 3481 Input Parameters: 3482 + fact - the factor matrix obtained with `MatGetFactor()` 3483 . mat - the matrix 3484 - info - options for factorization 3485 3486 Notes: 3487 See `MatQRFactor()` for in-place factorization. 3488 3489 Most users should employ the `KSP` interface for linear solvers 3490 instead of working directly with matrix algebra routines such as this. 3491 See, e.g., `KSPCreate()`. 3492 3493 Level: developer 3494 3495 Developer Note: 3496 The Fortran interface is not autogenerated as the f90 3497 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3498 3499 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3500 @*/ 3501 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3502 { 3503 MatFactorInfo tinfo; 3504 3505 PetscFunctionBegin; 3506 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3507 PetscValidType(mat, 2); 3508 PetscValidPointer(fact, 1); 3509 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3510 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3511 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, 3512 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3513 3514 MatCheckPreallocated(mat, 2); 3515 if (!info) { 3516 PetscCall(MatFactorInfoInitialize(&tinfo)); 3517 info = &tinfo; 3518 } 3519 3520 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3521 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3522 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3523 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3524 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3525 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3526 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3527 PetscFunctionReturn(0); 3528 } 3529 3530 /* ----------------------------------------------------------------*/ 3531 /*@ 3532 MatSolve - Solves A x = b, given a factored matrix. 3533 3534 Neighbor-wise Collective on mat 3535 3536 Input Parameters: 3537 + mat - the factored matrix 3538 - b - the right-hand-side vector 3539 3540 Output Parameter: 3541 . x - the result vector 3542 3543 Notes: 3544 The vectors b and x cannot be the same. I.e., one cannot 3545 call `MatSolve`(A,x,x). 3546 3547 Most users should employ the `KSP` interface for linear solvers 3548 instead of working directly with matrix algebra routines such as this. 3549 See, e.g., `KSPCreate()`. 3550 3551 Level: developer 3552 3553 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3554 @*/ 3555 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3556 { 3557 PetscFunctionBegin; 3558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3559 PetscValidType(mat, 1); 3560 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3561 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3562 PetscCheckSameComm(mat, 1, b, 2); 3563 PetscCheckSameComm(mat, 1, x, 3); 3564 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3565 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); 3566 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); 3567 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); 3568 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3569 MatCheckPreallocated(mat, 1); 3570 3571 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3572 if (mat->factorerrortype) { 3573 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3574 PetscCall(VecSetInf(x)); 3575 } else PetscUseTypeMethod(mat, solve, b, x); 3576 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3577 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3578 PetscFunctionReturn(0); 3579 } 3580 3581 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3582 { 3583 Vec b, x; 3584 PetscInt N, i; 3585 PetscErrorCode (*f)(Mat, Vec, Vec); 3586 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3587 3588 PetscFunctionBegin; 3589 if (A->factorerrortype) { 3590 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3591 PetscCall(MatSetInf(X)); 3592 PetscFunctionReturn(0); 3593 } 3594 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3595 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3596 PetscCall(MatBoundToCPU(A, &Abound)); 3597 if (!Abound) { 3598 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3599 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3600 } 3601 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3602 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3603 PetscCall(MatGetSize(B, NULL, &N)); 3604 for (i = 0; i < N; i++) { 3605 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3606 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3607 PetscCall((*f)(A, b, x)); 3608 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3609 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3610 } 3611 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3612 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3613 PetscFunctionReturn(0); 3614 } 3615 3616 /*@ 3617 MatMatSolve - Solves A X = B, given a factored matrix. 3618 3619 Neighbor-wise Collective on A 3620 3621 Input Parameters: 3622 + A - the factored matrix 3623 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3624 3625 Output Parameter: 3626 . X - the result matrix (dense matrix) 3627 3628 Note: 3629 If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO; 3630 otherwise, B and X cannot be the same. 3631 3632 Level: developer 3633 3634 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3635 @*/ 3636 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3637 { 3638 PetscFunctionBegin; 3639 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3640 PetscValidType(A, 1); 3641 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3642 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3643 PetscCheckSameComm(A, 1, B, 2); 3644 PetscCheckSameComm(A, 1, X, 3); 3645 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); 3646 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); 3647 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"); 3648 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3649 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3650 MatCheckPreallocated(A, 1); 3651 3652 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3653 if (!A->ops->matsolve) { 3654 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3655 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3656 } else PetscUseTypeMethod(A, matsolve, B, X); 3657 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3658 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3659 PetscFunctionReturn(0); 3660 } 3661 3662 /*@ 3663 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3664 3665 Neighbor-wise Collective on A 3666 3667 Input Parameters: 3668 + A - the factored matrix 3669 - B - the right-hand-side matrix (`MATDENSE` matrix) 3670 3671 Output Parameter: 3672 . X - the result matrix (dense matrix) 3673 3674 Note: 3675 The matrices B and X cannot be the same. I.e., one cannot 3676 call `MatMatSolveTranspose`(A,X,X). 3677 3678 Level: developer 3679 3680 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3681 @*/ 3682 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3683 { 3684 PetscFunctionBegin; 3685 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3686 PetscValidType(A, 1); 3687 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3688 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3689 PetscCheckSameComm(A, 1, B, 2); 3690 PetscCheckSameComm(A, 1, X, 3); 3691 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3692 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); 3693 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); 3694 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); 3695 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"); 3696 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3697 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3698 MatCheckPreallocated(A, 1); 3699 3700 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3701 if (!A->ops->matsolvetranspose) { 3702 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3703 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3704 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3705 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3706 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3707 PetscFunctionReturn(0); 3708 } 3709 3710 /*@ 3711 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3712 3713 Neighbor-wise Collective on A 3714 3715 Input Parameters: 3716 + A - the factored matrix 3717 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3718 3719 Output Parameter: 3720 . X - the result matrix (dense matrix) 3721 3722 Note: 3723 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 3724 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3725 3726 Level: developer 3727 3728 .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3729 @*/ 3730 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3731 { 3732 PetscFunctionBegin; 3733 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3734 PetscValidType(A, 1); 3735 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3736 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3737 PetscCheckSameComm(A, 1, Bt, 2); 3738 PetscCheckSameComm(A, 1, X, 3); 3739 3740 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3741 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); 3742 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); 3743 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"); 3744 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3745 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3746 MatCheckPreallocated(A, 1); 3747 3748 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3749 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3750 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3751 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3752 PetscFunctionReturn(0); 3753 } 3754 3755 /*@ 3756 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3757 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3758 3759 Neighbor-wise Collective on mat 3760 3761 Input Parameters: 3762 + mat - the factored matrix 3763 - b - the right-hand-side vector 3764 3765 Output Parameter: 3766 . x - the result vector 3767 3768 Notes: 3769 `MatSolve()` should be used for most applications, as it performs 3770 a forward solve followed by a backward solve. 3771 3772 The vectors b and x cannot be the same, i.e., one cannot 3773 call `MatForwardSolve`(A,x,x). 3774 3775 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3776 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3777 `MatForwardSolve()` solves U^T*D y = b, and 3778 `MatBackwardSolve()` solves U x = y. 3779 Thus they do not provide a symmetric preconditioner. 3780 3781 Level: developer 3782 3783 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3784 @*/ 3785 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3786 { 3787 PetscFunctionBegin; 3788 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3789 PetscValidType(mat, 1); 3790 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3791 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3792 PetscCheckSameComm(mat, 1, b, 2); 3793 PetscCheckSameComm(mat, 1, x, 3); 3794 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3795 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); 3796 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); 3797 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); 3798 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3799 MatCheckPreallocated(mat, 1); 3800 3801 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3802 PetscUseTypeMethod(mat, forwardsolve, b, x); 3803 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3804 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3805 PetscFunctionReturn(0); 3806 } 3807 3808 /*@ 3809 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3810 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3811 3812 Neighbor-wise Collective on mat 3813 3814 Input Parameters: 3815 + mat - the factored matrix 3816 - b - the right-hand-side vector 3817 3818 Output Parameter: 3819 . x - the result vector 3820 3821 Notes: 3822 `MatSolve()` should be used for most applications, as it performs 3823 a forward solve followed by a backward solve. 3824 3825 The vectors b and x cannot be the same. I.e., one cannot 3826 call `MatBackwardSolve`(A,x,x). 3827 3828 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3829 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3830 `MatForwardSolve()` solves U^T*D y = b, and 3831 `MatBackwardSolve()` solves U x = y. 3832 Thus they do not provide a symmetric preconditioner. 3833 3834 Level: developer 3835 3836 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3837 @*/ 3838 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3839 { 3840 PetscFunctionBegin; 3841 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3842 PetscValidType(mat, 1); 3843 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3844 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3845 PetscCheckSameComm(mat, 1, b, 2); 3846 PetscCheckSameComm(mat, 1, x, 3); 3847 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3848 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); 3849 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); 3850 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); 3851 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3852 MatCheckPreallocated(mat, 1); 3853 3854 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3855 PetscUseTypeMethod(mat, backwardsolve, b, x); 3856 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3857 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3858 PetscFunctionReturn(0); 3859 } 3860 3861 /*@ 3862 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3863 3864 Neighbor-wise Collective on mat 3865 3866 Input Parameters: 3867 + mat - the factored matrix 3868 . b - the right-hand-side vector 3869 - y - the vector to be added to 3870 3871 Output Parameter: 3872 . x - the result vector 3873 3874 Note: 3875 The vectors b and x cannot be the same. I.e., one cannot 3876 call `MatSolveAdd`(A,x,y,x). 3877 3878 Level: developer 3879 3880 .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3881 @*/ 3882 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3883 { 3884 PetscScalar one = 1.0; 3885 Vec tmp; 3886 3887 PetscFunctionBegin; 3888 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3889 PetscValidType(mat, 1); 3890 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3891 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3892 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3893 PetscCheckSameComm(mat, 1, b, 2); 3894 PetscCheckSameComm(mat, 1, y, 3); 3895 PetscCheckSameComm(mat, 1, x, 4); 3896 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3897 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); 3898 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); 3899 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); 3900 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); 3901 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); 3902 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3903 MatCheckPreallocated(mat, 1); 3904 3905 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3906 if (mat->factorerrortype) { 3907 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3908 PetscCall(VecSetInf(x)); 3909 } else if (mat->ops->solveadd) { 3910 PetscUseTypeMethod(mat, solveadd, b, y, x); 3911 } else { 3912 /* do the solve then the add manually */ 3913 if (x != y) { 3914 PetscCall(MatSolve(mat, b, x)); 3915 PetscCall(VecAXPY(x, one, y)); 3916 } else { 3917 PetscCall(VecDuplicate(x, &tmp)); 3918 PetscCall(VecCopy(x, tmp)); 3919 PetscCall(MatSolve(mat, b, x)); 3920 PetscCall(VecAXPY(x, one, tmp)); 3921 PetscCall(VecDestroy(&tmp)); 3922 } 3923 } 3924 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3925 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3926 PetscFunctionReturn(0); 3927 } 3928 3929 /*@ 3930 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3931 3932 Neighbor-wise Collective on mat 3933 3934 Input Parameters: 3935 + mat - the factored matrix 3936 - b - the right-hand-side vector 3937 3938 Output Parameter: 3939 . x - the result vector 3940 3941 Notes: 3942 The vectors b and x cannot be the same. I.e., one cannot 3943 call `MatSolveTranspose`(A,x,x). 3944 3945 Most users should employ the `KSP` interface for linear solvers 3946 instead of working directly with matrix algebra routines such as this. 3947 See, e.g., `KSPCreate()`. 3948 3949 Level: developer 3950 3951 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3952 @*/ 3953 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3954 { 3955 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3956 3957 PetscFunctionBegin; 3958 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3959 PetscValidType(mat, 1); 3960 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3961 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3962 PetscCheckSameComm(mat, 1, b, 2); 3963 PetscCheckSameComm(mat, 1, x, 3); 3964 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3965 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); 3966 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); 3967 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3968 MatCheckPreallocated(mat, 1); 3969 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 3970 if (mat->factorerrortype) { 3971 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3972 PetscCall(VecSetInf(x)); 3973 } else { 3974 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 3975 PetscCall((*f)(mat, b, x)); 3976 } 3977 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 3978 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3979 PetscFunctionReturn(0); 3980 } 3981 3982 /*@ 3983 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 3984 factored matrix. 3985 3986 Neighbor-wise Collective on mat 3987 3988 Input Parameters: 3989 + mat - the factored matrix 3990 . b - the right-hand-side vector 3991 - y - the vector to be added to 3992 3993 Output Parameter: 3994 . x - the result vector 3995 3996 Note: 3997 The vectors b and x cannot be the same. I.e., one cannot 3998 call `MatSolveTransposeAdd`(A,x,y,x). 3999 4000 Level: developer 4001 4002 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4003 @*/ 4004 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4005 { 4006 PetscScalar one = 1.0; 4007 Vec tmp; 4008 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4009 4010 PetscFunctionBegin; 4011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4012 PetscValidType(mat, 1); 4013 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4014 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4015 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4016 PetscCheckSameComm(mat, 1, b, 2); 4017 PetscCheckSameComm(mat, 1, y, 3); 4018 PetscCheckSameComm(mat, 1, x, 4); 4019 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4020 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); 4021 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); 4022 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); 4023 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); 4024 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 4025 MatCheckPreallocated(mat, 1); 4026 4027 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4028 if (mat->factorerrortype) { 4029 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4030 PetscCall(VecSetInf(x)); 4031 } else if (f) { 4032 PetscCall((*f)(mat, b, y, x)); 4033 } else { 4034 /* do the solve then the add manually */ 4035 if (x != y) { 4036 PetscCall(MatSolveTranspose(mat, b, x)); 4037 PetscCall(VecAXPY(x, one, y)); 4038 } else { 4039 PetscCall(VecDuplicate(x, &tmp)); 4040 PetscCall(VecCopy(x, tmp)); 4041 PetscCall(MatSolveTranspose(mat, b, x)); 4042 PetscCall(VecAXPY(x, one, tmp)); 4043 PetscCall(VecDestroy(&tmp)); 4044 } 4045 } 4046 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4047 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4048 PetscFunctionReturn(0); 4049 } 4050 /* ----------------------------------------------------------------*/ 4051 4052 /*@ 4053 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4054 4055 Neighbor-wise Collective on mat 4056 4057 Input Parameters: 4058 + mat - the matrix 4059 . b - the right hand side 4060 . omega - the relaxation factor 4061 . flag - flag indicating the type of SOR (see below) 4062 . shift - diagonal shift 4063 . its - the number of iterations 4064 - lits - the number of local iterations 4065 4066 Output Parameter: 4067 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4068 4069 SOR Flags: 4070 + `SOR_FORWARD_SWEEP` - forward SOR 4071 . `SOR_BACKWARD_SWEEP` - backward SOR 4072 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4073 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4074 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4075 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4076 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4077 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4078 upper/lower triangular part of matrix to 4079 vector (with omega) 4080 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4081 4082 Notes: 4083 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4084 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4085 on each processor. 4086 4087 Application programmers will not generally use `MatSOR()` directly, 4088 but instead will employ the `KSP`/`PC` interface. 4089 4090 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4091 4092 Most users should employ the `KSP` interface for linear solvers 4093 instead of working directly with matrix algebra routines such as this. 4094 See, e.g., `KSPCreate()`. 4095 4096 Vectors x and b CANNOT be the same 4097 4098 Notes for Advanced Users: 4099 The flags are implemented as bitwise inclusive or operations. 4100 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4101 to specify a zero initial guess for SSOR. 4102 4103 Developer Note: 4104 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4105 4106 Level: developer 4107 4108 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4109 @*/ 4110 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4111 { 4112 PetscFunctionBegin; 4113 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4114 PetscValidType(mat, 1); 4115 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4116 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4117 PetscCheckSameComm(mat, 1, b, 2); 4118 PetscCheckSameComm(mat, 1, x, 8); 4119 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4120 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4121 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); 4122 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); 4123 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); 4124 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4125 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4126 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4127 4128 MatCheckPreallocated(mat, 1); 4129 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4130 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4131 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4132 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4133 PetscFunctionReturn(0); 4134 } 4135 4136 /* 4137 Default matrix copy routine. 4138 */ 4139 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4140 { 4141 PetscInt i, rstart = 0, rend = 0, nz; 4142 const PetscInt *cwork; 4143 const PetscScalar *vwork; 4144 4145 PetscFunctionBegin; 4146 if (B->assembled) PetscCall(MatZeroEntries(B)); 4147 if (str == SAME_NONZERO_PATTERN) { 4148 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4149 for (i = rstart; i < rend; i++) { 4150 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4151 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4152 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4153 } 4154 } else { 4155 PetscCall(MatAYPX(B, 0.0, A, str)); 4156 } 4157 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4158 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4159 PetscFunctionReturn(0); 4160 } 4161 4162 /*@ 4163 MatCopy - Copies a matrix to another matrix. 4164 4165 Collective on A 4166 4167 Input Parameters: 4168 + A - the matrix 4169 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4170 4171 Output Parameter: 4172 . B - where the copy is put 4173 4174 Notes: 4175 If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash. 4176 4177 `MatCopy()` copies the matrix entries of a matrix to another existing 4178 matrix (after first zeroing the second matrix). A related routine is 4179 `MatConvert()`, which first creates a new matrix and then copies the data. 4180 4181 Level: intermediate 4182 4183 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()` 4184 @*/ 4185 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4186 { 4187 PetscInt i; 4188 4189 PetscFunctionBegin; 4190 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4191 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4192 PetscValidType(A, 1); 4193 PetscValidType(B, 2); 4194 PetscCheckSameComm(A, 1, B, 2); 4195 MatCheckPreallocated(B, 2); 4196 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4197 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4198 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, 4199 A->cmap->N, B->cmap->N); 4200 MatCheckPreallocated(A, 1); 4201 if (A == B) PetscFunctionReturn(0); 4202 4203 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4204 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4205 else PetscCall(MatCopy_Basic(A, B, str)); 4206 4207 B->stencil.dim = A->stencil.dim; 4208 B->stencil.noc = A->stencil.noc; 4209 for (i = 0; i <= A->stencil.dim; i++) { 4210 B->stencil.dims[i] = A->stencil.dims[i]; 4211 B->stencil.starts[i] = A->stencil.starts[i]; 4212 } 4213 4214 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4215 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4216 PetscFunctionReturn(0); 4217 } 4218 4219 /*@C 4220 MatConvert - Converts a matrix to another matrix, either of the same 4221 or different type. 4222 4223 Collective on mat 4224 4225 Input Parameters: 4226 + mat - the matrix 4227 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4228 same type as the original matrix. 4229 - reuse - denotes if the destination matrix is to be created or reused. 4230 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 4231 `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). 4232 4233 Output Parameter: 4234 . M - pointer to place new matrix 4235 4236 Notes: 4237 `MatConvert()` first creates a new matrix and then copies the data from 4238 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4239 entries of one matrix to another already existing matrix context. 4240 4241 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4242 the MPI communicator of the generated matrix is always the same as the communicator 4243 of the input matrix. 4244 4245 Level: intermediate 4246 4247 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4248 @*/ 4249 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4250 { 4251 PetscBool sametype, issame, flg; 4252 PetscBool3 issymmetric, ishermitian; 4253 char convname[256], mtype[256]; 4254 Mat B; 4255 4256 PetscFunctionBegin; 4257 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4258 PetscValidType(mat, 1); 4259 PetscValidPointer(M, 4); 4260 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4261 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4262 MatCheckPreallocated(mat, 1); 4263 4264 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4265 if (flg) newtype = mtype; 4266 4267 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4268 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4269 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4270 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"); 4271 4272 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4273 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4274 PetscFunctionReturn(0); 4275 } 4276 4277 /* Cache Mat options because some converters use MatHeaderReplace */ 4278 issymmetric = mat->symmetric; 4279 ishermitian = mat->hermitian; 4280 4281 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4282 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4283 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4284 } else { 4285 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4286 const char *prefix[3] = {"seq", "mpi", ""}; 4287 PetscInt i; 4288 /* 4289 Order of precedence: 4290 0) See if newtype is a superclass of the current matrix. 4291 1) See if a specialized converter is known to the current matrix. 4292 2) See if a specialized converter is known to the desired matrix class. 4293 3) See if a good general converter is registered for the desired class 4294 (as of 6/27/03 only MATMPIADJ falls into this category). 4295 4) See if a good general converter is known for the current matrix. 4296 5) Use a really basic converter. 4297 */ 4298 4299 /* 0) See if newtype is a superclass of the current matrix. 4300 i.e mat is mpiaij and newtype is aij */ 4301 for (i = 0; i < 2; i++) { 4302 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4303 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4304 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4305 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4306 if (flg) { 4307 if (reuse == MAT_INPLACE_MATRIX) { 4308 PetscCall(PetscInfo(mat, "Early return\n")); 4309 PetscFunctionReturn(0); 4310 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4311 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4312 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4313 PetscFunctionReturn(0); 4314 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4315 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4316 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4317 PetscFunctionReturn(0); 4318 } 4319 } 4320 } 4321 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4322 for (i = 0; i < 3; i++) { 4323 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4324 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4325 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4326 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4327 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4328 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4329 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4330 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4331 if (conv) goto foundconv; 4332 } 4333 4334 /* 2) See if a specialized converter is known to the desired matrix class. */ 4335 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4336 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4337 PetscCall(MatSetType(B, newtype)); 4338 for (i = 0; i < 3; i++) { 4339 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4340 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4341 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4342 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4343 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4344 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4345 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4346 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4347 if (conv) { 4348 PetscCall(MatDestroy(&B)); 4349 goto foundconv; 4350 } 4351 } 4352 4353 /* 3) See if a good general converter is registered for the desired class */ 4354 conv = B->ops->convertfrom; 4355 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4356 PetscCall(MatDestroy(&B)); 4357 if (conv) goto foundconv; 4358 4359 /* 4) See if a good general converter is known for the current matrix */ 4360 if (mat->ops->convert) conv = mat->ops->convert; 4361 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4362 if (conv) goto foundconv; 4363 4364 /* 5) Use a really basic converter. */ 4365 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4366 conv = MatConvert_Basic; 4367 4368 foundconv: 4369 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4370 PetscCall((*conv)(mat, newtype, reuse, M)); 4371 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4372 /* the block sizes must be same if the mappings are copied over */ 4373 (*M)->rmap->bs = mat->rmap->bs; 4374 (*M)->cmap->bs = mat->cmap->bs; 4375 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4376 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4377 (*M)->rmap->mapping = mat->rmap->mapping; 4378 (*M)->cmap->mapping = mat->cmap->mapping; 4379 } 4380 (*M)->stencil.dim = mat->stencil.dim; 4381 (*M)->stencil.noc = mat->stencil.noc; 4382 for (i = 0; i <= mat->stencil.dim; i++) { 4383 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4384 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4385 } 4386 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4387 } 4388 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4389 4390 /* Copy Mat options */ 4391 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4392 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4393 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4394 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4395 PetscFunctionReturn(0); 4396 } 4397 4398 /*@C 4399 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4400 4401 Not Collective 4402 4403 Input Parameter: 4404 . mat - the matrix, must be a factored matrix 4405 4406 Output Parameter: 4407 . type - the string name of the package (do not free this string) 4408 4409 Note: 4410 In Fortran you pass in a empty string and the package name will be copied into it. 4411 (Make sure the string is long enough) 4412 4413 Level: intermediate 4414 4415 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4416 @*/ 4417 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4418 { 4419 PetscErrorCode (*conv)(Mat, MatSolverType *); 4420 4421 PetscFunctionBegin; 4422 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4423 PetscValidType(mat, 1); 4424 PetscValidPointer(type, 2); 4425 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4426 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4427 if (conv) PetscCall((*conv)(mat, type)); 4428 else *type = MATSOLVERPETSC; 4429 PetscFunctionReturn(0); 4430 } 4431 4432 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4433 struct _MatSolverTypeForSpecifcType { 4434 MatType mtype; 4435 /* no entry for MAT_FACTOR_NONE */ 4436 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4437 MatSolverTypeForSpecifcType next; 4438 }; 4439 4440 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4441 struct _MatSolverTypeHolder { 4442 char *name; 4443 MatSolverTypeForSpecifcType handlers; 4444 MatSolverTypeHolder next; 4445 }; 4446 4447 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4448 4449 /*@C 4450 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4451 4452 Input Parameters: 4453 + package - name of the package, for example petsc or superlu 4454 . mtype - the matrix type that works with this package 4455 . ftype - the type of factorization supported by the package 4456 - createfactor - routine that will create the factored matrix ready to be used 4457 4458 Level: developer 4459 4460 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4461 @*/ 4462 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4463 { 4464 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4465 PetscBool flg; 4466 MatSolverTypeForSpecifcType inext, iprev = NULL; 4467 4468 PetscFunctionBegin; 4469 PetscCall(MatInitializePackage()); 4470 if (!next) { 4471 PetscCall(PetscNew(&MatSolverTypeHolders)); 4472 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4473 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4474 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4475 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4476 PetscFunctionReturn(0); 4477 } 4478 while (next) { 4479 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4480 if (flg) { 4481 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4482 inext = next->handlers; 4483 while (inext) { 4484 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4485 if (flg) { 4486 inext->createfactor[(int)ftype - 1] = createfactor; 4487 PetscFunctionReturn(0); 4488 } 4489 iprev = inext; 4490 inext = inext->next; 4491 } 4492 PetscCall(PetscNew(&iprev->next)); 4493 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4494 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4495 PetscFunctionReturn(0); 4496 } 4497 prev = next; 4498 next = next->next; 4499 } 4500 PetscCall(PetscNew(&prev->next)); 4501 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4502 PetscCall(PetscNew(&prev->next->handlers)); 4503 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4504 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4505 PetscFunctionReturn(0); 4506 } 4507 4508 /*@C 4509 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4510 4511 Input Parameters: 4512 + type - name of the package, for example petsc or superlu 4513 . ftype - the type of factorization supported by the type 4514 - mtype - the matrix type that works with this type 4515 4516 Output Parameters: 4517 + foundtype - `PETSC_TRUE` if the type was registered 4518 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4519 - createfactor - routine that will create the factored matrix ready to be used or NULL if not found 4520 4521 Level: developer 4522 4523 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4524 @*/ 4525 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4526 { 4527 MatSolverTypeHolder next = MatSolverTypeHolders; 4528 PetscBool flg; 4529 MatSolverTypeForSpecifcType inext; 4530 4531 PetscFunctionBegin; 4532 if (foundtype) *foundtype = PETSC_FALSE; 4533 if (foundmtype) *foundmtype = PETSC_FALSE; 4534 if (createfactor) *createfactor = NULL; 4535 4536 if (type) { 4537 while (next) { 4538 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4539 if (flg) { 4540 if (foundtype) *foundtype = PETSC_TRUE; 4541 inext = next->handlers; 4542 while (inext) { 4543 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4544 if (flg) { 4545 if (foundmtype) *foundmtype = PETSC_TRUE; 4546 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4547 PetscFunctionReturn(0); 4548 } 4549 inext = inext->next; 4550 } 4551 } 4552 next = next->next; 4553 } 4554 } else { 4555 while (next) { 4556 inext = next->handlers; 4557 while (inext) { 4558 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4559 if (flg && inext->createfactor[(int)ftype - 1]) { 4560 if (foundtype) *foundtype = PETSC_TRUE; 4561 if (foundmtype) *foundmtype = PETSC_TRUE; 4562 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4563 PetscFunctionReturn(0); 4564 } 4565 inext = inext->next; 4566 } 4567 next = next->next; 4568 } 4569 /* try with base classes inext->mtype */ 4570 next = MatSolverTypeHolders; 4571 while (next) { 4572 inext = next->handlers; 4573 while (inext) { 4574 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4575 if (flg && inext->createfactor[(int)ftype - 1]) { 4576 if (foundtype) *foundtype = PETSC_TRUE; 4577 if (foundmtype) *foundmtype = PETSC_TRUE; 4578 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4579 PetscFunctionReturn(0); 4580 } 4581 inext = inext->next; 4582 } 4583 next = next->next; 4584 } 4585 } 4586 PetscFunctionReturn(0); 4587 } 4588 4589 PetscErrorCode MatSolverTypeDestroy(void) 4590 { 4591 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4592 MatSolverTypeForSpecifcType inext, iprev; 4593 4594 PetscFunctionBegin; 4595 while (next) { 4596 PetscCall(PetscFree(next->name)); 4597 inext = next->handlers; 4598 while (inext) { 4599 PetscCall(PetscFree(inext->mtype)); 4600 iprev = inext; 4601 inext = inext->next; 4602 PetscCall(PetscFree(iprev)); 4603 } 4604 prev = next; 4605 next = next->next; 4606 PetscCall(PetscFree(prev)); 4607 } 4608 MatSolverTypeHolders = NULL; 4609 PetscFunctionReturn(0); 4610 } 4611 4612 /*@C 4613 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4614 4615 Logically Collective on mat 4616 4617 Input Parameters: 4618 . mat - the matrix 4619 4620 Output Parameters: 4621 . flg - `PETSC_TRUE` if uses the ordering 4622 4623 Note: 4624 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4625 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4626 4627 Level: developer 4628 4629 .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4630 @*/ 4631 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4632 { 4633 PetscFunctionBegin; 4634 *flg = mat->canuseordering; 4635 PetscFunctionReturn(0); 4636 } 4637 4638 /*@C 4639 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4640 4641 Logically Collective on mat 4642 4643 Input Parameters: 4644 . mat - the matrix obtained with `MatGetFactor()` 4645 4646 Output Parameters: 4647 . otype - the preferred type 4648 4649 Level: developer 4650 4651 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4652 @*/ 4653 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4654 { 4655 PetscFunctionBegin; 4656 *otype = mat->preferredordering[ftype]; 4657 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4658 PetscFunctionReturn(0); 4659 } 4660 4661 /*@C 4662 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4663 4664 Collective on mat 4665 4666 Input Parameters: 4667 + mat - the matrix 4668 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4669 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4670 4671 Output Parameters: 4672 . f - the factor matrix used with MatXXFactorSymbolic() calls 4673 4674 Options Database Key: 4675 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4676 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4677 4678 Notes: 4679 Users usually access the factorization solvers via `KSP` 4680 4681 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4682 such as pastix, superlu, mumps etc. 4683 4684 PETSc must have been ./configure to use the external solver, using the option --download-package 4685 4686 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4687 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4688 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4689 4690 Developer Note: 4691 This should actually be called `MatCreateFactor()` since it creates a new factor object 4692 4693 Level: intermediate 4694 4695 .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4696 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4697 @*/ 4698 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4699 { 4700 PetscBool foundtype, foundmtype; 4701 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4702 4703 PetscFunctionBegin; 4704 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4705 PetscValidType(mat, 1); 4706 4707 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4708 MatCheckPreallocated(mat, 1); 4709 4710 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4711 if (!foundtype) { 4712 if (type) { 4713 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], 4714 ((PetscObject)mat)->type_name, type); 4715 } else { 4716 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); 4717 } 4718 } 4719 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4720 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); 4721 4722 PetscCall((*conv)(mat, ftype, f)); 4723 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4724 PetscFunctionReturn(0); 4725 } 4726 4727 /*@C 4728 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4729 4730 Not Collective 4731 4732 Input Parameters: 4733 + mat - the matrix 4734 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4735 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4736 4737 Output Parameter: 4738 . flg - PETSC_TRUE if the factorization is available 4739 4740 Notes: 4741 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4742 such as pastix, superlu, mumps etc. 4743 4744 PETSc must have been ./configure to use the external solver, using the option --download-package 4745 4746 Developer Note: 4747 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4748 4749 Level: intermediate 4750 4751 .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4752 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4753 @*/ 4754 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4755 { 4756 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4757 4758 PetscFunctionBegin; 4759 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4760 PetscValidType(mat, 1); 4761 PetscValidBoolPointer(flg, 4); 4762 4763 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4764 MatCheckPreallocated(mat, 1); 4765 4766 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4767 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4768 PetscFunctionReturn(0); 4769 } 4770 4771 /*@ 4772 MatDuplicate - Duplicates a matrix including the non-zero structure. 4773 4774 Collective on mat 4775 4776 Input Parameters: 4777 + mat - the matrix 4778 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4779 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4780 4781 Output Parameter: 4782 . M - pointer to place new matrix 4783 4784 Level: intermediate 4785 4786 Notes: 4787 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4788 4789 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. 4790 4791 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 4792 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4793 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4794 4795 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4796 @*/ 4797 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4798 { 4799 Mat B; 4800 VecType vtype; 4801 PetscInt i; 4802 PetscObject dm; 4803 void (*viewf)(void); 4804 4805 PetscFunctionBegin; 4806 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4807 PetscValidType(mat, 1); 4808 PetscValidPointer(M, 3); 4809 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4810 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4811 MatCheckPreallocated(mat, 1); 4812 4813 *M = NULL; 4814 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4815 PetscUseTypeMethod(mat, duplicate, op, M); 4816 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4817 B = *M; 4818 4819 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4820 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4821 PetscCall(MatGetVecType(mat, &vtype)); 4822 PetscCall(MatSetVecType(B, vtype)); 4823 4824 B->stencil.dim = mat->stencil.dim; 4825 B->stencil.noc = mat->stencil.noc; 4826 for (i = 0; i <= mat->stencil.dim; i++) { 4827 B->stencil.dims[i] = mat->stencil.dims[i]; 4828 B->stencil.starts[i] = mat->stencil.starts[i]; 4829 } 4830 4831 B->nooffproczerorows = mat->nooffproczerorows; 4832 B->nooffprocentries = mat->nooffprocentries; 4833 4834 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4835 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4836 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4837 PetscFunctionReturn(0); 4838 } 4839 4840 /*@ 4841 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4842 4843 Logically Collective on mat 4844 4845 Input Parameters: 4846 + mat - the matrix 4847 - v - the vector for storing the diagonal 4848 4849 Output Parameter: 4850 . v - the diagonal of the matrix 4851 4852 Level: intermediate 4853 4854 Note: 4855 Currently only correct in parallel for square matrices. 4856 4857 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4858 @*/ 4859 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4860 { 4861 PetscFunctionBegin; 4862 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4863 PetscValidType(mat, 1); 4864 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4865 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4866 MatCheckPreallocated(mat, 1); 4867 4868 PetscUseTypeMethod(mat, getdiagonal, v); 4869 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4870 PetscFunctionReturn(0); 4871 } 4872 4873 /*@C 4874 MatGetRowMin - Gets the minimum value (of the real part) of each 4875 row of the matrix 4876 4877 Logically Collective on mat 4878 4879 Input Parameter: 4880 . mat - the matrix 4881 4882 Output Parameters: 4883 + v - the vector for storing the maximums 4884 - idx - the indices of the column found for each row (optional) 4885 4886 Level: intermediate 4887 4888 Note: 4889 The result of this call are the same as if one converted the matrix to dense format 4890 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4891 4892 This code is only implemented for a couple of matrix formats. 4893 4894 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4895 `MatGetRowMax()` 4896 @*/ 4897 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4898 { 4899 PetscFunctionBegin; 4900 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4901 PetscValidType(mat, 1); 4902 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4903 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4904 4905 if (!mat->cmap->N) { 4906 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4907 if (idx) { 4908 PetscInt i, m = mat->rmap->n; 4909 for (i = 0; i < m; i++) idx[i] = -1; 4910 } 4911 } else { 4912 MatCheckPreallocated(mat, 1); 4913 } 4914 PetscUseTypeMethod(mat, getrowmin, v, idx); 4915 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4916 PetscFunctionReturn(0); 4917 } 4918 4919 /*@C 4920 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4921 row of the matrix 4922 4923 Logically Collective on mat 4924 4925 Input Parameter: 4926 . mat - the matrix 4927 4928 Output Parameters: 4929 + v - the vector for storing the minimums 4930 - idx - the indices of the column found for each row (or NULL if not needed) 4931 4932 Level: intermediate 4933 4934 Notes: 4935 if a row is completely empty or has only 0.0 values then the idx[] value for that 4936 row is 0 (the first column). 4937 4938 This code is only implemented for a couple of matrix formats. 4939 4940 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4941 @*/ 4942 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4943 { 4944 PetscFunctionBegin; 4945 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4946 PetscValidType(mat, 1); 4947 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4948 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4949 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4950 4951 if (!mat->cmap->N) { 4952 PetscCall(VecSet(v, 0.0)); 4953 if (idx) { 4954 PetscInt i, m = mat->rmap->n; 4955 for (i = 0; i < m; i++) idx[i] = -1; 4956 } 4957 } else { 4958 MatCheckPreallocated(mat, 1); 4959 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4960 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4961 } 4962 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4963 PetscFunctionReturn(0); 4964 } 4965 4966 /*@C 4967 MatGetRowMax - Gets the maximum value (of the real part) of each 4968 row of the matrix 4969 4970 Logically Collective on mat 4971 4972 Input Parameter: 4973 . mat - the matrix 4974 4975 Output Parameters: 4976 + v - the vector for storing the maximums 4977 - idx - the indices of the column found for each row (optional) 4978 4979 Level: intermediate 4980 4981 Notes: 4982 The result of this call are the same as if one converted the matrix to dense format 4983 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4984 4985 This code is only implemented for a couple of matrix formats. 4986 4987 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 4988 @*/ 4989 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 4990 { 4991 PetscFunctionBegin; 4992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4993 PetscValidType(mat, 1); 4994 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4995 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4996 4997 if (!mat->cmap->N) { 4998 PetscCall(VecSet(v, PETSC_MIN_REAL)); 4999 if (idx) { 5000 PetscInt i, m = mat->rmap->n; 5001 for (i = 0; i < m; i++) idx[i] = -1; 5002 } 5003 } else { 5004 MatCheckPreallocated(mat, 1); 5005 PetscUseTypeMethod(mat, getrowmax, v, idx); 5006 } 5007 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5008 PetscFunctionReturn(0); 5009 } 5010 5011 /*@C 5012 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5013 row of the matrix 5014 5015 Logically Collective on mat 5016 5017 Input Parameter: 5018 . mat - the matrix 5019 5020 Output Parameters: 5021 + v - the vector for storing the maximums 5022 - idx - the indices of the column found for each row (or NULL if not needed) 5023 5024 Level: intermediate 5025 5026 Notes: 5027 if a row is completely empty or has only 0.0 values then the idx[] value for that 5028 row is 0 (the first column). 5029 5030 This code is only implemented for a couple of matrix formats. 5031 5032 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5033 @*/ 5034 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5035 { 5036 PetscFunctionBegin; 5037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5038 PetscValidType(mat, 1); 5039 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5040 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5041 5042 if (!mat->cmap->N) { 5043 PetscCall(VecSet(v, 0.0)); 5044 if (idx) { 5045 PetscInt i, m = mat->rmap->n; 5046 for (i = 0; i < m; i++) idx[i] = -1; 5047 } 5048 } else { 5049 MatCheckPreallocated(mat, 1); 5050 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5051 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5052 } 5053 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5054 PetscFunctionReturn(0); 5055 } 5056 5057 /*@ 5058 MatGetRowSum - Gets the sum of each row of the matrix 5059 5060 Logically or Neighborhood Collective on mat 5061 5062 Input Parameters: 5063 . mat - the matrix 5064 5065 Output Parameter: 5066 . v - the vector for storing the sum of rows 5067 5068 Level: intermediate 5069 5070 Notes: 5071 This code is slow since it is not currently specialized for different formats 5072 5073 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5074 @*/ 5075 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5076 { 5077 Vec ones; 5078 5079 PetscFunctionBegin; 5080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5081 PetscValidType(mat, 1); 5082 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5083 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5084 MatCheckPreallocated(mat, 1); 5085 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5086 PetscCall(VecSet(ones, 1.)); 5087 PetscCall(MatMult(mat, ones, v)); 5088 PetscCall(VecDestroy(&ones)); 5089 PetscFunctionReturn(0); 5090 } 5091 5092 /*@ 5093 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5094 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5095 5096 Collective on mat 5097 5098 Input Parameter: 5099 . mat - the matrix to provide the transpose 5100 5101 Output Parameter: 5102 . 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 5103 5104 Level: advanced 5105 5106 Note: 5107 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 5108 routine allows bypassing that call. 5109 5110 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5111 @*/ 5112 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5113 { 5114 PetscContainer rB = NULL; 5115 MatParentState *rb = NULL; 5116 5117 PetscFunctionBegin; 5118 PetscCall(PetscNew(&rb)); 5119 rb->id = ((PetscObject)mat)->id; 5120 rb->state = 0; 5121 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5122 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5123 PetscCall(PetscContainerSetPointer(rB, rb)); 5124 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5125 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5126 PetscCall(PetscObjectDereference((PetscObject)rB)); 5127 PetscFunctionReturn(0); 5128 } 5129 5130 /*@ 5131 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5132 5133 Collective on mat 5134 5135 Input Parameters: 5136 + mat - the matrix to transpose 5137 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5138 5139 Output Parameter: 5140 . B - the transpose 5141 5142 Notes: 5143 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5144 5145 `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 5146 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5147 5148 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. 5149 5150 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5151 5152 If mat is unchanged from the last call this function returns immediately without recomputing the result 5153 5154 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5155 5156 Level: intermediate 5157 5158 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5159 `MatTransposeSymbolic()` 5160 @*/ 5161 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5162 { 5163 PetscContainer rB = NULL; 5164 MatParentState *rb = NULL; 5165 5166 PetscFunctionBegin; 5167 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5168 PetscValidType(mat, 1); 5169 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5170 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5171 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5172 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5173 MatCheckPreallocated(mat, 1); 5174 if (reuse == MAT_REUSE_MATRIX) { 5175 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5176 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5177 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5178 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5179 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0); 5180 } 5181 5182 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5183 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5184 PetscUseTypeMethod(mat, transpose, reuse, B); 5185 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5186 } 5187 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5188 5189 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5190 if (reuse != MAT_INPLACE_MATRIX) { 5191 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5192 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5193 rb->state = ((PetscObject)mat)->state; 5194 rb->nonzerostate = mat->nonzerostate; 5195 } 5196 PetscFunctionReturn(0); 5197 } 5198 5199 /*@ 5200 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5201 5202 Collective on A 5203 5204 Input Parameters: 5205 . A - the matrix to transpose 5206 5207 Output Parameter: 5208 . 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 5209 numerical portion. 5210 5211 Level: intermediate 5212 5213 Note: 5214 This is not supported for many matrix types, use `MatTranspose()` in those cases 5215 5216 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5217 @*/ 5218 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5219 { 5220 PetscFunctionBegin; 5221 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5222 PetscValidType(A, 1); 5223 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5224 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5225 PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 5226 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5227 PetscCall((*A->ops->transposesymbolic)(A, B)); 5228 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5229 5230 PetscCall(MatTransposeSetPrecursor(A, *B)); 5231 PetscFunctionReturn(0); 5232 } 5233 5234 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5235 { 5236 PetscContainer rB; 5237 MatParentState *rb; 5238 5239 PetscFunctionBegin; 5240 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5241 PetscValidType(A, 1); 5242 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5243 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5244 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5245 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5246 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5247 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5248 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5249 PetscFunctionReturn(0); 5250 } 5251 5252 /*@ 5253 MatIsTranspose - Test whether a matrix is another one's transpose, 5254 or its own, in which case it tests symmetry. 5255 5256 Collective on A 5257 5258 Input Parameters: 5259 + A - the matrix to test 5260 - B - the matrix to test against, this can equal the first parameter 5261 5262 Output Parameters: 5263 . flg - the result 5264 5265 Notes: 5266 Only available for `MATAIJ` matrices. 5267 5268 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5269 test involves parallel copies of the block-offdiagonal parts of the matrix. 5270 5271 Level: intermediate 5272 5273 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5274 @*/ 5275 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5276 { 5277 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5278 5279 PetscFunctionBegin; 5280 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5281 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5282 PetscValidBoolPointer(flg, 4); 5283 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5284 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5285 *flg = PETSC_FALSE; 5286 if (f && g) { 5287 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5288 PetscCall((*f)(A, B, tol, flg)); 5289 } else { 5290 MatType mattype; 5291 5292 PetscCall(MatGetType(f ? B : A, &mattype)); 5293 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5294 } 5295 PetscFunctionReturn(0); 5296 } 5297 5298 /*@ 5299 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5300 5301 Collective on mat 5302 5303 Input Parameters: 5304 + mat - the matrix to transpose and complex conjugate 5305 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5306 5307 Output Parameter: 5308 . B - the Hermitian transpose 5309 5310 Level: intermediate 5311 5312 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5313 @*/ 5314 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5315 { 5316 PetscFunctionBegin; 5317 PetscCall(MatTranspose(mat, reuse, B)); 5318 #if defined(PETSC_USE_COMPLEX) 5319 PetscCall(MatConjugate(*B)); 5320 #endif 5321 PetscFunctionReturn(0); 5322 } 5323 5324 /*@ 5325 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5326 5327 Collective on A 5328 5329 Input Parameters: 5330 + A - the matrix to test 5331 - B - the matrix to test against, this can equal the first parameter 5332 5333 Output Parameters: 5334 . flg - the result 5335 5336 Notes: 5337 Only available for `MATAIJ` matrices. 5338 5339 The sequential algorithm 5340 has a running time of the order of the number of nonzeros; the parallel 5341 test involves parallel copies of the block-offdiagonal parts of the matrix. 5342 5343 Level: intermediate 5344 5345 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5346 @*/ 5347 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5348 { 5349 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5350 5351 PetscFunctionBegin; 5352 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5353 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5354 PetscValidBoolPointer(flg, 4); 5355 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5356 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5357 if (f && g) { 5358 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5359 PetscCall((*f)(A, B, tol, flg)); 5360 } 5361 PetscFunctionReturn(0); 5362 } 5363 5364 /*@ 5365 MatPermute - Creates a new matrix with rows and columns permuted from the 5366 original. 5367 5368 Collective on mat 5369 5370 Input Parameters: 5371 + mat - the matrix to permute 5372 . row - row permutation, each processor supplies only the permutation for its rows 5373 - col - column permutation, each processor supplies only the permutation for its columns 5374 5375 Output Parameters: 5376 . B - the permuted matrix 5377 5378 Level: advanced 5379 5380 Note: 5381 The index sets map from row/col of permuted matrix to row/col of original matrix. 5382 The index sets should be on the same communicator as mat and have the same local sizes. 5383 5384 Developer Note: 5385 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5386 exploit the fact that row and col are permutations, consider implementing the 5387 more general `MatCreateSubMatrix()` instead. 5388 5389 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5390 @*/ 5391 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5392 { 5393 PetscFunctionBegin; 5394 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5395 PetscValidType(mat, 1); 5396 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5397 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5398 PetscValidPointer(B, 4); 5399 PetscCheckSameComm(mat, 1, row, 2); 5400 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5401 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5402 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5403 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5404 MatCheckPreallocated(mat, 1); 5405 5406 if (mat->ops->permute) { 5407 PetscUseTypeMethod(mat, permute, row, col, B); 5408 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5409 } else { 5410 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5411 } 5412 PetscFunctionReturn(0); 5413 } 5414 5415 /*@ 5416 MatEqual - Compares two matrices. 5417 5418 Collective on A 5419 5420 Input Parameters: 5421 + A - the first matrix 5422 - B - the second matrix 5423 5424 Output Parameter: 5425 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5426 5427 Level: intermediate 5428 5429 .seealso: `Mat` 5430 @*/ 5431 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5432 { 5433 PetscFunctionBegin; 5434 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5435 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5436 PetscValidType(A, 1); 5437 PetscValidType(B, 2); 5438 PetscValidBoolPointer(flg, 3); 5439 PetscCheckSameComm(A, 1, B, 2); 5440 MatCheckPreallocated(A, 1); 5441 MatCheckPreallocated(B, 2); 5442 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5443 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5444 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, 5445 B->cmap->N); 5446 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5447 PetscUseTypeMethod(A, equal, B, flg); 5448 } else { 5449 PetscCall(MatMultEqual(A, B, 10, flg)); 5450 } 5451 PetscFunctionReturn(0); 5452 } 5453 5454 /*@ 5455 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5456 matrices that are stored as vectors. Either of the two scaling 5457 matrices can be NULL. 5458 5459 Collective on mat 5460 5461 Input Parameters: 5462 + mat - the matrix to be scaled 5463 . l - the left scaling vector (or NULL) 5464 - r - the right scaling vector (or NULL) 5465 5466 Note: 5467 `MatDiagonalScale()` computes A = LAR, where 5468 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5469 The L scales the rows of the matrix, the R scales the columns of the matrix. 5470 5471 Level: intermediate 5472 5473 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5474 @*/ 5475 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5476 { 5477 PetscFunctionBegin; 5478 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5479 PetscValidType(mat, 1); 5480 if (l) { 5481 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5482 PetscCheckSameComm(mat, 1, l, 2); 5483 } 5484 if (r) { 5485 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5486 PetscCheckSameComm(mat, 1, r, 3); 5487 } 5488 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5489 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5490 MatCheckPreallocated(mat, 1); 5491 if (!l && !r) PetscFunctionReturn(0); 5492 5493 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5494 PetscUseTypeMethod(mat, diagonalscale, l, r); 5495 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5496 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5497 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5498 PetscFunctionReturn(0); 5499 } 5500 5501 /*@ 5502 MatScale - Scales all elements of a matrix by a given number. 5503 5504 Logically Collective on mat 5505 5506 Input Parameters: 5507 + mat - the matrix to be scaled 5508 - a - the scaling value 5509 5510 Output Parameter: 5511 . mat - the scaled matrix 5512 5513 Level: intermediate 5514 5515 .seealso: `Mat`, `MatDiagonalScale()` 5516 @*/ 5517 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5518 { 5519 PetscFunctionBegin; 5520 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5521 PetscValidType(mat, 1); 5522 PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 5523 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5524 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5525 PetscValidLogicalCollectiveScalar(mat, a, 2); 5526 MatCheckPreallocated(mat, 1); 5527 5528 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5529 if (a != (PetscScalar)1.0) { 5530 PetscUseTypeMethod(mat, scale, a); 5531 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5532 } 5533 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5534 PetscFunctionReturn(0); 5535 } 5536 5537 /*@ 5538 MatNorm - Calculates various norms of a matrix. 5539 5540 Collective on mat 5541 5542 Input Parameters: 5543 + mat - the matrix 5544 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5545 5546 Output Parameter: 5547 . nrm - the resulting norm 5548 5549 Level: intermediate 5550 5551 .seealso: `Mat` 5552 @*/ 5553 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5554 { 5555 PetscFunctionBegin; 5556 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5557 PetscValidType(mat, 1); 5558 PetscValidRealPointer(nrm, 3); 5559 5560 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5561 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5562 MatCheckPreallocated(mat, 1); 5563 5564 PetscUseTypeMethod(mat, norm, type, nrm); 5565 PetscFunctionReturn(0); 5566 } 5567 5568 /* 5569 This variable is used to prevent counting of MatAssemblyBegin() that 5570 are called from within a MatAssemblyEnd(). 5571 */ 5572 static PetscInt MatAssemblyEnd_InUse = 0; 5573 /*@ 5574 MatAssemblyBegin - Begins assembling the matrix. This routine should 5575 be called after completing all calls to `MatSetValues()`. 5576 5577 Collective on mat 5578 5579 Input Parameters: 5580 + mat - the matrix 5581 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5582 5583 Notes: 5584 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5585 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5586 5587 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5588 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5589 using the matrix. 5590 5591 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5592 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 5593 a global collective operation requring all processes that share the matrix. 5594 5595 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5596 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5597 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5598 5599 Level: beginner 5600 5601 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5602 @*/ 5603 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5604 { 5605 PetscFunctionBegin; 5606 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5607 PetscValidType(mat, 1); 5608 MatCheckPreallocated(mat, 1); 5609 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5610 if (mat->assembled) { 5611 mat->was_assembled = PETSC_TRUE; 5612 mat->assembled = PETSC_FALSE; 5613 } 5614 5615 if (!MatAssemblyEnd_InUse) { 5616 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5617 PetscTryTypeMethod(mat, assemblybegin, type); 5618 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5619 } else PetscTryTypeMethod(mat, assemblybegin, type); 5620 PetscFunctionReturn(0); 5621 } 5622 5623 /*@ 5624 MatAssembled - Indicates if a matrix has been assembled and is ready for 5625 use; for example, in matrix-vector product. 5626 5627 Not Collective 5628 5629 Input Parameter: 5630 . mat - the matrix 5631 5632 Output Parameter: 5633 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5634 5635 Level: advanced 5636 5637 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5638 @*/ 5639 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5640 { 5641 PetscFunctionBegin; 5642 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5643 PetscValidBoolPointer(assembled, 2); 5644 *assembled = mat->assembled; 5645 PetscFunctionReturn(0); 5646 } 5647 5648 /*@ 5649 MatAssemblyEnd - Completes assembling the matrix. This routine should 5650 be called after `MatAssemblyBegin()`. 5651 5652 Collective on Mat 5653 5654 Input Parameters: 5655 + mat - the matrix 5656 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5657 5658 Options Database Keys: 5659 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5660 . -mat_view ::ascii_info_detail - Prints more detailed info 5661 . -mat_view - Prints matrix in ASCII format 5662 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5663 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5664 . -display <name> - Sets display name (default is host) 5665 . -draw_pause <sec> - Sets number of seconds to pause after display 5666 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5667 . -viewer_socket_machine <machine> - Machine to use for socket 5668 . -viewer_socket_port <port> - Port number to use for socket 5669 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5670 5671 Level: beginner 5672 5673 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5674 @*/ 5675 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5676 { 5677 static PetscInt inassm = 0; 5678 PetscBool flg = PETSC_FALSE; 5679 5680 PetscFunctionBegin; 5681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5682 PetscValidType(mat, 1); 5683 5684 inassm++; 5685 MatAssemblyEnd_InUse++; 5686 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5687 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5688 PetscTryTypeMethod(mat, assemblyend, type); 5689 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5690 } else PetscTryTypeMethod(mat, assemblyend, type); 5691 5692 /* Flush assembly is not a true assembly */ 5693 if (type != MAT_FLUSH_ASSEMBLY) { 5694 if (mat->num_ass) { 5695 if (!mat->symmetry_eternal) { 5696 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5697 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5698 } 5699 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5700 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5701 } 5702 mat->num_ass++; 5703 mat->assembled = PETSC_TRUE; 5704 mat->ass_nonzerostate = mat->nonzerostate; 5705 } 5706 5707 mat->insertmode = NOT_SET_VALUES; 5708 MatAssemblyEnd_InUse--; 5709 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5710 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5711 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5712 5713 if (mat->checksymmetryonassembly) { 5714 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5715 if (flg) { 5716 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5717 } else { 5718 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5719 } 5720 } 5721 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5722 } 5723 inassm--; 5724 PetscFunctionReturn(0); 5725 } 5726 5727 /*@ 5728 MatSetOption - Sets a parameter option for a matrix. Some options 5729 may be specific to certain storage formats. Some options 5730 determine how values will be inserted (or added). Sorted, 5731 row-oriented input will generally assemble the fastest. The default 5732 is row-oriented. 5733 5734 Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5735 5736 Input Parameters: 5737 + mat - the matrix 5738 . option - the option, one of those listed below (and possibly others), 5739 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5740 5741 Options Describing Matrix Structure: 5742 + `MAT_SPD` - symmetric positive definite 5743 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5744 . `MAT_HERMITIAN` - transpose is the complex conjugation 5745 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5746 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5747 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5748 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5749 5750 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5751 do not need to be computed (usually at a high cost) 5752 5753 Options For Use with `MatSetValues()`: 5754 Insert a logically dense subblock, which can be 5755 . `MAT_ROW_ORIENTED` - row-oriented (default) 5756 5757 Note these options reflect the data you pass in with `MatSetValues()`; it has 5758 nothing to do with how the data is stored internally in the matrix 5759 data structure. 5760 5761 When (re)assembling a matrix, we can restrict the input for 5762 efficiency/debugging purposes. These options include 5763 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5764 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5765 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5766 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5767 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5768 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5769 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5770 performance for very large process counts. 5771 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5772 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5773 functions, instead sending only neighbor messages. 5774 5775 Notes: 5776 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5777 5778 Some options are relevant only for particular matrix types and 5779 are thus ignored by others. Other options are not supported by 5780 certain matrix types and will generate an error message if set. 5781 5782 If using a Fortran 77 module to compute a matrix, one may need to 5783 use the column-oriented option (or convert to the row-oriented 5784 format). 5785 5786 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5787 that would generate a new entry in the nonzero structure is instead 5788 ignored. Thus, if memory has not alredy been allocated for this particular 5789 data, then the insertion is ignored. For dense matrices, in which 5790 the entire array is allocated, no entries are ever ignored. 5791 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5792 5793 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5794 that would generate a new entry in the nonzero structure instead produces 5795 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 5796 5797 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5798 that would generate a new entry that has not been preallocated will 5799 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5800 only.) This is a useful flag when debugging matrix memory preallocation. 5801 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5802 5803 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5804 other processors should be dropped, rather than stashed. 5805 This is useful if you know that the "owning" processor is also 5806 always generating the correct matrix entries, so that PETSc need 5807 not transfer duplicate entries generated on another processor. 5808 5809 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5810 searches during matrix assembly. When this flag is set, the hash table 5811 is created during the first matrix assembly. This hash table is 5812 used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()` 5813 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5814 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5815 supported by` MATMPIBAIJ` format only. 5816 5817 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5818 are kept in the nonzero structure 5819 5820 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5821 a zero location in the matrix 5822 5823 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5824 5825 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5826 zero row routines and thus improves performance for very large process counts. 5827 5828 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5829 part of the matrix (since they should match the upper triangular part). 5830 5831 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5832 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5833 with finite difference schemes with non-periodic boundary conditions. 5834 5835 Developer Note: 5836 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5837 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5838 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5839 not changed. 5840 5841 Level: intermediate 5842 5843 .seealso: `MatOption`, `Mat`, `MatGetOption()` 5844 @*/ 5845 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5846 { 5847 PetscFunctionBegin; 5848 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5849 if (op > 0) { 5850 PetscValidLogicalCollectiveEnum(mat, op, 2); 5851 PetscValidLogicalCollectiveBool(mat, flg, 3); 5852 } 5853 5854 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); 5855 5856 switch (op) { 5857 case MAT_FORCE_DIAGONAL_ENTRIES: 5858 mat->force_diagonals = flg; 5859 PetscFunctionReturn(0); 5860 case MAT_NO_OFF_PROC_ENTRIES: 5861 mat->nooffprocentries = flg; 5862 PetscFunctionReturn(0); 5863 case MAT_SUBSET_OFF_PROC_ENTRIES: 5864 mat->assembly_subset = flg; 5865 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5866 #if !defined(PETSC_HAVE_MPIUNI) 5867 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5868 #endif 5869 mat->stash.first_assembly_done = PETSC_FALSE; 5870 } 5871 PetscFunctionReturn(0); 5872 case MAT_NO_OFF_PROC_ZERO_ROWS: 5873 mat->nooffproczerorows = flg; 5874 PetscFunctionReturn(0); 5875 case MAT_SPD: 5876 if (flg) { 5877 mat->spd = PETSC_BOOL3_TRUE; 5878 mat->symmetric = PETSC_BOOL3_TRUE; 5879 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5880 } else { 5881 mat->spd = PETSC_BOOL3_FALSE; 5882 } 5883 break; 5884 case MAT_SYMMETRIC: 5885 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5886 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5887 #if !defined(PETSC_USE_COMPLEX) 5888 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5889 #endif 5890 break; 5891 case MAT_HERMITIAN: 5892 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5893 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5894 #if !defined(PETSC_USE_COMPLEX) 5895 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5896 #endif 5897 break; 5898 case MAT_STRUCTURALLY_SYMMETRIC: 5899 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5900 break; 5901 case MAT_SYMMETRY_ETERNAL: 5902 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"); 5903 mat->symmetry_eternal = flg; 5904 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5905 break; 5906 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5907 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"); 5908 mat->structural_symmetry_eternal = flg; 5909 break; 5910 case MAT_SPD_ETERNAL: 5911 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"); 5912 mat->spd_eternal = flg; 5913 if (flg) { 5914 mat->structural_symmetry_eternal = PETSC_TRUE; 5915 mat->symmetry_eternal = PETSC_TRUE; 5916 } 5917 break; 5918 case MAT_STRUCTURE_ONLY: 5919 mat->structure_only = flg; 5920 break; 5921 case MAT_SORTED_FULL: 5922 mat->sortedfull = flg; 5923 break; 5924 default: 5925 break; 5926 } 5927 PetscTryTypeMethod(mat, setoption, op, flg); 5928 PetscFunctionReturn(0); 5929 } 5930 5931 /*@ 5932 MatGetOption - Gets a parameter option that has been set for a matrix. 5933 5934 Logically Collective on mat 5935 5936 Input Parameters: 5937 + mat - the matrix 5938 - option - the option, this only responds to certain options, check the code for which ones 5939 5940 Output Parameter: 5941 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5942 5943 Notes: 5944 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5945 5946 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5947 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5948 5949 Level: intermediate 5950 5951 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5952 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5953 @*/ 5954 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5955 { 5956 PetscFunctionBegin; 5957 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5958 PetscValidType(mat, 1); 5959 5960 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); 5961 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()"); 5962 5963 switch (op) { 5964 case MAT_NO_OFF_PROC_ENTRIES: 5965 *flg = mat->nooffprocentries; 5966 break; 5967 case MAT_NO_OFF_PROC_ZERO_ROWS: 5968 *flg = mat->nooffproczerorows; 5969 break; 5970 case MAT_SYMMETRIC: 5971 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 5972 break; 5973 case MAT_HERMITIAN: 5974 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 5975 break; 5976 case MAT_STRUCTURALLY_SYMMETRIC: 5977 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 5978 break; 5979 case MAT_SPD: 5980 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 5981 break; 5982 case MAT_SYMMETRY_ETERNAL: 5983 *flg = mat->symmetry_eternal; 5984 break; 5985 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5986 *flg = mat->symmetry_eternal; 5987 break; 5988 default: 5989 break; 5990 } 5991 PetscFunctionReturn(0); 5992 } 5993 5994 /*@ 5995 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 5996 this routine retains the old nonzero structure. 5997 5998 Logically Collective on mat 5999 6000 Input Parameters: 6001 . mat - the matrix 6002 6003 Level: intermediate 6004 6005 Note: 6006 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. 6007 See the Performance chapter of the users manual for information on preallocating matrices. 6008 6009 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6010 @*/ 6011 PetscErrorCode MatZeroEntries(Mat mat) 6012 { 6013 PetscFunctionBegin; 6014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6015 PetscValidType(mat, 1); 6016 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6017 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"); 6018 MatCheckPreallocated(mat, 1); 6019 6020 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6021 PetscUseTypeMethod(mat, zeroentries); 6022 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6023 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6024 PetscFunctionReturn(0); 6025 } 6026 6027 /*@ 6028 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6029 of a set of rows and columns of a matrix. 6030 6031 Collective on mat 6032 6033 Input Parameters: 6034 + mat - the matrix 6035 . numRows - the number of rows to remove 6036 . rows - the global row indices 6037 . diag - value put in the diagonal of the eliminated rows 6038 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6039 - b - optional vector of right hand side, that will be adjusted by provided solution 6040 6041 Notes: 6042 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6043 6044 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 6045 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 6046 6047 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6048 Krylov method to take advantage of the known solution on the zeroed rows. 6049 6050 For the parallel case, all processes that share the matrix (i.e., 6051 those in the communicator used for matrix creation) MUST call this 6052 routine, regardless of whether any rows being zeroed are owned by 6053 them. 6054 6055 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6056 6057 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6058 list only rows local to itself). 6059 6060 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6061 6062 Level: intermediate 6063 6064 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6065 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6066 @*/ 6067 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6068 { 6069 PetscFunctionBegin; 6070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6071 PetscValidType(mat, 1); 6072 if (numRows) PetscValidIntPointer(rows, 3); 6073 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6074 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6075 MatCheckPreallocated(mat, 1); 6076 6077 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6078 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6079 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6080 PetscFunctionReturn(0); 6081 } 6082 6083 /*@ 6084 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6085 of a set of rows and columns of a matrix. 6086 6087 Collective on mat 6088 6089 Input Parameters: 6090 + mat - the matrix 6091 . is - the rows to zero 6092 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6093 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6094 - b - optional vector of right hand side, that will be adjusted by provided solution 6095 6096 Note: 6097 See `MatZeroRowsColumns()` for details on how this routine operates. 6098 6099 Level: intermediate 6100 6101 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6102 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6103 @*/ 6104 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6105 { 6106 PetscInt numRows; 6107 const PetscInt *rows; 6108 6109 PetscFunctionBegin; 6110 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6111 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6112 PetscValidType(mat, 1); 6113 PetscValidType(is, 2); 6114 PetscCall(ISGetLocalSize(is, &numRows)); 6115 PetscCall(ISGetIndices(is, &rows)); 6116 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6117 PetscCall(ISRestoreIndices(is, &rows)); 6118 PetscFunctionReturn(0); 6119 } 6120 6121 /*@ 6122 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6123 of a set of rows of a matrix. 6124 6125 Collective on mat 6126 6127 Input Parameters: 6128 + mat - the matrix 6129 . numRows - the number of rows to remove 6130 . rows - the global row indices 6131 . diag - value put in the diagonal of the eliminated rows 6132 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6133 - b - optional vector of right hand side, that will be adjusted by provided solution 6134 6135 Notes: 6136 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6137 6138 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 6139 6140 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6141 Krylov method to take advantage of the known solution on the zeroed rows. 6142 6143 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) 6144 from the matrix. 6145 6146 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6147 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 6148 formats this does not alter the nonzero structure. 6149 6150 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6151 of the matrix is not changed the values are 6152 merely zeroed. 6153 6154 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6155 formats can optionally remove the main diagonal entry from the 6156 nonzero structure as well, by passing 0.0 as the final argument). 6157 6158 For the parallel case, all processes that share the matrix (i.e., 6159 those in the communicator used for matrix creation) MUST call this 6160 routine, regardless of whether any rows being zeroed are owned by 6161 them. 6162 6163 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6164 list only rows local to itself). 6165 6166 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6167 owns that are to be zeroed. This saves a global synchronization in the implementation. 6168 6169 Level: intermediate 6170 6171 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6172 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6173 @*/ 6174 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6175 { 6176 PetscFunctionBegin; 6177 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6178 PetscValidType(mat, 1); 6179 if (numRows) PetscValidIntPointer(rows, 3); 6180 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6181 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6182 MatCheckPreallocated(mat, 1); 6183 6184 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6185 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6186 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6187 PetscFunctionReturn(0); 6188 } 6189 6190 /*@ 6191 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6192 of a set of rows of a matrix. 6193 6194 Collective on Mat 6195 6196 Input Parameters: 6197 + mat - the matrix 6198 . is - index set of rows to remove (if NULL then no row is removed) 6199 . diag - value put in all diagonals of eliminated rows 6200 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6201 - b - optional vector of right hand side, that will be adjusted by provided solution 6202 6203 Note: 6204 See `MatZeroRows()` for details on how this routine operates. 6205 6206 Level: intermediate 6207 6208 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6209 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6210 @*/ 6211 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6212 { 6213 PetscInt numRows = 0; 6214 const PetscInt *rows = NULL; 6215 6216 PetscFunctionBegin; 6217 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6218 PetscValidType(mat, 1); 6219 if (is) { 6220 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6221 PetscCall(ISGetLocalSize(is, &numRows)); 6222 PetscCall(ISGetIndices(is, &rows)); 6223 } 6224 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6225 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6226 PetscFunctionReturn(0); 6227 } 6228 6229 /*@ 6230 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6231 of a set of rows of a matrix. These rows must be local to the process. 6232 6233 Collective on mat 6234 6235 Input Parameters: 6236 + mat - the matrix 6237 . numRows - the number of rows to remove 6238 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6239 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6240 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6241 - b - optional vector of right hand side, that will be adjusted by provided solution 6242 6243 Notes: 6244 See `MatZeroRows()` for details on how this routine operates. 6245 6246 The grid coordinates are across the entire grid, not just the local portion 6247 6248 In Fortran idxm and idxn should be declared as 6249 $ MatStencil idxm(4,m) 6250 and the values inserted using 6251 $ idxm(MatStencil_i,1) = i 6252 $ idxm(MatStencil_j,1) = j 6253 $ idxm(MatStencil_k,1) = k 6254 $ idxm(MatStencil_c,1) = c 6255 etc 6256 6257 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6258 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6259 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6260 `DM_BOUNDARY_PERIODIC` boundary type. 6261 6262 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 6263 a single value per point) you can skip filling those indices. 6264 6265 Level: intermediate 6266 6267 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6268 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6269 @*/ 6270 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6271 { 6272 PetscInt dim = mat->stencil.dim; 6273 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6274 PetscInt *dims = mat->stencil.dims + 1; 6275 PetscInt *starts = mat->stencil.starts; 6276 PetscInt *dxm = (PetscInt *)rows; 6277 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6278 6279 PetscFunctionBegin; 6280 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6281 PetscValidType(mat, 1); 6282 if (numRows) PetscValidPointer(rows, 3); 6283 6284 PetscCall(PetscMalloc1(numRows, &jdxm)); 6285 for (i = 0; i < numRows; ++i) { 6286 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6287 for (j = 0; j < 3 - sdim; ++j) dxm++; 6288 /* Local index in X dir */ 6289 tmp = *dxm++ - starts[0]; 6290 /* Loop over remaining dimensions */ 6291 for (j = 0; j < dim - 1; ++j) { 6292 /* If nonlocal, set index to be negative */ 6293 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6294 /* Update local index */ 6295 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6296 } 6297 /* Skip component slot if necessary */ 6298 if (mat->stencil.noc) dxm++; 6299 /* Local row number */ 6300 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6301 } 6302 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6303 PetscCall(PetscFree(jdxm)); 6304 PetscFunctionReturn(0); 6305 } 6306 6307 /*@ 6308 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6309 of a set of rows and columns of a matrix. 6310 6311 Collective on mat 6312 6313 Input Parameters: 6314 + mat - the matrix 6315 . numRows - the number of rows/columns to remove 6316 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6317 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6318 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6319 - b - optional vector of right hand side, that will be adjusted by provided solution 6320 6321 Notes: 6322 See `MatZeroRowsColumns()` for details on how this routine operates. 6323 6324 The grid coordinates are across the entire grid, not just the local portion 6325 6326 In Fortran idxm and idxn should be declared as 6327 $ MatStencil idxm(4,m) 6328 and the values inserted using 6329 $ idxm(MatStencil_i,1) = i 6330 $ idxm(MatStencil_j,1) = j 6331 $ idxm(MatStencil_k,1) = k 6332 $ idxm(MatStencil_c,1) = c 6333 etc 6334 6335 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6336 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6337 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6338 `DM_BOUNDARY_PERIODIC` boundary type. 6339 6340 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 6341 a single value per point) you can skip filling those indices. 6342 6343 Level: intermediate 6344 6345 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6346 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6347 @*/ 6348 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6349 { 6350 PetscInt dim = mat->stencil.dim; 6351 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6352 PetscInt *dims = mat->stencil.dims + 1; 6353 PetscInt *starts = mat->stencil.starts; 6354 PetscInt *dxm = (PetscInt *)rows; 6355 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6356 6357 PetscFunctionBegin; 6358 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6359 PetscValidType(mat, 1); 6360 if (numRows) PetscValidPointer(rows, 3); 6361 6362 PetscCall(PetscMalloc1(numRows, &jdxm)); 6363 for (i = 0; i < numRows; ++i) { 6364 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6365 for (j = 0; j < 3 - sdim; ++j) dxm++; 6366 /* Local index in X dir */ 6367 tmp = *dxm++ - starts[0]; 6368 /* Loop over remaining dimensions */ 6369 for (j = 0; j < dim - 1; ++j) { 6370 /* If nonlocal, set index to be negative */ 6371 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6372 /* Update local index */ 6373 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6374 } 6375 /* Skip component slot if necessary */ 6376 if (mat->stencil.noc) dxm++; 6377 /* Local row number */ 6378 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6379 } 6380 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6381 PetscCall(PetscFree(jdxm)); 6382 PetscFunctionReturn(0); 6383 } 6384 6385 /*@C 6386 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6387 of a set of rows of a matrix; using local numbering of rows. 6388 6389 Collective on mat 6390 6391 Input Parameters: 6392 + mat - the matrix 6393 . numRows - the number of rows to remove 6394 . rows - the local row indices 6395 . diag - value put in all diagonals of eliminated rows 6396 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6397 - b - optional vector of right hand side, that will be adjusted by provided solution 6398 6399 Notes: 6400 Before calling `MatZeroRowsLocal()`, the user must first set the 6401 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6402 6403 See `MatZeroRows()` for details on how this routine operates. 6404 6405 Level: intermediate 6406 6407 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6408 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6409 @*/ 6410 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6411 { 6412 PetscFunctionBegin; 6413 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6414 PetscValidType(mat, 1); 6415 if (numRows) PetscValidIntPointer(rows, 3); 6416 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6417 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6418 MatCheckPreallocated(mat, 1); 6419 6420 if (mat->ops->zerorowslocal) { 6421 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6422 } else { 6423 IS is, newis; 6424 const PetscInt *newRows; 6425 6426 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6427 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6428 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6429 PetscCall(ISGetIndices(newis, &newRows)); 6430 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6431 PetscCall(ISRestoreIndices(newis, &newRows)); 6432 PetscCall(ISDestroy(&newis)); 6433 PetscCall(ISDestroy(&is)); 6434 } 6435 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6436 PetscFunctionReturn(0); 6437 } 6438 6439 /*@ 6440 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6441 of a set of rows of a matrix; using local numbering of rows. 6442 6443 Collective on mat 6444 6445 Input Parameters: 6446 + mat - the matrix 6447 . is - index set of rows to remove 6448 . diag - value put in all diagonals of eliminated rows 6449 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6450 - b - optional vector of right hand side, that will be adjusted by provided solution 6451 6452 Notes: 6453 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6454 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6455 6456 See `MatZeroRows()` for details on how this routine operates. 6457 6458 Level: intermediate 6459 6460 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6461 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6462 @*/ 6463 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6464 { 6465 PetscInt numRows; 6466 const PetscInt *rows; 6467 6468 PetscFunctionBegin; 6469 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6470 PetscValidType(mat, 1); 6471 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6472 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6473 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6474 MatCheckPreallocated(mat, 1); 6475 6476 PetscCall(ISGetLocalSize(is, &numRows)); 6477 PetscCall(ISGetIndices(is, &rows)); 6478 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6479 PetscCall(ISRestoreIndices(is, &rows)); 6480 PetscFunctionReturn(0); 6481 } 6482 6483 /*@ 6484 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6485 of a set of rows and columns of a matrix; using local numbering of rows. 6486 6487 Collective on mat 6488 6489 Input Parameters: 6490 + mat - the matrix 6491 . numRows - the number of rows to remove 6492 . rows - the global row indices 6493 . diag - value put in all diagonals of eliminated rows 6494 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6495 - b - optional vector of right hand side, that will be adjusted by provided solution 6496 6497 Notes: 6498 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6499 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6500 6501 See `MatZeroRowsColumns()` for details on how this routine operates. 6502 6503 Level: intermediate 6504 6505 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6506 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6507 @*/ 6508 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6509 { 6510 IS is, newis; 6511 const PetscInt *newRows; 6512 6513 PetscFunctionBegin; 6514 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6515 PetscValidType(mat, 1); 6516 if (numRows) PetscValidIntPointer(rows, 3); 6517 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6518 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6519 MatCheckPreallocated(mat, 1); 6520 6521 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6522 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6523 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6524 PetscCall(ISGetIndices(newis, &newRows)); 6525 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6526 PetscCall(ISRestoreIndices(newis, &newRows)); 6527 PetscCall(ISDestroy(&newis)); 6528 PetscCall(ISDestroy(&is)); 6529 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6530 PetscFunctionReturn(0); 6531 } 6532 6533 /*@ 6534 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6535 of a set of rows and columns of a matrix; using local numbering of rows. 6536 6537 Collective on Mat 6538 6539 Input Parameters: 6540 + mat - the matrix 6541 . is - index set of rows to remove 6542 . diag - value put in all diagonals of eliminated rows 6543 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6544 - b - optional vector of right hand side, that will be adjusted by provided solution 6545 6546 Notes: 6547 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6548 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6549 6550 See `MatZeroRowsColumns()` for details on how this routine operates. 6551 6552 Level: intermediate 6553 6554 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6555 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6556 @*/ 6557 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6558 { 6559 PetscInt numRows; 6560 const PetscInt *rows; 6561 6562 PetscFunctionBegin; 6563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6564 PetscValidType(mat, 1); 6565 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6566 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6567 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6568 MatCheckPreallocated(mat, 1); 6569 6570 PetscCall(ISGetLocalSize(is, &numRows)); 6571 PetscCall(ISGetIndices(is, &rows)); 6572 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6573 PetscCall(ISRestoreIndices(is, &rows)); 6574 PetscFunctionReturn(0); 6575 } 6576 6577 /*@C 6578 MatGetSize - Returns the numbers of rows and columns in a matrix. 6579 6580 Not Collective 6581 6582 Input Parameter: 6583 . mat - the matrix 6584 6585 Output Parameters: 6586 + m - the number of global rows 6587 - n - the number of global columns 6588 6589 Note: both output parameters can be NULL on input. 6590 6591 Level: beginner 6592 6593 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6594 @*/ 6595 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6596 { 6597 PetscFunctionBegin; 6598 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6599 if (m) *m = mat->rmap->N; 6600 if (n) *n = mat->cmap->N; 6601 PetscFunctionReturn(0); 6602 } 6603 6604 /*@C 6605 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6606 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6607 6608 Not Collective 6609 6610 Input Parameter: 6611 . mat - the matrix 6612 6613 Output Parameters: 6614 + m - the number of local rows, use `NULL` to not obtain this value 6615 - n - the number of local columns, use `NULL` to not obtain this value 6616 6617 Level: beginner 6618 6619 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()` 6620 @*/ 6621 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6622 { 6623 PetscFunctionBegin; 6624 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6625 if (m) PetscValidIntPointer(m, 2); 6626 if (n) PetscValidIntPointer(n, 3); 6627 if (m) *m = mat->rmap->n; 6628 if (n) *n = mat->cmap->n; 6629 PetscFunctionReturn(0); 6630 } 6631 6632 /*@C 6633 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6634 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6635 6636 Not Collective, unless matrix has not been allocated, then collective on mat 6637 6638 Input Parameter: 6639 . mat - the matrix 6640 6641 Output Parameters: 6642 + m - the global index of the first local column, use `NULL` to not obtain this value 6643 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6644 6645 Level: developer 6646 6647 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6648 @*/ 6649 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6650 { 6651 PetscFunctionBegin; 6652 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6653 PetscValidType(mat, 1); 6654 if (m) PetscValidIntPointer(m, 2); 6655 if (n) PetscValidIntPointer(n, 3); 6656 MatCheckPreallocated(mat, 1); 6657 if (m) *m = mat->cmap->rstart; 6658 if (n) *n = mat->cmap->rend; 6659 PetscFunctionReturn(0); 6660 } 6661 6662 /*@C 6663 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6664 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 6665 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6666 6667 Not Collective 6668 6669 Input Parameter: 6670 . mat - the matrix 6671 6672 Output Parameters: 6673 + m - the global index of the first local row, use `NULL` to not obtain this value 6674 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6675 6676 Note: 6677 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6678 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6679 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6680 6681 Level: beginner 6682 6683 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6684 `PetscLayout` 6685 @*/ 6686 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6687 { 6688 PetscFunctionBegin; 6689 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6690 PetscValidType(mat, 1); 6691 if (m) PetscValidIntPointer(m, 2); 6692 if (n) PetscValidIntPointer(n, 3); 6693 MatCheckPreallocated(mat, 1); 6694 if (m) *m = mat->rmap->rstart; 6695 if (n) *n = mat->rmap->rend; 6696 PetscFunctionReturn(0); 6697 } 6698 6699 /*@C 6700 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6701 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 6702 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6703 6704 Not Collective, unless matrix has not been allocated, then collective on mat 6705 6706 Input Parameters: 6707 . mat - the matrix 6708 6709 Output Parameters: 6710 . ranges - start of each processors portion plus one more than the total length at the end 6711 6712 Level: beginner 6713 6714 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6715 @*/ 6716 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6717 { 6718 PetscFunctionBegin; 6719 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6720 PetscValidType(mat, 1); 6721 MatCheckPreallocated(mat, 1); 6722 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6723 PetscFunctionReturn(0); 6724 } 6725 6726 /*@C 6727 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6728 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6729 6730 Not Collective, unless matrix has not been allocated, then collective on Mat 6731 6732 Input Parameters: 6733 . mat - the matrix 6734 6735 Output Parameters: 6736 . ranges - start of each processors portion plus one more then the total length at the end 6737 6738 Level: beginner 6739 6740 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6741 @*/ 6742 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6743 { 6744 PetscFunctionBegin; 6745 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6746 PetscValidType(mat, 1); 6747 MatCheckPreallocated(mat, 1); 6748 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6749 PetscFunctionReturn(0); 6750 } 6751 6752 /*@C 6753 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6754 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6755 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6756 6757 Not Collective 6758 6759 Input Parameter: 6760 . A - matrix 6761 6762 Output Parameters: 6763 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6764 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6765 6766 Level: intermediate 6767 6768 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6769 @*/ 6770 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6771 { 6772 PetscErrorCode (*f)(Mat, IS *, IS *); 6773 6774 PetscFunctionBegin; 6775 MatCheckPreallocated(A, 1); 6776 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6777 if (f) { 6778 PetscCall((*f)(A, rows, cols)); 6779 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6780 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6781 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6782 } 6783 PetscFunctionReturn(0); 6784 } 6785 6786 /*@C 6787 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6788 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6789 to complete the factorization. 6790 6791 Collective on fact 6792 6793 Input Parameters: 6794 + fact - the factorized matrix obtained with `MatGetFactor()` 6795 . mat - the matrix 6796 . row - row permutation 6797 . column - column permutation 6798 - info - structure containing 6799 $ levels - number of levels of fill. 6800 $ expected fill - as ratio of original fill. 6801 $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6802 missing diagonal entries) 6803 6804 Output Parameters: 6805 . fact - new matrix that has been symbolically factored 6806 6807 Level: developer 6808 6809 Notes: 6810 See [Matrix Factorization](sec_matfactor) for additional information. 6811 6812 Most users should employ the `KSP` interface for linear solvers 6813 instead of working directly with matrix algebra routines such as this. 6814 See, e.g., `KSPCreate()`. 6815 6816 Uses the definition of level of fill as in Y. Saad, 2003 6817 6818 Developer Note: 6819 The Fortran interface is not autogenerated as the f90 6820 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6821 6822 References: 6823 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6824 6825 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6826 `MatGetOrdering()`, `MatFactorInfo` 6827 @*/ 6828 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6829 { 6830 PetscFunctionBegin; 6831 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6832 PetscValidType(mat, 2); 6833 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6834 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6835 PetscValidPointer(info, 5); 6836 PetscValidPointer(fact, 1); 6837 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6838 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6839 if (!fact->ops->ilufactorsymbolic) { 6840 MatSolverType stype; 6841 PetscCall(MatFactorGetSolverType(fact, &stype)); 6842 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype); 6843 } 6844 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6845 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6846 MatCheckPreallocated(mat, 2); 6847 6848 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6849 PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info)); 6850 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6851 PetscFunctionReturn(0); 6852 } 6853 6854 /*@C 6855 MatICCFactorSymbolic - Performs symbolic incomplete 6856 Cholesky factorization for a symmetric matrix. Use 6857 `MatCholeskyFactorNumeric()` to complete the factorization. 6858 6859 Collective on fact 6860 6861 Input Parameters: 6862 + fact - the factorized matrix obtained with `MatGetFactor()` 6863 . mat - the matrix to be factored 6864 . perm - row and column permutation 6865 - info - structure containing 6866 $ levels - number of levels of fill. 6867 $ expected fill - as ratio of original fill. 6868 6869 Output Parameter: 6870 . fact - the factored matrix 6871 6872 Level: developer 6873 6874 Notes: 6875 Most users should employ the `KSP` interface for linear solvers 6876 instead of working directly with matrix algebra routines such as this. 6877 See, e.g., `KSPCreate()`. 6878 6879 This uses the definition of level of fill as in Y. Saad, 2003 6880 6881 Developer Note: 6882 The Fortran interface is not autogenerated as the f90 6883 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6884 6885 References: 6886 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6887 6888 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6889 @*/ 6890 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6891 { 6892 PetscFunctionBegin; 6893 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6894 PetscValidType(mat, 2); 6895 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6896 PetscValidPointer(info, 4); 6897 PetscValidPointer(fact, 1); 6898 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6899 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6900 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6901 if (!(fact)->ops->iccfactorsymbolic) { 6902 MatSolverType stype; 6903 PetscCall(MatFactorGetSolverType(fact, &stype)); 6904 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype); 6905 } 6906 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6907 MatCheckPreallocated(mat, 2); 6908 6909 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6910 PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info)); 6911 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6912 PetscFunctionReturn(0); 6913 } 6914 6915 /*@C 6916 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6917 points to an array of valid matrices, they may be reused to store the new 6918 submatrices. 6919 6920 Collective on mat 6921 6922 Input Parameters: 6923 + mat - the matrix 6924 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6925 . irow, icol - index sets of rows and columns to extract 6926 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6927 6928 Output Parameter: 6929 . submat - the array of submatrices 6930 6931 Notes: 6932 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6933 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6934 to extract a parallel submatrix. 6935 6936 Some matrix types place restrictions on the row and column 6937 indices, such as that they be sorted or that they be equal to each other. 6938 6939 The index sets may not have duplicate entries. 6940 6941 When extracting submatrices from a parallel matrix, each processor can 6942 form a different submatrix by setting the rows and columns of its 6943 individual index sets according to the local submatrix desired. 6944 6945 When finished using the submatrices, the user should destroy 6946 them with `MatDestroySubMatrices()`. 6947 6948 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6949 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6950 6951 This routine creates the matrices in submat; you should NOT create them before 6952 calling it. It also allocates the array of matrix pointers submat. 6953 6954 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6955 request one row/column in a block, they must request all rows/columns that are in 6956 that block. For example, if the block size is 2 you cannot request just row 0 and 6957 column 0. 6958 6959 Fortran Note: 6960 The Fortran interface is slightly different from that given below; it 6961 requires one to pass in as submat a `Mat` (integer) array of size at least n+1. 6962 6963 Level: advanced 6964 6965 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6966 @*/ 6967 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 6968 { 6969 PetscInt i; 6970 PetscBool eq; 6971 6972 PetscFunctionBegin; 6973 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6974 PetscValidType(mat, 1); 6975 if (n) { 6976 PetscValidPointer(irow, 3); 6977 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 6978 PetscValidPointer(icol, 4); 6979 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 6980 } 6981 PetscValidPointer(submat, 6); 6982 if (n && scall == MAT_REUSE_MATRIX) { 6983 PetscValidPointer(*submat, 6); 6984 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 6985 } 6986 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6987 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6988 MatCheckPreallocated(mat, 1); 6989 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 6990 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 6991 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 6992 for (i = 0; i < n; i++) { 6993 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 6994 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 6995 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 6996 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 6997 if (mat->boundtocpu && mat->bindingpropagates) { 6998 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 6999 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7000 } 7001 #endif 7002 } 7003 PetscFunctionReturn(0); 7004 } 7005 7006 /*@C 7007 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7008 7009 Collective on mat 7010 7011 Input Parameters: 7012 + mat - the matrix 7013 . n - the number of submatrixes to be extracted 7014 . irow, icol - index sets of rows and columns to extract 7015 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7016 7017 Output Parameter: 7018 . submat - the array of submatrices 7019 7020 Level: advanced 7021 7022 Note: 7023 This is used by `PCGASM` 7024 7025 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7026 @*/ 7027 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7028 { 7029 PetscInt i; 7030 PetscBool eq; 7031 7032 PetscFunctionBegin; 7033 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7034 PetscValidType(mat, 1); 7035 if (n) { 7036 PetscValidPointer(irow, 3); 7037 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7038 PetscValidPointer(icol, 4); 7039 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7040 } 7041 PetscValidPointer(submat, 6); 7042 if (n && scall == MAT_REUSE_MATRIX) { 7043 PetscValidPointer(*submat, 6); 7044 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7045 } 7046 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7047 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7048 MatCheckPreallocated(mat, 1); 7049 7050 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7051 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7052 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7053 for (i = 0; i < n; i++) { 7054 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7055 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7056 } 7057 PetscFunctionReturn(0); 7058 } 7059 7060 /*@C 7061 MatDestroyMatrices - Destroys an array of matrices. 7062 7063 Collective on mat 7064 7065 Input Parameters: 7066 + n - the number of local matrices 7067 - mat - the matrices (note that this is a pointer to the array of matrices) 7068 7069 Level: advanced 7070 7071 Note: 7072 Frees not only the matrices, but also the array that contains the matrices 7073 In Fortran will not free the array. 7074 7075 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7076 @*/ 7077 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7078 { 7079 PetscInt i; 7080 7081 PetscFunctionBegin; 7082 if (!*mat) PetscFunctionReturn(0); 7083 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7084 PetscValidPointer(mat, 2); 7085 7086 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7087 7088 /* memory is allocated even if n = 0 */ 7089 PetscCall(PetscFree(*mat)); 7090 PetscFunctionReturn(0); 7091 } 7092 7093 /*@C 7094 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7095 7096 Collective on mat 7097 7098 Input Parameters: 7099 + n - the number of local matrices 7100 - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling 7101 sequence of MatCreateSubMatrices()) 7102 7103 Level: advanced 7104 7105 Note: 7106 Frees not only the matrices, but also the array that contains the matrices 7107 In Fortran will not free the array. 7108 7109 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7110 @*/ 7111 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7112 { 7113 Mat mat0; 7114 7115 PetscFunctionBegin; 7116 if (!*mat) PetscFunctionReturn(0); 7117 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7118 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7119 PetscValidPointer(mat, 2); 7120 7121 mat0 = (*mat)[0]; 7122 if (mat0 && mat0->ops->destroysubmatrices) { 7123 PetscCall((mat0->ops->destroysubmatrices)(n, mat)); 7124 } else { 7125 PetscCall(MatDestroyMatrices(n, mat)); 7126 } 7127 PetscFunctionReturn(0); 7128 } 7129 7130 /*@C 7131 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7132 7133 Collective on mat 7134 7135 Input Parameters: 7136 . mat - the matrix 7137 7138 Output Parameter: 7139 . matstruct - the sequential matrix with the nonzero structure of mat 7140 7141 Level: developer 7142 7143 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7144 @*/ 7145 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7146 { 7147 PetscFunctionBegin; 7148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7149 PetscValidPointer(matstruct, 2); 7150 7151 PetscValidType(mat, 1); 7152 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7153 MatCheckPreallocated(mat, 1); 7154 7155 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7156 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7157 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7158 PetscFunctionReturn(0); 7159 } 7160 7161 /*@C 7162 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7163 7164 Collective on mat 7165 7166 Input Parameters: 7167 . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling 7168 sequence of `MatGetSequentialNonzeroStructure()`) 7169 7170 Level: advanced 7171 7172 Note: 7173 Frees not only the matrices, but also the array that contains the matrices 7174 7175 .seealso: `Mat`, `MatGetSeqNonzeroStructure()` 7176 @*/ 7177 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7178 { 7179 PetscFunctionBegin; 7180 PetscValidPointer(mat, 1); 7181 PetscCall(MatDestroy(mat)); 7182 PetscFunctionReturn(0); 7183 } 7184 7185 /*@ 7186 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7187 replaces the index sets by larger ones that represent submatrices with 7188 additional overlap. 7189 7190 Collective on mat 7191 7192 Input Parameters: 7193 + mat - the matrix 7194 . n - the number of index sets 7195 . is - the array of index sets (these index sets will changed during the call) 7196 - ov - the additional overlap requested 7197 7198 Options Database: 7199 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7200 7201 Level: developer 7202 7203 Developer Note: 7204 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. 7205 7206 .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7207 @*/ 7208 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7209 { 7210 PetscInt i, bs, cbs; 7211 7212 PetscFunctionBegin; 7213 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7214 PetscValidType(mat, 1); 7215 PetscValidLogicalCollectiveInt(mat, n, 2); 7216 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7217 if (n) { 7218 PetscValidPointer(is, 3); 7219 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7220 } 7221 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7222 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7223 MatCheckPreallocated(mat, 1); 7224 7225 if (!ov || !n) PetscFunctionReturn(0); 7226 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7227 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7228 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7229 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7230 if (bs == cbs) { 7231 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7232 } 7233 PetscFunctionReturn(0); 7234 } 7235 7236 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7237 7238 /*@ 7239 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7240 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7241 additional overlap. 7242 7243 Collective on mat 7244 7245 Input Parameters: 7246 + mat - the matrix 7247 . n - the number of index sets 7248 . is - the array of index sets (these index sets will changed during the call) 7249 - ov - the additional overlap requested 7250 7251 ` Options Database: 7252 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7253 7254 Level: developer 7255 7256 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7257 @*/ 7258 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7259 { 7260 PetscInt i; 7261 7262 PetscFunctionBegin; 7263 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7264 PetscValidType(mat, 1); 7265 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7266 if (n) { 7267 PetscValidPointer(is, 3); 7268 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7269 } 7270 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7271 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7272 MatCheckPreallocated(mat, 1); 7273 if (!ov) PetscFunctionReturn(0); 7274 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7275 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7276 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7277 PetscFunctionReturn(0); 7278 } 7279 7280 /*@ 7281 MatGetBlockSize - Returns the matrix block size. 7282 7283 Not Collective 7284 7285 Input Parameter: 7286 . mat - the matrix 7287 7288 Output Parameter: 7289 . bs - block size 7290 7291 Notes: 7292 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7293 7294 If the block size has not been set yet this routine returns 1. 7295 7296 Level: intermediate 7297 7298 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7299 @*/ 7300 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7301 { 7302 PetscFunctionBegin; 7303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7304 PetscValidIntPointer(bs, 2); 7305 *bs = PetscAbs(mat->rmap->bs); 7306 PetscFunctionReturn(0); 7307 } 7308 7309 /*@ 7310 MatGetBlockSizes - Returns the matrix block row and column sizes. 7311 7312 Not Collective 7313 7314 Input Parameter: 7315 . mat - the matrix 7316 7317 Output Parameters: 7318 + rbs - row block size 7319 - cbs - column block size 7320 7321 Notes: 7322 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7323 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7324 7325 If a block size has not been set yet this routine returns 1. 7326 7327 Level: intermediate 7328 7329 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7330 @*/ 7331 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7332 { 7333 PetscFunctionBegin; 7334 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7335 if (rbs) PetscValidIntPointer(rbs, 2); 7336 if (cbs) PetscValidIntPointer(cbs, 3); 7337 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7338 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7339 PetscFunctionReturn(0); 7340 } 7341 7342 /*@ 7343 MatSetBlockSize - Sets the matrix block size. 7344 7345 Logically Collective on mat 7346 7347 Input Parameters: 7348 + mat - the matrix 7349 - bs - block size 7350 7351 Notes: 7352 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7353 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7354 7355 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7356 is compatible with the matrix local sizes. 7357 7358 Level: intermediate 7359 7360 .seealso: `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7361 @*/ 7362 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7363 { 7364 PetscFunctionBegin; 7365 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7366 PetscValidLogicalCollectiveInt(mat, bs, 2); 7367 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7368 PetscFunctionReturn(0); 7369 } 7370 7371 typedef struct { 7372 PetscInt n; 7373 IS *is; 7374 Mat *mat; 7375 PetscObjectState nonzerostate; 7376 Mat C; 7377 } EnvelopeData; 7378 7379 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7380 { 7381 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7382 PetscCall(PetscFree(edata->is)); 7383 PetscCall(PetscFree(edata)); 7384 return 0; 7385 } 7386 7387 /* 7388 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7389 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7390 7391 Collective on mat 7392 7393 Input Parameter: 7394 . mat - the matrix 7395 7396 Notes: 7397 There can be zeros within the blocks 7398 7399 The blocks can overlap between processes, including laying on more than two processes 7400 7401 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7402 */ 7403 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7404 { 7405 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7406 PetscInt *diag, *odiag, sc; 7407 VecScatter scatter; 7408 PetscScalar *seqv; 7409 const PetscScalar *parv; 7410 const PetscInt *ia, *ja; 7411 PetscBool set, flag, done; 7412 Mat AA = mat, A; 7413 MPI_Comm comm; 7414 PetscMPIInt rank, size, tag; 7415 MPI_Status status; 7416 PetscContainer container; 7417 EnvelopeData *edata; 7418 Vec seq, par; 7419 IS isglobal; 7420 7421 PetscFunctionBegin; 7422 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7423 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7424 if (!set || !flag) { 7425 /* TOO: only needs nonzero structure of transpose */ 7426 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7427 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7428 } 7429 PetscCall(MatAIJGetLocalMat(AA, &A)); 7430 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7431 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7432 7433 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7434 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7435 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7436 PetscCallMPI(MPI_Comm_size(comm, &size)); 7437 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7438 7439 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7440 7441 if (rank > 0) { 7442 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7443 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7444 } 7445 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7446 for (i = 0; i < n; i++) { 7447 env = PetscMax(env, ja[ia[i + 1] - 1]); 7448 II = rstart + i; 7449 if (env == II) { 7450 starts[lblocks] = tbs; 7451 sizes[lblocks++] = 1 + II - tbs; 7452 tbs = 1 + II; 7453 } 7454 } 7455 if (rank < size - 1) { 7456 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7457 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7458 } 7459 7460 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7461 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7462 PetscCall(MatDestroy(&A)); 7463 7464 PetscCall(PetscNew(&edata)); 7465 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7466 edata->n = lblocks; 7467 /* create IS needed for extracting blocks from the original matrix */ 7468 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7469 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7470 7471 /* Create the resulting inverse matrix structure with preallocation information */ 7472 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7473 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7474 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7475 PetscCall(MatSetType(edata->C, MATAIJ)); 7476 7477 /* Communicate the start and end of each row, from each block to the correct rank */ 7478 /* TODO: Use PetscSF instead of VecScatter */ 7479 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7480 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7481 PetscCall(VecGetArrayWrite(seq, &seqv)); 7482 for (PetscInt i = 0; i < lblocks; i++) { 7483 for (PetscInt j = 0; j < sizes[i]; j++) { 7484 seqv[cnt] = starts[i]; 7485 seqv[cnt + 1] = starts[i] + sizes[i]; 7486 cnt += 2; 7487 } 7488 } 7489 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7490 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7491 sc -= cnt; 7492 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7493 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7494 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7495 PetscCall(ISDestroy(&isglobal)); 7496 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7497 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7498 PetscCall(VecScatterDestroy(&scatter)); 7499 PetscCall(VecDestroy(&seq)); 7500 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7501 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7502 PetscCall(VecGetArrayRead(par, &parv)); 7503 cnt = 0; 7504 PetscCall(MatGetSize(mat, NULL, &n)); 7505 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7506 PetscInt start, end, d = 0, od = 0; 7507 7508 start = (PetscInt)PetscRealPart(parv[cnt]); 7509 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7510 cnt += 2; 7511 7512 if (start < cstart) { 7513 od += cstart - start + n - cend; 7514 d += cend - cstart; 7515 } else if (start < cend) { 7516 od += n - cend; 7517 d += cend - start; 7518 } else od += n - start; 7519 if (end <= cstart) { 7520 od -= cstart - end + n - cend; 7521 d -= cend - cstart; 7522 } else if (end < cend) { 7523 od -= n - cend; 7524 d -= cend - end; 7525 } else od -= n - end; 7526 7527 odiag[i] = od; 7528 diag[i] = d; 7529 } 7530 PetscCall(VecRestoreArrayRead(par, &parv)); 7531 PetscCall(VecDestroy(&par)); 7532 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7533 PetscCall(PetscFree2(diag, odiag)); 7534 PetscCall(PetscFree2(sizes, starts)); 7535 7536 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7537 PetscCall(PetscContainerSetPointer(container, edata)); 7538 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7539 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7540 PetscCall(PetscObjectDereference((PetscObject)container)); 7541 PetscFunctionReturn(0); 7542 } 7543 7544 /*@ 7545 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7546 7547 Collective on A 7548 7549 Input Parameters: 7550 . A - the matrix 7551 7552 Output Parameters: 7553 . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 7554 7555 Note: 7556 For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal. 7557 7558 Level: advanced 7559 7560 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7561 @*/ 7562 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7563 { 7564 PetscContainer container; 7565 EnvelopeData *edata; 7566 PetscObjectState nonzerostate; 7567 7568 PetscFunctionBegin; 7569 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7570 if (!container) { 7571 PetscCall(MatComputeVariableBlockEnvelope(A)); 7572 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7573 } 7574 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7575 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7576 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7577 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7578 7579 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7580 *C = edata->C; 7581 7582 for (PetscInt i = 0; i < edata->n; i++) { 7583 Mat D; 7584 PetscScalar *dvalues; 7585 7586 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7587 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7588 PetscCall(MatSeqDenseInvert(D)); 7589 PetscCall(MatDenseGetArray(D, &dvalues)); 7590 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7591 PetscCall(MatDestroy(&D)); 7592 } 7593 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7594 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7595 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7596 PetscFunctionReturn(0); 7597 } 7598 7599 /*@ 7600 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7601 7602 Logically Collective on mat 7603 7604 Input Parameters: 7605 + mat - the matrix 7606 . nblocks - the number of blocks on this process, each block can only exist on a single process 7607 - bsizes - the block sizes 7608 7609 Notes: 7610 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7611 7612 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. 7613 7614 Level: intermediate 7615 7616 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7617 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7618 @*/ 7619 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7620 { 7621 PetscInt i, ncnt = 0, nlocal; 7622 7623 PetscFunctionBegin; 7624 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7625 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7626 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7627 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7628 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); 7629 PetscCall(PetscFree(mat->bsizes)); 7630 mat->nblocks = nblocks; 7631 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7632 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7633 PetscFunctionReturn(0); 7634 } 7635 7636 /*@C 7637 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7638 7639 Logically Collective on mat 7640 7641 Input Parameter: 7642 . mat - the matrix 7643 7644 Output Parameters: 7645 + nblocks - the number of blocks on this process 7646 - bsizes - the block sizes 7647 7648 Fortran Note: 7649 Currently not supported from Fortran 7650 7651 Level: intermediate 7652 7653 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7654 @*/ 7655 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7656 { 7657 PetscFunctionBegin; 7658 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7659 *nblocks = mat->nblocks; 7660 *bsizes = mat->bsizes; 7661 PetscFunctionReturn(0); 7662 } 7663 7664 /*@ 7665 MatSetBlockSizes - Sets the matrix block row and column sizes. 7666 7667 Logically Collective on mat 7668 7669 Input Parameters: 7670 + mat - the matrix 7671 . rbs - row block size 7672 - cbs - column block size 7673 7674 Notes: 7675 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7676 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7677 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7678 7679 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7680 are compatible with the matrix local sizes. 7681 7682 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7683 7684 Level: intermediate 7685 7686 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7687 @*/ 7688 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7689 { 7690 PetscFunctionBegin; 7691 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7692 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7693 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7694 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7695 if (mat->rmap->refcnt) { 7696 ISLocalToGlobalMapping l2g = NULL; 7697 PetscLayout nmap = NULL; 7698 7699 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7700 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7701 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7702 mat->rmap = nmap; 7703 mat->rmap->mapping = l2g; 7704 } 7705 if (mat->cmap->refcnt) { 7706 ISLocalToGlobalMapping l2g = NULL; 7707 PetscLayout nmap = NULL; 7708 7709 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7710 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7711 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7712 mat->cmap = nmap; 7713 mat->cmap->mapping = l2g; 7714 } 7715 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7716 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7717 PetscFunctionReturn(0); 7718 } 7719 7720 /*@ 7721 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7722 7723 Logically Collective on mat 7724 7725 Input Parameters: 7726 + mat - the matrix 7727 . fromRow - matrix from which to copy row block size 7728 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7729 7730 Level: developer 7731 7732 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7733 @*/ 7734 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7735 { 7736 PetscFunctionBegin; 7737 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7738 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7739 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7740 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7741 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7742 PetscFunctionReturn(0); 7743 } 7744 7745 /*@ 7746 MatResidual - Default routine to calculate the residual r = b - Ax 7747 7748 Collective on mat 7749 7750 Input Parameters: 7751 + mat - the matrix 7752 . b - the right-hand-side 7753 - x - the approximate solution 7754 7755 Output Parameter: 7756 . r - location to store the residual 7757 7758 Level: developer 7759 7760 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7761 @*/ 7762 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7763 { 7764 PetscFunctionBegin; 7765 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7766 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7767 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7768 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7769 PetscValidType(mat, 1); 7770 MatCheckPreallocated(mat, 1); 7771 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7772 if (!mat->ops->residual) { 7773 PetscCall(MatMult(mat, x, r)); 7774 PetscCall(VecAYPX(r, -1.0, b)); 7775 } else { 7776 PetscUseTypeMethod(mat, residual, b, x, r); 7777 } 7778 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7779 PetscFunctionReturn(0); 7780 } 7781 7782 /*@C 7783 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7784 7785 Collective on mat 7786 7787 Input Parameters: 7788 + mat - the matrix 7789 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7790 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7791 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7792 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7793 always used. 7794 7795 Output Parameters: 7796 + n - number of local rows in the (possibly compressed) matrix, use NULL if not needed 7797 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix, use NULL if not needed 7798 . ja - the column indices, use NULL if not needed 7799 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7800 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7801 7802 Level: developer 7803 7804 Notes: 7805 You CANNOT change any of the ia[] or ja[] values. 7806 7807 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7808 7809 Fortran Notes: 7810 In Fortran use 7811 $ 7812 $ PetscInt ia(1), ja(1) 7813 $ PetscOffset iia, jja 7814 $ call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr) 7815 $ ! Access the ith and jth entries via ia(iia + i) and ja(jja + j) 7816 7817 or 7818 $ 7819 $ PetscInt, pointer :: ia(:),ja(:) 7820 $ call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7821 $ ! Access the ith and jth entries via ia(i) and ja(j) 7822 7823 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7824 @*/ 7825 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7826 { 7827 PetscFunctionBegin; 7828 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7829 PetscValidType(mat, 1); 7830 if (n) PetscValidIntPointer(n, 5); 7831 if (ia) PetscValidPointer(ia, 6); 7832 if (ja) PetscValidPointer(ja, 7); 7833 if (done) PetscValidBoolPointer(done, 8); 7834 MatCheckPreallocated(mat, 1); 7835 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7836 else { 7837 if (done) *done = PETSC_TRUE; 7838 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7839 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7840 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7841 } 7842 PetscFunctionReturn(0); 7843 } 7844 7845 /*@C 7846 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7847 7848 Collective on mat 7849 7850 Input Parameters: 7851 + mat - the matrix 7852 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7853 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7854 symmetrized 7855 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7856 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7857 always used. 7858 . n - number of columns in the (possibly compressed) matrix 7859 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7860 - ja - the row indices 7861 7862 Output Parameters: 7863 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7864 7865 Level: developer 7866 7867 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7868 @*/ 7869 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7870 { 7871 PetscFunctionBegin; 7872 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7873 PetscValidType(mat, 1); 7874 PetscValidIntPointer(n, 5); 7875 if (ia) PetscValidPointer(ia, 6); 7876 if (ja) PetscValidPointer(ja, 7); 7877 PetscValidBoolPointer(done, 8); 7878 MatCheckPreallocated(mat, 1); 7879 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7880 else { 7881 *done = PETSC_TRUE; 7882 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7883 } 7884 PetscFunctionReturn(0); 7885 } 7886 7887 /*@C 7888 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7889 7890 Collective on mat 7891 7892 Input Parameters: 7893 + mat - the matrix 7894 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7895 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7896 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7897 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7898 always used. 7899 . n - size of (possibly compressed) matrix 7900 . ia - the row pointers 7901 - ja - the column indices 7902 7903 Output Parameters: 7904 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7905 7906 Note: 7907 This routine zeros out n, ia, and ja. This is to prevent accidental 7908 us of the array after it has been restored. If you pass NULL, it will 7909 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7910 7911 Level: developer 7912 7913 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7914 @*/ 7915 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7916 { 7917 PetscFunctionBegin; 7918 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7919 PetscValidType(mat, 1); 7920 if (ia) PetscValidPointer(ia, 6); 7921 if (ja) PetscValidPointer(ja, 7); 7922 if (done) PetscValidBoolPointer(done, 8); 7923 MatCheckPreallocated(mat, 1); 7924 7925 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 7926 else { 7927 if (done) *done = PETSC_TRUE; 7928 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7929 if (n) *n = 0; 7930 if (ia) *ia = NULL; 7931 if (ja) *ja = NULL; 7932 } 7933 PetscFunctionReturn(0); 7934 } 7935 7936 /*@C 7937 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 7938 7939 Collective on Mat 7940 7941 Input Parameters: 7942 + mat - the matrix 7943 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7944 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7945 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7946 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7947 always used. 7948 7949 Output Parameters: 7950 + n - size of (possibly compressed) matrix 7951 . ia - the column pointers 7952 . ja - the row indices 7953 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7954 7955 Level: developer 7956 7957 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()` 7958 @*/ 7959 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7960 { 7961 PetscFunctionBegin; 7962 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7963 PetscValidType(mat, 1); 7964 if (ia) PetscValidPointer(ia, 6); 7965 if (ja) PetscValidPointer(ja, 7); 7966 PetscValidBoolPointer(done, 8); 7967 MatCheckPreallocated(mat, 1); 7968 7969 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 7970 else { 7971 *done = PETSC_TRUE; 7972 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7973 if (n) *n = 0; 7974 if (ia) *ia = NULL; 7975 if (ja) *ja = NULL; 7976 } 7977 PetscFunctionReturn(0); 7978 } 7979 7980 /*@C 7981 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 7982 7983 Collective on mat 7984 7985 Input Parameters: 7986 + mat - the matrix 7987 . ncolors - max color value 7988 . n - number of entries in colorarray 7989 - colorarray - array indicating color for each column 7990 7991 Output Parameters: 7992 . iscoloring - coloring generated using colorarray information 7993 7994 Level: developer 7995 7996 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()` 7997 @*/ 7998 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 7999 { 8000 PetscFunctionBegin; 8001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8002 PetscValidType(mat, 1); 8003 PetscValidIntPointer(colorarray, 4); 8004 PetscValidPointer(iscoloring, 5); 8005 MatCheckPreallocated(mat, 1); 8006 8007 if (!mat->ops->coloringpatch) { 8008 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8009 } else { 8010 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8011 } 8012 PetscFunctionReturn(0); 8013 } 8014 8015 /*@ 8016 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8017 8018 Logically Collective on mat 8019 8020 Input Parameter: 8021 . mat - the factored matrix to be reset 8022 8023 Notes: 8024 This routine should be used only with factored matrices formed by in-place 8025 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8026 format). This option can save memory, for example, when solving nonlinear 8027 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8028 ILU(0) preconditioner. 8029 8030 Note that one can specify in-place ILU(0) factorization by calling 8031 .vb 8032 PCType(pc,PCILU); 8033 PCFactorSeUseInPlace(pc); 8034 .ve 8035 or by using the options -pc_type ilu -pc_factor_in_place 8036 8037 In-place factorization ILU(0) can also be used as a local 8038 solver for the blocks within the block Jacobi or additive Schwarz 8039 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8040 for details on setting local solver options. 8041 8042 Most users should employ the `KSP` interface for linear solvers 8043 instead of working directly with matrix algebra routines such as this. 8044 See, e.g., `KSPCreate()`. 8045 8046 Level: developer 8047 8048 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8049 @*/ 8050 PetscErrorCode MatSetUnfactored(Mat mat) 8051 { 8052 PetscFunctionBegin; 8053 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8054 PetscValidType(mat, 1); 8055 MatCheckPreallocated(mat, 1); 8056 mat->factortype = MAT_FACTOR_NONE; 8057 if (!mat->ops->setunfactored) PetscFunctionReturn(0); 8058 PetscUseTypeMethod(mat, setunfactored); 8059 PetscFunctionReturn(0); 8060 } 8061 8062 /*MC 8063 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8064 8065 Synopsis: 8066 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8067 8068 Not collective 8069 8070 Input Parameter: 8071 . x - matrix 8072 8073 Output Parameters: 8074 + xx_v - the Fortran pointer to the array 8075 - ierr - error code 8076 8077 Example of Usage: 8078 .vb 8079 PetscScalar, pointer xx_v(:,:) 8080 .... 8081 call MatDenseGetArrayF90(x,xx_v,ierr) 8082 a = xx_v(3) 8083 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8084 .ve 8085 8086 Level: advanced 8087 8088 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8089 8090 M*/ 8091 8092 /*MC 8093 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8094 accessed with `MatDenseGetArrayF90()`. 8095 8096 Synopsis: 8097 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8098 8099 Not collective 8100 8101 Input Parameters: 8102 + x - matrix 8103 - xx_v - the Fortran90 pointer to the array 8104 8105 Output Parameter: 8106 . ierr - error code 8107 8108 Example of Usage: 8109 .vb 8110 PetscScalar, pointer xx_v(:,:) 8111 .... 8112 call MatDenseGetArrayF90(x,xx_v,ierr) 8113 a = xx_v(3) 8114 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8115 .ve 8116 8117 Level: advanced 8118 8119 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8120 8121 M*/ 8122 8123 /*MC 8124 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8125 8126 Synopsis: 8127 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8128 8129 Not collective 8130 8131 Input Parameter: 8132 . x - matrix 8133 8134 Output Parameters: 8135 + xx_v - the Fortran pointer to the array 8136 - ierr - error code 8137 8138 Example of Usage: 8139 .vb 8140 PetscScalar, pointer xx_v(:) 8141 .... 8142 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8143 a = xx_v(3) 8144 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8145 .ve 8146 8147 Level: advanced 8148 8149 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8150 8151 M*/ 8152 8153 /*MC 8154 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8155 accessed with `MatSeqAIJGetArrayF90()`. 8156 8157 Synopsis: 8158 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8159 8160 Not collective 8161 8162 Input Parameters: 8163 + x - matrix 8164 - xx_v - the Fortran90 pointer to the array 8165 8166 Output Parameter: 8167 . ierr - error code 8168 8169 Example of Usage: 8170 .vb 8171 PetscScalar, pointer xx_v(:) 8172 .... 8173 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8174 a = xx_v(3) 8175 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8176 .ve 8177 8178 Level: advanced 8179 8180 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8181 8182 M*/ 8183 8184 /*@ 8185 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8186 as the original matrix. 8187 8188 Collective on mat 8189 8190 Input Parameters: 8191 + mat - the original matrix 8192 . isrow - parallel IS containing the rows this processor should obtain 8193 . 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. 8194 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8195 8196 Output Parameter: 8197 . newmat - the new submatrix, of the same type as the old 8198 8199 Level: advanced 8200 8201 Notes: 8202 The submatrix will be able to be multiplied with vectors using the same layout as iscol. 8203 8204 Some matrix types place restrictions on the row and column indices, such 8205 as that they be sorted or that they be equal to each other. 8206 8207 The index sets may not have duplicate entries. 8208 8209 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8210 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8211 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8212 will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when 8213 you are finished using it. 8214 8215 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8216 the input matrix. 8217 8218 If iscol is NULL then all columns are obtained (not supported in Fortran). 8219 8220 Example usage: 8221 Consider the following 8x8 matrix with 34 non-zero values, that is 8222 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8223 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8224 as follows: 8225 8226 .vb 8227 1 2 0 | 0 3 0 | 0 4 8228 Proc0 0 5 6 | 7 0 0 | 8 0 8229 9 0 10 | 11 0 0 | 12 0 8230 ------------------------------------- 8231 13 0 14 | 15 16 17 | 0 0 8232 Proc1 0 18 0 | 19 20 21 | 0 0 8233 0 0 0 | 22 23 0 | 24 0 8234 ------------------------------------- 8235 Proc2 25 26 27 | 0 0 28 | 29 0 8236 30 0 0 | 31 32 33 | 0 34 8237 .ve 8238 8239 Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8240 8241 .vb 8242 2 0 | 0 3 0 | 0 8243 Proc0 5 6 | 7 0 0 | 8 8244 ------------------------------- 8245 Proc1 18 0 | 19 20 21 | 0 8246 ------------------------------- 8247 Proc2 26 27 | 0 0 28 | 29 8248 0 0 | 31 32 33 | 0 8249 .ve 8250 8251 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8252 @*/ 8253 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8254 { 8255 PetscMPIInt size; 8256 Mat *local; 8257 IS iscoltmp; 8258 PetscBool flg; 8259 8260 PetscFunctionBegin; 8261 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8262 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8263 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8264 PetscValidPointer(newmat, 5); 8265 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8266 PetscValidType(mat, 1); 8267 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8268 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8269 8270 MatCheckPreallocated(mat, 1); 8271 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8272 8273 if (!iscol || isrow == iscol) { 8274 PetscBool stride; 8275 PetscMPIInt grabentirematrix = 0, grab; 8276 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8277 if (stride) { 8278 PetscInt first, step, n, rstart, rend; 8279 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8280 if (step == 1) { 8281 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8282 if (rstart == first) { 8283 PetscCall(ISGetLocalSize(isrow, &n)); 8284 if (n == rend - rstart) grabentirematrix = 1; 8285 } 8286 } 8287 } 8288 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8289 if (grab) { 8290 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8291 if (cll == MAT_INITIAL_MATRIX) { 8292 *newmat = mat; 8293 PetscCall(PetscObjectReference((PetscObject)mat)); 8294 } 8295 PetscFunctionReturn(0); 8296 } 8297 } 8298 8299 if (!iscol) { 8300 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8301 } else { 8302 iscoltmp = iscol; 8303 } 8304 8305 /* if original matrix is on just one processor then use submatrix generated */ 8306 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8307 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8308 goto setproperties; 8309 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8310 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8311 *newmat = *local; 8312 PetscCall(PetscFree(local)); 8313 goto setproperties; 8314 } else if (!mat->ops->createsubmatrix) { 8315 /* Create a new matrix type that implements the operation using the full matrix */ 8316 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8317 switch (cll) { 8318 case MAT_INITIAL_MATRIX: 8319 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8320 break; 8321 case MAT_REUSE_MATRIX: 8322 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8323 break; 8324 default: 8325 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8326 } 8327 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8328 goto setproperties; 8329 } 8330 8331 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8332 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8333 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8334 8335 setproperties: 8336 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8337 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8338 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8339 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8340 PetscFunctionReturn(0); 8341 } 8342 8343 /*@ 8344 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8345 8346 Not Collective 8347 8348 Input Parameters: 8349 + A - the matrix we wish to propagate options from 8350 - B - the matrix we wish to propagate options to 8351 8352 Level: beginner 8353 8354 Note: 8355 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8356 8357 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8358 @*/ 8359 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8360 { 8361 PetscFunctionBegin; 8362 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8363 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8364 B->symmetry_eternal = A->symmetry_eternal; 8365 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8366 B->symmetric = A->symmetric; 8367 B->structurally_symmetric = A->structurally_symmetric; 8368 B->spd = A->spd; 8369 B->hermitian = A->hermitian; 8370 PetscFunctionReturn(0); 8371 } 8372 8373 /*@ 8374 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8375 used during the assembly process to store values that belong to 8376 other processors. 8377 8378 Not Collective 8379 8380 Input Parameters: 8381 + mat - the matrix 8382 . size - the initial size of the stash. 8383 - bsize - the initial size of the block-stash(if used). 8384 8385 Options Database Keys: 8386 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8387 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8388 8389 Level: intermediate 8390 8391 Notes: 8392 The block-stash is used for values set with `MatSetValuesBlocked()` while 8393 the stash is used for values set with `MatSetValues()` 8394 8395 Run with the option -info and look for output of the form 8396 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8397 to determine the appropriate value, MM, to use for size and 8398 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8399 to determine the value, BMM to use for bsize 8400 8401 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8402 @*/ 8403 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8404 { 8405 PetscFunctionBegin; 8406 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8407 PetscValidType(mat, 1); 8408 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8409 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8410 PetscFunctionReturn(0); 8411 } 8412 8413 /*@ 8414 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8415 the matrix 8416 8417 Neighbor-wise Collective on mat 8418 8419 Input Parameters: 8420 + mat - the matrix 8421 . x,y - the vectors 8422 - w - where the result is stored 8423 8424 Level: intermediate 8425 8426 Notes: 8427 w may be the same vector as y. 8428 8429 This allows one to use either the restriction or interpolation (its transpose) 8430 matrix to do the interpolation 8431 8432 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8433 @*/ 8434 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8435 { 8436 PetscInt M, N, Ny; 8437 8438 PetscFunctionBegin; 8439 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8440 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8441 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8442 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8443 PetscCall(MatGetSize(A, &M, &N)); 8444 PetscCall(VecGetSize(y, &Ny)); 8445 if (M == Ny) { 8446 PetscCall(MatMultAdd(A, x, y, w)); 8447 } else { 8448 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8449 } 8450 PetscFunctionReturn(0); 8451 } 8452 8453 /*@ 8454 MatInterpolate - y = A*x or A'*x depending on the shape of 8455 the matrix 8456 8457 Neighbor-wise Collective on mat 8458 8459 Input Parameters: 8460 + mat - the matrix 8461 - x,y - the vectors 8462 8463 Level: intermediate 8464 8465 Note: 8466 This allows one to use either the restriction or interpolation (its transpose) 8467 matrix to do the interpolation 8468 8469 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8470 @*/ 8471 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8472 { 8473 PetscInt M, N, Ny; 8474 8475 PetscFunctionBegin; 8476 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8477 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8478 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8479 PetscCall(MatGetSize(A, &M, &N)); 8480 PetscCall(VecGetSize(y, &Ny)); 8481 if (M == Ny) { 8482 PetscCall(MatMult(A, x, y)); 8483 } else { 8484 PetscCall(MatMultTranspose(A, x, y)); 8485 } 8486 PetscFunctionReturn(0); 8487 } 8488 8489 /*@ 8490 MatRestrict - y = A*x or A'*x 8491 8492 Neighbor-wise Collective on Mat 8493 8494 Input Parameters: 8495 + mat - the matrix 8496 - x,y - the vectors 8497 8498 Level: intermediate 8499 8500 Note: 8501 This allows one to use either the restriction or interpolation (its transpose) 8502 matrix to do the restriction 8503 8504 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8505 @*/ 8506 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8507 { 8508 PetscInt M, N, Ny; 8509 8510 PetscFunctionBegin; 8511 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8512 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8513 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8514 PetscCall(MatGetSize(A, &M, &N)); 8515 PetscCall(VecGetSize(y, &Ny)); 8516 if (M == Ny) { 8517 PetscCall(MatMult(A, x, y)); 8518 } else { 8519 PetscCall(MatMultTranspose(A, x, y)); 8520 } 8521 PetscFunctionReturn(0); 8522 } 8523 8524 /*@ 8525 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8526 8527 Neighbor-wise Collective on Mat 8528 8529 Input Parameters: 8530 + mat - the matrix 8531 - w, x - the input dense matrices 8532 8533 Output Parameters: 8534 . y - the output dense matrix 8535 8536 Level: intermediate 8537 8538 Note: 8539 This allows one to use either the restriction or interpolation (its transpose) 8540 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8541 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8542 8543 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8544 @*/ 8545 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8546 { 8547 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8548 PetscBool trans = PETSC_TRUE; 8549 MatReuse reuse = MAT_INITIAL_MATRIX; 8550 8551 PetscFunctionBegin; 8552 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8553 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8554 PetscValidType(x, 2); 8555 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8556 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8557 PetscCall(MatGetSize(A, &M, &N)); 8558 PetscCall(MatGetSize(x, &Mx, &Nx)); 8559 if (N == Mx) trans = PETSC_FALSE; 8560 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); 8561 Mo = trans ? N : M; 8562 if (*y) { 8563 PetscCall(MatGetSize(*y, &My, &Ny)); 8564 if (Mo == My && Nx == Ny) { 8565 reuse = MAT_REUSE_MATRIX; 8566 } else { 8567 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); 8568 PetscCall(MatDestroy(y)); 8569 } 8570 } 8571 8572 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8573 PetscBool flg; 8574 8575 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8576 if (w) { 8577 PetscInt My, Ny, Mw, Nw; 8578 8579 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8580 PetscCall(MatGetSize(*y, &My, &Ny)); 8581 PetscCall(MatGetSize(w, &Mw, &Nw)); 8582 if (!flg || My != Mw || Ny != Nw) w = NULL; 8583 } 8584 if (!w) { 8585 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8586 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8587 PetscCall(PetscObjectDereference((PetscObject)w)); 8588 } else { 8589 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8590 } 8591 } 8592 if (!trans) { 8593 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8594 } else { 8595 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8596 } 8597 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8598 PetscFunctionReturn(0); 8599 } 8600 8601 /*@ 8602 MatMatInterpolate - Y = A*X or A'*X 8603 8604 Neighbor-wise Collective on Mat 8605 8606 Input Parameters: 8607 + mat - the matrix 8608 - x - the input dense matrix 8609 8610 Output Parameters: 8611 . y - the output dense matrix 8612 8613 Level: intermediate 8614 8615 Note: 8616 This allows one to use either the restriction or interpolation (its transpose) 8617 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8618 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8619 8620 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8621 @*/ 8622 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8623 { 8624 PetscFunctionBegin; 8625 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8626 PetscFunctionReturn(0); 8627 } 8628 8629 /*@ 8630 MatMatRestrict - Y = A*X or A'*X 8631 8632 Neighbor-wise Collective on Mat 8633 8634 Input Parameters: 8635 + mat - the matrix 8636 - x - the input dense matrix 8637 8638 Output Parameters: 8639 . y - the output dense matrix 8640 8641 Level: intermediate 8642 8643 Note: 8644 This allows one to use either the restriction or interpolation (its transpose) 8645 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8646 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8647 8648 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8649 @*/ 8650 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8651 { 8652 PetscFunctionBegin; 8653 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8654 PetscFunctionReturn(0); 8655 } 8656 8657 /*@ 8658 MatGetNullSpace - retrieves the null space of a matrix. 8659 8660 Logically Collective on mat 8661 8662 Input Parameters: 8663 + mat - the matrix 8664 - nullsp - the null space object 8665 8666 Level: developer 8667 8668 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8669 @*/ 8670 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8671 { 8672 PetscFunctionBegin; 8673 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8674 PetscValidPointer(nullsp, 2); 8675 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8676 PetscFunctionReturn(0); 8677 } 8678 8679 /*@ 8680 MatSetNullSpace - attaches a null space to a matrix. 8681 8682 Logically Collective on mat 8683 8684 Input Parameters: 8685 + mat - the matrix 8686 - nullsp - the null space object 8687 8688 Level: advanced 8689 8690 Notes: 8691 This null space is used by the `KSP` linear solvers to solve singular systems. 8692 8693 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 8694 8695 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 8696 to zero but the linear system will still be solved in a least squares sense. 8697 8698 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8699 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). 8700 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 8701 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 8702 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). 8703 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8704 8705 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8706 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8707 routine also automatically calls `MatSetTransposeNullSpace()`. 8708 8709 The user should call `MatNullSpaceDestroy()`. 8710 8711 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8712 `KSPSetPCSide()` 8713 @*/ 8714 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8715 { 8716 PetscFunctionBegin; 8717 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8718 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8719 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8720 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8721 mat->nullsp = nullsp; 8722 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8723 PetscFunctionReturn(0); 8724 } 8725 8726 /*@ 8727 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8728 8729 Logically Collective on mat 8730 8731 Input Parameters: 8732 + mat - the matrix 8733 - nullsp - the null space object 8734 8735 Level: developer 8736 8737 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8738 @*/ 8739 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8740 { 8741 PetscFunctionBegin; 8742 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8743 PetscValidType(mat, 1); 8744 PetscValidPointer(nullsp, 2); 8745 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8746 PetscFunctionReturn(0); 8747 } 8748 8749 /*@ 8750 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8751 8752 Logically Collective on mat 8753 8754 Input Parameters: 8755 + mat - the matrix 8756 - nullsp - the null space object 8757 8758 Level: advanced 8759 8760 Notes: 8761 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8762 8763 See `MatSetNullSpace()` 8764 8765 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8766 @*/ 8767 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8768 { 8769 PetscFunctionBegin; 8770 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8771 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8772 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8773 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8774 mat->transnullsp = nullsp; 8775 PetscFunctionReturn(0); 8776 } 8777 8778 /*@ 8779 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8780 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8781 8782 Logically Collective on mat 8783 8784 Input Parameters: 8785 + mat - the matrix 8786 - nullsp - the null space object 8787 8788 Level: advanced 8789 8790 Notes: 8791 Overwrites any previous near null space that may have been attached 8792 8793 You can remove the null space by calling this routine with an nullsp of NULL 8794 8795 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8796 @*/ 8797 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8798 { 8799 PetscFunctionBegin; 8800 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8801 PetscValidType(mat, 1); 8802 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8803 MatCheckPreallocated(mat, 1); 8804 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8805 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8806 mat->nearnullsp = nullsp; 8807 PetscFunctionReturn(0); 8808 } 8809 8810 /*@ 8811 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8812 8813 Not Collective 8814 8815 Input Parameter: 8816 . mat - the matrix 8817 8818 Output Parameter: 8819 . nullsp - the null space object, NULL if not set 8820 8821 Level: advanced 8822 8823 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8824 @*/ 8825 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8826 { 8827 PetscFunctionBegin; 8828 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8829 PetscValidType(mat, 1); 8830 PetscValidPointer(nullsp, 2); 8831 MatCheckPreallocated(mat, 1); 8832 *nullsp = mat->nearnullsp; 8833 PetscFunctionReturn(0); 8834 } 8835 8836 /*@C 8837 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8838 8839 Collective on mat 8840 8841 Input Parameters: 8842 + mat - the matrix 8843 . row - row/column permutation 8844 . fill - expected fill factor >= 1.0 8845 - level - level of fill, for ICC(k) 8846 8847 Notes: 8848 Probably really in-place only when level of fill is zero, otherwise allocates 8849 new space to store factored matrix and deletes previous memory. 8850 8851 Most users should employ the `KSP` interface for linear solvers 8852 instead of working directly with matrix algebra routines such as this. 8853 See, e.g., `KSPCreate()`. 8854 8855 Level: developer 8856 8857 Developer Note: 8858 The Fortran interface is not autogenerated as the f90 8859 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8860 8861 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8862 @*/ 8863 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8864 { 8865 PetscFunctionBegin; 8866 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8867 PetscValidType(mat, 1); 8868 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8869 PetscValidPointer(info, 3); 8870 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8871 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8872 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8873 MatCheckPreallocated(mat, 1); 8874 PetscUseTypeMethod(mat, iccfactor, row, info); 8875 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8876 PetscFunctionReturn(0); 8877 } 8878 8879 /*@ 8880 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8881 ghosted ones. 8882 8883 Not Collective 8884 8885 Input Parameters: 8886 + mat - the matrix 8887 - diag - the diagonal values, including ghost ones 8888 8889 Level: developer 8890 8891 Notes: 8892 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8893 8894 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8895 8896 .seealso: `MatDiagonalScale()` 8897 @*/ 8898 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8899 { 8900 PetscMPIInt size; 8901 8902 PetscFunctionBegin; 8903 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8904 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8905 PetscValidType(mat, 1); 8906 8907 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8908 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8909 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8910 if (size == 1) { 8911 PetscInt n, m; 8912 PetscCall(VecGetSize(diag, &n)); 8913 PetscCall(MatGetSize(mat, NULL, &m)); 8914 if (m == n) { 8915 PetscCall(MatDiagonalScale(mat, NULL, diag)); 8916 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 8917 } else { 8918 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 8919 } 8920 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 8921 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8922 PetscFunctionReturn(0); 8923 } 8924 8925 /*@ 8926 MatGetInertia - Gets the inertia from a factored matrix 8927 8928 Collective on mat 8929 8930 Input Parameter: 8931 . mat - the matrix 8932 8933 Output Parameters: 8934 + nneg - number of negative eigenvalues 8935 . nzero - number of zero eigenvalues 8936 - npos - number of positive eigenvalues 8937 8938 Level: advanced 8939 8940 Note: 8941 Matrix must have been factored by `MatCholeskyFactor()` 8942 8943 .seealso: `MatGetFactor()`, `MatCholeskyFactor()` 8944 @*/ 8945 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 8946 { 8947 PetscFunctionBegin; 8948 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8949 PetscValidType(mat, 1); 8950 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 8951 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 8952 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 8953 PetscFunctionReturn(0); 8954 } 8955 8956 /* ----------------------------------------------------------------*/ 8957 /*@C 8958 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 8959 8960 Neighbor-wise Collective on mat 8961 8962 Input Parameters: 8963 + mat - the factored matrix obtained with `MatGetFactor()` 8964 - b - the right-hand-side vectors 8965 8966 Output Parameter: 8967 . x - the result vectors 8968 8969 Note: 8970 The vectors b and x cannot be the same. I.e., one cannot 8971 call `MatSolves`(A,x,x). 8972 8973 Level: developer 8974 8975 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 8976 @*/ 8977 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 8978 { 8979 PetscFunctionBegin; 8980 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8981 PetscValidType(mat, 1); 8982 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 8983 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 8984 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 8985 8986 MatCheckPreallocated(mat, 1); 8987 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 8988 PetscUseTypeMethod(mat, solves, b, x); 8989 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 8990 PetscFunctionReturn(0); 8991 } 8992 8993 /*@ 8994 MatIsSymmetric - Test whether a matrix is symmetric 8995 8996 Collective on mat 8997 8998 Input Parameters: 8999 + A - the matrix to test 9000 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9001 9002 Output Parameters: 9003 . flg - the result 9004 9005 Notes: 9006 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9007 9008 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9009 9010 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9011 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9012 9013 Level: intermediate 9014 9015 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9016 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9017 @*/ 9018 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9019 { 9020 PetscFunctionBegin; 9021 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9022 PetscValidBoolPointer(flg, 3); 9023 9024 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9025 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9026 else { 9027 if (!A->ops->issymmetric) { 9028 MatType mattype; 9029 PetscCall(MatGetType(A, &mattype)); 9030 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype); 9031 } 9032 PetscUseTypeMethod(A, issymmetric, tol, flg); 9033 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9034 } 9035 PetscFunctionReturn(0); 9036 } 9037 9038 /*@ 9039 MatIsHermitian - Test whether a matrix is Hermitian 9040 9041 Collective on Mat 9042 9043 Input Parameters: 9044 + A - the matrix to test 9045 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9046 9047 Output Parameters: 9048 . flg - the result 9049 9050 Level: intermediate 9051 9052 Notes: 9053 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9054 9055 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9056 9057 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9058 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9059 9060 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9061 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9062 @*/ 9063 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9064 { 9065 PetscFunctionBegin; 9066 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9067 PetscValidBoolPointer(flg, 3); 9068 9069 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9070 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9071 else { 9072 if (!A->ops->ishermitian) { 9073 MatType mattype; 9074 PetscCall(MatGetType(A, &mattype)); 9075 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype); 9076 } 9077 PetscUseTypeMethod(A, ishermitian, tol, flg); 9078 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9079 } 9080 PetscFunctionReturn(0); 9081 } 9082 9083 /*@ 9084 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9085 9086 Not Collective 9087 9088 Input Parameter: 9089 . A - the matrix to check 9090 9091 Output Parameters: 9092 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9093 - flg - the result (only valid if set is `PETSC_TRUE`) 9094 9095 Level: advanced 9096 9097 Notes: 9098 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9099 if you want it explicitly checked 9100 9101 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9102 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9103 9104 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9105 @*/ 9106 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9107 { 9108 PetscFunctionBegin; 9109 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9110 PetscValidBoolPointer(set, 2); 9111 PetscValidBoolPointer(flg, 3); 9112 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9113 *set = PETSC_TRUE; 9114 *flg = PetscBool3ToBool(A->symmetric); 9115 } else { 9116 *set = PETSC_FALSE; 9117 } 9118 PetscFunctionReturn(0); 9119 } 9120 9121 /*@ 9122 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9123 9124 Not Collective 9125 9126 Input Parameter: 9127 . A - the matrix to check 9128 9129 Output Parameters: 9130 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9131 - flg - the result (only valid if set is `PETSC_TRUE`) 9132 9133 Level: advanced 9134 9135 Notes: 9136 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9137 9138 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9139 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9140 9141 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9142 @*/ 9143 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9144 { 9145 PetscFunctionBegin; 9146 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9147 PetscValidBoolPointer(set, 2); 9148 PetscValidBoolPointer(flg, 3); 9149 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9150 *set = PETSC_TRUE; 9151 *flg = PetscBool3ToBool(A->spd); 9152 } else { 9153 *set = PETSC_FALSE; 9154 } 9155 PetscFunctionReturn(0); 9156 } 9157 9158 /*@ 9159 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9160 9161 Not Collective 9162 9163 Input Parameter: 9164 . A - the matrix to check 9165 9166 Output Parameters: 9167 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9168 - flg - the result (only valid if set is `PETSC_TRUE`) 9169 9170 Level: advanced 9171 9172 Notes: 9173 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9174 if you want it explicitly checked 9175 9176 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9177 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9178 9179 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9180 @*/ 9181 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9182 { 9183 PetscFunctionBegin; 9184 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9185 PetscValidBoolPointer(set, 2); 9186 PetscValidBoolPointer(flg, 3); 9187 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9188 *set = PETSC_TRUE; 9189 *flg = PetscBool3ToBool(A->hermitian); 9190 } else { 9191 *set = PETSC_FALSE; 9192 } 9193 PetscFunctionReturn(0); 9194 } 9195 9196 /*@ 9197 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9198 9199 Collective on Mat 9200 9201 Input Parameter: 9202 . A - the matrix to test 9203 9204 Output Parameters: 9205 . flg - the result 9206 9207 Notes: 9208 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9209 9210 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 9211 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9212 9213 Level: intermediate 9214 9215 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9216 @*/ 9217 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9218 { 9219 PetscFunctionBegin; 9220 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9221 PetscValidBoolPointer(flg, 2); 9222 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9223 *flg = PetscBool3ToBool(A->structurally_symmetric); 9224 } else { 9225 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9226 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9227 } 9228 PetscFunctionReturn(0); 9229 } 9230 9231 /*@ 9232 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9233 9234 Not Collective 9235 9236 Input Parameter: 9237 . A - the matrix to check 9238 9239 Output Parameters: 9240 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9241 - flg - the result (only valid if set is PETSC_TRUE) 9242 9243 Level: advanced 9244 9245 Notes: 9246 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 9247 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9248 9249 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9250 9251 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9252 @*/ 9253 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9254 { 9255 PetscFunctionBegin; 9256 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9257 PetscValidBoolPointer(set, 2); 9258 PetscValidBoolPointer(flg, 3); 9259 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9260 *set = PETSC_TRUE; 9261 *flg = PetscBool3ToBool(A->structurally_symmetric); 9262 } else { 9263 *set = PETSC_FALSE; 9264 } 9265 PetscFunctionReturn(0); 9266 } 9267 9268 /*@ 9269 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9270 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9271 9272 Not collective 9273 9274 Input Parameter: 9275 . mat - the matrix 9276 9277 Output Parameters: 9278 + nstash - the size of the stash 9279 . reallocs - the number of additional mallocs incurred. 9280 . bnstash - the size of the block stash 9281 - breallocs - the number of additional mallocs incurred.in the block stash 9282 9283 Level: advanced 9284 9285 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9286 @*/ 9287 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9288 { 9289 PetscFunctionBegin; 9290 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9291 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9292 PetscFunctionReturn(0); 9293 } 9294 9295 /*@C 9296 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9297 parallel layout, `PetscLayout` for rows and columns 9298 9299 Collective on mat 9300 9301 Input Parameter: 9302 . mat - the matrix 9303 9304 Output Parameters: 9305 + right - (optional) vector that the matrix can be multiplied against 9306 - left - (optional) vector that the matrix vector product can be stored in 9307 9308 Notes: 9309 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()`. 9310 9311 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9312 9313 Level: advanced 9314 9315 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9316 @*/ 9317 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9318 { 9319 PetscFunctionBegin; 9320 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9321 PetscValidType(mat, 1); 9322 if (mat->ops->getvecs) { 9323 PetscUseTypeMethod(mat, getvecs, right, left); 9324 } else { 9325 PetscInt rbs, cbs; 9326 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9327 if (right) { 9328 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9329 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9330 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9331 PetscCall(VecSetBlockSize(*right, cbs)); 9332 PetscCall(VecSetType(*right, mat->defaultvectype)); 9333 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 9334 if (mat->boundtocpu && mat->bindingpropagates) { 9335 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9336 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9337 } 9338 #endif 9339 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9340 } 9341 if (left) { 9342 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9343 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9344 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9345 PetscCall(VecSetBlockSize(*left, rbs)); 9346 PetscCall(VecSetType(*left, mat->defaultvectype)); 9347 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 9348 if (mat->boundtocpu && mat->bindingpropagates) { 9349 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9350 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9351 } 9352 #endif 9353 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9354 } 9355 } 9356 PetscFunctionReturn(0); 9357 } 9358 9359 /*@C 9360 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9361 with default values. 9362 9363 Not Collective 9364 9365 Input Parameters: 9366 . info - the `MatFactorInfo` data structure 9367 9368 Notes: 9369 The solvers are generally used through the `KSP` and `PC` objects, for example 9370 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9371 9372 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9373 9374 Level: developer 9375 9376 Developer Note: 9377 The Fortran interface is not autogenerated as the f90 9378 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9379 9380 .seealso: `MatGetFactor()`, `MatFactorInfo` 9381 @*/ 9382 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9383 { 9384 PetscFunctionBegin; 9385 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9386 PetscFunctionReturn(0); 9387 } 9388 9389 /*@ 9390 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9391 9392 Collective on mat 9393 9394 Input Parameters: 9395 + mat - the factored matrix 9396 - is - the index set defining the Schur indices (0-based) 9397 9398 Notes: 9399 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9400 9401 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9402 9403 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9404 9405 Level: advanced 9406 9407 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9408 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9409 9410 @*/ 9411 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9412 { 9413 PetscErrorCode (*f)(Mat, IS); 9414 9415 PetscFunctionBegin; 9416 PetscValidType(mat, 1); 9417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9418 PetscValidType(is, 2); 9419 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9420 PetscCheckSameComm(mat, 1, is, 2); 9421 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9422 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9423 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9424 PetscCall(MatDestroy(&mat->schur)); 9425 PetscCall((*f)(mat, is)); 9426 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9427 PetscFunctionReturn(0); 9428 } 9429 9430 /*@ 9431 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9432 9433 Logically Collective on mat 9434 9435 Input Parameters: 9436 + F - the factored matrix obtained by calling `MatGetFactor()` 9437 . S - location where to return the Schur complement, can be NULL 9438 - status - the status of the Schur complement matrix, can be NULL 9439 9440 Notes: 9441 You must call `MatFactorSetSchurIS()` before calling this routine. 9442 9443 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9444 9445 The routine provides a copy of the Schur matrix stored within the solver data structures. 9446 The caller must destroy the object when it is no longer needed. 9447 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9448 9449 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) 9450 9451 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9452 9453 Developer Note: 9454 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9455 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9456 9457 Level: advanced 9458 9459 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9460 @*/ 9461 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9462 { 9463 PetscFunctionBegin; 9464 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9465 if (S) PetscValidPointer(S, 2); 9466 if (status) PetscValidPointer(status, 3); 9467 if (S) { 9468 PetscErrorCode (*f)(Mat, Mat *); 9469 9470 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9471 if (f) { 9472 PetscCall((*f)(F, S)); 9473 } else { 9474 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9475 } 9476 } 9477 if (status) *status = F->schur_status; 9478 PetscFunctionReturn(0); 9479 } 9480 9481 /*@ 9482 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9483 9484 Logically Collective on mat 9485 9486 Input Parameters: 9487 + F - the factored matrix obtained by calling `MatGetFactor()` 9488 . *S - location where to return the Schur complement, can be NULL 9489 - status - the status of the Schur complement matrix, can be NULL 9490 9491 Notes: 9492 You must call `MatFactorSetSchurIS()` before calling this routine. 9493 9494 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9495 9496 The routine returns a the Schur Complement stored within the data strutures of the solver. 9497 9498 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9499 9500 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9501 9502 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9503 9504 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9505 9506 Level: advanced 9507 9508 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9509 @*/ 9510 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9511 { 9512 PetscFunctionBegin; 9513 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9514 if (S) PetscValidPointer(S, 2); 9515 if (status) PetscValidPointer(status, 3); 9516 if (S) *S = F->schur; 9517 if (status) *status = F->schur_status; 9518 PetscFunctionReturn(0); 9519 } 9520 9521 /*@ 9522 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9523 9524 Logically Collective on mat 9525 9526 Input Parameters: 9527 + F - the factored matrix obtained by calling `MatGetFactor()` 9528 . *S - location where the Schur complement is stored 9529 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9530 9531 Level: advanced 9532 9533 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9534 @*/ 9535 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9536 { 9537 PetscFunctionBegin; 9538 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9539 if (S) { 9540 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9541 *S = NULL; 9542 } 9543 F->schur_status = status; 9544 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9545 PetscFunctionReturn(0); 9546 } 9547 9548 /*@ 9549 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9550 9551 Logically Collective on mat 9552 9553 Input Parameters: 9554 + F - the factored matrix obtained by calling `MatGetFactor()` 9555 . rhs - location where the right hand side of the Schur complement system is stored 9556 - sol - location where the solution of the Schur complement system has to be returned 9557 9558 Notes: 9559 The sizes of the vectors should match the size of the Schur complement 9560 9561 Must be called after `MatFactorSetSchurIS()` 9562 9563 Level: advanced 9564 9565 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9566 @*/ 9567 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9568 { 9569 PetscFunctionBegin; 9570 PetscValidType(F, 1); 9571 PetscValidType(rhs, 2); 9572 PetscValidType(sol, 3); 9573 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9574 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9575 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9576 PetscCheckSameComm(F, 1, rhs, 2); 9577 PetscCheckSameComm(F, 1, sol, 3); 9578 PetscCall(MatFactorFactorizeSchurComplement(F)); 9579 switch (F->schur_status) { 9580 case MAT_FACTOR_SCHUR_FACTORED: 9581 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9582 break; 9583 case MAT_FACTOR_SCHUR_INVERTED: 9584 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9585 break; 9586 default: 9587 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9588 } 9589 PetscFunctionReturn(0); 9590 } 9591 9592 /*@ 9593 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9594 9595 Logically Collective on mat 9596 9597 Input Parameters: 9598 + F - the factored matrix obtained by calling `MatGetFactor()` 9599 . rhs - location where the right hand side of the Schur complement system is stored 9600 - sol - location where the solution of the Schur complement system has to be returned 9601 9602 Notes: 9603 The sizes of the vectors should match the size of the Schur complement 9604 9605 Must be called after `MatFactorSetSchurIS()` 9606 9607 Level: advanced 9608 9609 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9610 @*/ 9611 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9612 { 9613 PetscFunctionBegin; 9614 PetscValidType(F, 1); 9615 PetscValidType(rhs, 2); 9616 PetscValidType(sol, 3); 9617 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9618 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9619 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9620 PetscCheckSameComm(F, 1, rhs, 2); 9621 PetscCheckSameComm(F, 1, sol, 3); 9622 PetscCall(MatFactorFactorizeSchurComplement(F)); 9623 switch (F->schur_status) { 9624 case MAT_FACTOR_SCHUR_FACTORED: 9625 PetscCall(MatSolve(F->schur, rhs, sol)); 9626 break; 9627 case MAT_FACTOR_SCHUR_INVERTED: 9628 PetscCall(MatMult(F->schur, rhs, sol)); 9629 break; 9630 default: 9631 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9632 } 9633 PetscFunctionReturn(0); 9634 } 9635 9636 /*@ 9637 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9638 9639 Logically Collective on F 9640 9641 Input Parameters: 9642 . F - the factored matrix obtained by calling `MatGetFactor()` 9643 9644 Notes: 9645 Must be called after `MatFactorSetSchurIS()`. 9646 9647 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9648 9649 Level: advanced 9650 9651 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9652 @*/ 9653 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9654 { 9655 PetscFunctionBegin; 9656 PetscValidType(F, 1); 9657 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9658 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0); 9659 PetscCall(MatFactorFactorizeSchurComplement(F)); 9660 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9661 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9662 PetscFunctionReturn(0); 9663 } 9664 9665 /*@ 9666 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9667 9668 Logically Collective on mat 9669 9670 Input Parameters: 9671 . F - the factored matrix obtained by calling `MatGetFactor()` 9672 9673 Note: 9674 Must be called after `MatFactorSetSchurIS()` 9675 9676 Level: advanced 9677 9678 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9679 @*/ 9680 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9681 { 9682 PetscFunctionBegin; 9683 PetscValidType(F, 1); 9684 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9685 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0); 9686 PetscCall(MatFactorFactorizeSchurComplement_Private(F)); 9687 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9688 PetscFunctionReturn(0); 9689 } 9690 9691 /*@ 9692 MatPtAP - Creates the matrix product C = P^T * A * P 9693 9694 Neighbor-wise Collective on A 9695 9696 Input Parameters: 9697 + A - the matrix 9698 . P - the projection matrix 9699 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9700 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9701 if the result is a dense matrix this is irrelevant 9702 9703 Output Parameters: 9704 . C - the product matrix 9705 9706 Notes: 9707 C will be created and must be destroyed by the user with `MatDestroy()`. 9708 9709 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9710 9711 Developer Note: 9712 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9713 9714 Level: intermediate 9715 9716 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9717 @*/ 9718 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9719 { 9720 PetscFunctionBegin; 9721 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9722 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9723 9724 if (scall == MAT_INITIAL_MATRIX) { 9725 PetscCall(MatProductCreate(A, P, NULL, C)); 9726 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9727 PetscCall(MatProductSetAlgorithm(*C, "default")); 9728 PetscCall(MatProductSetFill(*C, fill)); 9729 9730 (*C)->product->api_user = PETSC_TRUE; 9731 PetscCall(MatProductSetFromOptions(*C)); 9732 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); 9733 PetscCall(MatProductSymbolic(*C)); 9734 } else { /* scall == MAT_REUSE_MATRIX */ 9735 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9736 } 9737 9738 PetscCall(MatProductNumeric(*C)); 9739 (*C)->symmetric = A->symmetric; 9740 (*C)->spd = A->spd; 9741 PetscFunctionReturn(0); 9742 } 9743 9744 /*@ 9745 MatRARt - Creates the matrix product C = R * A * R^T 9746 9747 Neighbor-wise Collective on A 9748 9749 Input Parameters: 9750 + A - the matrix 9751 . R - the projection matrix 9752 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9753 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9754 if the result is a dense matrix this is irrelevant 9755 9756 Output Parameters: 9757 . C - the product matrix 9758 9759 Notes: 9760 C will be created and must be destroyed by the user with `MatDestroy()`. 9761 9762 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9763 9764 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9765 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9766 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9767 We recommend using MatPtAP(). 9768 9769 Level: intermediate 9770 9771 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9772 @*/ 9773 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9774 { 9775 PetscFunctionBegin; 9776 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9777 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9778 9779 if (scall == MAT_INITIAL_MATRIX) { 9780 PetscCall(MatProductCreate(A, R, NULL, C)); 9781 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9782 PetscCall(MatProductSetAlgorithm(*C, "default")); 9783 PetscCall(MatProductSetFill(*C, fill)); 9784 9785 (*C)->product->api_user = PETSC_TRUE; 9786 PetscCall(MatProductSetFromOptions(*C)); 9787 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); 9788 PetscCall(MatProductSymbolic(*C)); 9789 } else { /* scall == MAT_REUSE_MATRIX */ 9790 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9791 } 9792 9793 PetscCall(MatProductNumeric(*C)); 9794 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9795 PetscFunctionReturn(0); 9796 } 9797 9798 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9799 { 9800 PetscFunctionBegin; 9801 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9802 9803 if (scall == MAT_INITIAL_MATRIX) { 9804 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9805 PetscCall(MatProductCreate(A, B, NULL, C)); 9806 PetscCall(MatProductSetType(*C, ptype)); 9807 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9808 PetscCall(MatProductSetFill(*C, fill)); 9809 9810 (*C)->product->api_user = PETSC_TRUE; 9811 PetscCall(MatProductSetFromOptions(*C)); 9812 PetscCall(MatProductSymbolic(*C)); 9813 } else { /* scall == MAT_REUSE_MATRIX */ 9814 Mat_Product *product = (*C)->product; 9815 PetscBool isdense; 9816 9817 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9818 if (isdense && product && product->type != ptype) { 9819 PetscCall(MatProductClear(*C)); 9820 product = NULL; 9821 } 9822 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9823 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9824 if (isdense) { 9825 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9826 product = (*C)->product; 9827 product->fill = fill; 9828 product->api_user = PETSC_TRUE; 9829 product->clear = PETSC_TRUE; 9830 9831 PetscCall(MatProductSetType(*C, ptype)); 9832 PetscCall(MatProductSetFromOptions(*C)); 9833 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); 9834 PetscCall(MatProductSymbolic(*C)); 9835 } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9836 } else { /* user may change input matrices A or B when REUSE */ 9837 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9838 } 9839 } 9840 PetscCall(MatProductNumeric(*C)); 9841 PetscFunctionReturn(0); 9842 } 9843 9844 /*@ 9845 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9846 9847 Neighbor-wise Collective on A 9848 9849 Input Parameters: 9850 + A - the left matrix 9851 . B - the right matrix 9852 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9853 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9854 if the result is a dense matrix this is irrelevant 9855 9856 Output Parameters: 9857 . C - the product matrix 9858 9859 Notes: 9860 Unless scall is `MAT_REUSE_MATRIX` C will be created. 9861 9862 `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 9863 call to this function with `MAT_INITIAL_MATRIX`. 9864 9865 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 9866 9867 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`, 9868 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 9869 9870 Example of Usage: 9871 .vb 9872 MatProductCreate(A,B,NULL,&C); 9873 MatProductSetType(C,MATPRODUCT_AB); 9874 MatProductSymbolic(C); 9875 MatProductNumeric(C); // compute C=A * B 9876 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 9877 MatProductNumeric(C); 9878 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 9879 MatProductNumeric(C); 9880 .ve 9881 9882 Level: intermediate 9883 9884 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 9885 @*/ 9886 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9887 { 9888 PetscFunctionBegin; 9889 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 9890 PetscFunctionReturn(0); 9891 } 9892 9893 /*@ 9894 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 9895 9896 Neighbor-wise Collective on A 9897 9898 Input Parameters: 9899 + A - the left matrix 9900 . B - the right matrix 9901 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9902 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9903 9904 Output Parameters: 9905 . C - the product matrix 9906 9907 Notes: 9908 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 9909 9910 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 9911 9912 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9913 actually needed. 9914 9915 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 9916 and for pairs of `MATMPIDENSE` matrices. 9917 9918 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 9919 9920 Options Database Keys: 9921 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 9922 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 9923 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 9924 9925 Level: intermediate 9926 9927 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 9928 @*/ 9929 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9930 { 9931 PetscFunctionBegin; 9932 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 9933 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9934 PetscFunctionReturn(0); 9935 } 9936 9937 /*@ 9938 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 9939 9940 Neighbor-wise Collective on A 9941 9942 Input Parameters: 9943 + A - the left matrix 9944 . B - the right matrix 9945 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9946 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9947 9948 Output Parameters: 9949 . C - the product matrix 9950 9951 Notes: 9952 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 9953 9954 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 9955 9956 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 9957 9958 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9959 actually needed. 9960 9961 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 9962 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 9963 9964 Level: intermediate 9965 9966 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 9967 @*/ 9968 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9969 { 9970 PetscFunctionBegin; 9971 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 9972 PetscFunctionReturn(0); 9973 } 9974 9975 /*@ 9976 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 9977 9978 Neighbor-wise Collective on A 9979 9980 Input Parameters: 9981 + A - the left matrix 9982 . B - the middle matrix 9983 . C - the right matrix 9984 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9985 - 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 9986 if the result is a dense matrix this is irrelevant 9987 9988 Output Parameters: 9989 . D - the product matrix 9990 9991 Notes: 9992 Unless scall is `MAT_REUSE_MATRIX` D will be created. 9993 9994 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 9995 9996 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 9997 9998 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9999 actually needed. 10000 10001 If you have many matrices with the same non-zero structure to multiply, you 10002 should use `MAT_REUSE_MATRIX` in all calls but the first 10003 10004 Level: intermediate 10005 10006 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10007 @*/ 10008 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10009 { 10010 PetscFunctionBegin; 10011 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10012 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10013 10014 if (scall == MAT_INITIAL_MATRIX) { 10015 PetscCall(MatProductCreate(A, B, C, D)); 10016 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10017 PetscCall(MatProductSetAlgorithm(*D, "default")); 10018 PetscCall(MatProductSetFill(*D, fill)); 10019 10020 (*D)->product->api_user = PETSC_TRUE; 10021 PetscCall(MatProductSetFromOptions(*D)); 10022 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, 10023 ((PetscObject)C)->type_name); 10024 PetscCall(MatProductSymbolic(*D)); 10025 } else { /* user may change input matrices when REUSE */ 10026 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10027 } 10028 PetscCall(MatProductNumeric(*D)); 10029 PetscFunctionReturn(0); 10030 } 10031 10032 /*@ 10033 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10034 10035 Collective on mat 10036 10037 Input Parameters: 10038 + mat - the matrix 10039 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10040 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10041 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10042 10043 Output Parameter: 10044 . matredundant - redundant matrix 10045 10046 Notes: 10047 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10048 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10049 10050 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10051 calling it. 10052 10053 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10054 10055 Level: advanced 10056 10057 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10058 @*/ 10059 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10060 { 10061 MPI_Comm comm; 10062 PetscMPIInt size; 10063 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10064 Mat_Redundant *redund = NULL; 10065 PetscSubcomm psubcomm = NULL; 10066 MPI_Comm subcomm_in = subcomm; 10067 Mat *matseq; 10068 IS isrow, iscol; 10069 PetscBool newsubcomm = PETSC_FALSE; 10070 10071 PetscFunctionBegin; 10072 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10073 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10074 PetscValidPointer(*matredundant, 5); 10075 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10076 } 10077 10078 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10079 if (size == 1 || nsubcomm == 1) { 10080 if (reuse == MAT_INITIAL_MATRIX) { 10081 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10082 } else { 10083 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"); 10084 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10085 } 10086 PetscFunctionReturn(0); 10087 } 10088 10089 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10090 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10091 MatCheckPreallocated(mat, 1); 10092 10093 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10094 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10095 /* create psubcomm, then get subcomm */ 10096 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10097 PetscCallMPI(MPI_Comm_size(comm, &size)); 10098 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10099 10100 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10101 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10102 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10103 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10104 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10105 newsubcomm = PETSC_TRUE; 10106 PetscCall(PetscSubcommDestroy(&psubcomm)); 10107 } 10108 10109 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10110 if (reuse == MAT_INITIAL_MATRIX) { 10111 mloc_sub = PETSC_DECIDE; 10112 nloc_sub = PETSC_DECIDE; 10113 if (bs < 1) { 10114 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10115 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10116 } else { 10117 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10118 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10119 } 10120 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10121 rstart = rend - mloc_sub; 10122 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10123 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10124 } else { /* reuse == MAT_REUSE_MATRIX */ 10125 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"); 10126 /* retrieve subcomm */ 10127 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10128 redund = (*matredundant)->redundant; 10129 isrow = redund->isrow; 10130 iscol = redund->iscol; 10131 matseq = redund->matseq; 10132 } 10133 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10134 10135 /* get matredundant over subcomm */ 10136 if (reuse == MAT_INITIAL_MATRIX) { 10137 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10138 10139 /* create a supporting struct and attach it to C for reuse */ 10140 PetscCall(PetscNew(&redund)); 10141 (*matredundant)->redundant = redund; 10142 redund->isrow = isrow; 10143 redund->iscol = iscol; 10144 redund->matseq = matseq; 10145 if (newsubcomm) { 10146 redund->subcomm = subcomm; 10147 } else { 10148 redund->subcomm = MPI_COMM_NULL; 10149 } 10150 } else { 10151 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10152 } 10153 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 10154 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10155 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10156 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10157 } 10158 #endif 10159 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10160 PetscFunctionReturn(0); 10161 } 10162 10163 /*@C 10164 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10165 a given `Mat`. Each submatrix can span multiple procs. 10166 10167 Collective on mat 10168 10169 Input Parameters: 10170 + mat - the matrix 10171 . subcomm - the subcommunicator obtained by MPI_Com_split(comm) 10172 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10173 10174 Output Parameter: 10175 . subMat - 'parallel submatrices each spans a given subcomm 10176 10177 Notes: 10178 The submatrix partition across processors is dictated by 'subComm' a 10179 communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm 10180 is not restriced to be grouped with consecutive original ranks. 10181 10182 Due the MPI_Comm_split() usage, the parallel layout of the submatrices 10183 map directly to the layout of the original matrix [wrt the local 10184 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10185 into the 'DiagonalMat' of the subMat, hence it is used directly from 10186 the subMat. However the offDiagMat looses some columns - and this is 10187 reconstructed with `MatSetValues()` 10188 10189 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10190 10191 Level: advanced 10192 10193 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10194 @*/ 10195 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10196 { 10197 PetscMPIInt commsize, subCommSize; 10198 10199 PetscFunctionBegin; 10200 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10201 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10202 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10203 10204 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"); 10205 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10206 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10207 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10208 PetscFunctionReturn(0); 10209 } 10210 10211 /*@ 10212 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10213 10214 Not Collective 10215 10216 Input Parameters: 10217 + mat - matrix to extract local submatrix from 10218 . isrow - local row indices for submatrix 10219 - iscol - local column indices for submatrix 10220 10221 Output Parameter: 10222 . submat - the submatrix 10223 10224 Level: intermediate 10225 10226 Notes: 10227 The submat should be returned with `MatRestoreLocalSubMatrix()`. 10228 10229 Depending on the format of mat, the returned submat may not implement `MatMult()`. Its communicator may be 10230 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's. 10231 10232 The submat always implements `MatSetValuesLocal()`. If isrow and iscol have the same block size, then 10233 `MatSetValuesBlockedLocal()` will also be implemented. 10234 10235 The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10236 Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided. 10237 10238 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10239 @*/ 10240 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10241 { 10242 PetscFunctionBegin; 10243 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10244 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10245 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10246 PetscCheckSameComm(isrow, 2, iscol, 3); 10247 PetscValidPointer(submat, 4); 10248 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10249 10250 if (mat->ops->getlocalsubmatrix) { 10251 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10252 } else { 10253 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10254 } 10255 PetscFunctionReturn(0); 10256 } 10257 10258 /*@ 10259 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10260 10261 Not Collective 10262 10263 Input Parameters: 10264 + mat - matrix to extract local submatrix from 10265 . isrow - local row indices for submatrix 10266 . iscol - local column indices for submatrix 10267 - submat - the submatrix 10268 10269 Level: intermediate 10270 10271 .seealso: `MatGetLocalSubMatrix()` 10272 @*/ 10273 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10274 { 10275 PetscFunctionBegin; 10276 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10277 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10278 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10279 PetscCheckSameComm(isrow, 2, iscol, 3); 10280 PetscValidPointer(submat, 4); 10281 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10282 10283 if (mat->ops->restorelocalsubmatrix) { 10284 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10285 } else { 10286 PetscCall(MatDestroy(submat)); 10287 } 10288 *submat = NULL; 10289 PetscFunctionReturn(0); 10290 } 10291 10292 /* --------------------------------------------------------*/ 10293 /*@ 10294 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10295 10296 Collective on mat 10297 10298 Input Parameter: 10299 . mat - the matrix 10300 10301 Output Parameter: 10302 . is - if any rows have zero diagonals this contains the list of them 10303 10304 Level: developer 10305 10306 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10307 @*/ 10308 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10309 { 10310 PetscFunctionBegin; 10311 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10312 PetscValidType(mat, 1); 10313 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10314 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10315 10316 if (!mat->ops->findzerodiagonals) { 10317 Vec diag; 10318 const PetscScalar *a; 10319 PetscInt *rows; 10320 PetscInt rStart, rEnd, r, nrow = 0; 10321 10322 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10323 PetscCall(MatGetDiagonal(mat, diag)); 10324 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10325 PetscCall(VecGetArrayRead(diag, &a)); 10326 for (r = 0; r < rEnd - rStart; ++r) 10327 if (a[r] == 0.0) ++nrow; 10328 PetscCall(PetscMalloc1(nrow, &rows)); 10329 nrow = 0; 10330 for (r = 0; r < rEnd - rStart; ++r) 10331 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10332 PetscCall(VecRestoreArrayRead(diag, &a)); 10333 PetscCall(VecDestroy(&diag)); 10334 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10335 } else { 10336 PetscUseTypeMethod(mat, findzerodiagonals, is); 10337 } 10338 PetscFunctionReturn(0); 10339 } 10340 10341 /*@ 10342 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10343 10344 Collective on mat 10345 10346 Input Parameter: 10347 . mat - the matrix 10348 10349 Output Parameter: 10350 . is - contains the list of rows with off block diagonal entries 10351 10352 Level: developer 10353 10354 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10355 @*/ 10356 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10357 { 10358 PetscFunctionBegin; 10359 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10360 PetscValidType(mat, 1); 10361 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10362 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10363 10364 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10365 PetscFunctionReturn(0); 10366 } 10367 10368 /*@C 10369 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10370 10371 Collective on mat 10372 10373 Input Parameters: 10374 . mat - the matrix 10375 10376 Output Parameters: 10377 . values - the block inverses in column major order (FORTRAN-like) 10378 10379 Notes: 10380 The size of the blocks is determined by the block size of the matrix. 10381 10382 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10383 10384 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10385 10386 Fortran Note: 10387 This routine is not available from Fortran. 10388 10389 Level: advanced 10390 10391 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10392 @*/ 10393 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10394 { 10395 PetscFunctionBegin; 10396 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10397 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10398 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10399 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10400 PetscFunctionReturn(0); 10401 } 10402 10403 /*@C 10404 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10405 10406 Collective on mat 10407 10408 Input Parameters: 10409 + mat - the matrix 10410 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10411 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10412 10413 Output Parameters: 10414 . values - the block inverses in column major order (FORTRAN-like) 10415 10416 Notes: 10417 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10418 10419 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10420 10421 Fortran Note: 10422 This routine is not available from Fortran. 10423 10424 Level: advanced 10425 10426 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10427 @*/ 10428 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10429 { 10430 PetscFunctionBegin; 10431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10432 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10433 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10434 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10435 PetscFunctionReturn(0); 10436 } 10437 10438 /*@ 10439 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10440 10441 Collective on Mat 10442 10443 Input Parameters: 10444 + A - the matrix 10445 - C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 10446 10447 Note: 10448 The blocksize of the matrix is used to determine the blocks on the diagonal of C 10449 10450 Level: advanced 10451 10452 .seealso: `MatInvertBlockDiagonal()` 10453 @*/ 10454 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10455 { 10456 const PetscScalar *vals; 10457 PetscInt *dnnz; 10458 PetscInt m, rstart, rend, bs, i, j; 10459 10460 PetscFunctionBegin; 10461 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10462 PetscCall(MatGetBlockSize(A, &bs)); 10463 PetscCall(MatGetLocalSize(A, &m, NULL)); 10464 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10465 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10466 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10467 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10468 PetscCall(PetscFree(dnnz)); 10469 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10470 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10471 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10472 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10473 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10474 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10475 PetscFunctionReturn(0); 10476 } 10477 10478 /*@C 10479 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10480 via `MatTransposeColoringCreate()`. 10481 10482 Collective on c 10483 10484 Input Parameter: 10485 . c - coloring context 10486 10487 Level: intermediate 10488 10489 .seealso: `MatTransposeColoringCreate()` 10490 @*/ 10491 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10492 { 10493 MatTransposeColoring matcolor = *c; 10494 10495 PetscFunctionBegin; 10496 if (!matcolor) PetscFunctionReturn(0); 10497 if (--((PetscObject)matcolor)->refct > 0) { 10498 matcolor = NULL; 10499 PetscFunctionReturn(0); 10500 } 10501 10502 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10503 PetscCall(PetscFree(matcolor->rows)); 10504 PetscCall(PetscFree(matcolor->den2sp)); 10505 PetscCall(PetscFree(matcolor->colorforcol)); 10506 PetscCall(PetscFree(matcolor->columns)); 10507 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10508 PetscCall(PetscHeaderDestroy(c)); 10509 PetscFunctionReturn(0); 10510 } 10511 10512 /*@C 10513 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10514 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10515 `MatTransposeColoring` to sparse B. 10516 10517 Collective on coloring 10518 10519 Input Parameters: 10520 + B - sparse matrix B 10521 . Btdense - symbolic dense matrix B^T 10522 - coloring - coloring context created with `MatTransposeColoringCreate()` 10523 10524 Output Parameter: 10525 . Btdense - dense matrix B^T 10526 10527 Level: developer 10528 10529 Note: 10530 These are used internally for some implementations of `MatRARt()` 10531 10532 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10533 10534 @*/ 10535 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10536 { 10537 PetscFunctionBegin; 10538 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10539 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10540 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10541 10542 PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10543 PetscFunctionReturn(0); 10544 } 10545 10546 /*@C 10547 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10548 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10549 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10550 Csp from Cden. 10551 10552 Collective on matcoloring 10553 10554 Input Parameters: 10555 + coloring - coloring context created with `MatTransposeColoringCreate()` 10556 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10557 10558 Output Parameter: 10559 . Csp - sparse matrix 10560 10561 Level: developer 10562 10563 Note: 10564 These are used internally for some implementations of `MatRARt()` 10565 10566 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10567 10568 @*/ 10569 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10570 { 10571 PetscFunctionBegin; 10572 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10573 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10574 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10575 10576 PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10577 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10578 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10579 PetscFunctionReturn(0); 10580 } 10581 10582 /*@C 10583 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10584 10585 Collective on mat 10586 10587 Input Parameters: 10588 + mat - the matrix product C 10589 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10590 10591 Output Parameter: 10592 . color - the new coloring context 10593 10594 Level: intermediate 10595 10596 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10597 `MatTransColoringApplyDenToSp()` 10598 @*/ 10599 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10600 { 10601 MatTransposeColoring c; 10602 MPI_Comm comm; 10603 10604 PetscFunctionBegin; 10605 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10606 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10607 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10608 10609 c->ctype = iscoloring->ctype; 10610 if (mat->ops->transposecoloringcreate) { 10611 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10612 } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name); 10613 10614 *color = c; 10615 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10616 PetscFunctionReturn(0); 10617 } 10618 10619 /*@ 10620 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10621 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10622 same, otherwise it will be larger 10623 10624 Not Collective 10625 10626 Input Parameter: 10627 . A - the matrix 10628 10629 Output Parameter: 10630 . state - the current state 10631 10632 Notes: 10633 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10634 different matrices 10635 10636 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10637 10638 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10639 10640 Level: intermediate 10641 10642 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()` 10643 @*/ 10644 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10645 { 10646 PetscFunctionBegin; 10647 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10648 *state = mat->nonzerostate; 10649 PetscFunctionReturn(0); 10650 } 10651 10652 /*@ 10653 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10654 matrices from each processor 10655 10656 Collective 10657 10658 Input Parameters: 10659 + comm - the communicators the parallel matrix will live on 10660 . seqmat - the input sequential matrices 10661 . n - number of local columns (or `PETSC_DECIDE`) 10662 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10663 10664 Output Parameter: 10665 . mpimat - the parallel matrix generated 10666 10667 Level: developer 10668 10669 Note: 10670 The number of columns of the matrix in EACH processor MUST be the same. 10671 10672 .seealso: `Mat` 10673 @*/ 10674 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10675 { 10676 PetscMPIInt size; 10677 10678 PetscFunctionBegin; 10679 PetscCallMPI(MPI_Comm_size(comm, &size)); 10680 if (size == 1) { 10681 if (reuse == MAT_INITIAL_MATRIX) { 10682 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10683 } else { 10684 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10685 } 10686 PetscFunctionReturn(0); 10687 } 10688 10689 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"); 10690 10691 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10692 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10693 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10694 PetscFunctionReturn(0); 10695 } 10696 10697 /*@ 10698 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10699 10700 Collective on A 10701 10702 Input Parameters: 10703 + A - the matrix to create subdomains from 10704 - N - requested number of subdomains 10705 10706 Output Parameters: 10707 + n - number of subdomains resulting on this rank 10708 - iss - `IS` list with indices of subdomains on this rank 10709 10710 Level: advanced 10711 10712 Note: 10713 The number of subdomains must be smaller than the communicator size 10714 10715 .seealso: `Mat`, `IS` 10716 @*/ 10717 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10718 { 10719 MPI_Comm comm, subcomm; 10720 PetscMPIInt size, rank, color; 10721 PetscInt rstart, rend, k; 10722 10723 PetscFunctionBegin; 10724 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10725 PetscCallMPI(MPI_Comm_size(comm, &size)); 10726 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10727 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); 10728 *n = 1; 10729 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10730 color = rank / k; 10731 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10732 PetscCall(PetscMalloc1(1, iss)); 10733 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10734 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10735 PetscCallMPI(MPI_Comm_free(&subcomm)); 10736 PetscFunctionReturn(0); 10737 } 10738 10739 /*@ 10740 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10741 10742 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10743 If they are not the same, uses `MatMatMatMult()`. 10744 10745 Once the coarse grid problem is constructed, correct for interpolation operators 10746 that are not of full rank, which can legitimately happen in the case of non-nested 10747 geometric multigrid. 10748 10749 Input Parameters: 10750 + restrct - restriction operator 10751 . dA - fine grid matrix 10752 . interpolate - interpolation operator 10753 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10754 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10755 10756 Output Parameters: 10757 . A - the Galerkin coarse matrix 10758 10759 Options Database Key: 10760 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10761 10762 Level: developer 10763 10764 .seealso: `MatPtAP()`, `MatMatMatMult()` 10765 @*/ 10766 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10767 { 10768 IS zerorows; 10769 Vec diag; 10770 10771 PetscFunctionBegin; 10772 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10773 /* Construct the coarse grid matrix */ 10774 if (interpolate == restrct) { 10775 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10776 } else { 10777 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10778 } 10779 10780 /* If the interpolation matrix is not of full rank, A will have zero rows. 10781 This can legitimately happen in the case of non-nested geometric multigrid. 10782 In that event, we set the rows of the matrix to the rows of the identity, 10783 ignoring the equations (as the RHS will also be zero). */ 10784 10785 PetscCall(MatFindZeroRows(*A, &zerorows)); 10786 10787 if (zerorows != NULL) { /* if there are any zero rows */ 10788 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10789 PetscCall(MatGetDiagonal(*A, diag)); 10790 PetscCall(VecISSet(diag, zerorows, 1.0)); 10791 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10792 PetscCall(VecDestroy(&diag)); 10793 PetscCall(ISDestroy(&zerorows)); 10794 } 10795 PetscFunctionReturn(0); 10796 } 10797 10798 /*@C 10799 MatSetOperation - Allows user to set a matrix operation for any matrix type 10800 10801 Logically Collective on mat 10802 10803 Input Parameters: 10804 + mat - the matrix 10805 . op - the name of the operation 10806 - f - the function that provides the operation 10807 10808 Level: developer 10809 10810 Usage: 10811 $ extern PetscErrorCode usermult(Mat,Vec,Vec); 10812 $ PetscCall(MatCreateXXX(comm,...&A); 10813 $ PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult); 10814 10815 Notes: 10816 See the file include/petscmat.h for a complete list of matrix 10817 operations, which all have the form MATOP_<OPERATION>, where 10818 <OPERATION> is the name (in all capital letters) of the 10819 user interface routine (e.g., MatMult() -> MATOP_MULT). 10820 10821 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10822 sequence as the usual matrix interface routines, since they 10823 are intended to be accessed via the usual matrix interface 10824 routines, e.g., 10825 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 10826 10827 In particular each function MUST return an error code of 0 on success and 10828 nonzero on failure. 10829 10830 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10831 10832 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10833 @*/ 10834 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10835 { 10836 PetscFunctionBegin; 10837 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10838 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10839 (((void (**)(void))mat->ops)[op]) = f; 10840 PetscFunctionReturn(0); 10841 } 10842 10843 /*@C 10844 MatGetOperation - Gets a matrix operation for any matrix type. 10845 10846 Not Collective 10847 10848 Input Parameters: 10849 + mat - the matrix 10850 - op - the name of the operation 10851 10852 Output Parameter: 10853 . f - the function that provides the operation 10854 10855 Level: developer 10856 10857 Usage: 10858 $ PetscErrorCode (*usermult)(Mat,Vec,Vec); 10859 $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult); 10860 10861 Notes: 10862 See the file include/petscmat.h for a complete list of matrix 10863 operations, which all have the form MATOP_<OPERATION>, where 10864 <OPERATION> is the name (in all capital letters) of the 10865 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10866 10867 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 10868 10869 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 10870 @*/ 10871 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 10872 { 10873 PetscFunctionBegin; 10874 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10875 *f = (((void (**)(void))mat->ops)[op]); 10876 PetscFunctionReturn(0); 10877 } 10878 10879 /*@ 10880 MatHasOperation - Determines whether the given matrix supports the particular operation. 10881 10882 Not Collective 10883 10884 Input Parameters: 10885 + mat - the matrix 10886 - op - the operation, for example, `MATOP_GET_DIAGONAL` 10887 10888 Output Parameter: 10889 . has - either `PETSC_TRUE` or `PETSC_FALSE` 10890 10891 Level: advanced 10892 10893 Note: 10894 See the file include/petscmat.h for a complete list of matrix 10895 operations, which all have the form MATOP_<OPERATION>, where 10896 <OPERATION> is the name (in all capital letters) of the 10897 user-level routine. E.g., `MatNorm()` -> `MATOP_NORM`. 10898 10899 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 10900 @*/ 10901 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 10902 { 10903 PetscFunctionBegin; 10904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10905 PetscValidBoolPointer(has, 3); 10906 if (mat->ops->hasoperation) { 10907 PetscUseTypeMethod(mat, hasoperation, op, has); 10908 } else { 10909 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 10910 else { 10911 *has = PETSC_FALSE; 10912 if (op == MATOP_CREATE_SUBMATRIX) { 10913 PetscMPIInt size; 10914 10915 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10916 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 10917 } 10918 } 10919 } 10920 PetscFunctionReturn(0); 10921 } 10922 10923 /*@ 10924 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 10925 10926 Collective on mat 10927 10928 Input Parameters: 10929 . mat - the matrix 10930 10931 Output Parameter: 10932 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 10933 10934 Level: beginner 10935 10936 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout` 10937 @*/ 10938 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 10939 { 10940 PetscFunctionBegin; 10941 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10942 PetscValidType(mat, 1); 10943 PetscValidBoolPointer(cong, 2); 10944 if (!mat->rmap || !mat->cmap) { 10945 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 10946 PetscFunctionReturn(0); 10947 } 10948 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 10949 PetscCall(PetscLayoutSetUp(mat->rmap)); 10950 PetscCall(PetscLayoutSetUp(mat->cmap)); 10951 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 10952 if (*cong) mat->congruentlayouts = 1; 10953 else mat->congruentlayouts = 0; 10954 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 10955 PetscFunctionReturn(0); 10956 } 10957 10958 PetscErrorCode MatSetInf(Mat A) 10959 { 10960 PetscFunctionBegin; 10961 PetscUseTypeMethod(A, setinf); 10962 PetscFunctionReturn(0); 10963 } 10964 10965 /*C 10966 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 10967 and possibly removes small values from the graph structure. 10968 10969 Collective on mat 10970 10971 Input Parameters: 10972 + A - the matrix 10973 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 10974 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 10975 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 10976 10977 Output Parameter: 10978 . graph - the resulting graph 10979 10980 Level: advanced 10981 10982 .seealso: `MatCreate()`, `PCGAMG` 10983 */ 10984 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 10985 { 10986 PetscFunctionBegin; 10987 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 10988 PetscValidType(A, 1); 10989 PetscValidPointer(graph, 3); 10990 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 10991 PetscFunctionReturn(0); 10992 } 10993