1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure; 36 PetscLogEvent MAT_GetMultiProcBlock; 37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 52 for sparse matrices that already have locations it fills the locations with random numbers 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and 59 it will create one internally. 60 61 Output Parameter: 62 . x - the matrix 63 64 Example of Usage: 65 .vb 66 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 67 MatSetRandom(x,rctx); 68 PetscRandomDestroy(rctx); 69 .ve 70 71 Level: intermediate 72 73 .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 74 @*/ 75 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 76 { 77 PetscRandom randObj = NULL; 78 79 PetscFunctionBegin; 80 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 81 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 82 PetscValidType(x, 1); 83 MatCheckPreallocated(x, 1); 84 85 if (!rctx) { 86 MPI_Comm comm; 87 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 88 PetscCall(PetscRandomCreate(comm, &randObj)); 89 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 90 PetscCall(PetscRandomSetFromOptions(randObj)); 91 rctx = randObj; 92 } 93 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 94 PetscUseTypeMethod(x, setrandom, rctx); 95 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 96 97 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 98 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 99 PetscCall(PetscRandomDestroy(&randObj)); 100 PetscFunctionReturn(0); 101 } 102 103 /*@ 104 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 105 106 Logically Collective 107 108 Input Parameter: 109 . mat - the factored matrix 110 111 Output Parameters: 112 + pivot - the pivot value computed 113 - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes 114 the share the matrix 115 116 Level: advanced 117 118 Notes: 119 This routine does not work for factorizations done with external packages. 120 121 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 122 123 This can be called on non-factored matrices that come from, for example, matrices used in SOR. 124 125 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 126 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 127 @*/ 128 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 129 { 130 PetscFunctionBegin; 131 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 132 PetscValidRealPointer(pivot, 2); 133 PetscValidIntPointer(row, 3); 134 *pivot = mat->factorerror_zeropivot_value; 135 *row = mat->factorerror_zeropivot_row; 136 PetscFunctionReturn(0); 137 } 138 139 /*@ 140 MatFactorGetError - gets the error code from a factorization 141 142 Logically Collective 143 144 Input Parameters: 145 . mat - the factored matrix 146 147 Output Parameter: 148 . err - the error code 149 150 Level: advanced 151 152 Note: 153 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 154 155 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 156 `MatFactorError` 157 @*/ 158 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 159 { 160 PetscFunctionBegin; 161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 162 PetscValidPointer(err, 2); 163 *err = mat->factorerrortype; 164 PetscFunctionReturn(0); 165 } 166 167 /*@ 168 MatFactorClearError - clears the error code in a factorization 169 170 Logically Collective 171 172 Input Parameter: 173 . mat - the factored matrix 174 175 Level: developer 176 177 Note: 178 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 179 180 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 181 `MatGetErrorCode()`, `MatFactorError` 182 @*/ 183 PetscErrorCode MatFactorClearError(Mat mat) 184 { 185 PetscFunctionBegin; 186 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 187 mat->factorerrortype = MAT_FACTOR_NOERROR; 188 mat->factorerror_zeropivot_value = 0.0; 189 mat->factorerror_zeropivot_row = 0; 190 PetscFunctionReturn(0); 191 } 192 193 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 194 { 195 Vec r, l; 196 const PetscScalar *al; 197 PetscInt i, nz, gnz, N, n; 198 199 PetscFunctionBegin; 200 PetscCall(MatCreateVecs(mat, &r, &l)); 201 if (!cols) { /* nonzero rows */ 202 PetscCall(MatGetSize(mat, &N, NULL)); 203 PetscCall(MatGetLocalSize(mat, &n, NULL)); 204 PetscCall(VecSet(l, 0.0)); 205 PetscCall(VecSetRandom(r, NULL)); 206 PetscCall(MatMult(mat, r, l)); 207 PetscCall(VecGetArrayRead(l, &al)); 208 } else { /* nonzero columns */ 209 PetscCall(MatGetSize(mat, NULL, &N)); 210 PetscCall(MatGetLocalSize(mat, NULL, &n)); 211 PetscCall(VecSet(r, 0.0)); 212 PetscCall(VecSetRandom(l, NULL)); 213 PetscCall(MatMultTranspose(mat, l, r)); 214 PetscCall(VecGetArrayRead(r, &al)); 215 } 216 if (tol <= 0.0) { 217 for (i = 0, nz = 0; i < n; i++) 218 if (al[i] != 0.0) nz++; 219 } else { 220 for (i = 0, nz = 0; i < n; i++) 221 if (PetscAbsScalar(al[i]) > tol) nz++; 222 } 223 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 224 if (gnz != N) { 225 PetscInt *nzr; 226 PetscCall(PetscMalloc1(nz, &nzr)); 227 if (nz) { 228 if (tol < 0) { 229 for (i = 0, nz = 0; i < n; i++) 230 if (al[i] != 0.0) nzr[nz++] = i; 231 } else { 232 for (i = 0, nz = 0; i < n; i++) 233 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 234 } 235 } 236 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 237 } else *nonzero = NULL; 238 if (!cols) { /* nonzero rows */ 239 PetscCall(VecRestoreArrayRead(l, &al)); 240 } else { 241 PetscCall(VecRestoreArrayRead(r, &al)); 242 } 243 PetscCall(VecDestroy(&l)); 244 PetscCall(VecDestroy(&r)); 245 PetscFunctionReturn(0); 246 } 247 248 /*@ 249 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 250 251 Input Parameter: 252 . A - the matrix 253 254 Output Parameter: 255 . keptrows - the rows that are not completely zero 256 257 Note: 258 keptrows is set to NULL if all rows are nonzero. 259 260 Level: intermediate 261 262 .seealso: `Mat`, `MatFindZeroRows()` 263 @*/ 264 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 265 { 266 PetscFunctionBegin; 267 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 268 PetscValidType(mat, 1); 269 PetscValidPointer(keptrows, 2); 270 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 271 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 272 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 273 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 274 PetscFunctionReturn(0); 275 } 276 277 /*@ 278 MatFindZeroRows - Locate all rows that are completely zero in the matrix 279 280 Input Parameter: 281 . A - the matrix 282 283 Output Parameter: 284 . zerorows - the rows that are completely zero 285 286 Note: 287 zerorows is set to NULL if no rows are zero. 288 289 Level: intermediate 290 291 .seealso: `Mat`, `MatFindNonzeroRows()` 292 @*/ 293 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 294 { 295 IS keptrows; 296 PetscInt m, n; 297 298 PetscFunctionBegin; 299 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 300 PetscValidType(mat, 1); 301 PetscValidPointer(zerorows, 2); 302 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 303 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 304 In keeping with this convention, we set zerorows to NULL if there are no zero 305 rows. */ 306 if (keptrows == NULL) { 307 *zerorows = NULL; 308 } else { 309 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 310 PetscCall(ISComplement(keptrows, m, n, zerorows)); 311 PetscCall(ISDestroy(&keptrows)); 312 } 313 PetscFunctionReturn(0); 314 } 315 316 /*@ 317 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 318 319 Not Collective 320 321 Input Parameters: 322 . A - the matrix 323 324 Output Parameters: 325 . a - the diagonal part (which is a SEQUENTIAL matrix) 326 327 Notes: 328 See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 329 330 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation. 331 332 Level: advanced 333 334 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 335 @*/ 336 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 337 { 338 PetscFunctionBegin; 339 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 340 PetscValidType(A, 1); 341 PetscValidPointer(a, 2); 342 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 343 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 344 else { 345 PetscMPIInt size; 346 347 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 348 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 349 *a = A; 350 } 351 PetscFunctionReturn(0); 352 } 353 354 /*@ 355 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 356 357 Collective 358 359 Input Parameters: 360 . mat - the matrix 361 362 Output Parameter: 363 . trace - the sum of the diagonal entries 364 365 Level: advanced 366 367 .seealso: `Mat` 368 @*/ 369 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 370 { 371 Vec diag; 372 373 PetscFunctionBegin; 374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 375 PetscValidScalarPointer(trace, 2); 376 PetscCall(MatCreateVecs(mat, &diag, NULL)); 377 PetscCall(MatGetDiagonal(mat, diag)); 378 PetscCall(VecSum(diag, trace)); 379 PetscCall(VecDestroy(&diag)); 380 PetscFunctionReturn(0); 381 } 382 383 /*@ 384 MatRealPart - Zeros out the imaginary part of the matrix 385 386 Logically Collective 387 388 Input Parameters: 389 . mat - the matrix 390 391 Level: advanced 392 393 .seealso: `MatImaginaryPart()` 394 @*/ 395 PetscErrorCode MatRealPart(Mat mat) 396 { 397 PetscFunctionBegin; 398 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 399 PetscValidType(mat, 1); 400 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 401 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 402 MatCheckPreallocated(mat, 1); 403 PetscUseTypeMethod(mat, realpart); 404 PetscFunctionReturn(0); 405 } 406 407 /*@C 408 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 409 410 Collective 411 412 Input Parameter: 413 . mat - the matrix 414 415 Output Parameters: 416 + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 417 - ghosts - the global indices of the ghost points 418 419 Note: 420 the nghosts and ghosts are suitable to pass into `VecCreateGhost()` 421 422 Level: advanced 423 424 .seealso: `Mat`, `VecCreateGhost()` 425 @*/ 426 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 427 { 428 PetscFunctionBegin; 429 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 430 PetscValidType(mat, 1); 431 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 432 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 433 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 434 else { 435 if (nghosts) *nghosts = 0; 436 if (ghosts) *ghosts = NULL; 437 } 438 PetscFunctionReturn(0); 439 } 440 441 /*@ 442 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 443 444 Logically Collective 445 446 Input Parameters: 447 . mat - the matrix 448 449 Level: advanced 450 451 .seealso: `MatRealPart()` 452 @*/ 453 PetscErrorCode MatImaginaryPart(Mat mat) 454 { 455 PetscFunctionBegin; 456 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 457 PetscValidType(mat, 1); 458 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 459 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 460 MatCheckPreallocated(mat, 1); 461 PetscUseTypeMethod(mat, imaginarypart); 462 PetscFunctionReturn(0); 463 } 464 465 /*@ 466 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 467 468 Not Collective 469 470 Input Parameter: 471 . mat - the matrix 472 473 Output Parameters: 474 + missing - is any diagonal missing 475 - dd - first diagonal entry that is missing (optional) on this process 476 477 Level: advanced 478 479 .seealso: `Mat` 480 @*/ 481 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 482 { 483 PetscFunctionBegin; 484 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 485 PetscValidType(mat, 1); 486 PetscValidBoolPointer(missing, 2); 487 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 488 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 489 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 490 PetscFunctionReturn(0); 491 } 492 493 /*@C 494 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 495 for each row that you get to ensure that your application does 496 not bleed memory. 497 498 Not Collective 499 500 Input Parameters: 501 + mat - the matrix 502 - row - the row to get 503 504 Output Parameters: 505 + ncols - if not NULL, the number of nonzeros in the row 506 . cols - if not NULL, the column numbers 507 - vals - if not NULL, the values 508 509 Notes: 510 This routine is provided for people who need to have direct access 511 to the structure of a matrix. We hope that we provide enough 512 high-level matrix routines that few users will need it. 513 514 `MatGetRow()` always returns 0-based column indices, regardless of 515 whether the internal representation is 0-based (default) or 1-based. 516 517 For better efficiency, set cols and/or vals to NULL if you do 518 not wish to extract these quantities. 519 520 The user can only examine the values extracted with `MatGetRow()`; 521 the values cannot be altered. To change the matrix entries, one 522 must use `MatSetValues()`. 523 524 You can only have one call to `MatGetRow()` outstanding for a particular 525 matrix at a time, per processor. `MatGetRow()` can only obtain rows 526 associated with the given processor, it cannot get rows from the 527 other processors; for that we suggest using `MatCreateSubMatrices()`, then 528 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 529 is in the global number of rows. 530 531 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 532 533 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 534 535 Fortran Note: 536 The calling sequence from Fortran is 537 .vb 538 MatGetRow(matrix,row,ncols,cols,values,ierr) 539 Mat matrix (input) 540 integer row (input) 541 integer ncols (output) 542 integer cols(maxcols) (output) 543 double precision (or double complex) values(maxcols) output 544 .ve 545 where maxcols >= maximum nonzeros in any row of the matrix. 546 547 Caution: 548 Do not try to change the contents of the output arrays (cols and vals). 549 In some cases, this may corrupt the matrix. 550 551 Level: advanced 552 553 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 554 @*/ 555 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 556 { 557 PetscInt incols; 558 559 PetscFunctionBegin; 560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 561 PetscValidType(mat, 1); 562 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 563 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 564 MatCheckPreallocated(mat, 1); 565 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 566 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 567 PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals)); 568 if (ncols) *ncols = incols; 569 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 570 PetscFunctionReturn(0); 571 } 572 573 /*@ 574 MatConjugate - replaces the matrix values with their complex conjugates 575 576 Logically Collective 577 578 Input Parameters: 579 . mat - the matrix 580 581 Level: advanced 582 583 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 584 @*/ 585 PetscErrorCode MatConjugate(Mat mat) 586 { 587 PetscFunctionBegin; 588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 589 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 590 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 591 PetscUseTypeMethod(mat, conjugate); 592 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 593 } 594 PetscFunctionReturn(0); 595 } 596 597 /*@C 598 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 599 600 Not Collective 601 602 Input Parameters: 603 + mat - the matrix 604 . row - the row to get 605 . ncols, cols - the number of nonzeros and their columns 606 - vals - if nonzero the column values 607 608 Notes: 609 This routine should be called after you have finished examining the entries. 610 611 This routine zeros out ncols, cols, and vals. This is to prevent accidental 612 us of the array after it has been restored. If you pass NULL, it will 613 not zero the pointers. Use of cols or vals after `MatRestoreRow()` is invalid. 614 615 Fortran Notes: 616 The calling sequence from Fortran is 617 .vb 618 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 619 Mat matrix (input) 620 integer row (input) 621 integer ncols (output) 622 integer cols(maxcols) (output) 623 double precision (or double complex) values(maxcols) output 624 .ve 625 Where maxcols >= maximum nonzeros in any row of the matrix. 626 627 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 628 before another call to `MatGetRow()` can be made. 629 630 Level: advanced 631 632 .seealso: `MatGetRow()` 633 @*/ 634 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 635 { 636 PetscFunctionBegin; 637 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 638 if (ncols) PetscValidIntPointer(ncols, 3); 639 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 640 if (!mat->ops->restorerow) PetscFunctionReturn(0); 641 PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals)); 642 if (ncols) *ncols = 0; 643 if (cols) *cols = NULL; 644 if (vals) *vals = NULL; 645 PetscFunctionReturn(0); 646 } 647 648 /*@ 649 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 650 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 651 652 Not Collective 653 654 Input Parameters: 655 . mat - the matrix 656 657 Note: 658 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 659 660 Level: advanced 661 662 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 663 @*/ 664 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 665 { 666 PetscFunctionBegin; 667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 668 PetscValidType(mat, 1); 669 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 670 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 671 MatCheckPreallocated(mat, 1); 672 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0); 673 PetscUseTypeMethod(mat, getrowuppertriangular); 674 PetscFunctionReturn(0); 675 } 676 677 /*@ 678 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 679 680 Not Collective 681 682 Input Parameters: 683 . mat - the matrix 684 685 Note: 686 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 687 688 Level: advanced 689 690 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0); 701 PetscUseTypeMethod(mat, restorerowuppertriangular); 702 PetscFunctionReturn(0); 703 } 704 705 /*@C 706 MatSetOptionsPrefix - Sets the prefix used for searching for all 707 `Mat` options in the database. 708 709 Logically Collective on A 710 711 Input Parameters: 712 + A - the matrix 713 - prefix - the prefix to prepend to all option names 714 715 Notes: 716 A hyphen (-) must NOT be given at the beginning of the prefix name. 717 The first character of all runtime options is AUTOMATICALLY the hyphen. 718 719 This is NOT used for options for the factorization of the matrix. Normally the 720 prefix is automatically passed in from the PC calling the factorization. To set 721 it directly use `MatSetOptionsPrefixFactor()` 722 723 Level: advanced 724 725 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 726 @*/ 727 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 728 { 729 PetscFunctionBegin; 730 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 731 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 732 PetscFunctionReturn(0); 733 } 734 735 /*@C 736 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 737 for matrices created with `MatGetFactor()` 738 739 Logically Collective on A 740 741 Input Parameters: 742 + A - the matrix 743 - prefix - the prefix to prepend to all option names for the factored matrix 744 745 Notes: 746 A hyphen (-) must NOT be given at the beginning of the prefix name. 747 The first character of all runtime options is AUTOMATICALLY the hyphen. 748 749 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 750 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 751 752 Level: developer 753 754 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 755 @*/ 756 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 757 { 758 PetscFunctionBegin; 759 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 760 if (prefix) { 761 PetscValidCharPointer(prefix, 2); 762 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 763 if (prefix != A->factorprefix) { 764 PetscCall(PetscFree(A->factorprefix)); 765 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 766 } 767 } else PetscCall(PetscFree(A->factorprefix)); 768 PetscFunctionReturn(0); 769 } 770 771 /*@C 772 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 773 for matrices created with `MatGetFactor()` 774 775 Logically Collective on A 776 777 Input Parameters: 778 + A - the matrix 779 - prefix - the prefix to prepend to all option names for the factored matrix 780 781 Notes: 782 A hyphen (-) must NOT be given at the beginning of the prefix name. 783 The first character of all runtime options is AUTOMATICALLY the hyphen. 784 785 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 786 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 787 788 Level: developer 789 790 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 791 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 792 `MatSetOptionsPrefix()` 793 @*/ 794 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 795 { 796 char *buf = A->factorprefix; 797 size_t len1, len2; 798 799 PetscFunctionBegin; 800 PetscValidHeader(A, 1); 801 if (!prefix) PetscFunctionReturn(0); 802 if (!buf) { 803 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 804 PetscFunctionReturn(0); 805 } 806 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 807 808 PetscCall(PetscStrlen(prefix, &len1)); 809 PetscCall(PetscStrlen(buf, &len2)); 810 PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix)); 811 PetscCall(PetscStrcpy(A->factorprefix, buf)); 812 PetscCall(PetscStrcat(A->factorprefix, prefix)); 813 PetscCall(PetscFree(buf)); 814 PetscFunctionReturn(0); 815 } 816 817 /*@C 818 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 819 matrix options in the database. 820 821 Logically Collective on A 822 823 Input Parameters: 824 + A - the matrix 825 - prefix - the prefix to prepend to all option names 826 827 Note: 828 A hyphen (-) must NOT be given at the beginning of the prefix name. 829 The first character of all runtime options is AUTOMATICALLY the hyphen. 830 831 Level: advanced 832 833 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 834 @*/ 835 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 836 { 837 PetscFunctionBegin; 838 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 839 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 840 PetscFunctionReturn(0); 841 } 842 843 /*@C 844 MatGetOptionsPrefix - Gets the prefix used for searching for all 845 matrix options in the database. 846 847 Not Collective 848 849 Input Parameter: 850 . A - the matrix 851 852 Output Parameter: 853 . prefix - pointer to the prefix string used 854 855 Level: advanced 856 857 Fortran Note: 858 On the fortran side, the user should pass in a string 'prefix' of 859 sufficient length to hold the prefix. 860 861 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 862 @*/ 863 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 864 { 865 PetscFunctionBegin; 866 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 867 PetscValidPointer(prefix, 2); 868 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 869 PetscFunctionReturn(0); 870 } 871 872 /*@ 873 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 874 875 Collective on A 876 877 Input Parameters: 878 . A - the matrix 879 880 Notes: 881 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 882 883 Users can reset the preallocation to access the original memory. 884 885 Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices. 886 887 Level: beginner 888 889 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 890 @*/ 891 PetscErrorCode MatResetPreallocation(Mat A) 892 { 893 PetscFunctionBegin; 894 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 895 PetscValidType(A, 1); 896 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 897 PetscFunctionReturn(0); 898 } 899 900 /*@ 901 MatSetUp - Sets up the internal matrix data structures for later use. 902 903 Collective on A 904 905 Input Parameters: 906 . A - the matrix 907 908 Notes: 909 If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used. 910 911 If a suitable preallocation routine is used, this function does not need to be called. 912 913 See the Performance chapter of the PETSc users manual for how to preallocate matrices 914 915 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 916 917 Level: intermediate 918 919 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()` 920 @*/ 921 PetscErrorCode MatSetUp(Mat A) 922 { 923 PetscFunctionBegin; 924 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 925 if (!((PetscObject)A)->type_name) { 926 PetscMPIInt size; 927 928 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 929 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 930 } 931 if (!A->preallocated && A->ops->setup) { 932 PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n")); 933 PetscUseTypeMethod(A, setup); 934 } 935 PetscCall(PetscLayoutSetUp(A->rmap)); 936 PetscCall(PetscLayoutSetUp(A->cmap)); 937 A->preallocated = PETSC_TRUE; 938 PetscFunctionReturn(0); 939 } 940 941 #if defined(PETSC_HAVE_SAWS) 942 #include <petscviewersaws.h> 943 #endif 944 945 /*@C 946 MatViewFromOptions - View properties of the matrix from the options database 947 948 Collective on A 949 950 Input Parameters: 951 + A - the matrix 952 . obj - optional additional object that provides the options prefix to use 953 - name - command line option 954 955 Options Database Key: 956 . -mat_view [viewertype]:... - the viewer and its options 957 958 Notes: 959 .vb 960 If no value is provided ascii:stdout is used 961 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 962 for example ascii::ascii_info prints just the information about the object not all details 963 unless :append is given filename opens in write mode, overwriting what was already there 964 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 965 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 966 socket[:port] defaults to the standard output port 967 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 968 .ve 969 970 Level: intermediate 971 972 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 973 @*/ 974 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 975 { 976 PetscFunctionBegin; 977 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 978 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 979 PetscFunctionReturn(0); 980 } 981 982 /*@C 983 MatView - display information about a matrix in a variety ways 984 985 Collective 986 987 Input Parameters: 988 + mat - the matrix 989 - viewer - visualization context 990 991 Notes: 992 The available visualization contexts include 993 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 994 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 995 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 996 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 997 998 The user can open alternative visualization contexts with 999 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1000 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1001 specified file; corresponding input uses MatLoad() 1002 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1003 an X window display 1004 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1005 Currently only the sequential dense and AIJ 1006 matrix types support the Socket viewer. 1007 1008 The user can call `PetscViewerPushFormat()` to specify the output 1009 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1010 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1011 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1012 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1013 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1014 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1015 format common among all matrix types 1016 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1017 format (which is in many cases the same as the default) 1018 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1019 size and structure (not the matrix entries) 1020 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1021 the matrix structure 1022 1023 Options Database Keys: 1024 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1025 . -mat_view ::ascii_info_detail - Prints more detailed info 1026 . -mat_view - Prints matrix in ASCII format 1027 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1028 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1029 . -display <name> - Sets display name (default is host) 1030 . -draw_pause <sec> - Sets number of seconds to pause after display 1031 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1032 . -viewer_socket_machine <machine> - 1033 . -viewer_socket_port <port> - 1034 . -mat_view binary - save matrix to file in binary format 1035 - -viewer_binary_filename <name> - 1036 1037 Level: beginner 1038 1039 Notes: 1040 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1041 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1042 1043 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1044 1045 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1046 viewer is used. 1047 1048 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1049 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1050 1051 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1052 and then use the following mouse functions. 1053 .vb 1054 left mouse: zoom in 1055 middle mouse: zoom out 1056 right mouse: continue with the simulation 1057 .ve 1058 1059 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`, 1060 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1061 @*/ 1062 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1063 { 1064 PetscInt rows, cols, rbs, cbs; 1065 PetscBool isascii, isstring, issaws; 1066 PetscViewerFormat format; 1067 PetscMPIInt size; 1068 1069 PetscFunctionBegin; 1070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1071 PetscValidType(mat, 1); 1072 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1073 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1074 PetscCheckSameComm(mat, 1, viewer, 2); 1075 1076 PetscCall(PetscViewerGetFormat(viewer, &format)); 1077 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1078 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0); 1079 1080 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1081 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1082 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1083 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1084 1085 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1086 if (isascii) { 1087 if (!mat->preallocated) { 1088 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1089 PetscFunctionReturn(0); 1090 } 1091 if (!mat->assembled) { 1092 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1093 PetscFunctionReturn(0); 1094 } 1095 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1096 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1097 MatNullSpace nullsp, transnullsp; 1098 1099 PetscCall(PetscViewerASCIIPushTab(viewer)); 1100 PetscCall(MatGetSize(mat, &rows, &cols)); 1101 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1102 if (rbs != 1 || cbs != 1) { 1103 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1104 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1105 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1106 if (mat->factortype) { 1107 MatSolverType solver; 1108 PetscCall(MatFactorGetSolverType(mat, &solver)); 1109 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1110 } 1111 if (mat->ops->getinfo) { 1112 MatInfo info; 1113 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1114 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1115 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1116 } 1117 PetscCall(MatGetNullSpace(mat, &nullsp)); 1118 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1119 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1120 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1121 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1122 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1123 PetscCall(PetscViewerASCIIPushTab(viewer)); 1124 PetscCall(MatProductView(mat, viewer)); 1125 PetscCall(PetscViewerASCIIPopTab(viewer)); 1126 } 1127 } else if (issaws) { 1128 #if defined(PETSC_HAVE_SAWS) 1129 PetscMPIInt rank; 1130 1131 PetscCall(PetscObjectName((PetscObject)mat)); 1132 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1133 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1134 #endif 1135 } else if (isstring) { 1136 const char *type; 1137 PetscCall(MatGetType(mat, &type)); 1138 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1139 PetscTryTypeMethod(mat, view, viewer); 1140 } 1141 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1142 PetscCall(PetscViewerASCIIPushTab(viewer)); 1143 PetscUseTypeMethod(mat, viewnative, viewer); 1144 PetscCall(PetscViewerASCIIPopTab(viewer)); 1145 } else if (mat->ops->view) { 1146 PetscCall(PetscViewerASCIIPushTab(viewer)); 1147 PetscUseTypeMethod(mat, view, viewer); 1148 PetscCall(PetscViewerASCIIPopTab(viewer)); 1149 } 1150 if (isascii) { 1151 PetscCall(PetscViewerGetFormat(viewer, &format)); 1152 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1153 } 1154 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1155 PetscFunctionReturn(0); 1156 } 1157 1158 #if defined(PETSC_USE_DEBUG) 1159 #include <../src/sys/totalview/tv_data_display.h> 1160 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1161 { 1162 TV_add_row("Local rows", "int", &mat->rmap->n); 1163 TV_add_row("Local columns", "int", &mat->cmap->n); 1164 TV_add_row("Global rows", "int", &mat->rmap->N); 1165 TV_add_row("Global columns", "int", &mat->cmap->N); 1166 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1167 return TV_format_OK; 1168 } 1169 #endif 1170 1171 /*@C 1172 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1173 with `MatView()`. The matrix format is determined from the options database. 1174 Generates a parallel MPI matrix if the communicator has more than one 1175 processor. The default matrix type is `MATAIJ`. 1176 1177 Collective 1178 1179 Input Parameters: 1180 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1181 or some related function before a call to `MatLoad()` 1182 - viewer - binary/HDF5 file viewer 1183 1184 Options Database Keys: 1185 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1186 block size 1187 . -matload_block_size <bs> - set block size 1188 1189 Level: beginner 1190 1191 Notes: 1192 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1193 `Mat` before calling this routine if you wish to set it from the options database. 1194 1195 `MatLoad()` automatically loads into the options database any options 1196 given in the file filename.info where filename is the name of the file 1197 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1198 file will be ignored if you use the -viewer_binary_skip_info option. 1199 1200 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1201 sets the default matrix type AIJ and sets the local and global sizes. 1202 If type and/or size is already set, then the same are used. 1203 1204 In parallel, each processor can load a subset of rows (or the 1205 entire matrix). This routine is especially useful when a large 1206 matrix is stored on disk and only part of it is desired on each 1207 processor. For example, a parallel solver may access only some of 1208 the rows from each processor. The algorithm used here reads 1209 relatively small blocks of data rather than reading the entire 1210 matrix and then subsetting it. 1211 1212 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1213 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1214 or the sequence like 1215 .vb 1216 `PetscViewer` v; 1217 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1218 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1219 `PetscViewerSetFromOptions`(v); 1220 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1221 `PetscViewerFileSetName`(v,"datafile"); 1222 .ve 1223 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1224 $ -viewer_type {binary,hdf5} 1225 1226 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1227 and src/mat/tutorials/ex10.c with the second approach. 1228 1229 Notes about the PETSc binary format: 1230 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1231 is read onto rank 0 and then shipped to its destination rank, one after another. 1232 Multiple objects, both matrices and vectors, can be stored within the same file. 1233 Their PetscObject name is ignored; they are loaded in the order of their storage. 1234 1235 Most users should not need to know the details of the binary storage 1236 format, since `MatLoad()` and `MatView()` completely hide these details. 1237 But for anyone who's interested, the standard binary matrix storage 1238 format is 1239 1240 $ PetscInt MAT_FILE_CLASSID 1241 $ PetscInt number of rows 1242 $ PetscInt number of columns 1243 $ PetscInt total number of nonzeros 1244 $ PetscInt *number nonzeros in each row 1245 $ PetscInt *column indices of all nonzeros (starting index is zero) 1246 $ PetscScalar *values of all nonzeros 1247 1248 PETSc automatically does the byte swapping for 1249 machines that store the bytes reversed, e.g. DEC alpha, freebsd, 1250 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary 1251 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1252 and `PetscBinaryWrite()` to see how this may be done. 1253 1254 Notes about the HDF5 (MATLAB MAT-File Version 7.3) format: 1255 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1256 Each processor's chunk is loaded independently by its owning rank. 1257 Multiple objects, both matrices and vectors, can be stored within the same file. 1258 They are looked up by their PetscObject name. 1259 1260 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1261 by default the same structure and naming of the AIJ arrays and column count 1262 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1263 $ save example.mat A b -v7.3 1264 can be directly read by this routine (see Reference 1 for details). 1265 Note that depending on your MATLAB version, this format might be a default, 1266 otherwise you can set it as default in Preferences. 1267 1268 Unless -nocompression flag is used to save the file in MATLAB, 1269 PETSc must be configured with ZLIB package. 1270 1271 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1272 1273 Current HDF5 (MAT-File) limitations: 1274 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices. 1275 1276 Corresponding `MatView()` is not yet implemented. 1277 1278 The loaded matrix is actually a transpose of the original one in MATLAB, 1279 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1280 With this format, matrix is automatically transposed by PETSc, 1281 unless the matrix is marked as SPD or symmetric 1282 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1283 1284 References: 1285 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1286 1287 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1288 @*/ 1289 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1290 { 1291 PetscBool flg; 1292 1293 PetscFunctionBegin; 1294 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1295 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1296 1297 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1298 1299 flg = PETSC_FALSE; 1300 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1301 if (flg) { 1302 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1303 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1304 } 1305 flg = PETSC_FALSE; 1306 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1307 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1308 1309 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1310 PetscUseTypeMethod(mat, load, viewer); 1311 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1312 PetscFunctionReturn(0); 1313 } 1314 1315 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1316 { 1317 Mat_Redundant *redund = *redundant; 1318 1319 PetscFunctionBegin; 1320 if (redund) { 1321 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1322 PetscCall(ISDestroy(&redund->isrow)); 1323 PetscCall(ISDestroy(&redund->iscol)); 1324 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1325 } else { 1326 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1327 PetscCall(PetscFree(redund->sbuf_j)); 1328 PetscCall(PetscFree(redund->sbuf_a)); 1329 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1330 PetscCall(PetscFree(redund->rbuf_j[i])); 1331 PetscCall(PetscFree(redund->rbuf_a[i])); 1332 } 1333 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1334 } 1335 1336 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1337 PetscCall(PetscFree(redund)); 1338 } 1339 PetscFunctionReturn(0); 1340 } 1341 1342 /*@C 1343 MatDestroy - Frees space taken by a matrix. 1344 1345 Collective on A 1346 1347 Input Parameter: 1348 . A - the matrix 1349 1350 Level: beginner 1351 1352 Developer Note: 1353 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1354 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1355 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1356 if changes are needed here. 1357 1358 .seealso: `Mat`, `MatCreate()` 1359 @*/ 1360 PetscErrorCode MatDestroy(Mat *A) 1361 { 1362 PetscFunctionBegin; 1363 if (!*A) PetscFunctionReturn(0); 1364 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1365 if (--((PetscObject)(*A))->refct > 0) { 1366 *A = NULL; 1367 PetscFunctionReturn(0); 1368 } 1369 1370 /* if memory was published with SAWs then destroy it */ 1371 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1372 PetscTryTypeMethod((*A), destroy); 1373 1374 PetscCall(PetscFree((*A)->factorprefix)); 1375 PetscCall(PetscFree((*A)->defaultvectype)); 1376 PetscCall(PetscFree((*A)->defaultrandtype)); 1377 PetscCall(PetscFree((*A)->bsizes)); 1378 PetscCall(PetscFree((*A)->solvertype)); 1379 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1380 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1381 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1382 PetscCall(MatProductClear(*A)); 1383 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1384 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1385 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1386 PetscCall(MatDestroy(&(*A)->schur)); 1387 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1388 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1389 PetscCall(PetscHeaderDestroy(A)); 1390 PetscFunctionReturn(0); 1391 } 1392 1393 /*@C 1394 MatSetValues - Inserts or adds a block of values into a matrix. 1395 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1396 MUST be called after all calls to `MatSetValues()` have been completed. 1397 1398 Not Collective 1399 1400 Input Parameters: 1401 + mat - the matrix 1402 . v - a logically two-dimensional array of values 1403 . m, idxm - the number of rows and their global indices 1404 . n, idxn - the number of columns and their global indices 1405 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1406 1407 Notes: 1408 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1409 `MatSetUp()` before using this routine 1410 1411 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1412 1413 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1414 options cannot be mixed without intervening calls to the assembly 1415 routines. 1416 1417 `MatSetValues()` uses 0-based row and column numbers in Fortran 1418 as well as in C. 1419 1420 Negative indices may be passed in idxm and idxn, these rows and columns are 1421 simply ignored. This allows easily inserting element stiffness matrices 1422 with homogeneous Dirchlet boundary conditions that you don't want represented 1423 in the matrix. 1424 1425 Efficiency Alert: 1426 The routine `MatSetValuesBlocked()` may offer much better efficiency 1427 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1428 1429 Level: beginner 1430 1431 Developer Note: 1432 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1433 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1434 1435 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1436 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1437 @*/ 1438 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1439 { 1440 PetscFunctionBeginHot; 1441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1442 PetscValidType(mat, 1); 1443 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1444 PetscValidIntPointer(idxm, 3); 1445 PetscValidIntPointer(idxn, 5); 1446 MatCheckPreallocated(mat, 1); 1447 1448 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1449 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1450 1451 if (PetscDefined(USE_DEBUG)) { 1452 PetscInt i, j; 1453 1454 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1455 for (i = 0; i < m; i++) { 1456 for (j = 0; j < n; j++) { 1457 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1458 #if defined(PETSC_USE_COMPLEX) 1459 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1460 #else 1461 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1462 #endif 1463 } 1464 } 1465 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1466 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1467 } 1468 1469 if (mat->assembled) { 1470 mat->was_assembled = PETSC_TRUE; 1471 mat->assembled = PETSC_FALSE; 1472 } 1473 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1474 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1475 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1476 PetscFunctionReturn(0); 1477 } 1478 1479 /*@C 1480 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1481 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1482 MUST be called after all calls to `MatSetValues()` have been completed. 1483 1484 Not Collective 1485 1486 Input Parameters: 1487 + mat - the matrix 1488 . v - a logically two-dimensional array of values 1489 . ism - the rows to provide 1490 . isn - the columns to provide 1491 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1492 1493 Level: beginner 1494 1495 Notes: 1496 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1497 `MatSetUp()` before using this routine 1498 1499 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1500 1501 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1502 options cannot be mixed without intervening calls to the assembly 1503 routines. 1504 1505 `MatSetValues()` uses 0-based row and column numbers in Fortran 1506 as well as in C. 1507 1508 Negative indices may be passed in ism and isn, these rows and columns are 1509 simply ignored. This allows easily inserting element stiffness matrices 1510 with homogeneous Dirchlet boundary conditions that you don't want represented 1511 in the matrix. 1512 1513 Efficiency Alert: 1514 The routine `MatSetValuesBlocked()` may offer much better efficiency 1515 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1516 1517 This is currently not optimized for any particular `ISType` 1518 1519 Developer Notes: 1520 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1521 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1522 1523 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1524 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1525 @*/ 1526 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1527 { 1528 PetscInt m, n; 1529 const PetscInt *rows, *cols; 1530 1531 PetscFunctionBeginHot; 1532 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1533 PetscCall(ISGetIndices(ism, &rows)); 1534 PetscCall(ISGetIndices(isn, &cols)); 1535 PetscCall(ISGetLocalSize(ism, &m)); 1536 PetscCall(ISGetLocalSize(isn, &n)); 1537 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1538 PetscCall(ISRestoreIndices(ism, &rows)); 1539 PetscCall(ISRestoreIndices(isn, &cols)); 1540 PetscFunctionReturn(0); 1541 } 1542 1543 /*@ 1544 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1545 values into a matrix 1546 1547 Not Collective 1548 1549 Input Parameters: 1550 + mat - the matrix 1551 . row - the (block) row to set 1552 - v - a logically two-dimensional array of values 1553 1554 Notes: 1555 By the values, v, are column-oriented (for the block version) and sorted 1556 1557 All the nonzeros in the row must be provided 1558 1559 The matrix must have previously had its column indices set 1560 1561 The row must belong to this process 1562 1563 Level: intermediate 1564 1565 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1566 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1567 @*/ 1568 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1569 { 1570 PetscInt globalrow; 1571 1572 PetscFunctionBegin; 1573 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1574 PetscValidType(mat, 1); 1575 PetscValidScalarPointer(v, 3); 1576 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1577 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1578 PetscFunctionReturn(0); 1579 } 1580 1581 /*@ 1582 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1583 values into a matrix 1584 1585 Not Collective 1586 1587 Input Parameters: 1588 + mat - the matrix 1589 . row - the (block) row to set 1590 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1591 1592 Notes: 1593 The values, v, are column-oriented for the block version. 1594 1595 All the nonzeros in the row must be provided 1596 1597 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1598 1599 The row must belong to this process 1600 1601 Level: advanced 1602 1603 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1604 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1605 @*/ 1606 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1607 { 1608 PetscFunctionBeginHot; 1609 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1610 PetscValidType(mat, 1); 1611 MatCheckPreallocated(mat, 1); 1612 PetscValidScalarPointer(v, 3); 1613 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1614 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1615 mat->insertmode = INSERT_VALUES; 1616 1617 if (mat->assembled) { 1618 mat->was_assembled = PETSC_TRUE; 1619 mat->assembled = PETSC_FALSE; 1620 } 1621 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1622 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1623 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1624 PetscFunctionReturn(0); 1625 } 1626 1627 /*@ 1628 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1629 Using structured grid indexing 1630 1631 Not Collective 1632 1633 Input Parameters: 1634 + mat - the matrix 1635 . m - number of rows being entered 1636 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1637 . n - number of columns being entered 1638 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1639 . v - a logically two-dimensional array of values 1640 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1641 1642 Level: beginner 1643 1644 Notes: 1645 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1646 1647 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1648 options cannot be mixed without intervening calls to the assembly 1649 routines. 1650 1651 The grid coordinates are across the entire grid, not just the local portion 1652 1653 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1654 as well as in C. 1655 1656 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1657 1658 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1659 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1660 1661 The columns and rows in the stencil passed in MUST be contained within the 1662 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1663 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1664 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1665 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1666 1667 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1668 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1669 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1670 `DM_BOUNDARY_PERIODIC` boundary type. 1671 1672 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1673 a single value per point) you can skip filling those indices. 1674 1675 Inspired by the structured grid interface to the HYPRE package 1676 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1677 1678 Efficiency Alert: 1679 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1680 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1681 1682 Fortran Note: 1683 In Fortran idxm and idxn should be declared as 1684 $ MatStencil idxm(4,m),idxn(4,n) 1685 and the values inserted using 1686 .vb 1687 idxm(MatStencil_i,1) = i 1688 idxm(MatStencil_j,1) = j 1689 idxm(MatStencil_k,1) = k 1690 idxm(MatStencil_c,1) = c 1691 etc 1692 .ve 1693 1694 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1695 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1696 @*/ 1697 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1698 { 1699 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1700 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1701 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1702 1703 PetscFunctionBegin; 1704 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1705 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1706 PetscValidType(mat, 1); 1707 PetscValidPointer(idxm, 3); 1708 PetscValidPointer(idxn, 5); 1709 1710 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1711 jdxm = buf; 1712 jdxn = buf + m; 1713 } else { 1714 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1715 jdxm = bufm; 1716 jdxn = bufn; 1717 } 1718 for (i = 0; i < m; i++) { 1719 for (j = 0; j < 3 - sdim; j++) dxm++; 1720 tmp = *dxm++ - starts[0]; 1721 for (j = 0; j < dim - 1; j++) { 1722 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1723 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1724 } 1725 if (mat->stencil.noc) dxm++; 1726 jdxm[i] = tmp; 1727 } 1728 for (i = 0; i < n; i++) { 1729 for (j = 0; j < 3 - sdim; j++) dxn++; 1730 tmp = *dxn++ - starts[0]; 1731 for (j = 0; j < dim - 1; j++) { 1732 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1733 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1734 } 1735 if (mat->stencil.noc) dxn++; 1736 jdxn[i] = tmp; 1737 } 1738 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1739 PetscCall(PetscFree2(bufm, bufn)); 1740 PetscFunctionReturn(0); 1741 } 1742 1743 /*@ 1744 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1745 Using structured grid indexing 1746 1747 Not Collective 1748 1749 Input Parameters: 1750 + mat - the matrix 1751 . m - number of rows being entered 1752 . idxm - grid coordinates for matrix rows being entered 1753 . n - number of columns being entered 1754 . idxn - grid coordinates for matrix columns being entered 1755 . v - a logically two-dimensional array of values 1756 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1757 1758 Level: beginner 1759 1760 Notes: 1761 By default the values, v, are row-oriented and unsorted. 1762 See `MatSetOption()` for other options. 1763 1764 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1765 options cannot be mixed without intervening calls to the assembly 1766 routines. 1767 1768 The grid coordinates are across the entire grid, not just the local portion 1769 1770 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1771 as well as in C. 1772 1773 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1774 1775 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1776 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1777 1778 The columns and rows in the stencil passed in MUST be contained within the 1779 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1780 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1781 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1782 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1783 1784 Negative indices may be passed in idxm and idxn, these rows and columns are 1785 simply ignored. This allows easily inserting element stiffness matrices 1786 with homogeneous Dirchlet boundary conditions that you don't want represented 1787 in the matrix. 1788 1789 Inspired by the structured grid interface to the HYPRE package 1790 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1791 1792 Fortran Note: 1793 In Fortran idxm and idxn should be declared as 1794 $ MatStencil idxm(4,m),idxn(4,n) 1795 and the values inserted using 1796 .vb 1797 idxm(MatStencil_i,1) = i 1798 idxm(MatStencil_j,1) = j 1799 idxm(MatStencil_k,1) = k 1800 etc 1801 .ve 1802 1803 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1804 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1805 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1806 @*/ 1807 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1808 { 1809 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1810 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1811 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1812 1813 PetscFunctionBegin; 1814 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1815 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1816 PetscValidType(mat, 1); 1817 PetscValidPointer(idxm, 3); 1818 PetscValidPointer(idxn, 5); 1819 PetscValidScalarPointer(v, 6); 1820 1821 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1822 jdxm = buf; 1823 jdxn = buf + m; 1824 } else { 1825 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1826 jdxm = bufm; 1827 jdxn = bufn; 1828 } 1829 for (i = 0; i < m; i++) { 1830 for (j = 0; j < 3 - sdim; j++) dxm++; 1831 tmp = *dxm++ - starts[0]; 1832 for (j = 0; j < sdim - 1; j++) { 1833 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1834 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1835 } 1836 dxm++; 1837 jdxm[i] = tmp; 1838 } 1839 for (i = 0; i < n; i++) { 1840 for (j = 0; j < 3 - sdim; j++) dxn++; 1841 tmp = *dxn++ - starts[0]; 1842 for (j = 0; j < sdim - 1; j++) { 1843 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1844 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1845 } 1846 dxn++; 1847 jdxn[i] = tmp; 1848 } 1849 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1850 PetscCall(PetscFree2(bufm, bufn)); 1851 PetscFunctionReturn(0); 1852 } 1853 1854 /*@ 1855 MatSetStencil - Sets the grid information for setting values into a matrix via 1856 `MatSetValuesStencil()` 1857 1858 Not Collective 1859 1860 Input Parameters: 1861 + mat - the matrix 1862 . dim - dimension of the grid 1, 2, or 3 1863 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1864 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1865 - dof - number of degrees of freedom per node 1866 1867 Notes: 1868 Inspired by the structured grid interface to the HYPRE package 1869 (www.llnl.gov/CASC/hyper) 1870 1871 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1872 user. 1873 1874 Level: beginner 1875 1876 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1877 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1878 @*/ 1879 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1880 { 1881 PetscFunctionBegin; 1882 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1883 PetscValidIntPointer(dims, 3); 1884 PetscValidIntPointer(starts, 4); 1885 1886 mat->stencil.dim = dim + (dof > 1); 1887 for (PetscInt i = 0; i < dim; i++) { 1888 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1889 mat->stencil.starts[i] = starts[dim - i - 1]; 1890 } 1891 mat->stencil.dims[dim] = dof; 1892 mat->stencil.starts[dim] = 0; 1893 mat->stencil.noc = (PetscBool)(dof == 1); 1894 PetscFunctionReturn(0); 1895 } 1896 1897 /*@C 1898 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1899 1900 Not Collective 1901 1902 Input Parameters: 1903 + mat - the matrix 1904 . v - a logically two-dimensional array of values 1905 . m, idxm - the number of block rows and their global block indices 1906 . n, idxn - the number of block columns and their global block indices 1907 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1908 1909 Level: intermediate 1910 1911 Notes: 1912 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1913 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1914 1915 The m and n count the NUMBER of blocks in the row direction and column direction, 1916 NOT the total number of rows/columns; for example, if the block size is 2 and 1917 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1918 The values in idxm would be 1 2; that is the first index for each block divided by 1919 the block size. 1920 1921 Note that you must call `MatSetBlockSize()` when constructing this matrix (before 1922 preallocating it). 1923 1924 By default the values, v, are row-oriented, so the layout of 1925 v is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1926 1927 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1928 options cannot be mixed without intervening calls to the assembly 1929 routines. 1930 1931 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1932 as well as in C. 1933 1934 Negative indices may be passed in idxm and idxn, these rows and columns are 1935 simply ignored. This allows easily inserting element stiffness matrices 1936 with homogeneous Dirchlet boundary conditions that you don't want represented 1937 in the matrix. 1938 1939 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1940 internal searching must be done to determine where to place the 1941 data in the matrix storage space. By instead inserting blocks of 1942 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1943 reduced. 1944 1945 Example: 1946 .vb 1947 Suppose m=n=2 and block size(bs) = 2 The array is 1948 1949 1 2 | 3 4 1950 5 6 | 7 8 1951 - - - | - - - 1952 9 10 | 11 12 1953 13 14 | 15 16 1954 1955 v[] should be passed in like 1956 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1957 1958 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1959 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1960 .ve 1961 1962 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1963 @*/ 1964 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1965 { 1966 PetscFunctionBeginHot; 1967 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1968 PetscValidType(mat, 1); 1969 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1970 PetscValidIntPointer(idxm, 3); 1971 PetscValidIntPointer(idxn, 5); 1972 MatCheckPreallocated(mat, 1); 1973 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1974 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1975 if (PetscDefined(USE_DEBUG)) { 1976 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1977 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1978 } 1979 if (PetscDefined(USE_DEBUG)) { 1980 PetscInt rbs, cbs, M, N, i; 1981 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1982 PetscCall(MatGetSize(mat, &M, &N)); 1983 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 1984 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 1985 } 1986 if (mat->assembled) { 1987 mat->was_assembled = PETSC_TRUE; 1988 mat->assembled = PETSC_FALSE; 1989 } 1990 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1991 if (mat->ops->setvaluesblocked) { 1992 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1993 } else { 1994 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1995 PetscInt i, j, bs, cbs; 1996 1997 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1998 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1999 iidxm = buf; 2000 iidxn = buf + m * bs; 2001 } else { 2002 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2003 iidxm = bufr; 2004 iidxn = bufc; 2005 } 2006 for (i = 0; i < m; i++) { 2007 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2008 } 2009 if (m != n || bs != cbs || idxm != idxn) { 2010 for (i = 0; i < n; i++) { 2011 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2012 } 2013 } else iidxn = iidxm; 2014 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2015 PetscCall(PetscFree2(bufr, bufc)); 2016 } 2017 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2018 PetscFunctionReturn(0); 2019 } 2020 2021 /*@C 2022 MatGetValues - Gets a block of local values from a matrix. 2023 2024 Not Collective; can only return values that are owned by the give process 2025 2026 Input Parameters: 2027 + mat - the matrix 2028 . v - a logically two-dimensional array for storing the values 2029 . m, idxm - the number of rows and their global indices 2030 - n, idxn - the number of columns and their global indices 2031 2032 Notes: 2033 The user must allocate space (m*n `PetscScalar`s) for the values, v. 2034 The values, v, are then returned in a row-oriented format, 2035 analogous to that used by default in `MatSetValues()`. 2036 2037 `MatGetValues()` uses 0-based row and column numbers in 2038 Fortran as well as in C. 2039 2040 `MatGetValues()` requires that the matrix has been assembled 2041 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2042 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2043 without intermediate matrix assembly. 2044 2045 Negative row or column indices will be ignored and those locations in v[] will be 2046 left unchanged. 2047 2048 For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank. 2049 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2050 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2051 2052 Level: advanced 2053 2054 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2055 @*/ 2056 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2057 { 2058 PetscFunctionBegin; 2059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2060 PetscValidType(mat, 1); 2061 if (!m || !n) PetscFunctionReturn(0); 2062 PetscValidIntPointer(idxm, 3); 2063 PetscValidIntPointer(idxn, 5); 2064 PetscValidScalarPointer(v, 6); 2065 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2066 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2067 MatCheckPreallocated(mat, 1); 2068 2069 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2070 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2071 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2072 PetscFunctionReturn(0); 2073 } 2074 2075 /*@C 2076 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2077 defined previously by `MatSetLocalToGlobalMapping()` 2078 2079 Not Collective 2080 2081 Input Parameters: 2082 + mat - the matrix 2083 . nrow, irow - number of rows and their local indices 2084 - ncol, icol - number of columns and their local indices 2085 2086 Output Parameter: 2087 . y - a logically two-dimensional array of values 2088 2089 Level: advanced 2090 2091 Notes: 2092 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2093 2094 This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering, 2095 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2096 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2097 with `MatSetLocalToGlobalMapping()`. 2098 2099 Developer Note: 2100 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2101 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2102 2103 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2104 `MatSetValuesLocal()`, `MatGetValues()` 2105 @*/ 2106 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2107 { 2108 PetscFunctionBeginHot; 2109 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2110 PetscValidType(mat, 1); 2111 MatCheckPreallocated(mat, 1); 2112 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */ 2113 PetscValidIntPointer(irow, 3); 2114 PetscValidIntPointer(icol, 5); 2115 if (PetscDefined(USE_DEBUG)) { 2116 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2117 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2118 } 2119 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2120 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2121 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2122 else { 2123 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2124 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2125 irowm = buf; 2126 icolm = buf + nrow; 2127 } else { 2128 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2129 irowm = bufr; 2130 icolm = bufc; 2131 } 2132 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2133 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2134 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2135 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2136 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2137 PetscCall(PetscFree2(bufr, bufc)); 2138 } 2139 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2140 PetscFunctionReturn(0); 2141 } 2142 2143 /*@ 2144 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2145 the same size. Currently, this can only be called once and creates the given matrix. 2146 2147 Not Collective 2148 2149 Input Parameters: 2150 + mat - the matrix 2151 . nb - the number of blocks 2152 . bs - the number of rows (and columns) in each block 2153 . rows - a concatenation of the rows for each block 2154 - v - a concatenation of logically two-dimensional arrays of values 2155 2156 Note: 2157 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2158 2159 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2160 2161 Level: advanced 2162 2163 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2164 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2165 @*/ 2166 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2167 { 2168 PetscFunctionBegin; 2169 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2170 PetscValidType(mat, 1); 2171 PetscValidIntPointer(rows, 4); 2172 PetscValidScalarPointer(v, 5); 2173 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2174 2175 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2176 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2177 else { 2178 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2179 } 2180 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2181 PetscFunctionReturn(0); 2182 } 2183 2184 /*@ 2185 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2186 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2187 using a local (per-processor) numbering. 2188 2189 Not Collective 2190 2191 Input Parameters: 2192 + x - the matrix 2193 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2194 - cmapping - column mapping 2195 2196 Level: intermediate 2197 2198 Note: 2199 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2200 2201 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2202 @*/ 2203 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2204 { 2205 PetscFunctionBegin; 2206 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2207 PetscValidType(x, 1); 2208 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2209 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2210 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2211 else { 2212 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2213 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2214 } 2215 PetscFunctionReturn(0); 2216 } 2217 2218 /*@ 2219 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2220 2221 Not Collective 2222 2223 Input Parameter: 2224 . A - the matrix 2225 2226 Output Parameters: 2227 + rmapping - row mapping 2228 - cmapping - column mapping 2229 2230 Level: advanced 2231 2232 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2233 @*/ 2234 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2235 { 2236 PetscFunctionBegin; 2237 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2238 PetscValidType(A, 1); 2239 if (rmapping) { 2240 PetscValidPointer(rmapping, 2); 2241 *rmapping = A->rmap->mapping; 2242 } 2243 if (cmapping) { 2244 PetscValidPointer(cmapping, 3); 2245 *cmapping = A->cmap->mapping; 2246 } 2247 PetscFunctionReturn(0); 2248 } 2249 2250 /*@ 2251 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2252 2253 Logically Collective on A 2254 2255 Input Parameters: 2256 + A - the matrix 2257 . rmap - row layout 2258 - cmap - column layout 2259 2260 Level: advanced 2261 2262 Note: 2263 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2264 2265 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2266 @*/ 2267 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2268 { 2269 PetscFunctionBegin; 2270 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2271 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2272 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2273 PetscFunctionReturn(0); 2274 } 2275 2276 /*@ 2277 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2278 2279 Not Collective 2280 2281 Input Parameter: 2282 . A - the matrix 2283 2284 Output Parameters: 2285 + rmap - row layout 2286 - cmap - column layout 2287 2288 Level: advanced 2289 2290 .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2291 @*/ 2292 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2293 { 2294 PetscFunctionBegin; 2295 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2296 PetscValidType(A, 1); 2297 if (rmap) { 2298 PetscValidPointer(rmap, 2); 2299 *rmap = A->rmap; 2300 } 2301 if (cmap) { 2302 PetscValidPointer(cmap, 3); 2303 *cmap = A->cmap; 2304 } 2305 PetscFunctionReturn(0); 2306 } 2307 2308 /*@C 2309 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2310 using a local numbering of the nodes. 2311 2312 Not Collective 2313 2314 Input Parameters: 2315 + mat - the matrix 2316 . nrow, irow - number of rows and their local indices 2317 . ncol, icol - number of columns and their local indices 2318 . y - a logically two-dimensional array of values 2319 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2320 2321 Notes: 2322 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2323 `MatSetUp()` before using this routine 2324 2325 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2326 2327 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2328 options cannot be mixed without intervening calls to the assembly 2329 routines. 2330 2331 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2332 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2333 2334 Level: intermediate 2335 2336 Developer Note: 2337 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2338 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2339 2340 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2341 `MatGetValuesLocal()` 2342 @*/ 2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2344 { 2345 PetscFunctionBeginHot; 2346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2347 PetscValidType(mat, 1); 2348 MatCheckPreallocated(mat, 1); 2349 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2350 PetscValidIntPointer(irow, 3); 2351 PetscValidIntPointer(icol, 5); 2352 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2353 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2354 if (PetscDefined(USE_DEBUG)) { 2355 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2356 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2357 } 2358 2359 if (mat->assembled) { 2360 mat->was_assembled = PETSC_TRUE; 2361 mat->assembled = PETSC_FALSE; 2362 } 2363 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2364 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2365 else { 2366 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2367 const PetscInt *irowm, *icolm; 2368 2369 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2370 bufr = buf; 2371 bufc = buf + nrow; 2372 irowm = bufr; 2373 icolm = bufc; 2374 } else { 2375 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2376 irowm = bufr; 2377 icolm = bufc; 2378 } 2379 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2380 else irowm = irow; 2381 if (mat->cmap->mapping) { 2382 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2383 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2384 } else icolm = irowm; 2385 } else icolm = icol; 2386 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2387 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2388 } 2389 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2390 PetscFunctionReturn(0); 2391 } 2392 2393 /*@C 2394 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2395 using a local ordering of the nodes a block at a time. 2396 2397 Not Collective 2398 2399 Input Parameters: 2400 + x - the matrix 2401 . nrow, irow - number of rows and their local indices 2402 . ncol, icol - number of columns and their local indices 2403 . y - a logically two-dimensional array of values 2404 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2405 2406 Notes: 2407 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2408 `MatSetUp()` before using this routine 2409 2410 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2411 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2412 2413 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2414 options cannot be mixed without intervening calls to the assembly 2415 routines. 2416 2417 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2418 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2419 2420 Level: intermediate 2421 2422 Developer Note: 2423 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2424 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2425 2426 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2427 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2428 @*/ 2429 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2430 { 2431 PetscFunctionBeginHot; 2432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2433 PetscValidType(mat, 1); 2434 MatCheckPreallocated(mat, 1); 2435 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2436 PetscValidIntPointer(irow, 3); 2437 PetscValidIntPointer(icol, 5); 2438 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2439 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2440 if (PetscDefined(USE_DEBUG)) { 2441 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2442 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2443 } 2444 2445 if (mat->assembled) { 2446 mat->was_assembled = PETSC_TRUE; 2447 mat->assembled = PETSC_FALSE; 2448 } 2449 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2450 PetscInt irbs, rbs; 2451 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2452 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2453 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2454 } 2455 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2456 PetscInt icbs, cbs; 2457 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2458 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2459 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2460 } 2461 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2462 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2463 else { 2464 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2465 const PetscInt *irowm, *icolm; 2466 2467 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2468 bufr = buf; 2469 bufc = buf + nrow; 2470 irowm = bufr; 2471 icolm = bufc; 2472 } else { 2473 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2474 irowm = bufr; 2475 icolm = bufc; 2476 } 2477 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2478 else irowm = irow; 2479 if (mat->cmap->mapping) { 2480 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2481 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2482 } else icolm = irowm; 2483 } else icolm = icol; 2484 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2485 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2486 } 2487 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2488 PetscFunctionReturn(0); 2489 } 2490 2491 /*@ 2492 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2493 2494 Collective 2495 2496 Input Parameters: 2497 + mat - the matrix 2498 - x - the vector to be multiplied 2499 2500 Output Parameters: 2501 . y - the result 2502 2503 Note: 2504 The vectors x and y cannot be the same. I.e., one cannot 2505 call `MatMultDiagonalBlock`(A,y,y). 2506 2507 Level: developer 2508 2509 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2510 @*/ 2511 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2512 { 2513 PetscFunctionBegin; 2514 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2515 PetscValidType(mat, 1); 2516 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2517 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2518 2519 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2520 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2521 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2522 MatCheckPreallocated(mat, 1); 2523 2524 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2525 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2526 PetscFunctionReturn(0); 2527 } 2528 2529 /* --------------------------------------------------------*/ 2530 /*@ 2531 MatMult - Computes the matrix-vector product, y = Ax. 2532 2533 Neighbor-wise Collective 2534 2535 Input Parameters: 2536 + mat - the matrix 2537 - x - the vector to be multiplied 2538 2539 Output Parameters: 2540 . y - the result 2541 2542 Note: 2543 The vectors x and y cannot be the same. I.e., one cannot 2544 call `MatMult`(A,y,y). 2545 2546 Level: beginner 2547 2548 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2549 @*/ 2550 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2551 { 2552 PetscFunctionBegin; 2553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2554 PetscValidType(mat, 1); 2555 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2556 VecCheckAssembled(x); 2557 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2558 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2559 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2560 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2561 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2562 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2563 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2564 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2565 PetscCall(VecSetErrorIfLocked(y, 3)); 2566 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2567 MatCheckPreallocated(mat, 1); 2568 2569 PetscCall(VecLockReadPush(x)); 2570 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2571 PetscUseTypeMethod(mat, mult, x, y); 2572 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2573 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2574 PetscCall(VecLockReadPop(x)); 2575 PetscFunctionReturn(0); 2576 } 2577 2578 /*@ 2579 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2580 2581 Neighbor-wise Collective 2582 2583 Input Parameters: 2584 + mat - the matrix 2585 - x - the vector to be multiplied 2586 2587 Output Parameters: 2588 . y - the result 2589 2590 Notes: 2591 The vectors x and y cannot be the same. I.e., one cannot 2592 call `MatMultTranspose`(A,y,y). 2593 2594 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2595 use `MatMultHermitianTranspose()` 2596 2597 Level: beginner 2598 2599 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2600 @*/ 2601 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2602 { 2603 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2604 2605 PetscFunctionBegin; 2606 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2607 PetscValidType(mat, 1); 2608 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2609 VecCheckAssembled(x); 2610 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2611 2612 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2613 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2614 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2615 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2616 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2617 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2618 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2619 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2620 MatCheckPreallocated(mat, 1); 2621 2622 if (!mat->ops->multtranspose) { 2623 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2624 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2625 } else op = mat->ops->multtranspose; 2626 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2627 PetscCall(VecLockReadPush(x)); 2628 PetscCall((*op)(mat, x, y)); 2629 PetscCall(VecLockReadPop(x)); 2630 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2631 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2632 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2633 PetscFunctionReturn(0); 2634 } 2635 2636 /*@ 2637 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2638 2639 Neighbor-wise Collective 2640 2641 Input Parameters: 2642 + mat - the matrix 2643 - x - the vector to be multilplied 2644 2645 Output Parameters: 2646 . y - the result 2647 2648 Notes: 2649 The vectors x and y cannot be the same. I.e., one cannot 2650 call `MatMultHermitianTranspose`(A,y,y). 2651 2652 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2653 2654 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2655 2656 Level: beginner 2657 2658 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2659 @*/ 2660 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2661 { 2662 PetscFunctionBegin; 2663 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2664 PetscValidType(mat, 1); 2665 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2666 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2667 2668 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2669 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2670 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2671 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2672 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2673 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2674 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2675 MatCheckPreallocated(mat, 1); 2676 2677 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2678 #if defined(PETSC_USE_COMPLEX) 2679 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2680 PetscCall(VecLockReadPush(x)); 2681 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2682 else PetscUseTypeMethod(mat, mult, x, y); 2683 PetscCall(VecLockReadPop(x)); 2684 } else { 2685 Vec w; 2686 PetscCall(VecDuplicate(x, &w)); 2687 PetscCall(VecCopy(x, w)); 2688 PetscCall(VecConjugate(w)); 2689 PetscCall(MatMultTranspose(mat, w, y)); 2690 PetscCall(VecDestroy(&w)); 2691 PetscCall(VecConjugate(y)); 2692 } 2693 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2694 #else 2695 PetscCall(MatMultTranspose(mat, x, y)); 2696 #endif 2697 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2698 PetscFunctionReturn(0); 2699 } 2700 2701 /*@ 2702 MatMultAdd - Computes v3 = v2 + A * v1. 2703 2704 Neighbor-wise Collective 2705 2706 Input Parameters: 2707 + mat - the matrix 2708 - v1, v2 - the vectors 2709 2710 Output Parameters: 2711 . v3 - the result 2712 2713 Note: 2714 The vectors v1 and v3 cannot be the same. I.e., one cannot 2715 call `MatMultAdd`(A,v1,v2,v1). 2716 2717 Level: beginner 2718 2719 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2720 @*/ 2721 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2722 { 2723 PetscFunctionBegin; 2724 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2725 PetscValidType(mat, 1); 2726 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2727 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2728 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2729 2730 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2731 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2732 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2733 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2734 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2735 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2736 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2737 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2738 MatCheckPreallocated(mat, 1); 2739 2740 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2741 PetscCall(VecLockReadPush(v1)); 2742 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2743 PetscCall(VecLockReadPop(v1)); 2744 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2745 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2746 PetscFunctionReturn(0); 2747 } 2748 2749 /*@ 2750 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2751 2752 Neighbor-wise Collective 2753 2754 Input Parameters: 2755 + mat - the matrix 2756 - v1, v2 - the vectors 2757 2758 Output Parameters: 2759 . v3 - the result 2760 2761 Note: 2762 The vectors v1 and v3 cannot be the same. I.e., one cannot 2763 call `MatMultTransposeAdd`(A,v1,v2,v1). 2764 2765 Level: beginner 2766 2767 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2768 @*/ 2769 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2770 { 2771 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2772 2773 PetscFunctionBegin; 2774 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2775 PetscValidType(mat, 1); 2776 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2777 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2778 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2779 2780 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2781 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2782 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2783 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2784 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2785 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2786 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2787 MatCheckPreallocated(mat, 1); 2788 2789 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2790 PetscCall(VecLockReadPush(v1)); 2791 PetscCall((*op)(mat, v1, v2, v3)); 2792 PetscCall(VecLockReadPop(v1)); 2793 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2794 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2795 PetscFunctionReturn(0); 2796 } 2797 2798 /*@ 2799 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2800 2801 Neighbor-wise Collective 2802 2803 Input Parameters: 2804 + mat - the matrix 2805 - v1, v2 - the vectors 2806 2807 Output Parameters: 2808 . v3 - the result 2809 2810 Note: 2811 The vectors v1 and v3 cannot be the same. I.e., one cannot 2812 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2813 2814 Level: beginner 2815 2816 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2817 @*/ 2818 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2819 { 2820 PetscFunctionBegin; 2821 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2822 PetscValidType(mat, 1); 2823 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2824 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2825 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2826 2827 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2828 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2829 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2830 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2831 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2832 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2833 MatCheckPreallocated(mat, 1); 2834 2835 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2836 PetscCall(VecLockReadPush(v1)); 2837 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2838 else { 2839 Vec w, z; 2840 PetscCall(VecDuplicate(v1, &w)); 2841 PetscCall(VecCopy(v1, w)); 2842 PetscCall(VecConjugate(w)); 2843 PetscCall(VecDuplicate(v3, &z)); 2844 PetscCall(MatMultTranspose(mat, w, z)); 2845 PetscCall(VecDestroy(&w)); 2846 PetscCall(VecConjugate(z)); 2847 if (v2 != v3) { 2848 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2849 } else { 2850 PetscCall(VecAXPY(v3, 1.0, z)); 2851 } 2852 PetscCall(VecDestroy(&z)); 2853 } 2854 PetscCall(VecLockReadPop(v1)); 2855 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2856 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2857 PetscFunctionReturn(0); 2858 } 2859 2860 /*@C 2861 MatGetFactorType - gets the type of factorization it is 2862 2863 Not Collective 2864 2865 Input Parameters: 2866 . mat - the matrix 2867 2868 Output Parameters: 2869 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2870 2871 Level: intermediate 2872 2873 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2874 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2875 @*/ 2876 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2877 { 2878 PetscFunctionBegin; 2879 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2880 PetscValidType(mat, 1); 2881 PetscValidPointer(t, 2); 2882 *t = mat->factortype; 2883 PetscFunctionReturn(0); 2884 } 2885 2886 /*@C 2887 MatSetFactorType - sets the type of factorization it is 2888 2889 Logically Collective 2890 2891 Input Parameters: 2892 + mat - the matrix 2893 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2894 2895 Level: intermediate 2896 2897 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2898 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2899 @*/ 2900 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2901 { 2902 PetscFunctionBegin; 2903 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2904 PetscValidType(mat, 1); 2905 mat->factortype = t; 2906 PetscFunctionReturn(0); 2907 } 2908 2909 /* ------------------------------------------------------------*/ 2910 /*@C 2911 MatGetInfo - Returns information about matrix storage (number of 2912 nonzeros, memory, etc.). 2913 2914 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2915 2916 Input Parameter: 2917 . mat - the matrix 2918 2919 Output Parameters: 2920 + flag - flag indicating the type of parameters to be returned 2921 (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, 2922 MAT_GLOBAL_SUM - sum over all processors) 2923 - info - matrix information context 2924 2925 Notes: 2926 The `MatInfo` context contains a variety of matrix data, including 2927 number of nonzeros allocated and used, number of mallocs during 2928 matrix assembly, etc. Additional information for factored matrices 2929 is provided (such as the fill ratio, number of mallocs during 2930 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2931 when using the runtime options 2932 $ -info -mat_view ::ascii_info 2933 2934 Example for C/C++ Users: 2935 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2936 data within the MatInfo context. For example, 2937 .vb 2938 MatInfo info; 2939 Mat A; 2940 double mal, nz_a, nz_u; 2941 2942 MatGetInfo(A,MAT_LOCAL,&info); 2943 mal = info.mallocs; 2944 nz_a = info.nz_allocated; 2945 .ve 2946 2947 Example for Fortran Users: 2948 Fortran users should declare info as a double precision 2949 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2950 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2951 a complete list of parameter names. 2952 .vb 2953 double precision info(MAT_INFO_SIZE) 2954 double precision mal, nz_a 2955 Mat A 2956 integer ierr 2957 2958 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2959 mal = info(MAT_INFO_MALLOCS) 2960 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2961 .ve 2962 2963 Level: intermediate 2964 2965 Developer Note: 2966 Fortran interface is not autogenerated as the 2967 interface definition cannot be generated correctly [due to MatInfo] 2968 2969 .seealso: `MatInfo`, `MatStashGetInfo()` 2970 @*/ 2971 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2972 { 2973 PetscFunctionBegin; 2974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2975 PetscValidType(mat, 1); 2976 PetscValidPointer(info, 3); 2977 MatCheckPreallocated(mat, 1); 2978 PetscUseTypeMethod(mat, getinfo, flag, info); 2979 PetscFunctionReturn(0); 2980 } 2981 2982 /* 2983 This is used by external packages where it is not easy to get the info from the actual 2984 matrix factorization. 2985 */ 2986 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2987 { 2988 PetscFunctionBegin; 2989 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2990 PetscFunctionReturn(0); 2991 } 2992 2993 /* ----------------------------------------------------------*/ 2994 2995 /*@C 2996 MatLUFactor - Performs in-place LU factorization of matrix. 2997 2998 Collective 2999 3000 Input Parameters: 3001 + mat - the matrix 3002 . row - row permutation 3003 . col - column permutation 3004 - info - options for factorization, includes 3005 $ fill - expected fill as ratio of original fill. 3006 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3007 $ Run with the option -info to determine an optimal value to use 3008 3009 Notes: 3010 Most users should employ the `KSP` interface for linear solvers 3011 instead of working directly with matrix algebra routines such as this. 3012 See, e.g., `KSPCreate()`. 3013 3014 This changes the state of the matrix to a factored matrix; it cannot be used 3015 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3016 3017 This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3018 when not using `KSP`. 3019 3020 Level: developer 3021 3022 Developer Note: 3023 The Fortran interface is not autogenerated as the 3024 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3025 3026 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3027 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3028 @*/ 3029 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3030 { 3031 MatFactorInfo tinfo; 3032 3033 PetscFunctionBegin; 3034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3035 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3036 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3037 if (info) PetscValidPointer(info, 4); 3038 PetscValidType(mat, 1); 3039 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3040 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3041 MatCheckPreallocated(mat, 1); 3042 if (!info) { 3043 PetscCall(MatFactorInfoInitialize(&tinfo)); 3044 info = &tinfo; 3045 } 3046 3047 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3048 PetscUseTypeMethod(mat, lufactor, row, col, info); 3049 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3050 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3051 PetscFunctionReturn(0); 3052 } 3053 3054 /*@C 3055 MatILUFactor - Performs in-place ILU factorization of matrix. 3056 3057 Collective 3058 3059 Input Parameters: 3060 + mat - the matrix 3061 . row - row permutation 3062 . col - column permutation 3063 - info - structure containing 3064 $ levels - number of levels of fill. 3065 $ expected fill - as ratio of original fill. 3066 $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3067 missing diagonal entries) 3068 3069 Level: developer 3070 3071 Notes: 3072 Most users should employ the `KSP` interface for linear solvers 3073 instead of working directly with matrix algebra routines such as this. 3074 See, e.g., `KSPCreate()`. 3075 3076 Probably really in-place only when level of fill is zero, otherwise allocates 3077 new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3078 when not using `KSP`. 3079 3080 Developer Note: 3081 The Fortran interface is not autogenerated as the 3082 interface definition cannot be generated correctly [due to MatFactorInfo] 3083 3084 .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3085 @*/ 3086 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3087 { 3088 PetscFunctionBegin; 3089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3090 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3091 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3092 PetscValidPointer(info, 4); 3093 PetscValidType(mat, 1); 3094 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3095 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3096 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3097 MatCheckPreallocated(mat, 1); 3098 3099 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3100 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3101 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3102 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3103 PetscFunctionReturn(0); 3104 } 3105 3106 /*@C 3107 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3108 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3109 3110 Collective on fact 3111 3112 Input Parameters: 3113 + fact - the factor matrix obtained with `MatGetFactor()` 3114 . mat - the matrix 3115 . row, col - row and column permutations 3116 - info - options for factorization, includes 3117 .vb 3118 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3119 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3120 .ve 3121 3122 Level: developer 3123 3124 Notes: 3125 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3126 3127 Most users should employ the simplified `KSP` interface for linear solvers 3128 instead of working directly with matrix algebra routines such as this. 3129 See, e.g., `KSPCreate()`. 3130 3131 Developer Note: 3132 The Fortran interface is not autogenerated as the 3133 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3134 3135 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3136 @*/ 3137 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3138 { 3139 MatFactorInfo tinfo; 3140 3141 PetscFunctionBegin; 3142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3143 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3144 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3145 if (info) PetscValidPointer(info, 5); 3146 PetscValidType(mat, 2); 3147 PetscValidPointer(fact, 1); 3148 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3149 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3150 if (!(fact)->ops->lufactorsymbolic) { 3151 MatSolverType stype; 3152 PetscCall(MatFactorGetSolverType(fact, &stype)); 3153 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype); 3154 } 3155 MatCheckPreallocated(mat, 2); 3156 if (!info) { 3157 PetscCall(MatFactorInfoInitialize(&tinfo)); 3158 info = &tinfo; 3159 } 3160 3161 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3162 PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info)); 3163 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3164 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3165 PetscFunctionReturn(0); 3166 } 3167 3168 /*@C 3169 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3170 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3171 3172 Collective on fact 3173 3174 Input Parameters: 3175 + fact - the factor matrix obtained with `MatGetFactor()` 3176 . mat - the matrix 3177 - info - options for factorization 3178 3179 Level: developer 3180 3181 Notes: 3182 See `MatLUFactor()` for in-place factorization. See 3183 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3184 3185 Most users should employ the `KSP` interface for linear solvers 3186 instead of working directly with matrix algebra routines such as this. 3187 See, e.g., `KSPCreate()`. 3188 3189 Developer Note: 3190 The Fortran interface is not autogenerated as the 3191 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3192 3193 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3194 @*/ 3195 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3196 { 3197 MatFactorInfo tinfo; 3198 3199 PetscFunctionBegin; 3200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3201 PetscValidType(mat, 2); 3202 PetscValidPointer(fact, 1); 3203 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3204 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3205 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3206 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3207 3208 PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name); 3209 MatCheckPreallocated(mat, 2); 3210 if (!info) { 3211 PetscCall(MatFactorInfoInitialize(&tinfo)); 3212 info = &tinfo; 3213 } 3214 3215 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3216 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3217 PetscCall((fact->ops->lufactornumeric)(fact, mat, info)); 3218 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3219 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3220 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3221 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3222 PetscFunctionReturn(0); 3223 } 3224 3225 /*@C 3226 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3227 symmetric matrix. 3228 3229 Collective 3230 3231 Input Parameters: 3232 + mat - the matrix 3233 . perm - row and column permutations 3234 - f - expected fill as ratio of original fill 3235 3236 Level: developer 3237 3238 Notes: 3239 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3240 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3241 3242 Most users should employ the `KSP` interface for linear solvers 3243 instead of working directly with matrix algebra routines such as this. 3244 See, e.g., `KSPCreate()`. 3245 3246 Developer Note: 3247 The Fortran interface is not autogenerated as the 3248 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3249 3250 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3251 `MatGetOrdering()` 3252 @*/ 3253 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3254 { 3255 MatFactorInfo tinfo; 3256 3257 PetscFunctionBegin; 3258 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3259 PetscValidType(mat, 1); 3260 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3261 if (info) PetscValidPointer(info, 3); 3262 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3263 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3264 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3265 MatCheckPreallocated(mat, 1); 3266 if (!info) { 3267 PetscCall(MatFactorInfoInitialize(&tinfo)); 3268 info = &tinfo; 3269 } 3270 3271 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3272 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3273 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3274 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3275 PetscFunctionReturn(0); 3276 } 3277 3278 /*@C 3279 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3280 of a symmetric matrix. 3281 3282 Collective on fact 3283 3284 Input Parameters: 3285 + fact - the factor matrix obtained with `MatGetFactor()` 3286 . mat - the matrix 3287 . perm - row and column permutations 3288 - info - options for factorization, includes 3289 .vb 3290 fill - expected fill as ratio of original fill. 3291 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3292 Run with the option -info to determine an optimal value to use 3293 .ve 3294 3295 Level: developer 3296 3297 Notes: 3298 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3299 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3300 3301 Most users should employ the `KSP` interface for linear solvers 3302 instead of working directly with matrix algebra routines such as this. 3303 See, e.g., `KSPCreate()`. 3304 3305 Developer Note: 3306 The Fortran interface is not autogenerated as the 3307 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3308 3309 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3310 `MatGetOrdering()` 3311 @*/ 3312 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3313 { 3314 MatFactorInfo tinfo; 3315 3316 PetscFunctionBegin; 3317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3318 PetscValidType(mat, 2); 3319 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3320 if (info) PetscValidPointer(info, 4); 3321 PetscValidPointer(fact, 1); 3322 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3323 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3324 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3325 if (!(fact)->ops->choleskyfactorsymbolic) { 3326 MatSolverType stype; 3327 PetscCall(MatFactorGetSolverType(fact, &stype)); 3328 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype); 3329 } 3330 MatCheckPreallocated(mat, 2); 3331 if (!info) { 3332 PetscCall(MatFactorInfoInitialize(&tinfo)); 3333 info = &tinfo; 3334 } 3335 3336 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3337 PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info)); 3338 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3339 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3340 PetscFunctionReturn(0); 3341 } 3342 3343 /*@C 3344 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3345 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3346 `MatCholeskyFactorSymbolic()`. 3347 3348 Collective on fact 3349 3350 Input Parameters: 3351 + fact - the factor matrix obtained with `MatGetFactor()` 3352 . mat - the initial matrix 3353 . info - options for factorization 3354 - fact - the symbolic factor of mat 3355 3356 Level: developer 3357 3358 Note: 3359 Most users should employ the `KSP` interface for linear solvers 3360 instead of working directly with matrix algebra routines such as this. 3361 See, e.g., `KSPCreate()`. 3362 3363 Developer Note: 3364 The Fortran interface is not autogenerated as the 3365 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3366 3367 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3368 @*/ 3369 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3370 { 3371 MatFactorInfo tinfo; 3372 3373 PetscFunctionBegin; 3374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3375 PetscValidType(mat, 2); 3376 PetscValidPointer(fact, 1); 3377 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3378 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3379 PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name); 3380 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3381 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3382 MatCheckPreallocated(mat, 2); 3383 if (!info) { 3384 PetscCall(MatFactorInfoInitialize(&tinfo)); 3385 info = &tinfo; 3386 } 3387 3388 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3389 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3390 PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info)); 3391 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3392 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3393 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3394 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3395 PetscFunctionReturn(0); 3396 } 3397 3398 /*@ 3399 MatQRFactor - Performs in-place QR factorization of matrix. 3400 3401 Collective 3402 3403 Input Parameters: 3404 + mat - the matrix 3405 . col - column permutation 3406 - info - options for factorization, includes 3407 .vb 3408 fill - expected fill as ratio of original fill. 3409 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3410 Run with the option -info to determine an optimal value to use 3411 .ve 3412 3413 Level: developer 3414 3415 Notes: 3416 Most users should employ the `KSP` interface for linear solvers 3417 instead of working directly with matrix algebra routines such as this. 3418 See, e.g., `KSPCreate()`. 3419 3420 This changes the state of the matrix to a factored matrix; it cannot be used 3421 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3422 3423 Developer Note: 3424 The Fortran interface is not autogenerated as the 3425 interface definition cannot be generated correctly [due to MatFactorInfo] 3426 3427 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3428 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3429 @*/ 3430 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3431 { 3432 PetscFunctionBegin; 3433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3434 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3435 if (info) PetscValidPointer(info, 3); 3436 PetscValidType(mat, 1); 3437 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3438 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3439 MatCheckPreallocated(mat, 1); 3440 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3441 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3442 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3443 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3444 PetscFunctionReturn(0); 3445 } 3446 3447 /*@ 3448 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3449 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3450 3451 Collective on fact 3452 3453 Input Parameters: 3454 + fact - the factor matrix obtained with `MatGetFactor()` 3455 . mat - the matrix 3456 . col - column permutation 3457 - info - options for factorization, includes 3458 .vb 3459 fill - expected fill as ratio of original fill. 3460 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3461 Run with the option -info to determine an optimal value to use 3462 .ve 3463 3464 Level: developer 3465 3466 Note: 3467 Most users should employ the `KSP` interface for linear solvers 3468 instead of working directly with matrix algebra routines such as this. 3469 See, e.g., `KSPCreate()`. 3470 3471 Developer Note: 3472 The Fortran interface is not autogenerated as the 3473 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3474 3475 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3476 @*/ 3477 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3478 { 3479 MatFactorInfo tinfo; 3480 3481 PetscFunctionBegin; 3482 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3483 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3484 if (info) PetscValidPointer(info, 4); 3485 PetscValidType(mat, 2); 3486 PetscValidPointer(fact, 1); 3487 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3488 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3489 MatCheckPreallocated(mat, 2); 3490 if (!info) { 3491 PetscCall(MatFactorInfoInitialize(&tinfo)); 3492 info = &tinfo; 3493 } 3494 3495 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3496 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3497 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3498 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3499 PetscFunctionReturn(0); 3500 } 3501 3502 /*@ 3503 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3504 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3505 3506 Collective on fact 3507 3508 Input Parameters: 3509 + fact - the factor matrix obtained with `MatGetFactor()` 3510 . mat - the matrix 3511 - info - options for factorization 3512 3513 Level: developer 3514 3515 Notes: 3516 See `MatQRFactor()` for in-place factorization. 3517 3518 Most users should employ the `KSP` interface for linear solvers 3519 instead of working directly with matrix algebra routines such as this. 3520 See, e.g., `KSPCreate()`. 3521 3522 Developer Note: 3523 The Fortran interface is not autogenerated as the 3524 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3525 3526 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3527 @*/ 3528 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3529 { 3530 MatFactorInfo tinfo; 3531 3532 PetscFunctionBegin; 3533 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3534 PetscValidType(mat, 2); 3535 PetscValidPointer(fact, 1); 3536 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3537 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3538 PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3539 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3540 3541 MatCheckPreallocated(mat, 2); 3542 if (!info) { 3543 PetscCall(MatFactorInfoInitialize(&tinfo)); 3544 info = &tinfo; 3545 } 3546 3547 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3548 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3549 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3550 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3551 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3552 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3553 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3554 PetscFunctionReturn(0); 3555 } 3556 3557 /* ----------------------------------------------------------------*/ 3558 /*@ 3559 MatSolve - Solves A x = b, given a factored matrix. 3560 3561 Neighbor-wise Collective 3562 3563 Input Parameters: 3564 + mat - the factored matrix 3565 - b - the right-hand-side vector 3566 3567 Output Parameter: 3568 . x - the result vector 3569 3570 Notes: 3571 The vectors b and x cannot be the same. I.e., one cannot 3572 call `MatSolve`(A,x,x). 3573 3574 Most users should employ the `KSP` interface for linear solvers 3575 instead of working directly with matrix algebra routines such as this. 3576 See, e.g., `KSPCreate()`. 3577 3578 Level: developer 3579 3580 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3581 @*/ 3582 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3583 { 3584 PetscFunctionBegin; 3585 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3586 PetscValidType(mat, 1); 3587 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3588 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3589 PetscCheckSameComm(mat, 1, b, 2); 3590 PetscCheckSameComm(mat, 1, x, 3); 3591 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3592 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3593 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3594 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3595 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3596 MatCheckPreallocated(mat, 1); 3597 3598 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3599 if (mat->factorerrortype) { 3600 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3601 PetscCall(VecSetInf(x)); 3602 } else PetscUseTypeMethod(mat, solve, b, x); 3603 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3604 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3605 PetscFunctionReturn(0); 3606 } 3607 3608 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3609 { 3610 Vec b, x; 3611 PetscInt N, i; 3612 PetscErrorCode (*f)(Mat, Vec, Vec); 3613 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3614 3615 PetscFunctionBegin; 3616 if (A->factorerrortype) { 3617 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3618 PetscCall(MatSetInf(X)); 3619 PetscFunctionReturn(0); 3620 } 3621 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3622 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3623 PetscCall(MatBoundToCPU(A, &Abound)); 3624 if (!Abound) { 3625 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3626 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3627 } 3628 #if defined(PETSC_HAVE_CUDA) 3629 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3630 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3631 #elif (PETSC_HAVE_HIP) 3632 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3633 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3634 #endif 3635 PetscCall(MatGetSize(B, NULL, &N)); 3636 for (i = 0; i < N; i++) { 3637 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3638 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3639 PetscCall((*f)(A, b, x)); 3640 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3641 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3642 } 3643 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3644 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3645 PetscFunctionReturn(0); 3646 } 3647 3648 /*@ 3649 MatMatSolve - Solves A X = B, given a factored matrix. 3650 3651 Neighbor-wise Collective on A 3652 3653 Input Parameters: 3654 + A - the factored matrix 3655 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3656 3657 Output Parameter: 3658 . X - the result matrix (dense matrix) 3659 3660 Note: 3661 If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO; 3662 otherwise, B and X cannot be the same. 3663 3664 Level: developer 3665 3666 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3667 @*/ 3668 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3669 { 3670 PetscFunctionBegin; 3671 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3672 PetscValidType(A, 1); 3673 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3674 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3675 PetscCheckSameComm(A, 1, B, 2); 3676 PetscCheckSameComm(A, 1, X, 3); 3677 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3678 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3679 PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3680 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3681 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3682 MatCheckPreallocated(A, 1); 3683 3684 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3685 if (!A->ops->matsolve) { 3686 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3687 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3688 } else PetscUseTypeMethod(A, matsolve, B, X); 3689 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3690 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3691 PetscFunctionReturn(0); 3692 } 3693 3694 /*@ 3695 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3696 3697 Neighbor-wise Collective on A 3698 3699 Input Parameters: 3700 + A - the factored matrix 3701 - B - the right-hand-side matrix (`MATDENSE` matrix) 3702 3703 Output Parameter: 3704 . X - the result matrix (dense matrix) 3705 3706 Note: 3707 The matrices B and X cannot be the same. I.e., one cannot 3708 call `MatMatSolveTranspose`(A,X,X). 3709 3710 Level: developer 3711 3712 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3713 @*/ 3714 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3715 { 3716 PetscFunctionBegin; 3717 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3718 PetscValidType(A, 1); 3719 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3720 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3721 PetscCheckSameComm(A, 1, B, 2); 3722 PetscCheckSameComm(A, 1, X, 3); 3723 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3724 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3725 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3726 PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n); 3727 PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3728 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3729 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3730 MatCheckPreallocated(A, 1); 3731 3732 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3733 if (!A->ops->matsolvetranspose) { 3734 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3735 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3736 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3737 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3738 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3739 PetscFunctionReturn(0); 3740 } 3741 3742 /*@ 3743 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3744 3745 Neighbor-wise Collective on A 3746 3747 Input Parameters: 3748 + A - the factored matrix 3749 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3750 3751 Output Parameter: 3752 . X - the result matrix (dense matrix) 3753 3754 Note: 3755 For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row 3756 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3757 3758 Level: developer 3759 3760 .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3761 @*/ 3762 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3763 { 3764 PetscFunctionBegin; 3765 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3766 PetscValidType(A, 1); 3767 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3768 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3769 PetscCheckSameComm(A, 1, Bt, 2); 3770 PetscCheckSameComm(A, 1, X, 3); 3771 3772 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3773 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3774 PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N); 3775 PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix"); 3776 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3777 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3778 MatCheckPreallocated(A, 1); 3779 3780 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3781 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3782 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3783 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3784 PetscFunctionReturn(0); 3785 } 3786 3787 /*@ 3788 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3789 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3790 3791 Neighbor-wise Collective 3792 3793 Input Parameters: 3794 + mat - the factored matrix 3795 - b - the right-hand-side vector 3796 3797 Output Parameter: 3798 . x - the result vector 3799 3800 Notes: 3801 `MatSolve()` should be used for most applications, as it performs 3802 a forward solve followed by a backward solve. 3803 3804 The vectors b and x cannot be the same, i.e., one cannot 3805 call `MatForwardSolve`(A,x,x). 3806 3807 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3808 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3809 `MatForwardSolve()` solves U^T*D y = b, and 3810 `MatBackwardSolve()` solves U x = y. 3811 Thus they do not provide a symmetric preconditioner. 3812 3813 Level: developer 3814 3815 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3816 @*/ 3817 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3818 { 3819 PetscFunctionBegin; 3820 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3821 PetscValidType(mat, 1); 3822 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3823 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3824 PetscCheckSameComm(mat, 1, b, 2); 3825 PetscCheckSameComm(mat, 1, x, 3); 3826 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3827 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3828 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3829 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3830 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3831 MatCheckPreallocated(mat, 1); 3832 3833 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3834 PetscUseTypeMethod(mat, forwardsolve, b, x); 3835 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3836 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3837 PetscFunctionReturn(0); 3838 } 3839 3840 /*@ 3841 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3842 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3843 3844 Neighbor-wise Collective 3845 3846 Input Parameters: 3847 + mat - the factored matrix 3848 - b - the right-hand-side vector 3849 3850 Output Parameter: 3851 . x - the result vector 3852 3853 Notes: 3854 `MatSolve()` should be used for most applications, as it performs 3855 a forward solve followed by a backward solve. 3856 3857 The vectors b and x cannot be the same. I.e., one cannot 3858 call `MatBackwardSolve`(A,x,x). 3859 3860 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3861 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3862 `MatForwardSolve()` solves U^T*D y = b, and 3863 `MatBackwardSolve()` solves U x = y. 3864 Thus they do not provide a symmetric preconditioner. 3865 3866 Level: developer 3867 3868 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3869 @*/ 3870 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3871 { 3872 PetscFunctionBegin; 3873 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3874 PetscValidType(mat, 1); 3875 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3876 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3877 PetscCheckSameComm(mat, 1, b, 2); 3878 PetscCheckSameComm(mat, 1, x, 3); 3879 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3880 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3881 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3882 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3883 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3884 MatCheckPreallocated(mat, 1); 3885 3886 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3887 PetscUseTypeMethod(mat, backwardsolve, b, x); 3888 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3889 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3890 PetscFunctionReturn(0); 3891 } 3892 3893 /*@ 3894 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3895 3896 Neighbor-wise Collective 3897 3898 Input Parameters: 3899 + mat - the factored matrix 3900 . b - the right-hand-side vector 3901 - y - the vector to be added to 3902 3903 Output Parameter: 3904 . x - the result vector 3905 3906 Note: 3907 The vectors b and x cannot be the same. I.e., one cannot 3908 call `MatSolveAdd`(A,x,y,x). 3909 3910 Level: developer 3911 3912 .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3913 @*/ 3914 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3915 { 3916 PetscScalar one = 1.0; 3917 Vec tmp; 3918 3919 PetscFunctionBegin; 3920 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3921 PetscValidType(mat, 1); 3922 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3923 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3924 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3925 PetscCheckSameComm(mat, 1, b, 2); 3926 PetscCheckSameComm(mat, 1, y, 3); 3927 PetscCheckSameComm(mat, 1, x, 4); 3928 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3929 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3930 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3931 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 3932 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3933 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 3934 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3935 MatCheckPreallocated(mat, 1); 3936 3937 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3938 if (mat->factorerrortype) { 3939 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3940 PetscCall(VecSetInf(x)); 3941 } else if (mat->ops->solveadd) { 3942 PetscUseTypeMethod(mat, solveadd, b, y, x); 3943 } else { 3944 /* do the solve then the add manually */ 3945 if (x != y) { 3946 PetscCall(MatSolve(mat, b, x)); 3947 PetscCall(VecAXPY(x, one, y)); 3948 } else { 3949 PetscCall(VecDuplicate(x, &tmp)); 3950 PetscCall(VecCopy(x, tmp)); 3951 PetscCall(MatSolve(mat, b, x)); 3952 PetscCall(VecAXPY(x, one, tmp)); 3953 PetscCall(VecDestroy(&tmp)); 3954 } 3955 } 3956 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3957 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3958 PetscFunctionReturn(0); 3959 } 3960 3961 /*@ 3962 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3963 3964 Neighbor-wise Collective 3965 3966 Input Parameters: 3967 + mat - the factored matrix 3968 - b - the right-hand-side vector 3969 3970 Output Parameter: 3971 . x - the result vector 3972 3973 Notes: 3974 The vectors b and x cannot be the same. I.e., one cannot 3975 call `MatSolveTranspose`(A,x,x). 3976 3977 Most users should employ the `KSP` interface for linear solvers 3978 instead of working directly with matrix algebra routines such as this. 3979 See, e.g., `KSPCreate()`. 3980 3981 Level: developer 3982 3983 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3984 @*/ 3985 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3986 { 3987 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3988 3989 PetscFunctionBegin; 3990 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3991 PetscValidType(mat, 1); 3992 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3993 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3994 PetscCheckSameComm(mat, 1, b, 2); 3995 PetscCheckSameComm(mat, 1, x, 3); 3996 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3997 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 3998 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 3999 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 4000 MatCheckPreallocated(mat, 1); 4001 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4002 if (mat->factorerrortype) { 4003 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4004 PetscCall(VecSetInf(x)); 4005 } else { 4006 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4007 PetscCall((*f)(mat, b, x)); 4008 } 4009 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4010 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4011 PetscFunctionReturn(0); 4012 } 4013 4014 /*@ 4015 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4016 factored matrix. 4017 4018 Neighbor-wise Collective 4019 4020 Input Parameters: 4021 + mat - the factored matrix 4022 . b - the right-hand-side vector 4023 - y - the vector to be added to 4024 4025 Output Parameter: 4026 . x - the result vector 4027 4028 Note: 4029 The vectors b and x cannot be the same. I.e., one cannot 4030 call `MatSolveTransposeAdd`(A,x,y,x). 4031 4032 Level: developer 4033 4034 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4035 @*/ 4036 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4037 { 4038 PetscScalar one = 1.0; 4039 Vec tmp; 4040 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4041 4042 PetscFunctionBegin; 4043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4044 PetscValidType(mat, 1); 4045 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4046 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4047 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4048 PetscCheckSameComm(mat, 1, b, 2); 4049 PetscCheckSameComm(mat, 1, y, 3); 4050 PetscCheckSameComm(mat, 1, x, 4); 4051 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4052 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4053 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4054 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 4055 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 4056 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 4057 MatCheckPreallocated(mat, 1); 4058 4059 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4060 if (mat->factorerrortype) { 4061 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4062 PetscCall(VecSetInf(x)); 4063 } else if (f) { 4064 PetscCall((*f)(mat, b, y, x)); 4065 } else { 4066 /* do the solve then the add manually */ 4067 if (x != y) { 4068 PetscCall(MatSolveTranspose(mat, b, x)); 4069 PetscCall(VecAXPY(x, one, y)); 4070 } else { 4071 PetscCall(VecDuplicate(x, &tmp)); 4072 PetscCall(VecCopy(x, tmp)); 4073 PetscCall(MatSolveTranspose(mat, b, x)); 4074 PetscCall(VecAXPY(x, one, tmp)); 4075 PetscCall(VecDestroy(&tmp)); 4076 } 4077 } 4078 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4079 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4080 PetscFunctionReturn(0); 4081 } 4082 /* ----------------------------------------------------------------*/ 4083 4084 /*@ 4085 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4086 4087 Neighbor-wise Collective 4088 4089 Input Parameters: 4090 + mat - the matrix 4091 . b - the right hand side 4092 . omega - the relaxation factor 4093 . flag - flag indicating the type of SOR (see below) 4094 . shift - diagonal shift 4095 . its - the number of iterations 4096 - lits - the number of local iterations 4097 4098 Output Parameter: 4099 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4100 4101 SOR Flags: 4102 + `SOR_FORWARD_SWEEP` - forward SOR 4103 . `SOR_BACKWARD_SWEEP` - backward SOR 4104 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4105 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4106 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4107 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4108 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4109 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4110 upper/lower triangular part of matrix to 4111 vector (with omega) 4112 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4113 4114 Notes: 4115 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4116 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4117 on each processor. 4118 4119 Application programmers will not generally use `MatSOR()` directly, 4120 but instead will employ the `KSP`/`PC` interface. 4121 4122 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4123 4124 Most users should employ the `KSP` interface for linear solvers 4125 instead of working directly with matrix algebra routines such as this. 4126 See, e.g., `KSPCreate()`. 4127 4128 Vectors x and b CANNOT be the same 4129 4130 Notes for Advanced Users: 4131 The flags are implemented as bitwise inclusive or operations. 4132 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4133 to specify a zero initial guess for SSOR. 4134 4135 Developer Note: 4136 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4137 4138 Level: developer 4139 4140 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4141 @*/ 4142 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4143 { 4144 PetscFunctionBegin; 4145 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4146 PetscValidType(mat, 1); 4147 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4148 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4149 PetscCheckSameComm(mat, 1, b, 2); 4150 PetscCheckSameComm(mat, 1, x, 8); 4151 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4152 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4153 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 4154 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 4155 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 4156 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4157 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4158 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4159 4160 MatCheckPreallocated(mat, 1); 4161 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4162 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4163 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4164 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4165 PetscFunctionReturn(0); 4166 } 4167 4168 /* 4169 Default matrix copy routine. 4170 */ 4171 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4172 { 4173 PetscInt i, rstart = 0, rend = 0, nz; 4174 const PetscInt *cwork; 4175 const PetscScalar *vwork; 4176 4177 PetscFunctionBegin; 4178 if (B->assembled) PetscCall(MatZeroEntries(B)); 4179 if (str == SAME_NONZERO_PATTERN) { 4180 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4181 for (i = rstart; i < rend; i++) { 4182 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4183 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4184 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4185 } 4186 } else { 4187 PetscCall(MatAYPX(B, 0.0, A, str)); 4188 } 4189 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4190 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4191 PetscFunctionReturn(0); 4192 } 4193 4194 /*@ 4195 MatCopy - Copies a matrix to another matrix. 4196 4197 Collective on A 4198 4199 Input Parameters: 4200 + A - the matrix 4201 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4202 4203 Output Parameter: 4204 . B - where the copy is put 4205 4206 Notes: 4207 If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash. 4208 4209 `MatCopy()` copies the matrix entries of a matrix to another existing 4210 matrix (after first zeroing the second matrix). A related routine is 4211 `MatConvert()`, which first creates a new matrix and then copies the data. 4212 4213 Level: intermediate 4214 4215 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()` 4216 @*/ 4217 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4218 { 4219 PetscInt i; 4220 4221 PetscFunctionBegin; 4222 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4223 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4224 PetscValidType(A, 1); 4225 PetscValidType(B, 2); 4226 PetscCheckSameComm(A, 1, B, 2); 4227 MatCheckPreallocated(B, 2); 4228 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4229 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4230 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N, 4231 A->cmap->N, B->cmap->N); 4232 MatCheckPreallocated(A, 1); 4233 if (A == B) PetscFunctionReturn(0); 4234 4235 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4236 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4237 else PetscCall(MatCopy_Basic(A, B, str)); 4238 4239 B->stencil.dim = A->stencil.dim; 4240 B->stencil.noc = A->stencil.noc; 4241 for (i = 0; i <= A->stencil.dim; i++) { 4242 B->stencil.dims[i] = A->stencil.dims[i]; 4243 B->stencil.starts[i] = A->stencil.starts[i]; 4244 } 4245 4246 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4247 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4248 PetscFunctionReturn(0); 4249 } 4250 4251 /*@C 4252 MatConvert - Converts a matrix to another matrix, either of the same 4253 or different type. 4254 4255 Collective 4256 4257 Input Parameters: 4258 + mat - the matrix 4259 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4260 same type as the original matrix. 4261 - reuse - denotes if the destination matrix is to be created or reused. 4262 Use `MAT_INPLACE_MATRIX` for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use 4263 `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` (can only be used after the first call was made with `MAT_INITIAL_MATRIX`, causes the matrix space in M to be reused). 4264 4265 Output Parameter: 4266 . M - pointer to place new matrix 4267 4268 Notes: 4269 `MatConvert()` first creates a new matrix and then copies the data from 4270 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4271 entries of one matrix to another already existing matrix context. 4272 4273 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4274 the MPI communicator of the generated matrix is always the same as the communicator 4275 of the input matrix. 4276 4277 Level: intermediate 4278 4279 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4280 @*/ 4281 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4282 { 4283 PetscBool sametype, issame, flg; 4284 PetscBool3 issymmetric, ishermitian; 4285 char convname[256], mtype[256]; 4286 Mat B; 4287 4288 PetscFunctionBegin; 4289 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4290 PetscValidType(mat, 1); 4291 PetscValidPointer(M, 4); 4292 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4293 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4294 MatCheckPreallocated(mat, 1); 4295 4296 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4297 if (flg) newtype = mtype; 4298 4299 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4300 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4301 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4302 PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4303 4304 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4305 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4306 PetscFunctionReturn(0); 4307 } 4308 4309 /* Cache Mat options because some converters use MatHeaderReplace */ 4310 issymmetric = mat->symmetric; 4311 ishermitian = mat->hermitian; 4312 4313 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4314 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4315 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4316 } else { 4317 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4318 const char *prefix[3] = {"seq", "mpi", ""}; 4319 PetscInt i; 4320 /* 4321 Order of precedence: 4322 0) See if newtype is a superclass of the current matrix. 4323 1) See if a specialized converter is known to the current matrix. 4324 2) See if a specialized converter is known to the desired matrix class. 4325 3) See if a good general converter is registered for the desired class 4326 (as of 6/27/03 only MATMPIADJ falls into this category). 4327 4) See if a good general converter is known for the current matrix. 4328 5) Use a really basic converter. 4329 */ 4330 4331 /* 0) See if newtype is a superclass of the current matrix. 4332 i.e mat is mpiaij and newtype is aij */ 4333 for (i = 0; i < 2; i++) { 4334 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4335 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4336 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4337 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4338 if (flg) { 4339 if (reuse == MAT_INPLACE_MATRIX) { 4340 PetscCall(PetscInfo(mat, "Early return\n")); 4341 PetscFunctionReturn(0); 4342 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4343 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4344 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4345 PetscFunctionReturn(0); 4346 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4347 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4348 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4349 PetscFunctionReturn(0); 4350 } 4351 } 4352 } 4353 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4354 for (i = 0; i < 3; i++) { 4355 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4356 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4357 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4358 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4359 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4360 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4361 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4362 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4363 if (conv) goto foundconv; 4364 } 4365 4366 /* 2) See if a specialized converter is known to the desired matrix class. */ 4367 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4368 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4369 PetscCall(MatSetType(B, newtype)); 4370 for (i = 0; i < 3; i++) { 4371 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4372 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4373 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4374 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4375 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4376 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4377 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4378 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4379 if (conv) { 4380 PetscCall(MatDestroy(&B)); 4381 goto foundconv; 4382 } 4383 } 4384 4385 /* 3) See if a good general converter is registered for the desired class */ 4386 conv = B->ops->convertfrom; 4387 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4388 PetscCall(MatDestroy(&B)); 4389 if (conv) goto foundconv; 4390 4391 /* 4) See if a good general converter is known for the current matrix */ 4392 if (mat->ops->convert) conv = mat->ops->convert; 4393 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4394 if (conv) goto foundconv; 4395 4396 /* 5) Use a really basic converter. */ 4397 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4398 conv = MatConvert_Basic; 4399 4400 foundconv: 4401 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4402 PetscCall((*conv)(mat, newtype, reuse, M)); 4403 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4404 /* the block sizes must be same if the mappings are copied over */ 4405 (*M)->rmap->bs = mat->rmap->bs; 4406 (*M)->cmap->bs = mat->cmap->bs; 4407 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4408 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4409 (*M)->rmap->mapping = mat->rmap->mapping; 4410 (*M)->cmap->mapping = mat->cmap->mapping; 4411 } 4412 (*M)->stencil.dim = mat->stencil.dim; 4413 (*M)->stencil.noc = mat->stencil.noc; 4414 for (i = 0; i <= mat->stencil.dim; i++) { 4415 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4416 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4417 } 4418 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4419 } 4420 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4421 4422 /* Copy Mat options */ 4423 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4424 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4425 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4426 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4427 PetscFunctionReturn(0); 4428 } 4429 4430 /*@C 4431 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4432 4433 Not Collective 4434 4435 Input Parameter: 4436 . mat - the matrix, must be a factored matrix 4437 4438 Output Parameter: 4439 . type - the string name of the package (do not free this string) 4440 4441 Level: intermediate 4442 4443 Note: 4444 In Fortran you pass in a empty string and the package name will be copied into it. 4445 (Make sure the string is long enough) 4446 4447 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4448 @*/ 4449 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4450 { 4451 PetscErrorCode (*conv)(Mat, MatSolverType *); 4452 4453 PetscFunctionBegin; 4454 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4455 PetscValidType(mat, 1); 4456 PetscValidPointer(type, 2); 4457 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4458 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4459 if (conv) PetscCall((*conv)(mat, type)); 4460 else *type = MATSOLVERPETSC; 4461 PetscFunctionReturn(0); 4462 } 4463 4464 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4465 struct _MatSolverTypeForSpecifcType { 4466 MatType mtype; 4467 /* no entry for MAT_FACTOR_NONE */ 4468 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4469 MatSolverTypeForSpecifcType next; 4470 }; 4471 4472 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4473 struct _MatSolverTypeHolder { 4474 char *name; 4475 MatSolverTypeForSpecifcType handlers; 4476 MatSolverTypeHolder next; 4477 }; 4478 4479 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4480 4481 /*@C 4482 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4483 4484 Input Parameters: 4485 + package - name of the package, for example petsc or superlu 4486 . mtype - the matrix type that works with this package 4487 . ftype - the type of factorization supported by the package 4488 - createfactor - routine that will create the factored matrix ready to be used 4489 4490 Level: developer 4491 4492 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4493 @*/ 4494 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4495 { 4496 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4497 PetscBool flg; 4498 MatSolverTypeForSpecifcType inext, iprev = NULL; 4499 4500 PetscFunctionBegin; 4501 PetscCall(MatInitializePackage()); 4502 if (!next) { 4503 PetscCall(PetscNew(&MatSolverTypeHolders)); 4504 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4505 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4506 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4507 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4508 PetscFunctionReturn(0); 4509 } 4510 while (next) { 4511 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4512 if (flg) { 4513 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4514 inext = next->handlers; 4515 while (inext) { 4516 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4517 if (flg) { 4518 inext->createfactor[(int)ftype - 1] = createfactor; 4519 PetscFunctionReturn(0); 4520 } 4521 iprev = inext; 4522 inext = inext->next; 4523 } 4524 PetscCall(PetscNew(&iprev->next)); 4525 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4526 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4527 PetscFunctionReturn(0); 4528 } 4529 prev = next; 4530 next = next->next; 4531 } 4532 PetscCall(PetscNew(&prev->next)); 4533 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4534 PetscCall(PetscNew(&prev->next->handlers)); 4535 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4536 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4537 PetscFunctionReturn(0); 4538 } 4539 4540 /*@C 4541 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4542 4543 Input Parameters: 4544 + type - name of the package, for example petsc or superlu 4545 . ftype - the type of factorization supported by the type 4546 - mtype - the matrix type that works with this type 4547 4548 Output Parameters: 4549 + foundtype - `PETSC_TRUE` if the type was registered 4550 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4551 - createfactor - routine that will create the factored matrix ready to be used or NULL if not found 4552 4553 Level: developer 4554 4555 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4556 @*/ 4557 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4558 { 4559 MatSolverTypeHolder next = MatSolverTypeHolders; 4560 PetscBool flg; 4561 MatSolverTypeForSpecifcType inext; 4562 4563 PetscFunctionBegin; 4564 if (foundtype) *foundtype = PETSC_FALSE; 4565 if (foundmtype) *foundmtype = PETSC_FALSE; 4566 if (createfactor) *createfactor = NULL; 4567 4568 if (type) { 4569 while (next) { 4570 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4571 if (flg) { 4572 if (foundtype) *foundtype = PETSC_TRUE; 4573 inext = next->handlers; 4574 while (inext) { 4575 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4576 if (flg) { 4577 if (foundmtype) *foundmtype = PETSC_TRUE; 4578 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4579 PetscFunctionReturn(0); 4580 } 4581 inext = inext->next; 4582 } 4583 } 4584 next = next->next; 4585 } 4586 } else { 4587 while (next) { 4588 inext = next->handlers; 4589 while (inext) { 4590 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4591 if (flg && inext->createfactor[(int)ftype - 1]) { 4592 if (foundtype) *foundtype = PETSC_TRUE; 4593 if (foundmtype) *foundmtype = PETSC_TRUE; 4594 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4595 PetscFunctionReturn(0); 4596 } 4597 inext = inext->next; 4598 } 4599 next = next->next; 4600 } 4601 /* try with base classes inext->mtype */ 4602 next = MatSolverTypeHolders; 4603 while (next) { 4604 inext = next->handlers; 4605 while (inext) { 4606 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4607 if (flg && inext->createfactor[(int)ftype - 1]) { 4608 if (foundtype) *foundtype = PETSC_TRUE; 4609 if (foundmtype) *foundmtype = PETSC_TRUE; 4610 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4611 PetscFunctionReturn(0); 4612 } 4613 inext = inext->next; 4614 } 4615 next = next->next; 4616 } 4617 } 4618 PetscFunctionReturn(0); 4619 } 4620 4621 PetscErrorCode MatSolverTypeDestroy(void) 4622 { 4623 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4624 MatSolverTypeForSpecifcType inext, iprev; 4625 4626 PetscFunctionBegin; 4627 while (next) { 4628 PetscCall(PetscFree(next->name)); 4629 inext = next->handlers; 4630 while (inext) { 4631 PetscCall(PetscFree(inext->mtype)); 4632 iprev = inext; 4633 inext = inext->next; 4634 PetscCall(PetscFree(iprev)); 4635 } 4636 prev = next; 4637 next = next->next; 4638 PetscCall(PetscFree(prev)); 4639 } 4640 MatSolverTypeHolders = NULL; 4641 PetscFunctionReturn(0); 4642 } 4643 4644 /*@C 4645 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4646 4647 Logically Collective 4648 4649 Input Parameters: 4650 . mat - the matrix 4651 4652 Output Parameters: 4653 . flg - `PETSC_TRUE` if uses the ordering 4654 4655 Note: 4656 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4657 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4658 4659 Level: developer 4660 4661 .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4662 @*/ 4663 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4664 { 4665 PetscFunctionBegin; 4666 *flg = mat->canuseordering; 4667 PetscFunctionReturn(0); 4668 } 4669 4670 /*@C 4671 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4672 4673 Logically Collective 4674 4675 Input Parameters: 4676 . mat - the matrix obtained with `MatGetFactor()` 4677 4678 Output Parameters: 4679 . otype - the preferred type 4680 4681 Level: developer 4682 4683 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4684 @*/ 4685 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4686 { 4687 PetscFunctionBegin; 4688 *otype = mat->preferredordering[ftype]; 4689 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4690 PetscFunctionReturn(0); 4691 } 4692 4693 /*@C 4694 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4695 4696 Collective 4697 4698 Input Parameters: 4699 + mat - the matrix 4700 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4701 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4702 4703 Output Parameters: 4704 . f - the factor matrix used with MatXXFactorSymbolic() calls 4705 4706 Options Database Key: 4707 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4708 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4709 4710 Notes: 4711 Users usually access the factorization solvers via `KSP` 4712 4713 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4714 such as pastix, superlu, mumps etc. 4715 4716 PETSc must have been ./configure to use the external solver, using the option --download-package 4717 4718 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4719 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4720 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4721 4722 Developer Note: 4723 This should actually be called `MatCreateFactor()` since it creates a new factor object 4724 4725 Level: intermediate 4726 4727 .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4728 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4729 @*/ 4730 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4731 { 4732 PetscBool foundtype, foundmtype; 4733 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4734 4735 PetscFunctionBegin; 4736 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4737 PetscValidType(mat, 1); 4738 4739 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4740 MatCheckPreallocated(mat, 1); 4741 4742 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4743 if (!foundtype) { 4744 if (type) { 4745 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate solver type %s for factorization type %s and matrix type %s. Perhaps you must ./configure with --download-%s", type, MatFactorTypes[ftype], 4746 ((PetscObject)mat)->type_name, type); 4747 } else { 4748 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate a solver type for factorization type %s and matrix type %s.", MatFactorTypes[ftype], ((PetscObject)mat)->type_name); 4749 } 4750 } 4751 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4752 PetscCheck(conv, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support factorization type %s for matrix type %s", type, MatFactorTypes[ftype], ((PetscObject)mat)->type_name); 4753 4754 PetscCall((*conv)(mat, ftype, f)); 4755 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4756 PetscFunctionReturn(0); 4757 } 4758 4759 /*@C 4760 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4761 4762 Not Collective 4763 4764 Input Parameters: 4765 + mat - the matrix 4766 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4767 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4768 4769 Output Parameter: 4770 . flg - PETSC_TRUE if the factorization is available 4771 4772 Notes: 4773 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4774 such as pastix, superlu, mumps etc. 4775 4776 PETSc must have been ./configure to use the external solver, using the option --download-package 4777 4778 Developer Note: 4779 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4780 4781 Level: intermediate 4782 4783 .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4784 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4785 @*/ 4786 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4787 { 4788 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4789 4790 PetscFunctionBegin; 4791 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4792 PetscValidType(mat, 1); 4793 PetscValidBoolPointer(flg, 4); 4794 4795 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4796 MatCheckPreallocated(mat, 1); 4797 4798 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4799 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4800 PetscFunctionReturn(0); 4801 } 4802 4803 /*@ 4804 MatDuplicate - Duplicates a matrix including the non-zero structure. 4805 4806 Collective 4807 4808 Input Parameters: 4809 + mat - the matrix 4810 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4811 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4812 4813 Output Parameter: 4814 . M - pointer to place new matrix 4815 4816 Level: intermediate 4817 4818 Notes: 4819 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4820 4821 May be called with an unassembled input `Mat` if `MAT_DO_NOT_COPY_VALUES` is used, in which case the output `Mat` is unassembled as well. 4822 4823 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the simple matrix data structure of mat 4824 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4825 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4826 4827 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4828 @*/ 4829 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4830 { 4831 Mat B; 4832 VecType vtype; 4833 PetscInt i; 4834 PetscObject dm; 4835 void (*viewf)(void); 4836 4837 PetscFunctionBegin; 4838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4839 PetscValidType(mat, 1); 4840 PetscValidPointer(M, 3); 4841 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4842 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4843 MatCheckPreallocated(mat, 1); 4844 4845 *M = NULL; 4846 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4847 PetscUseTypeMethod(mat, duplicate, op, M); 4848 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4849 B = *M; 4850 4851 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4852 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4853 PetscCall(MatGetVecType(mat, &vtype)); 4854 PetscCall(MatSetVecType(B, vtype)); 4855 4856 B->stencil.dim = mat->stencil.dim; 4857 B->stencil.noc = mat->stencil.noc; 4858 for (i = 0; i <= mat->stencil.dim; i++) { 4859 B->stencil.dims[i] = mat->stencil.dims[i]; 4860 B->stencil.starts[i] = mat->stencil.starts[i]; 4861 } 4862 4863 B->nooffproczerorows = mat->nooffproczerorows; 4864 B->nooffprocentries = mat->nooffprocentries; 4865 4866 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4867 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4868 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4869 PetscFunctionReturn(0); 4870 } 4871 4872 /*@ 4873 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4874 4875 Logically Collective 4876 4877 Input Parameters: 4878 + mat - the matrix 4879 - v - the vector for storing the diagonal 4880 4881 Output Parameter: 4882 . v - the diagonal of the matrix 4883 4884 Level: intermediate 4885 4886 Note: 4887 Currently only correct in parallel for square matrices. 4888 4889 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4890 @*/ 4891 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4892 { 4893 PetscFunctionBegin; 4894 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4895 PetscValidType(mat, 1); 4896 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4897 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4898 MatCheckPreallocated(mat, 1); 4899 4900 PetscUseTypeMethod(mat, getdiagonal, v); 4901 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4902 PetscFunctionReturn(0); 4903 } 4904 4905 /*@C 4906 MatGetRowMin - Gets the minimum value (of the real part) of each 4907 row of the matrix 4908 4909 Logically Collective 4910 4911 Input Parameter: 4912 . mat - the matrix 4913 4914 Output Parameters: 4915 + v - the vector for storing the maximums 4916 - idx - the indices of the column found for each row (optional) 4917 4918 Level: intermediate 4919 4920 Note: 4921 The result of this call are the same as if one converted the matrix to dense format 4922 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4923 4924 This code is only implemented for a couple of matrix formats. 4925 4926 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4927 `MatGetRowMax()` 4928 @*/ 4929 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4930 { 4931 PetscFunctionBegin; 4932 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4933 PetscValidType(mat, 1); 4934 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4935 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4936 4937 if (!mat->cmap->N) { 4938 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4939 if (idx) { 4940 PetscInt i, m = mat->rmap->n; 4941 for (i = 0; i < m; i++) idx[i] = -1; 4942 } 4943 } else { 4944 MatCheckPreallocated(mat, 1); 4945 } 4946 PetscUseTypeMethod(mat, getrowmin, v, idx); 4947 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4948 PetscFunctionReturn(0); 4949 } 4950 4951 /*@C 4952 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4953 row of the matrix 4954 4955 Logically Collective 4956 4957 Input Parameter: 4958 . mat - the matrix 4959 4960 Output Parameters: 4961 + v - the vector for storing the minimums 4962 - idx - the indices of the column found for each row (or NULL if not needed) 4963 4964 Level: intermediate 4965 4966 Notes: 4967 if a row is completely empty or has only 0.0 values then the idx[] value for that 4968 row is 0 (the first column). 4969 4970 This code is only implemented for a couple of matrix formats. 4971 4972 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4973 @*/ 4974 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4975 { 4976 PetscFunctionBegin; 4977 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4978 PetscValidType(mat, 1); 4979 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4980 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4981 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4982 4983 if (!mat->cmap->N) { 4984 PetscCall(VecSet(v, 0.0)); 4985 if (idx) { 4986 PetscInt i, m = mat->rmap->n; 4987 for (i = 0; i < m; i++) idx[i] = -1; 4988 } 4989 } else { 4990 MatCheckPreallocated(mat, 1); 4991 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4992 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4993 } 4994 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4995 PetscFunctionReturn(0); 4996 } 4997 4998 /*@C 4999 MatGetRowMax - Gets the maximum value (of the real part) of each 5000 row of the matrix 5001 5002 Logically Collective 5003 5004 Input Parameter: 5005 . mat - the matrix 5006 5007 Output Parameters: 5008 + v - the vector for storing the maximums 5009 - idx - the indices of the column found for each row (optional) 5010 5011 Level: intermediate 5012 5013 Notes: 5014 The result of this call are the same as if one converted the matrix to dense format 5015 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5016 5017 This code is only implemented for a couple of matrix formats. 5018 5019 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5020 @*/ 5021 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5022 { 5023 PetscFunctionBegin; 5024 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5025 PetscValidType(mat, 1); 5026 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5027 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5028 5029 if (!mat->cmap->N) { 5030 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5031 if (idx) { 5032 PetscInt i, m = mat->rmap->n; 5033 for (i = 0; i < m; i++) idx[i] = -1; 5034 } 5035 } else { 5036 MatCheckPreallocated(mat, 1); 5037 PetscUseTypeMethod(mat, getrowmax, v, idx); 5038 } 5039 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5040 PetscFunctionReturn(0); 5041 } 5042 5043 /*@C 5044 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5045 row of the matrix 5046 5047 Logically Collective 5048 5049 Input Parameter: 5050 . mat - the matrix 5051 5052 Output Parameters: 5053 + v - the vector for storing the maximums 5054 - idx - the indices of the column found for each row (or NULL if not needed) 5055 5056 Level: intermediate 5057 5058 Notes: 5059 if a row is completely empty or has only 0.0 values then the idx[] value for that 5060 row is 0 (the first column). 5061 5062 This code is only implemented for a couple of matrix formats. 5063 5064 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5065 @*/ 5066 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5067 { 5068 PetscFunctionBegin; 5069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5070 PetscValidType(mat, 1); 5071 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5072 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5073 5074 if (!mat->cmap->N) { 5075 PetscCall(VecSet(v, 0.0)); 5076 if (idx) { 5077 PetscInt i, m = mat->rmap->n; 5078 for (i = 0; i < m; i++) idx[i] = -1; 5079 } 5080 } else { 5081 MatCheckPreallocated(mat, 1); 5082 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5083 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5084 } 5085 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5086 PetscFunctionReturn(0); 5087 } 5088 5089 /*@ 5090 MatGetRowSum - Gets the sum of each row of the matrix 5091 5092 Logically or Neighborhood Collective 5093 5094 Input Parameters: 5095 . mat - the matrix 5096 5097 Output Parameter: 5098 . v - the vector for storing the sum of rows 5099 5100 Level: intermediate 5101 5102 Notes: 5103 This code is slow since it is not currently specialized for different formats 5104 5105 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5106 @*/ 5107 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5108 { 5109 Vec ones; 5110 5111 PetscFunctionBegin; 5112 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5113 PetscValidType(mat, 1); 5114 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5115 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5116 MatCheckPreallocated(mat, 1); 5117 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5118 PetscCall(VecSet(ones, 1.)); 5119 PetscCall(MatMult(mat, ones, v)); 5120 PetscCall(VecDestroy(&ones)); 5121 PetscFunctionReturn(0); 5122 } 5123 5124 /*@ 5125 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5126 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5127 5128 Collective 5129 5130 Input Parameter: 5131 . mat - the matrix to provide the transpose 5132 5133 Output Parameter: 5134 . mat - the matrix to contain the transpose; it MUST have the nonzero structure of the transpose of A or the code will crash or generate incorrect results 5135 5136 Level: advanced 5137 5138 Note: 5139 Normally he use of `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) requires that B was obtained with a call to `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B). This 5140 routine allows bypassing that call. 5141 5142 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5143 @*/ 5144 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5145 { 5146 PetscContainer rB = NULL; 5147 MatParentState *rb = NULL; 5148 5149 PetscFunctionBegin; 5150 PetscCall(PetscNew(&rb)); 5151 rb->id = ((PetscObject)mat)->id; 5152 rb->state = 0; 5153 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5154 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5155 PetscCall(PetscContainerSetPointer(rB, rb)); 5156 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5157 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5158 PetscCall(PetscObjectDereference((PetscObject)rB)); 5159 PetscFunctionReturn(0); 5160 } 5161 5162 /*@ 5163 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5164 5165 Collective 5166 5167 Input Parameters: 5168 + mat - the matrix to transpose 5169 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5170 5171 Output Parameter: 5172 . B - the transpose 5173 5174 Notes: 5175 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5176 5177 `MAT_REUSE_MATRIX` uses the B matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the 5178 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5179 5180 If the nonzero structure of mat changed from the previous call to this function with the same matrices an error will be generated for some matrix types. 5181 5182 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5183 5184 If mat is unchanged from the last call this function returns immediately without recomputing the result 5185 5186 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5187 5188 Level: intermediate 5189 5190 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5191 `MatTransposeSymbolic()` 5192 @*/ 5193 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5194 { 5195 PetscContainer rB = NULL; 5196 MatParentState *rb = NULL; 5197 5198 PetscFunctionBegin; 5199 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5200 PetscValidType(mat, 1); 5201 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5202 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5203 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5204 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5205 MatCheckPreallocated(mat, 1); 5206 if (reuse == MAT_REUSE_MATRIX) { 5207 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5208 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5209 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5210 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5211 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0); 5212 } 5213 5214 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5215 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5216 PetscUseTypeMethod(mat, transpose, reuse, B); 5217 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5218 } 5219 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5220 5221 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5222 if (reuse != MAT_INPLACE_MATRIX) { 5223 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5224 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5225 rb->state = ((PetscObject)mat)->state; 5226 rb->nonzerostate = mat->nonzerostate; 5227 } 5228 PetscFunctionReturn(0); 5229 } 5230 5231 /*@ 5232 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5233 5234 Collective on A 5235 5236 Input Parameters: 5237 . A - the matrix to transpose 5238 5239 Output Parameter: 5240 . B - the transpose. This is a complete matrix but the numerical portion is invalid. One can call `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) to compute the 5241 numerical portion. 5242 5243 Level: intermediate 5244 5245 Note: 5246 This is not supported for many matrix types, use `MatTranspose()` in those cases 5247 5248 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5249 @*/ 5250 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5251 { 5252 PetscFunctionBegin; 5253 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5254 PetscValidType(A, 1); 5255 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5256 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5257 PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 5258 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5259 PetscCall((*A->ops->transposesymbolic)(A, B)); 5260 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5261 5262 PetscCall(MatTransposeSetPrecursor(A, *B)); 5263 PetscFunctionReturn(0); 5264 } 5265 5266 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5267 { 5268 PetscContainer rB; 5269 MatParentState *rb; 5270 5271 PetscFunctionBegin; 5272 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5273 PetscValidType(A, 1); 5274 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5275 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5276 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5277 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5278 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5279 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5280 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5281 PetscFunctionReturn(0); 5282 } 5283 5284 /*@ 5285 MatIsTranspose - Test whether a matrix is another one's transpose, 5286 or its own, in which case it tests symmetry. 5287 5288 Collective on A 5289 5290 Input Parameters: 5291 + A - the matrix to test 5292 - B - the matrix to test against, this can equal the first parameter 5293 5294 Output Parameters: 5295 . flg - the result 5296 5297 Notes: 5298 Only available for `MATAIJ` matrices. 5299 5300 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5301 test involves parallel copies of the block-offdiagonal parts of the matrix. 5302 5303 Level: intermediate 5304 5305 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5306 @*/ 5307 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5308 { 5309 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5310 5311 PetscFunctionBegin; 5312 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5313 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5314 PetscValidBoolPointer(flg, 4); 5315 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5316 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5317 *flg = PETSC_FALSE; 5318 if (f && g) { 5319 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5320 PetscCall((*f)(A, B, tol, flg)); 5321 } else { 5322 MatType mattype; 5323 5324 PetscCall(MatGetType(f ? B : A, &mattype)); 5325 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5326 } 5327 PetscFunctionReturn(0); 5328 } 5329 5330 /*@ 5331 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5332 5333 Collective 5334 5335 Input Parameters: 5336 + mat - the matrix to transpose and complex conjugate 5337 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5338 5339 Output Parameter: 5340 . B - the Hermitian transpose 5341 5342 Level: intermediate 5343 5344 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5345 @*/ 5346 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5347 { 5348 PetscFunctionBegin; 5349 PetscCall(MatTranspose(mat, reuse, B)); 5350 #if defined(PETSC_USE_COMPLEX) 5351 PetscCall(MatConjugate(*B)); 5352 #endif 5353 PetscFunctionReturn(0); 5354 } 5355 5356 /*@ 5357 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5358 5359 Collective on A 5360 5361 Input Parameters: 5362 + A - the matrix to test 5363 - B - the matrix to test against, this can equal the first parameter 5364 5365 Output Parameters: 5366 . flg - the result 5367 5368 Notes: 5369 Only available for `MATAIJ` matrices. 5370 5371 The sequential algorithm 5372 has a running time of the order of the number of nonzeros; the parallel 5373 test involves parallel copies of the block-offdiagonal parts of the matrix. 5374 5375 Level: intermediate 5376 5377 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5378 @*/ 5379 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5380 { 5381 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5382 5383 PetscFunctionBegin; 5384 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5385 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5386 PetscValidBoolPointer(flg, 4); 5387 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5388 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5389 if (f && g) { 5390 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5391 PetscCall((*f)(A, B, tol, flg)); 5392 } 5393 PetscFunctionReturn(0); 5394 } 5395 5396 /*@ 5397 MatPermute - Creates a new matrix with rows and columns permuted from the 5398 original. 5399 5400 Collective 5401 5402 Input Parameters: 5403 + mat - the matrix to permute 5404 . row - row permutation, each processor supplies only the permutation for its rows 5405 - col - column permutation, each processor supplies only the permutation for its columns 5406 5407 Output Parameters: 5408 . B - the permuted matrix 5409 5410 Level: advanced 5411 5412 Note: 5413 The index sets map from row/col of permuted matrix to row/col of original matrix. 5414 The index sets should be on the same communicator as mat and have the same local sizes. 5415 5416 Developer Note: 5417 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5418 exploit the fact that row and col are permutations, consider implementing the 5419 more general `MatCreateSubMatrix()` instead. 5420 5421 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5422 @*/ 5423 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5424 { 5425 PetscFunctionBegin; 5426 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5427 PetscValidType(mat, 1); 5428 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5429 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5430 PetscValidPointer(B, 4); 5431 PetscCheckSameComm(mat, 1, row, 2); 5432 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5433 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5434 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5435 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5436 MatCheckPreallocated(mat, 1); 5437 5438 if (mat->ops->permute) { 5439 PetscUseTypeMethod(mat, permute, row, col, B); 5440 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5441 } else { 5442 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5443 } 5444 PetscFunctionReturn(0); 5445 } 5446 5447 /*@ 5448 MatEqual - Compares two matrices. 5449 5450 Collective on A 5451 5452 Input Parameters: 5453 + A - the first matrix 5454 - B - the second matrix 5455 5456 Output Parameter: 5457 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5458 5459 Level: intermediate 5460 5461 .seealso: `Mat` 5462 @*/ 5463 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5464 { 5465 PetscFunctionBegin; 5466 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5467 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5468 PetscValidType(A, 1); 5469 PetscValidType(B, 2); 5470 PetscValidBoolPointer(flg, 3); 5471 PetscCheckSameComm(A, 1, B, 2); 5472 MatCheckPreallocated(A, 1); 5473 MatCheckPreallocated(B, 2); 5474 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5475 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5476 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N, 5477 B->cmap->N); 5478 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5479 PetscUseTypeMethod(A, equal, B, flg); 5480 } else { 5481 PetscCall(MatMultEqual(A, B, 10, flg)); 5482 } 5483 PetscFunctionReturn(0); 5484 } 5485 5486 /*@ 5487 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5488 matrices that are stored as vectors. Either of the two scaling 5489 matrices can be NULL. 5490 5491 Collective 5492 5493 Input Parameters: 5494 + mat - the matrix to be scaled 5495 . l - the left scaling vector (or NULL) 5496 - r - the right scaling vector (or NULL) 5497 5498 Note: 5499 `MatDiagonalScale()` computes A = LAR, where 5500 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5501 The L scales the rows of the matrix, the R scales the columns of the matrix. 5502 5503 Level: intermediate 5504 5505 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5506 @*/ 5507 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5508 { 5509 PetscFunctionBegin; 5510 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5511 PetscValidType(mat, 1); 5512 if (l) { 5513 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5514 PetscCheckSameComm(mat, 1, l, 2); 5515 } 5516 if (r) { 5517 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5518 PetscCheckSameComm(mat, 1, r, 3); 5519 } 5520 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5521 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5522 MatCheckPreallocated(mat, 1); 5523 if (!l && !r) PetscFunctionReturn(0); 5524 5525 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5526 PetscUseTypeMethod(mat, diagonalscale, l, r); 5527 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5528 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5529 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5530 PetscFunctionReturn(0); 5531 } 5532 5533 /*@ 5534 MatScale - Scales all elements of a matrix by a given number. 5535 5536 Logically Collective 5537 5538 Input Parameters: 5539 + mat - the matrix to be scaled 5540 - a - the scaling value 5541 5542 Output Parameter: 5543 . mat - the scaled matrix 5544 5545 Level: intermediate 5546 5547 .seealso: `Mat`, `MatDiagonalScale()` 5548 @*/ 5549 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5550 { 5551 PetscFunctionBegin; 5552 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5553 PetscValidType(mat, 1); 5554 PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 5555 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5556 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5557 PetscValidLogicalCollectiveScalar(mat, a, 2); 5558 MatCheckPreallocated(mat, 1); 5559 5560 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5561 if (a != (PetscScalar)1.0) { 5562 PetscUseTypeMethod(mat, scale, a); 5563 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5564 } 5565 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5566 PetscFunctionReturn(0); 5567 } 5568 5569 /*@ 5570 MatNorm - Calculates various norms of a matrix. 5571 5572 Collective 5573 5574 Input Parameters: 5575 + mat - the matrix 5576 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5577 5578 Output Parameter: 5579 . nrm - the resulting norm 5580 5581 Level: intermediate 5582 5583 .seealso: `Mat` 5584 @*/ 5585 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5586 { 5587 PetscFunctionBegin; 5588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5589 PetscValidType(mat, 1); 5590 PetscValidRealPointer(nrm, 3); 5591 5592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5593 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5594 MatCheckPreallocated(mat, 1); 5595 5596 PetscUseTypeMethod(mat, norm, type, nrm); 5597 PetscFunctionReturn(0); 5598 } 5599 5600 /* 5601 This variable is used to prevent counting of MatAssemblyBegin() that 5602 are called from within a MatAssemblyEnd(). 5603 */ 5604 static PetscInt MatAssemblyEnd_InUse = 0; 5605 /*@ 5606 MatAssemblyBegin - Begins assembling the matrix. This routine should 5607 be called after completing all calls to `MatSetValues()`. 5608 5609 Collective 5610 5611 Input Parameters: 5612 + mat - the matrix 5613 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5614 5615 Notes: 5616 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5617 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5618 5619 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5620 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5621 using the matrix. 5622 5623 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5624 same flag of `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` for all processes. Thus you CANNOT locally change from `ADD_VALUES` to `INSERT_VALUES`, that is 5625 a global collective operation requiring all processes that share the matrix. 5626 5627 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5628 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5629 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5630 5631 Level: beginner 5632 5633 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5634 @*/ 5635 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5636 { 5637 PetscFunctionBegin; 5638 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5639 PetscValidType(mat, 1); 5640 MatCheckPreallocated(mat, 1); 5641 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5642 if (mat->assembled) { 5643 mat->was_assembled = PETSC_TRUE; 5644 mat->assembled = PETSC_FALSE; 5645 } 5646 5647 if (!MatAssemblyEnd_InUse) { 5648 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5649 PetscTryTypeMethod(mat, assemblybegin, type); 5650 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5651 } else PetscTryTypeMethod(mat, assemblybegin, type); 5652 PetscFunctionReturn(0); 5653 } 5654 5655 /*@ 5656 MatAssembled - Indicates if a matrix has been assembled and is ready for 5657 use; for example, in matrix-vector product. 5658 5659 Not Collective 5660 5661 Input Parameter: 5662 . mat - the matrix 5663 5664 Output Parameter: 5665 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5666 5667 Level: advanced 5668 5669 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5670 @*/ 5671 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5672 { 5673 PetscFunctionBegin; 5674 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5675 PetscValidBoolPointer(assembled, 2); 5676 *assembled = mat->assembled; 5677 PetscFunctionReturn(0); 5678 } 5679 5680 /*@ 5681 MatAssemblyEnd - Completes assembling the matrix. This routine should 5682 be called after `MatAssemblyBegin()`. 5683 5684 Collective on Mat 5685 5686 Input Parameters: 5687 + mat - the matrix 5688 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5689 5690 Options Database Keys: 5691 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5692 . -mat_view ::ascii_info_detail - Prints more detailed info 5693 . -mat_view - Prints matrix in ASCII format 5694 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5695 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5696 . -display <name> - Sets display name (default is host) 5697 . -draw_pause <sec> - Sets number of seconds to pause after display 5698 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5699 . -viewer_socket_machine <machine> - Machine to use for socket 5700 . -viewer_socket_port <port> - Port number to use for socket 5701 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5702 5703 Level: beginner 5704 5705 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5706 @*/ 5707 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5708 { 5709 static PetscInt inassm = 0; 5710 PetscBool flg = PETSC_FALSE; 5711 5712 PetscFunctionBegin; 5713 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5714 PetscValidType(mat, 1); 5715 5716 inassm++; 5717 MatAssemblyEnd_InUse++; 5718 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5719 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5720 PetscTryTypeMethod(mat, assemblyend, type); 5721 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5722 } else PetscTryTypeMethod(mat, assemblyend, type); 5723 5724 /* Flush assembly is not a true assembly */ 5725 if (type != MAT_FLUSH_ASSEMBLY) { 5726 if (mat->num_ass) { 5727 if (!mat->symmetry_eternal) { 5728 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5729 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5730 } 5731 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5732 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5733 } 5734 mat->num_ass++; 5735 mat->assembled = PETSC_TRUE; 5736 mat->ass_nonzerostate = mat->nonzerostate; 5737 } 5738 5739 mat->insertmode = NOT_SET_VALUES; 5740 MatAssemblyEnd_InUse--; 5741 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5742 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5743 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5744 5745 if (mat->checksymmetryonassembly) { 5746 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5747 if (flg) { 5748 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5749 } else { 5750 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5751 } 5752 } 5753 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5754 } 5755 inassm--; 5756 PetscFunctionReturn(0); 5757 } 5758 5759 /*@ 5760 MatSetOption - Sets a parameter option for a matrix. Some options 5761 may be specific to certain storage formats. Some options 5762 determine how values will be inserted (or added). Sorted, 5763 row-oriented input will generally assemble the fastest. The default 5764 is row-oriented. 5765 5766 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5767 5768 Input Parameters: 5769 + mat - the matrix 5770 . option - the option, one of those listed below (and possibly others), 5771 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5772 5773 Options Describing Matrix Structure: 5774 + `MAT_SPD` - symmetric positive definite 5775 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5776 . `MAT_HERMITIAN` - transpose is the complex conjugation 5777 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5778 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5779 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5780 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5781 5782 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5783 do not need to be computed (usually at a high cost) 5784 5785 Options For Use with `MatSetValues()`: 5786 Insert a logically dense subblock, which can be 5787 . `MAT_ROW_ORIENTED` - row-oriented (default) 5788 5789 Note these options reflect the data you pass in with `MatSetValues()`; it has 5790 nothing to do with how the data is stored internally in the matrix 5791 data structure. 5792 5793 When (re)assembling a matrix, we can restrict the input for 5794 efficiency/debugging purposes. These options include 5795 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5796 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5797 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5798 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5799 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5800 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5801 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5802 performance for very large process counts. 5803 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5804 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5805 functions, instead sending only neighbor messages. 5806 5807 Notes: 5808 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5809 5810 Some options are relevant only for particular matrix types and 5811 are thus ignored by others. Other options are not supported by 5812 certain matrix types and will generate an error message if set. 5813 5814 If using Fortran to compute a matrix, one may need to 5815 use the column-oriented option (or convert to the row-oriented 5816 format). 5817 5818 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5819 that would generate a new entry in the nonzero structure is instead 5820 ignored. Thus, if memory has not alredy been allocated for this particular 5821 data, then the insertion is ignored. For dense matrices, in which 5822 the entire array is allocated, no entries are ever ignored. 5823 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5824 5825 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5826 that would generate a new entry in the nonzero structure instead produces 5827 an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats only.) If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5828 5829 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5830 that would generate a new entry that has not been preallocated will 5831 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5832 only.) This is a useful flag when debugging matrix memory preallocation. 5833 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5834 5835 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5836 other processors should be dropped, rather than stashed. 5837 This is useful if you know that the "owning" processor is also 5838 always generating the correct matrix entries, so that PETSc need 5839 not transfer duplicate entries generated on another processor. 5840 5841 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5842 searches during matrix assembly. When this flag is set, the hash table 5843 is created during the first matrix assembly. This hash table is 5844 used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()` 5845 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5846 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5847 supported by` MATMPIBAIJ` format only. 5848 5849 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5850 are kept in the nonzero structure 5851 5852 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5853 a zero location in the matrix 5854 5855 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5856 5857 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5858 zero row routines and thus improves performance for very large process counts. 5859 5860 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5861 part of the matrix (since they should match the upper triangular part). 5862 5863 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5864 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5865 with finite difference schemes with non-periodic boundary conditions. 5866 5867 Developer Note: 5868 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5869 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5870 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5871 not changed. 5872 5873 Level: intermediate 5874 5875 .seealso: `MatOption`, `Mat`, `MatGetOption()` 5876 @*/ 5877 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5878 { 5879 PetscFunctionBegin; 5880 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5881 if (op > 0) { 5882 PetscValidLogicalCollectiveEnum(mat, op, 2); 5883 PetscValidLogicalCollectiveBool(mat, flg, 3); 5884 } 5885 5886 PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op); 5887 5888 switch (op) { 5889 case MAT_FORCE_DIAGONAL_ENTRIES: 5890 mat->force_diagonals = flg; 5891 PetscFunctionReturn(0); 5892 case MAT_NO_OFF_PROC_ENTRIES: 5893 mat->nooffprocentries = flg; 5894 PetscFunctionReturn(0); 5895 case MAT_SUBSET_OFF_PROC_ENTRIES: 5896 mat->assembly_subset = flg; 5897 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5898 #if !defined(PETSC_HAVE_MPIUNI) 5899 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5900 #endif 5901 mat->stash.first_assembly_done = PETSC_FALSE; 5902 } 5903 PetscFunctionReturn(0); 5904 case MAT_NO_OFF_PROC_ZERO_ROWS: 5905 mat->nooffproczerorows = flg; 5906 PetscFunctionReturn(0); 5907 case MAT_SPD: 5908 if (flg) { 5909 mat->spd = PETSC_BOOL3_TRUE; 5910 mat->symmetric = PETSC_BOOL3_TRUE; 5911 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5912 } else { 5913 mat->spd = PETSC_BOOL3_FALSE; 5914 } 5915 break; 5916 case MAT_SYMMETRIC: 5917 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5918 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5919 #if !defined(PETSC_USE_COMPLEX) 5920 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5921 #endif 5922 break; 5923 case MAT_HERMITIAN: 5924 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5925 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5926 #if !defined(PETSC_USE_COMPLEX) 5927 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5928 #endif 5929 break; 5930 case MAT_STRUCTURALLY_SYMMETRIC: 5931 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5932 break; 5933 case MAT_SYMMETRY_ETERNAL: 5934 PetscCheck(mat->symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SYMMETRY_ETERNAL without first setting MAT_SYMMETRIC to true or false"); 5935 mat->symmetry_eternal = flg; 5936 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5937 break; 5938 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5939 PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURAL_SYMMETRIC to true or false"); 5940 mat->structural_symmetry_eternal = flg; 5941 break; 5942 case MAT_SPD_ETERNAL: 5943 PetscCheck(mat->spd != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SPD_ETERNAL without first setting MAT_SPD to true or false"); 5944 mat->spd_eternal = flg; 5945 if (flg) { 5946 mat->structural_symmetry_eternal = PETSC_TRUE; 5947 mat->symmetry_eternal = PETSC_TRUE; 5948 } 5949 break; 5950 case MAT_STRUCTURE_ONLY: 5951 mat->structure_only = flg; 5952 break; 5953 case MAT_SORTED_FULL: 5954 mat->sortedfull = flg; 5955 break; 5956 default: 5957 break; 5958 } 5959 PetscTryTypeMethod(mat, setoption, op, flg); 5960 PetscFunctionReturn(0); 5961 } 5962 5963 /*@ 5964 MatGetOption - Gets a parameter option that has been set for a matrix. 5965 5966 Logically Collective 5967 5968 Input Parameters: 5969 + mat - the matrix 5970 - option - the option, this only responds to certain options, check the code for which ones 5971 5972 Output Parameter: 5973 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5974 5975 Notes: 5976 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5977 5978 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5979 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5980 5981 Level: intermediate 5982 5983 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5984 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5985 @*/ 5986 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5987 { 5988 PetscFunctionBegin; 5989 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5990 PetscValidType(mat, 1); 5991 5992 PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op); 5993 PetscCheck(((PetscObject)mat)->type_name, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_TYPENOTSET, "Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()"); 5994 5995 switch (op) { 5996 case MAT_NO_OFF_PROC_ENTRIES: 5997 *flg = mat->nooffprocentries; 5998 break; 5999 case MAT_NO_OFF_PROC_ZERO_ROWS: 6000 *flg = mat->nooffproczerorows; 6001 break; 6002 case MAT_SYMMETRIC: 6003 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6004 break; 6005 case MAT_HERMITIAN: 6006 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6007 break; 6008 case MAT_STRUCTURALLY_SYMMETRIC: 6009 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6010 break; 6011 case MAT_SPD: 6012 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6013 break; 6014 case MAT_SYMMETRY_ETERNAL: 6015 *flg = mat->symmetry_eternal; 6016 break; 6017 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6018 *flg = mat->symmetry_eternal; 6019 break; 6020 default: 6021 break; 6022 } 6023 PetscFunctionReturn(0); 6024 } 6025 6026 /*@ 6027 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6028 this routine retains the old nonzero structure. 6029 6030 Logically Collective 6031 6032 Input Parameters: 6033 . mat - the matrix 6034 6035 Level: intermediate 6036 6037 Note: 6038 If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase. 6039 See the Performance chapter of the users manual for information on preallocating matrices. 6040 6041 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6042 @*/ 6043 PetscErrorCode MatZeroEntries(Mat mat) 6044 { 6045 PetscFunctionBegin; 6046 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6047 PetscValidType(mat, 1); 6048 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6049 PetscCheck(mat->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for matrices where you have set values but not yet assembled"); 6050 MatCheckPreallocated(mat, 1); 6051 6052 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6053 PetscUseTypeMethod(mat, zeroentries); 6054 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6055 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6056 PetscFunctionReturn(0); 6057 } 6058 6059 /*@ 6060 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6061 of a set of rows and columns of a matrix. 6062 6063 Collective 6064 6065 Input Parameters: 6066 + mat - the matrix 6067 . numRows - the number of rows to remove 6068 . rows - the global row indices 6069 . diag - value put in the diagonal of the eliminated rows 6070 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6071 - b - optional vector of right hand side, that will be adjusted by provided solution 6072 6073 Notes: 6074 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6075 6076 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 6077 The other entries of b will be adjusted by the known values of x times the corresponding matrix entries in the columns that are being eliminated 6078 6079 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6080 Krylov method to take advantage of the known solution on the zeroed rows. 6081 6082 For the parallel case, all processes that share the matrix (i.e., 6083 those in the communicator used for matrix creation) MUST call this 6084 routine, regardless of whether any rows being zeroed are owned by 6085 them. 6086 6087 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6088 6089 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6090 list only rows local to itself). 6091 6092 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6093 6094 Level: intermediate 6095 6096 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6097 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6098 @*/ 6099 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6100 { 6101 PetscFunctionBegin; 6102 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6103 PetscValidType(mat, 1); 6104 if (numRows) PetscValidIntPointer(rows, 3); 6105 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6106 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6107 MatCheckPreallocated(mat, 1); 6108 6109 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6110 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6111 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6112 PetscFunctionReturn(0); 6113 } 6114 6115 /*@ 6116 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6117 of a set of rows and columns of a matrix. 6118 6119 Collective 6120 6121 Input Parameters: 6122 + mat - the matrix 6123 . is - the rows to zero 6124 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6125 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6126 - b - optional vector of right hand side, that will be adjusted by provided solution 6127 6128 Note: 6129 See `MatZeroRowsColumns()` for details on how this routine operates. 6130 6131 Level: intermediate 6132 6133 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6134 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6135 @*/ 6136 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6137 { 6138 PetscInt numRows; 6139 const PetscInt *rows; 6140 6141 PetscFunctionBegin; 6142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6143 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6144 PetscValidType(mat, 1); 6145 PetscValidType(is, 2); 6146 PetscCall(ISGetLocalSize(is, &numRows)); 6147 PetscCall(ISGetIndices(is, &rows)); 6148 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6149 PetscCall(ISRestoreIndices(is, &rows)); 6150 PetscFunctionReturn(0); 6151 } 6152 6153 /*@ 6154 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6155 of a set of rows of a matrix. 6156 6157 Collective 6158 6159 Input Parameters: 6160 + mat - the matrix 6161 . numRows - the number of rows to remove 6162 . rows - the global row indices 6163 . diag - value put in the diagonal of the eliminated rows 6164 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6165 - b - optional vector of right hand side, that will be adjusted by provided solution 6166 6167 Notes: 6168 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6169 6170 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 6171 6172 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6173 Krylov method to take advantage of the known solution on the zeroed rows. 6174 6175 May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns) 6176 from the matrix. 6177 6178 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6179 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal 6180 formats this does not alter the nonzero structure. 6181 6182 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6183 of the matrix is not changed the values are 6184 merely zeroed. 6185 6186 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6187 formats can optionally remove the main diagonal entry from the 6188 nonzero structure as well, by passing 0.0 as the final argument). 6189 6190 For the parallel case, all processes that share the matrix (i.e., 6191 those in the communicator used for matrix creation) MUST call this 6192 routine, regardless of whether any rows being zeroed are owned by 6193 them. 6194 6195 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6196 list only rows local to itself). 6197 6198 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6199 owns that are to be zeroed. This saves a global synchronization in the implementation. 6200 6201 Level: intermediate 6202 6203 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6204 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6205 @*/ 6206 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6207 { 6208 PetscFunctionBegin; 6209 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6210 PetscValidType(mat, 1); 6211 if (numRows) PetscValidIntPointer(rows, 3); 6212 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6213 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6214 MatCheckPreallocated(mat, 1); 6215 6216 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6217 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6218 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6219 PetscFunctionReturn(0); 6220 } 6221 6222 /*@ 6223 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6224 of a set of rows of a matrix. 6225 6226 Collective on Mat 6227 6228 Input Parameters: 6229 + mat - the matrix 6230 . is - index set of rows to remove (if NULL then no row is removed) 6231 . diag - value put in all diagonals of eliminated rows 6232 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6233 - b - optional vector of right hand side, that will be adjusted by provided solution 6234 6235 Note: 6236 See `MatZeroRows()` for details on how this routine operates. 6237 6238 Level: intermediate 6239 6240 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6241 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6242 @*/ 6243 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6244 { 6245 PetscInt numRows = 0; 6246 const PetscInt *rows = NULL; 6247 6248 PetscFunctionBegin; 6249 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6250 PetscValidType(mat, 1); 6251 if (is) { 6252 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6253 PetscCall(ISGetLocalSize(is, &numRows)); 6254 PetscCall(ISGetIndices(is, &rows)); 6255 } 6256 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6257 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6258 PetscFunctionReturn(0); 6259 } 6260 6261 /*@ 6262 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6263 of a set of rows of a matrix. These rows must be local to the process. 6264 6265 Collective 6266 6267 Input Parameters: 6268 + mat - the matrix 6269 . numRows - the number of rows to remove 6270 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6271 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6272 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6273 - b - optional vector of right hand side, that will be adjusted by provided solution 6274 6275 Level: intermediate 6276 6277 Notes: 6278 See `MatZeroRows()` for details on how this routine operates. 6279 6280 The grid coordinates are across the entire grid, not just the local portion 6281 6282 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6283 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6284 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6285 `DM_BOUNDARY_PERIODIC` boundary type. 6286 6287 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 6288 a single value per point) you can skip filling those indices. 6289 6290 Fortran Note: 6291 idxm and idxn should be declared as 6292 $ MatStencil idxm(4,m) 6293 and the values inserted using 6294 .vb 6295 idxm(MatStencil_i,1) = i 6296 idxm(MatStencil_j,1) = j 6297 idxm(MatStencil_k,1) = k 6298 idxm(MatStencil_c,1) = c 6299 etc 6300 .ve 6301 6302 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6303 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6304 @*/ 6305 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6306 { 6307 PetscInt dim = mat->stencil.dim; 6308 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6309 PetscInt *dims = mat->stencil.dims + 1; 6310 PetscInt *starts = mat->stencil.starts; 6311 PetscInt *dxm = (PetscInt *)rows; 6312 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6313 6314 PetscFunctionBegin; 6315 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6316 PetscValidType(mat, 1); 6317 if (numRows) PetscValidPointer(rows, 3); 6318 6319 PetscCall(PetscMalloc1(numRows, &jdxm)); 6320 for (i = 0; i < numRows; ++i) { 6321 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6322 for (j = 0; j < 3 - sdim; ++j) dxm++; 6323 /* Local index in X dir */ 6324 tmp = *dxm++ - starts[0]; 6325 /* Loop over remaining dimensions */ 6326 for (j = 0; j < dim - 1; ++j) { 6327 /* If nonlocal, set index to be negative */ 6328 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6329 /* Update local index */ 6330 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6331 } 6332 /* Skip component slot if necessary */ 6333 if (mat->stencil.noc) dxm++; 6334 /* Local row number */ 6335 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6336 } 6337 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6338 PetscCall(PetscFree(jdxm)); 6339 PetscFunctionReturn(0); 6340 } 6341 6342 /*@ 6343 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6344 of a set of rows and columns of a matrix. 6345 6346 Collective 6347 6348 Input Parameters: 6349 + mat - the matrix 6350 . numRows - the number of rows/columns to remove 6351 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6352 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6353 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6354 - b - optional vector of right hand side, that will be adjusted by provided solution 6355 6356 Level: intermediate 6357 6358 Notes: 6359 See `MatZeroRowsColumns()` for details on how this routine operates. 6360 6361 The grid coordinates are across the entire grid, not just the local portion 6362 6363 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6364 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6365 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6366 `DM_BOUNDARY_PERIODIC` boundary type. 6367 6368 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 6369 a single value per point) you can skip filling those indices. 6370 6371 Fortran Note: 6372 In Fortran idxm and idxn should be declared as 6373 $ MatStencil idxm(4,m) 6374 and the values inserted using 6375 .vb 6376 idxm(MatStencil_i,1) = i 6377 idxm(MatStencil_j,1) = j 6378 idxm(MatStencil_k,1) = k 6379 idxm(MatStencil_c,1) = c 6380 etc 6381 .ve 6382 6383 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6384 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6385 @*/ 6386 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6387 { 6388 PetscInt dim = mat->stencil.dim; 6389 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6390 PetscInt *dims = mat->stencil.dims + 1; 6391 PetscInt *starts = mat->stencil.starts; 6392 PetscInt *dxm = (PetscInt *)rows; 6393 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6394 6395 PetscFunctionBegin; 6396 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6397 PetscValidType(mat, 1); 6398 if (numRows) PetscValidPointer(rows, 3); 6399 6400 PetscCall(PetscMalloc1(numRows, &jdxm)); 6401 for (i = 0; i < numRows; ++i) { 6402 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6403 for (j = 0; j < 3 - sdim; ++j) dxm++; 6404 /* Local index in X dir */ 6405 tmp = *dxm++ - starts[0]; 6406 /* Loop over remaining dimensions */ 6407 for (j = 0; j < dim - 1; ++j) { 6408 /* If nonlocal, set index to be negative */ 6409 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6410 /* Update local index */ 6411 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6412 } 6413 /* Skip component slot if necessary */ 6414 if (mat->stencil.noc) dxm++; 6415 /* Local row number */ 6416 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6417 } 6418 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6419 PetscCall(PetscFree(jdxm)); 6420 PetscFunctionReturn(0); 6421 } 6422 6423 /*@C 6424 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6425 of a set of rows of a matrix; using local numbering of rows. 6426 6427 Collective 6428 6429 Input Parameters: 6430 + mat - the matrix 6431 . numRows - the number of rows to remove 6432 . rows - the local row indices 6433 . diag - value put in all diagonals of eliminated rows 6434 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6435 - b - optional vector of right hand side, that will be adjusted by provided solution 6436 6437 Notes: 6438 Before calling `MatZeroRowsLocal()`, the user must first set the 6439 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6440 6441 See `MatZeroRows()` for details on how this routine operates. 6442 6443 Level: intermediate 6444 6445 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6446 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6447 @*/ 6448 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6449 { 6450 PetscFunctionBegin; 6451 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6452 PetscValidType(mat, 1); 6453 if (numRows) PetscValidIntPointer(rows, 3); 6454 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6455 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6456 MatCheckPreallocated(mat, 1); 6457 6458 if (mat->ops->zerorowslocal) { 6459 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6460 } else { 6461 IS is, newis; 6462 const PetscInt *newRows; 6463 6464 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6465 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6466 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6467 PetscCall(ISGetIndices(newis, &newRows)); 6468 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6469 PetscCall(ISRestoreIndices(newis, &newRows)); 6470 PetscCall(ISDestroy(&newis)); 6471 PetscCall(ISDestroy(&is)); 6472 } 6473 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6474 PetscFunctionReturn(0); 6475 } 6476 6477 /*@ 6478 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6479 of a set of rows of a matrix; using local numbering of rows. 6480 6481 Collective 6482 6483 Input Parameters: 6484 + mat - the matrix 6485 . is - index set of rows to remove 6486 . diag - value put in all diagonals of eliminated rows 6487 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6488 - b - optional vector of right hand side, that will be adjusted by provided solution 6489 6490 Notes: 6491 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6492 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6493 6494 See `MatZeroRows()` for details on how this routine operates. 6495 6496 Level: intermediate 6497 6498 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6499 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6500 @*/ 6501 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6502 { 6503 PetscInt numRows; 6504 const PetscInt *rows; 6505 6506 PetscFunctionBegin; 6507 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6508 PetscValidType(mat, 1); 6509 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6510 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6511 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6512 MatCheckPreallocated(mat, 1); 6513 6514 PetscCall(ISGetLocalSize(is, &numRows)); 6515 PetscCall(ISGetIndices(is, &rows)); 6516 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6517 PetscCall(ISRestoreIndices(is, &rows)); 6518 PetscFunctionReturn(0); 6519 } 6520 6521 /*@ 6522 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6523 of a set of rows and columns of a matrix; using local numbering of rows. 6524 6525 Collective 6526 6527 Input Parameters: 6528 + mat - the matrix 6529 . numRows - the number of rows to remove 6530 . rows - the global row indices 6531 . diag - value put in all diagonals of eliminated rows 6532 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6533 - b - optional vector of right hand side, that will be adjusted by provided solution 6534 6535 Notes: 6536 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6537 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6538 6539 See `MatZeroRowsColumns()` for details on how this routine operates. 6540 6541 Level: intermediate 6542 6543 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6544 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6545 @*/ 6546 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6547 { 6548 IS is, newis; 6549 const PetscInt *newRows; 6550 6551 PetscFunctionBegin; 6552 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6553 PetscValidType(mat, 1); 6554 if (numRows) PetscValidIntPointer(rows, 3); 6555 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6556 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6557 MatCheckPreallocated(mat, 1); 6558 6559 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6560 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6561 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6562 PetscCall(ISGetIndices(newis, &newRows)); 6563 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6564 PetscCall(ISRestoreIndices(newis, &newRows)); 6565 PetscCall(ISDestroy(&newis)); 6566 PetscCall(ISDestroy(&is)); 6567 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6568 PetscFunctionReturn(0); 6569 } 6570 6571 /*@ 6572 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6573 of a set of rows and columns of a matrix; using local numbering of rows. 6574 6575 Collective on Mat 6576 6577 Input Parameters: 6578 + mat - the matrix 6579 . is - index set of rows to remove 6580 . diag - value put in all diagonals of eliminated rows 6581 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6582 - b - optional vector of right hand side, that will be adjusted by provided solution 6583 6584 Notes: 6585 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6586 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6587 6588 See `MatZeroRowsColumns()` for details on how this routine operates. 6589 6590 Level: intermediate 6591 6592 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6593 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6594 @*/ 6595 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6596 { 6597 PetscInt numRows; 6598 const PetscInt *rows; 6599 6600 PetscFunctionBegin; 6601 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6602 PetscValidType(mat, 1); 6603 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6604 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6605 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6606 MatCheckPreallocated(mat, 1); 6607 6608 PetscCall(ISGetLocalSize(is, &numRows)); 6609 PetscCall(ISGetIndices(is, &rows)); 6610 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6611 PetscCall(ISRestoreIndices(is, &rows)); 6612 PetscFunctionReturn(0); 6613 } 6614 6615 /*@C 6616 MatGetSize - Returns the numbers of rows and columns in a matrix. 6617 6618 Not Collective 6619 6620 Input Parameter: 6621 . mat - the matrix 6622 6623 Output Parameters: 6624 + m - the number of global rows 6625 - n - the number of global columns 6626 6627 Note: both output parameters can be NULL on input. 6628 6629 Level: beginner 6630 6631 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6632 @*/ 6633 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6634 { 6635 PetscFunctionBegin; 6636 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6637 if (m) *m = mat->rmap->N; 6638 if (n) *n = mat->cmap->N; 6639 PetscFunctionReturn(0); 6640 } 6641 6642 /*@C 6643 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6644 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6645 6646 Not Collective 6647 6648 Input Parameter: 6649 . mat - the matrix 6650 6651 Output Parameters: 6652 + m - the number of local rows, use `NULL` to not obtain this value 6653 - n - the number of local columns, use `NULL` to not obtain this value 6654 6655 Level: beginner 6656 6657 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()` 6658 @*/ 6659 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6660 { 6661 PetscFunctionBegin; 6662 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6663 if (m) PetscValidIntPointer(m, 2); 6664 if (n) PetscValidIntPointer(n, 3); 6665 if (m) *m = mat->rmap->n; 6666 if (n) *n = mat->cmap->n; 6667 PetscFunctionReturn(0); 6668 } 6669 6670 /*@C 6671 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6672 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6673 6674 Not Collective, unless matrix has not been allocated, then collective 6675 6676 Input Parameter: 6677 . mat - the matrix 6678 6679 Output Parameters: 6680 + m - the global index of the first local column, use `NULL` to not obtain this value 6681 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6682 6683 Level: developer 6684 6685 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6686 @*/ 6687 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6688 { 6689 PetscFunctionBegin; 6690 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6691 PetscValidType(mat, 1); 6692 if (m) PetscValidIntPointer(m, 2); 6693 if (n) PetscValidIntPointer(n, 3); 6694 MatCheckPreallocated(mat, 1); 6695 if (m) *m = mat->cmap->rstart; 6696 if (n) *n = mat->cmap->rend; 6697 PetscFunctionReturn(0); 6698 } 6699 6700 /*@C 6701 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6702 this MPI rank. For all matrices it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix 6703 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6704 6705 Not Collective 6706 6707 Input Parameter: 6708 . mat - the matrix 6709 6710 Output Parameters: 6711 + m - the global index of the first local row, use `NULL` to not obtain this value 6712 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6713 6714 Note: 6715 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6716 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6717 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6718 6719 Level: beginner 6720 6721 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6722 `PetscLayout` 6723 @*/ 6724 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6725 { 6726 PetscFunctionBegin; 6727 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6728 PetscValidType(mat, 1); 6729 if (m) PetscValidIntPointer(m, 2); 6730 if (n) PetscValidIntPointer(n, 3); 6731 MatCheckPreallocated(mat, 1); 6732 if (m) *m = mat->rmap->rstart; 6733 if (n) *n = mat->rmap->rend; 6734 PetscFunctionReturn(0); 6735 } 6736 6737 /*@C 6738 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6739 each process. For all matrices it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix 6740 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6741 6742 Not Collective, unless matrix has not been allocated, then collective 6743 6744 Input Parameters: 6745 . mat - the matrix 6746 6747 Output Parameters: 6748 . ranges - start of each processors portion plus one more than the total length at the end 6749 6750 Level: beginner 6751 6752 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6753 @*/ 6754 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6755 { 6756 PetscFunctionBegin; 6757 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6758 PetscValidType(mat, 1); 6759 MatCheckPreallocated(mat, 1); 6760 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6761 PetscFunctionReturn(0); 6762 } 6763 6764 /*@C 6765 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6766 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6767 6768 Not Collective, unless matrix has not been allocated, then collective on Mat 6769 6770 Input Parameters: 6771 . mat - the matrix 6772 6773 Output Parameters: 6774 . ranges - start of each processors portion plus one more then the total length at the end 6775 6776 Level: beginner 6777 6778 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6779 @*/ 6780 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6781 { 6782 PetscFunctionBegin; 6783 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6784 PetscValidType(mat, 1); 6785 MatCheckPreallocated(mat, 1); 6786 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6787 PetscFunctionReturn(0); 6788 } 6789 6790 /*@C 6791 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6792 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6793 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6794 6795 Not Collective 6796 6797 Input Parameter: 6798 . A - matrix 6799 6800 Output Parameters: 6801 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6802 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6803 6804 Level: intermediate 6805 6806 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6807 @*/ 6808 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6809 { 6810 PetscErrorCode (*f)(Mat, IS *, IS *); 6811 6812 PetscFunctionBegin; 6813 MatCheckPreallocated(A, 1); 6814 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6815 if (f) { 6816 PetscCall((*f)(A, rows, cols)); 6817 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6818 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6819 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6820 } 6821 PetscFunctionReturn(0); 6822 } 6823 6824 /*@C 6825 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6826 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6827 to complete the factorization. 6828 6829 Collective on fact 6830 6831 Input Parameters: 6832 + fact - the factorized matrix obtained with `MatGetFactor()` 6833 . mat - the matrix 6834 . row - row permutation 6835 . column - column permutation 6836 - info - structure containing 6837 $ levels - number of levels of fill. 6838 $ expected fill - as ratio of original fill. 6839 $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6840 missing diagonal entries) 6841 6842 Output Parameters: 6843 . fact - new matrix that has been symbolically factored 6844 6845 Level: developer 6846 6847 Notes: 6848 See [Matrix Factorization](sec_matfactor) for additional information. 6849 6850 Most users should employ the `KSP` interface for linear solvers 6851 instead of working directly with matrix algebra routines such as this. 6852 See, e.g., `KSPCreate()`. 6853 6854 Uses the definition of level of fill as in Y. Saad, 2003 6855 6856 Developer Note: 6857 The Fortran interface is not autogenerated as the 6858 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6859 6860 References: 6861 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6862 6863 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6864 `MatGetOrdering()`, `MatFactorInfo` 6865 @*/ 6866 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6867 { 6868 PetscFunctionBegin; 6869 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6870 PetscValidType(mat, 2); 6871 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6872 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6873 PetscValidPointer(info, 5); 6874 PetscValidPointer(fact, 1); 6875 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6876 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6877 if (!fact->ops->ilufactorsymbolic) { 6878 MatSolverType stype; 6879 PetscCall(MatFactorGetSolverType(fact, &stype)); 6880 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype); 6881 } 6882 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6883 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6884 MatCheckPreallocated(mat, 2); 6885 6886 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6887 PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info)); 6888 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6889 PetscFunctionReturn(0); 6890 } 6891 6892 /*@C 6893 MatICCFactorSymbolic - Performs symbolic incomplete 6894 Cholesky factorization for a symmetric matrix. Use 6895 `MatCholeskyFactorNumeric()` to complete the factorization. 6896 6897 Collective on fact 6898 6899 Input Parameters: 6900 + fact - the factorized matrix obtained with `MatGetFactor()` 6901 . mat - the matrix to be factored 6902 . perm - row and column permutation 6903 - info - structure containing 6904 $ levels - number of levels of fill. 6905 $ expected fill - as ratio of original fill. 6906 6907 Output Parameter: 6908 . fact - the factored matrix 6909 6910 Level: developer 6911 6912 Notes: 6913 Most users should employ the `KSP` interface for linear solvers 6914 instead of working directly with matrix algebra routines such as this. 6915 See, e.g., `KSPCreate()`. 6916 6917 This uses the definition of level of fill as in Y. Saad, 2003 6918 6919 Developer Note: 6920 The Fortran interface is not autogenerated as the 6921 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6922 6923 References: 6924 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6925 6926 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6927 @*/ 6928 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6929 { 6930 PetscFunctionBegin; 6931 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6932 PetscValidType(mat, 2); 6933 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6934 PetscValidPointer(info, 4); 6935 PetscValidPointer(fact, 1); 6936 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6937 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6938 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6939 if (!(fact)->ops->iccfactorsymbolic) { 6940 MatSolverType stype; 6941 PetscCall(MatFactorGetSolverType(fact, &stype)); 6942 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype); 6943 } 6944 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6945 MatCheckPreallocated(mat, 2); 6946 6947 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6948 PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info)); 6949 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6950 PetscFunctionReturn(0); 6951 } 6952 6953 /*@C 6954 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6955 points to an array of valid matrices, they may be reused to store the new 6956 submatrices. 6957 6958 Collective 6959 6960 Input Parameters: 6961 + mat - the matrix 6962 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6963 . irow, icol - index sets of rows and columns to extract 6964 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6965 6966 Output Parameter: 6967 . submat - the array of submatrices 6968 6969 Notes: 6970 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6971 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6972 to extract a parallel submatrix. 6973 6974 Some matrix types place restrictions on the row and column 6975 indices, such as that they be sorted or that they be equal to each other. 6976 6977 The index sets may not have duplicate entries. 6978 6979 When extracting submatrices from a parallel matrix, each processor can 6980 form a different submatrix by setting the rows and columns of its 6981 individual index sets according to the local submatrix desired. 6982 6983 When finished using the submatrices, the user should destroy 6984 them with `MatDestroySubMatrices()`. 6985 6986 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6987 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6988 6989 This routine creates the matrices in submat; you should NOT create them before 6990 calling it. It also allocates the array of matrix pointers submat. 6991 6992 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6993 request one row/column in a block, they must request all rows/columns that are in 6994 that block. For example, if the block size is 2 you cannot request just row 0 and 6995 column 0. 6996 6997 Fortran Note: 6998 The Fortran interface is slightly different from that given below; it 6999 requires one to pass in as submat a `Mat` (integer) array of size at least n+1. 7000 7001 Level: advanced 7002 7003 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7004 @*/ 7005 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7006 { 7007 PetscInt i; 7008 PetscBool eq; 7009 7010 PetscFunctionBegin; 7011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7012 PetscValidType(mat, 1); 7013 if (n) { 7014 PetscValidPointer(irow, 3); 7015 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7016 PetscValidPointer(icol, 4); 7017 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7018 } 7019 PetscValidPointer(submat, 6); 7020 if (n && scall == MAT_REUSE_MATRIX) { 7021 PetscValidPointer(*submat, 6); 7022 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7023 } 7024 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7025 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7026 MatCheckPreallocated(mat, 1); 7027 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7028 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7029 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7030 for (i = 0; i < n; i++) { 7031 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7032 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7033 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7034 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7035 if (mat->boundtocpu && mat->bindingpropagates) { 7036 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7037 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7038 } 7039 #endif 7040 } 7041 PetscFunctionReturn(0); 7042 } 7043 7044 /*@C 7045 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7046 7047 Collective 7048 7049 Input Parameters: 7050 + mat - the matrix 7051 . n - the number of submatrixes to be extracted 7052 . irow, icol - index sets of rows and columns to extract 7053 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7054 7055 Output Parameter: 7056 . submat - the array of submatrices 7057 7058 Level: advanced 7059 7060 Note: 7061 This is used by `PCGASM` 7062 7063 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7064 @*/ 7065 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7066 { 7067 PetscInt i; 7068 PetscBool eq; 7069 7070 PetscFunctionBegin; 7071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7072 PetscValidType(mat, 1); 7073 if (n) { 7074 PetscValidPointer(irow, 3); 7075 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7076 PetscValidPointer(icol, 4); 7077 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7078 } 7079 PetscValidPointer(submat, 6); 7080 if (n && scall == MAT_REUSE_MATRIX) { 7081 PetscValidPointer(*submat, 6); 7082 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7083 } 7084 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7085 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7086 MatCheckPreallocated(mat, 1); 7087 7088 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7089 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7090 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7091 for (i = 0; i < n; i++) { 7092 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7093 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7094 } 7095 PetscFunctionReturn(0); 7096 } 7097 7098 /*@C 7099 MatDestroyMatrices - Destroys an array of matrices. 7100 7101 Collective 7102 7103 Input Parameters: 7104 + n - the number of local matrices 7105 - mat - the matrices (note that this is a pointer to the array of matrices) 7106 7107 Level: advanced 7108 7109 Note: 7110 Frees not only the matrices, but also the array that contains the matrices 7111 In Fortran will not free the array. 7112 7113 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7114 @*/ 7115 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7116 { 7117 PetscInt i; 7118 7119 PetscFunctionBegin; 7120 if (!*mat) PetscFunctionReturn(0); 7121 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7122 PetscValidPointer(mat, 2); 7123 7124 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7125 7126 /* memory is allocated even if n = 0 */ 7127 PetscCall(PetscFree(*mat)); 7128 PetscFunctionReturn(0); 7129 } 7130 7131 /*@C 7132 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7133 7134 Collective 7135 7136 Input Parameters: 7137 + n - the number of local matrices 7138 - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling 7139 sequence of MatCreateSubMatrices()) 7140 7141 Level: advanced 7142 7143 Note: 7144 Frees not only the matrices, but also the array that contains the matrices 7145 In Fortran will not free the array. 7146 7147 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7148 @*/ 7149 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7150 { 7151 Mat mat0; 7152 7153 PetscFunctionBegin; 7154 if (!*mat) PetscFunctionReturn(0); 7155 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7156 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7157 PetscValidPointer(mat, 2); 7158 7159 mat0 = (*mat)[0]; 7160 if (mat0 && mat0->ops->destroysubmatrices) { 7161 PetscCall((mat0->ops->destroysubmatrices)(n, mat)); 7162 } else { 7163 PetscCall(MatDestroyMatrices(n, mat)); 7164 } 7165 PetscFunctionReturn(0); 7166 } 7167 7168 /*@C 7169 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7170 7171 Collective 7172 7173 Input Parameters: 7174 . mat - the matrix 7175 7176 Output Parameter: 7177 . matstruct - the sequential matrix with the nonzero structure of mat 7178 7179 Level: developer 7180 7181 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7182 @*/ 7183 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7184 { 7185 PetscFunctionBegin; 7186 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7187 PetscValidPointer(matstruct, 2); 7188 7189 PetscValidType(mat, 1); 7190 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7191 MatCheckPreallocated(mat, 1); 7192 7193 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7194 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7195 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7196 PetscFunctionReturn(0); 7197 } 7198 7199 /*@C 7200 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7201 7202 Collective 7203 7204 Input Parameters: 7205 . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling 7206 sequence of `MatGetSequentialNonzeroStructure()`) 7207 7208 Level: advanced 7209 7210 Note: 7211 Frees not only the matrices, but also the array that contains the matrices 7212 7213 .seealso: `Mat`, `MatGetSeqNonzeroStructure()` 7214 @*/ 7215 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7216 { 7217 PetscFunctionBegin; 7218 PetscValidPointer(mat, 1); 7219 PetscCall(MatDestroy(mat)); 7220 PetscFunctionReturn(0); 7221 } 7222 7223 /*@ 7224 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7225 replaces the index sets by larger ones that represent submatrices with 7226 additional overlap. 7227 7228 Collective 7229 7230 Input Parameters: 7231 + mat - the matrix 7232 . n - the number of index sets 7233 . is - the array of index sets (these index sets will changed during the call) 7234 - ov - the additional overlap requested 7235 7236 Options Database Key: 7237 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7238 7239 Level: developer 7240 7241 Note: 7242 The computed overlap preserves the matrix block sizes when the blocks are square. 7243 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7244 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7245 7246 .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7247 @*/ 7248 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7249 { 7250 PetscInt i, bs, cbs; 7251 7252 PetscFunctionBegin; 7253 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7254 PetscValidType(mat, 1); 7255 PetscValidLogicalCollectiveInt(mat, n, 2); 7256 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7257 if (n) { 7258 PetscValidPointer(is, 3); 7259 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7260 } 7261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7262 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7263 MatCheckPreallocated(mat, 1); 7264 7265 if (!ov || !n) PetscFunctionReturn(0); 7266 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7267 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7268 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7269 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7270 if (bs == cbs) { 7271 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7272 } 7273 PetscFunctionReturn(0); 7274 } 7275 7276 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7277 7278 /*@ 7279 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7280 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7281 additional overlap. 7282 7283 Collective 7284 7285 Input Parameters: 7286 + mat - the matrix 7287 . n - the number of index sets 7288 . is - the array of index sets (these index sets will changed during the call) 7289 - ov - the additional overlap requested 7290 7291 ` Options Database Key: 7292 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7293 7294 Level: developer 7295 7296 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7297 @*/ 7298 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7299 { 7300 PetscInt i; 7301 7302 PetscFunctionBegin; 7303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7304 PetscValidType(mat, 1); 7305 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7306 if (n) { 7307 PetscValidPointer(is, 3); 7308 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7309 } 7310 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7311 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7312 MatCheckPreallocated(mat, 1); 7313 if (!ov) PetscFunctionReturn(0); 7314 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7315 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7316 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7317 PetscFunctionReturn(0); 7318 } 7319 7320 /*@ 7321 MatGetBlockSize - Returns the matrix block size. 7322 7323 Not Collective 7324 7325 Input Parameter: 7326 . mat - the matrix 7327 7328 Output Parameter: 7329 . bs - block size 7330 7331 Notes: 7332 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7333 7334 If the block size has not been set yet this routine returns 1. 7335 7336 Level: intermediate 7337 7338 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7339 @*/ 7340 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7341 { 7342 PetscFunctionBegin; 7343 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7344 PetscValidIntPointer(bs, 2); 7345 *bs = PetscAbs(mat->rmap->bs); 7346 PetscFunctionReturn(0); 7347 } 7348 7349 /*@ 7350 MatGetBlockSizes - Returns the matrix block row and column sizes. 7351 7352 Not Collective 7353 7354 Input Parameter: 7355 . mat - the matrix 7356 7357 Output Parameters: 7358 + rbs - row block size 7359 - cbs - column block size 7360 7361 Notes: 7362 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7363 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7364 7365 If a block size has not been set yet this routine returns 1. 7366 7367 Level: intermediate 7368 7369 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7370 @*/ 7371 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7372 { 7373 PetscFunctionBegin; 7374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7375 if (rbs) PetscValidIntPointer(rbs, 2); 7376 if (cbs) PetscValidIntPointer(cbs, 3); 7377 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7378 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7379 PetscFunctionReturn(0); 7380 } 7381 7382 /*@ 7383 MatSetBlockSize - Sets the matrix block size. 7384 7385 Logically Collective 7386 7387 Input Parameters: 7388 + mat - the matrix 7389 - bs - block size 7390 7391 Notes: 7392 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7393 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7394 7395 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7396 is compatible with the matrix local sizes. 7397 7398 Level: intermediate 7399 7400 .seealso: `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7401 @*/ 7402 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7403 { 7404 PetscFunctionBegin; 7405 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7406 PetscValidLogicalCollectiveInt(mat, bs, 2); 7407 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7408 PetscFunctionReturn(0); 7409 } 7410 7411 typedef struct { 7412 PetscInt n; 7413 IS *is; 7414 Mat *mat; 7415 PetscObjectState nonzerostate; 7416 Mat C; 7417 } EnvelopeData; 7418 7419 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7420 { 7421 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7422 PetscCall(PetscFree(edata->is)); 7423 PetscCall(PetscFree(edata)); 7424 return 0; 7425 } 7426 7427 /* 7428 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7429 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7430 7431 Collective 7432 7433 Input Parameter: 7434 . mat - the matrix 7435 7436 Notes: 7437 There can be zeros within the blocks 7438 7439 The blocks can overlap between processes, including laying on more than two processes 7440 7441 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7442 */ 7443 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7444 { 7445 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7446 PetscInt *diag, *odiag, sc; 7447 VecScatter scatter; 7448 PetscScalar *seqv; 7449 const PetscScalar *parv; 7450 const PetscInt *ia, *ja; 7451 PetscBool set, flag, done; 7452 Mat AA = mat, A; 7453 MPI_Comm comm; 7454 PetscMPIInt rank, size, tag; 7455 MPI_Status status; 7456 PetscContainer container; 7457 EnvelopeData *edata; 7458 Vec seq, par; 7459 IS isglobal; 7460 7461 PetscFunctionBegin; 7462 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7463 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7464 if (!set || !flag) { 7465 /* TOO: only needs nonzero structure of transpose */ 7466 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7467 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7468 } 7469 PetscCall(MatAIJGetLocalMat(AA, &A)); 7470 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7471 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7472 7473 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7474 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7475 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7476 PetscCallMPI(MPI_Comm_size(comm, &size)); 7477 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7478 7479 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7480 7481 if (rank > 0) { 7482 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7483 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7484 } 7485 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7486 for (i = 0; i < n; i++) { 7487 env = PetscMax(env, ja[ia[i + 1] - 1]); 7488 II = rstart + i; 7489 if (env == II) { 7490 starts[lblocks] = tbs; 7491 sizes[lblocks++] = 1 + II - tbs; 7492 tbs = 1 + II; 7493 } 7494 } 7495 if (rank < size - 1) { 7496 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7497 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7498 } 7499 7500 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7501 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7502 PetscCall(MatDestroy(&A)); 7503 7504 PetscCall(PetscNew(&edata)); 7505 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7506 edata->n = lblocks; 7507 /* create IS needed for extracting blocks from the original matrix */ 7508 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7509 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7510 7511 /* Create the resulting inverse matrix structure with preallocation information */ 7512 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7513 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7514 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7515 PetscCall(MatSetType(edata->C, MATAIJ)); 7516 7517 /* Communicate the start and end of each row, from each block to the correct rank */ 7518 /* TODO: Use PetscSF instead of VecScatter */ 7519 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7520 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7521 PetscCall(VecGetArrayWrite(seq, &seqv)); 7522 for (PetscInt i = 0; i < lblocks; i++) { 7523 for (PetscInt j = 0; j < sizes[i]; j++) { 7524 seqv[cnt] = starts[i]; 7525 seqv[cnt + 1] = starts[i] + sizes[i]; 7526 cnt += 2; 7527 } 7528 } 7529 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7530 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7531 sc -= cnt; 7532 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7533 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7534 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7535 PetscCall(ISDestroy(&isglobal)); 7536 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7537 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7538 PetscCall(VecScatterDestroy(&scatter)); 7539 PetscCall(VecDestroy(&seq)); 7540 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7541 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7542 PetscCall(VecGetArrayRead(par, &parv)); 7543 cnt = 0; 7544 PetscCall(MatGetSize(mat, NULL, &n)); 7545 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7546 PetscInt start, end, d = 0, od = 0; 7547 7548 start = (PetscInt)PetscRealPart(parv[cnt]); 7549 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7550 cnt += 2; 7551 7552 if (start < cstart) { 7553 od += cstart - start + n - cend; 7554 d += cend - cstart; 7555 } else if (start < cend) { 7556 od += n - cend; 7557 d += cend - start; 7558 } else od += n - start; 7559 if (end <= cstart) { 7560 od -= cstart - end + n - cend; 7561 d -= cend - cstart; 7562 } else if (end < cend) { 7563 od -= n - cend; 7564 d -= cend - end; 7565 } else od -= n - end; 7566 7567 odiag[i] = od; 7568 diag[i] = d; 7569 } 7570 PetscCall(VecRestoreArrayRead(par, &parv)); 7571 PetscCall(VecDestroy(&par)); 7572 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7573 PetscCall(PetscFree2(diag, odiag)); 7574 PetscCall(PetscFree2(sizes, starts)); 7575 7576 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7577 PetscCall(PetscContainerSetPointer(container, edata)); 7578 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7579 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7580 PetscCall(PetscObjectDereference((PetscObject)container)); 7581 PetscFunctionReturn(0); 7582 } 7583 7584 /*@ 7585 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7586 7587 Collective on A 7588 7589 Input Parameters: 7590 . A - the matrix 7591 7592 Output Parameters: 7593 . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 7594 7595 Note: 7596 For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal. 7597 7598 Level: advanced 7599 7600 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7601 @*/ 7602 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7603 { 7604 PetscContainer container; 7605 EnvelopeData *edata; 7606 PetscObjectState nonzerostate; 7607 7608 PetscFunctionBegin; 7609 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7610 if (!container) { 7611 PetscCall(MatComputeVariableBlockEnvelope(A)); 7612 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7613 } 7614 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7615 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7616 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7617 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7618 7619 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7620 *C = edata->C; 7621 7622 for (PetscInt i = 0; i < edata->n; i++) { 7623 Mat D; 7624 PetscScalar *dvalues; 7625 7626 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7627 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7628 PetscCall(MatSeqDenseInvert(D)); 7629 PetscCall(MatDenseGetArray(D, &dvalues)); 7630 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7631 PetscCall(MatDestroy(&D)); 7632 } 7633 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7634 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7635 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7636 PetscFunctionReturn(0); 7637 } 7638 7639 /*@ 7640 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7641 7642 Logically Collective 7643 7644 Input Parameters: 7645 + mat - the matrix 7646 . nblocks - the number of blocks on this process, each block can only exist on a single process 7647 - bsizes - the block sizes 7648 7649 Notes: 7650 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7651 7652 Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks. 7653 7654 Level: intermediate 7655 7656 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7657 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7658 @*/ 7659 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7660 { 7661 PetscInt i, ncnt = 0, nlocal; 7662 7663 PetscFunctionBegin; 7664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7665 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7666 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7667 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7668 PetscCheck(ncnt == nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local block sizes %" PetscInt_FMT " does not equal local size of matrix %" PetscInt_FMT, ncnt, nlocal); 7669 PetscCall(PetscFree(mat->bsizes)); 7670 mat->nblocks = nblocks; 7671 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7672 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7673 PetscFunctionReturn(0); 7674 } 7675 7676 /*@C 7677 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7678 7679 Logically Collective; No Fortran Support 7680 7681 Input Parameter: 7682 . mat - the matrix 7683 7684 Output Parameters: 7685 + nblocks - the number of blocks on this process 7686 - bsizes - the block sizes 7687 7688 Level: intermediate 7689 7690 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7691 @*/ 7692 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7693 { 7694 PetscFunctionBegin; 7695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7696 *nblocks = mat->nblocks; 7697 *bsizes = mat->bsizes; 7698 PetscFunctionReturn(0); 7699 } 7700 7701 /*@ 7702 MatSetBlockSizes - Sets the matrix block row and column sizes. 7703 7704 Logically Collective 7705 7706 Input Parameters: 7707 + mat - the matrix 7708 . rbs - row block size 7709 - cbs - column block size 7710 7711 Notes: 7712 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7713 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7714 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7715 7716 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7717 are compatible with the matrix local sizes. 7718 7719 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7720 7721 Level: intermediate 7722 7723 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7724 @*/ 7725 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7726 { 7727 PetscFunctionBegin; 7728 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7729 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7730 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7731 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7732 if (mat->rmap->refcnt) { 7733 ISLocalToGlobalMapping l2g = NULL; 7734 PetscLayout nmap = NULL; 7735 7736 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7737 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7738 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7739 mat->rmap = nmap; 7740 mat->rmap->mapping = l2g; 7741 } 7742 if (mat->cmap->refcnt) { 7743 ISLocalToGlobalMapping l2g = NULL; 7744 PetscLayout nmap = NULL; 7745 7746 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7747 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7748 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7749 mat->cmap = nmap; 7750 mat->cmap->mapping = l2g; 7751 } 7752 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7753 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7754 PetscFunctionReturn(0); 7755 } 7756 7757 /*@ 7758 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7759 7760 Logically Collective 7761 7762 Input Parameters: 7763 + mat - the matrix 7764 . fromRow - matrix from which to copy row block size 7765 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7766 7767 Level: developer 7768 7769 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7770 @*/ 7771 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7772 { 7773 PetscFunctionBegin; 7774 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7775 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7776 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7777 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7778 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7779 PetscFunctionReturn(0); 7780 } 7781 7782 /*@ 7783 MatResidual - Default routine to calculate the residual r = b - Ax 7784 7785 Collective 7786 7787 Input Parameters: 7788 + mat - the matrix 7789 . b - the right-hand-side 7790 - x - the approximate solution 7791 7792 Output Parameter: 7793 . r - location to store the residual 7794 7795 Level: developer 7796 7797 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7798 @*/ 7799 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7800 { 7801 PetscFunctionBegin; 7802 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7803 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7804 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7805 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7806 PetscValidType(mat, 1); 7807 MatCheckPreallocated(mat, 1); 7808 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7809 if (!mat->ops->residual) { 7810 PetscCall(MatMult(mat, x, r)); 7811 PetscCall(VecAYPX(r, -1.0, b)); 7812 } else { 7813 PetscUseTypeMethod(mat, residual, b, x, r); 7814 } 7815 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7816 PetscFunctionReturn(0); 7817 } 7818 7819 /*@C 7820 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7821 7822 Collective 7823 7824 Input Parameters: 7825 + mat - the matrix 7826 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7827 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7828 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7829 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7830 always used. 7831 7832 Output Parameters: 7833 + n - number of local rows in the (possibly compressed) matrix, use NULL if not needed 7834 . 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 7835 . ja - the column indices, use NULL if not needed 7836 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7837 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7838 7839 Level: developer 7840 7841 Notes: 7842 You CANNOT change any of the ia[] or ja[] values. 7843 7844 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7845 7846 Fortran Notes: 7847 In Fortran use 7848 .vb 7849 PetscInt ia(1), ja(1) 7850 PetscOffset iia, jja 7851 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr) 7852 ! Access the ith and jth entries via ia(iia + i) and ja(jja + j) 7853 .ve 7854 or 7855 .vb 7856 PetscInt, pointer :: ia(:),ja(:) 7857 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7858 ! Access the ith and jth entries via ia(i) and ja(j) 7859 .ve 7860 7861 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7862 @*/ 7863 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7864 { 7865 PetscFunctionBegin; 7866 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7867 PetscValidType(mat, 1); 7868 if (n) PetscValidIntPointer(n, 5); 7869 if (ia) PetscValidPointer(ia, 6); 7870 if (ja) PetscValidPointer(ja, 7); 7871 if (done) PetscValidBoolPointer(done, 8); 7872 MatCheckPreallocated(mat, 1); 7873 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7874 else { 7875 if (done) *done = PETSC_TRUE; 7876 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7877 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7878 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7879 } 7880 PetscFunctionReturn(0); 7881 } 7882 7883 /*@C 7884 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7885 7886 Collective 7887 7888 Input Parameters: 7889 + mat - the matrix 7890 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7891 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7892 symmetrized 7893 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7894 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7895 always used. 7896 . n - number of columns in the (possibly compressed) matrix 7897 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7898 - ja - the row indices 7899 7900 Output Parameters: 7901 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7902 7903 Level: developer 7904 7905 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7906 @*/ 7907 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7908 { 7909 PetscFunctionBegin; 7910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7911 PetscValidType(mat, 1); 7912 PetscValidIntPointer(n, 5); 7913 if (ia) PetscValidPointer(ia, 6); 7914 if (ja) PetscValidPointer(ja, 7); 7915 PetscValidBoolPointer(done, 8); 7916 MatCheckPreallocated(mat, 1); 7917 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7918 else { 7919 *done = PETSC_TRUE; 7920 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7921 } 7922 PetscFunctionReturn(0); 7923 } 7924 7925 /*@C 7926 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7927 7928 Collective 7929 7930 Input Parameters: 7931 + mat - the matrix 7932 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7933 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7934 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7935 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7936 always used. 7937 . n - size of (possibly compressed) matrix 7938 . ia - the row pointers 7939 - ja - the column indices 7940 7941 Output Parameters: 7942 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7943 7944 Note: 7945 This routine zeros out n, ia, and ja. This is to prevent accidental 7946 us of the array after it has been restored. If you pass NULL, it will 7947 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7948 7949 Level: developer 7950 7951 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7952 @*/ 7953 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7954 { 7955 PetscFunctionBegin; 7956 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7957 PetscValidType(mat, 1); 7958 if (ia) PetscValidPointer(ia, 6); 7959 if (ja) PetscValidPointer(ja, 7); 7960 if (done) PetscValidBoolPointer(done, 8); 7961 MatCheckPreallocated(mat, 1); 7962 7963 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 7964 else { 7965 if (done) *done = PETSC_TRUE; 7966 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7967 if (n) *n = 0; 7968 if (ia) *ia = NULL; 7969 if (ja) *ja = NULL; 7970 } 7971 PetscFunctionReturn(0); 7972 } 7973 7974 /*@C 7975 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 7976 7977 Collective on Mat 7978 7979 Input Parameters: 7980 + mat - the matrix 7981 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7982 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7983 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7984 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7985 always used. 7986 7987 Output Parameters: 7988 + n - size of (possibly compressed) matrix 7989 . ia - the column pointers 7990 . ja - the row indices 7991 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7992 7993 Level: developer 7994 7995 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()` 7996 @*/ 7997 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7998 { 7999 PetscFunctionBegin; 8000 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8001 PetscValidType(mat, 1); 8002 if (ia) PetscValidPointer(ia, 6); 8003 if (ja) PetscValidPointer(ja, 7); 8004 PetscValidBoolPointer(done, 8); 8005 MatCheckPreallocated(mat, 1); 8006 8007 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8008 else { 8009 *done = PETSC_TRUE; 8010 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8011 if (n) *n = 0; 8012 if (ia) *ia = NULL; 8013 if (ja) *ja = NULL; 8014 } 8015 PetscFunctionReturn(0); 8016 } 8017 8018 /*@C 8019 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8020 8021 Collective 8022 8023 Input Parameters: 8024 + mat - the matrix 8025 . ncolors - max color value 8026 . n - number of entries in colorarray 8027 - colorarray - array indicating color for each column 8028 8029 Output Parameters: 8030 . iscoloring - coloring generated using colorarray information 8031 8032 Level: developer 8033 8034 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()` 8035 @*/ 8036 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8037 { 8038 PetscFunctionBegin; 8039 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8040 PetscValidType(mat, 1); 8041 PetscValidIntPointer(colorarray, 4); 8042 PetscValidPointer(iscoloring, 5); 8043 MatCheckPreallocated(mat, 1); 8044 8045 if (!mat->ops->coloringpatch) { 8046 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8047 } else { 8048 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8049 } 8050 PetscFunctionReturn(0); 8051 } 8052 8053 /*@ 8054 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8055 8056 Logically Collective 8057 8058 Input Parameter: 8059 . mat - the factored matrix to be reset 8060 8061 Notes: 8062 This routine should be used only with factored matrices formed by in-place 8063 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8064 format). This option can save memory, for example, when solving nonlinear 8065 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8066 ILU(0) preconditioner. 8067 8068 Note that one can specify in-place ILU(0) factorization by calling 8069 .vb 8070 PCType(pc,PCILU); 8071 PCFactorSeUseInPlace(pc); 8072 .ve 8073 or by using the options -pc_type ilu -pc_factor_in_place 8074 8075 In-place factorization ILU(0) can also be used as a local 8076 solver for the blocks within the block Jacobi or additive Schwarz 8077 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8078 for details on setting local solver options. 8079 8080 Most users should employ the `KSP` interface for linear solvers 8081 instead of working directly with matrix algebra routines such as this. 8082 See, e.g., `KSPCreate()`. 8083 8084 Level: developer 8085 8086 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8087 @*/ 8088 PetscErrorCode MatSetUnfactored(Mat mat) 8089 { 8090 PetscFunctionBegin; 8091 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8092 PetscValidType(mat, 1); 8093 MatCheckPreallocated(mat, 1); 8094 mat->factortype = MAT_FACTOR_NONE; 8095 if (!mat->ops->setunfactored) PetscFunctionReturn(0); 8096 PetscUseTypeMethod(mat, setunfactored); 8097 PetscFunctionReturn(0); 8098 } 8099 8100 /*MC 8101 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8102 8103 Synopsis: 8104 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8105 8106 Not collective 8107 8108 Input Parameter: 8109 . x - matrix 8110 8111 Output Parameters: 8112 + xx_v - the Fortran pointer to the array 8113 - ierr - error code 8114 8115 Example of Usage: 8116 .vb 8117 PetscScalar, pointer xx_v(:,:) 8118 .... 8119 call MatDenseGetArrayF90(x,xx_v,ierr) 8120 a = xx_v(3) 8121 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8122 .ve 8123 8124 Level: advanced 8125 8126 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8127 8128 M*/ 8129 8130 /*MC 8131 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8132 accessed with `MatDenseGetArrayF90()`. 8133 8134 Synopsis: 8135 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8136 8137 Not collective 8138 8139 Input Parameters: 8140 + x - matrix 8141 - xx_v - the Fortran90 pointer to the array 8142 8143 Output Parameter: 8144 . ierr - error code 8145 8146 Example of Usage: 8147 .vb 8148 PetscScalar, pointer xx_v(:,:) 8149 .... 8150 call MatDenseGetArrayF90(x,xx_v,ierr) 8151 a = xx_v(3) 8152 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8153 .ve 8154 8155 Level: advanced 8156 8157 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8158 8159 M*/ 8160 8161 /*MC 8162 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8163 8164 Synopsis: 8165 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8166 8167 Not collective 8168 8169 Input Parameter: 8170 . x - matrix 8171 8172 Output Parameters: 8173 + xx_v - the Fortran pointer to the array 8174 - ierr - error code 8175 8176 Example of Usage: 8177 .vb 8178 PetscScalar, pointer xx_v(:) 8179 .... 8180 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8181 a = xx_v(3) 8182 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8183 .ve 8184 8185 Level: advanced 8186 8187 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8188 8189 M*/ 8190 8191 /*MC 8192 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8193 accessed with `MatSeqAIJGetArrayF90()`. 8194 8195 Synopsis: 8196 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8197 8198 Not collective 8199 8200 Input Parameters: 8201 + x - matrix 8202 - xx_v - the Fortran90 pointer to the array 8203 8204 Output Parameter: 8205 . ierr - error code 8206 8207 Example of Usage: 8208 .vb 8209 PetscScalar, pointer xx_v(:) 8210 .... 8211 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8212 a = xx_v(3) 8213 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8214 .ve 8215 8216 Level: advanced 8217 8218 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8219 8220 M*/ 8221 8222 /*@ 8223 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8224 as the original matrix. 8225 8226 Collective 8227 8228 Input Parameters: 8229 + mat - the original matrix 8230 . isrow - parallel IS containing the rows this processor should obtain 8231 . 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. 8232 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8233 8234 Output Parameter: 8235 . newmat - the new submatrix, of the same type as the old 8236 8237 Level: advanced 8238 8239 Notes: 8240 The submatrix will be able to be multiplied with vectors using the same layout as iscol. 8241 8242 Some matrix types place restrictions on the row and column indices, such 8243 as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block; 8244 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8245 8246 The index sets may not have duplicate entries. 8247 8248 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8249 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8250 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8251 will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when 8252 you are finished using it. 8253 8254 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8255 the input matrix. 8256 8257 If iscol is NULL then all columns are obtained (not supported in Fortran). 8258 8259 Example usage: 8260 Consider the following 8x8 matrix with 34 non-zero values, that is 8261 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8262 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8263 as follows: 8264 8265 .vb 8266 1 2 0 | 0 3 0 | 0 4 8267 Proc0 0 5 6 | 7 0 0 | 8 0 8268 9 0 10 | 11 0 0 | 12 0 8269 ------------------------------------- 8270 13 0 14 | 15 16 17 | 0 0 8271 Proc1 0 18 0 | 19 20 21 | 0 0 8272 0 0 0 | 22 23 0 | 24 0 8273 ------------------------------------- 8274 Proc2 25 26 27 | 0 0 28 | 29 0 8275 30 0 0 | 31 32 33 | 0 34 8276 .ve 8277 8278 Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8279 8280 .vb 8281 2 0 | 0 3 0 | 0 8282 Proc0 5 6 | 7 0 0 | 8 8283 ------------------------------- 8284 Proc1 18 0 | 19 20 21 | 0 8285 ------------------------------- 8286 Proc2 26 27 | 0 0 28 | 29 8287 0 0 | 31 32 33 | 0 8288 .ve 8289 8290 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8291 @*/ 8292 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8293 { 8294 PetscMPIInt size; 8295 Mat *local; 8296 IS iscoltmp; 8297 PetscBool flg; 8298 8299 PetscFunctionBegin; 8300 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8301 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8302 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8303 PetscValidPointer(newmat, 5); 8304 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8305 PetscValidType(mat, 1); 8306 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8307 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8308 8309 MatCheckPreallocated(mat, 1); 8310 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8311 8312 if (!iscol || isrow == iscol) { 8313 PetscBool stride; 8314 PetscMPIInt grabentirematrix = 0, grab; 8315 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8316 if (stride) { 8317 PetscInt first, step, n, rstart, rend; 8318 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8319 if (step == 1) { 8320 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8321 if (rstart == first) { 8322 PetscCall(ISGetLocalSize(isrow, &n)); 8323 if (n == rend - rstart) grabentirematrix = 1; 8324 } 8325 } 8326 } 8327 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8328 if (grab) { 8329 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8330 if (cll == MAT_INITIAL_MATRIX) { 8331 *newmat = mat; 8332 PetscCall(PetscObjectReference((PetscObject)mat)); 8333 } 8334 PetscFunctionReturn(0); 8335 } 8336 } 8337 8338 if (!iscol) { 8339 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8340 } else { 8341 iscoltmp = iscol; 8342 } 8343 8344 /* if original matrix is on just one processor then use submatrix generated */ 8345 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8346 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8347 goto setproperties; 8348 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8349 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8350 *newmat = *local; 8351 PetscCall(PetscFree(local)); 8352 goto setproperties; 8353 } else if (!mat->ops->createsubmatrix) { 8354 /* Create a new matrix type that implements the operation using the full matrix */ 8355 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8356 switch (cll) { 8357 case MAT_INITIAL_MATRIX: 8358 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8359 break; 8360 case MAT_REUSE_MATRIX: 8361 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8362 break; 8363 default: 8364 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8365 } 8366 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8367 goto setproperties; 8368 } 8369 8370 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8371 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8372 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8373 8374 setproperties: 8375 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8376 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8377 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8378 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8379 PetscFunctionReturn(0); 8380 } 8381 8382 /*@ 8383 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8384 8385 Not Collective 8386 8387 Input Parameters: 8388 + A - the matrix we wish to propagate options from 8389 - B - the matrix we wish to propagate options to 8390 8391 Level: beginner 8392 8393 Note: 8394 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8395 8396 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8397 @*/ 8398 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8399 { 8400 PetscFunctionBegin; 8401 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8402 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8403 B->symmetry_eternal = A->symmetry_eternal; 8404 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8405 B->symmetric = A->symmetric; 8406 B->structurally_symmetric = A->structurally_symmetric; 8407 B->spd = A->spd; 8408 B->hermitian = A->hermitian; 8409 PetscFunctionReturn(0); 8410 } 8411 8412 /*@ 8413 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8414 used during the assembly process to store values that belong to 8415 other processors. 8416 8417 Not Collective 8418 8419 Input Parameters: 8420 + mat - the matrix 8421 . size - the initial size of the stash. 8422 - bsize - the initial size of the block-stash(if used). 8423 8424 Options Database Keys: 8425 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8426 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8427 8428 Level: intermediate 8429 8430 Notes: 8431 The block-stash is used for values set with `MatSetValuesBlocked()` while 8432 the stash is used for values set with `MatSetValues()` 8433 8434 Run with the option -info and look for output of the form 8435 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8436 to determine the appropriate value, MM, to use for size and 8437 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8438 to determine the value, BMM to use for bsize 8439 8440 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8441 @*/ 8442 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8443 { 8444 PetscFunctionBegin; 8445 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8446 PetscValidType(mat, 1); 8447 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8448 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8449 PetscFunctionReturn(0); 8450 } 8451 8452 /*@ 8453 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8454 the matrix 8455 8456 Neighbor-wise Collective 8457 8458 Input Parameters: 8459 + mat - the matrix 8460 . x,y - the vectors 8461 - w - where the result is stored 8462 8463 Level: intermediate 8464 8465 Notes: 8466 w may be the same vector as y. 8467 8468 This allows one to use either the restriction or interpolation (its transpose) 8469 matrix to do the interpolation 8470 8471 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8472 @*/ 8473 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8474 { 8475 PetscInt M, N, Ny; 8476 8477 PetscFunctionBegin; 8478 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8479 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8480 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8481 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8482 PetscCall(MatGetSize(A, &M, &N)); 8483 PetscCall(VecGetSize(y, &Ny)); 8484 if (M == Ny) { 8485 PetscCall(MatMultAdd(A, x, y, w)); 8486 } else { 8487 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8488 } 8489 PetscFunctionReturn(0); 8490 } 8491 8492 /*@ 8493 MatInterpolate - y = A*x or A'*x depending on the shape of 8494 the matrix 8495 8496 Neighbor-wise Collective 8497 8498 Input Parameters: 8499 + mat - the matrix 8500 - x,y - the vectors 8501 8502 Level: intermediate 8503 8504 Note: 8505 This allows one to use either the restriction or interpolation (its transpose) 8506 matrix to do the interpolation 8507 8508 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8509 @*/ 8510 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8511 { 8512 PetscInt M, N, Ny; 8513 8514 PetscFunctionBegin; 8515 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8516 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8517 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8518 PetscCall(MatGetSize(A, &M, &N)); 8519 PetscCall(VecGetSize(y, &Ny)); 8520 if (M == Ny) { 8521 PetscCall(MatMult(A, x, y)); 8522 } else { 8523 PetscCall(MatMultTranspose(A, x, y)); 8524 } 8525 PetscFunctionReturn(0); 8526 } 8527 8528 /*@ 8529 MatRestrict - y = A*x or A'*x 8530 8531 Neighbor-wise Collective on Mat 8532 8533 Input Parameters: 8534 + mat - the matrix 8535 - x,y - the vectors 8536 8537 Level: intermediate 8538 8539 Note: 8540 This allows one to use either the restriction or interpolation (its transpose) 8541 matrix to do the restriction 8542 8543 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8544 @*/ 8545 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8546 { 8547 PetscInt M, N, Ny; 8548 8549 PetscFunctionBegin; 8550 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8551 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8552 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8553 PetscCall(MatGetSize(A, &M, &N)); 8554 PetscCall(VecGetSize(y, &Ny)); 8555 if (M == Ny) { 8556 PetscCall(MatMult(A, x, y)); 8557 } else { 8558 PetscCall(MatMultTranspose(A, x, y)); 8559 } 8560 PetscFunctionReturn(0); 8561 } 8562 8563 /*@ 8564 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8565 8566 Neighbor-wise Collective on Mat 8567 8568 Input Parameters: 8569 + mat - the matrix 8570 - w, x - the input dense matrices 8571 8572 Output Parameters: 8573 . y - the output dense matrix 8574 8575 Level: intermediate 8576 8577 Note: 8578 This allows one to use either the restriction or interpolation (its transpose) 8579 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8580 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8581 8582 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8583 @*/ 8584 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8585 { 8586 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8587 PetscBool trans = PETSC_TRUE; 8588 MatReuse reuse = MAT_INITIAL_MATRIX; 8589 8590 PetscFunctionBegin; 8591 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8592 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8593 PetscValidType(x, 2); 8594 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8595 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8596 PetscCall(MatGetSize(A, &M, &N)); 8597 PetscCall(MatGetSize(x, &Mx, &Nx)); 8598 if (N == Mx) trans = PETSC_FALSE; 8599 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); 8600 Mo = trans ? N : M; 8601 if (*y) { 8602 PetscCall(MatGetSize(*y, &My, &Ny)); 8603 if (Mo == My && Nx == Ny) { 8604 reuse = MAT_REUSE_MATRIX; 8605 } else { 8606 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); 8607 PetscCall(MatDestroy(y)); 8608 } 8609 } 8610 8611 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8612 PetscBool flg; 8613 8614 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8615 if (w) { 8616 PetscInt My, Ny, Mw, Nw; 8617 8618 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8619 PetscCall(MatGetSize(*y, &My, &Ny)); 8620 PetscCall(MatGetSize(w, &Mw, &Nw)); 8621 if (!flg || My != Mw || Ny != Nw) w = NULL; 8622 } 8623 if (!w) { 8624 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8625 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8626 PetscCall(PetscObjectDereference((PetscObject)w)); 8627 } else { 8628 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8629 } 8630 } 8631 if (!trans) { 8632 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8633 } else { 8634 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8635 } 8636 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8637 PetscFunctionReturn(0); 8638 } 8639 8640 /*@ 8641 MatMatInterpolate - Y = A*X or A'*X 8642 8643 Neighbor-wise Collective on Mat 8644 8645 Input Parameters: 8646 + mat - the matrix 8647 - x - the input dense matrix 8648 8649 Output Parameters: 8650 . y - the output dense matrix 8651 8652 Level: intermediate 8653 8654 Note: 8655 This allows one to use either the restriction or interpolation (its transpose) 8656 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8657 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8658 8659 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8660 @*/ 8661 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8662 { 8663 PetscFunctionBegin; 8664 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8665 PetscFunctionReturn(0); 8666 } 8667 8668 /*@ 8669 MatMatRestrict - Y = A*X or A'*X 8670 8671 Neighbor-wise Collective on Mat 8672 8673 Input Parameters: 8674 + mat - the matrix 8675 - x - the input dense matrix 8676 8677 Output Parameters: 8678 . y - the output dense matrix 8679 8680 Level: intermediate 8681 8682 Note: 8683 This allows one to use either the restriction or interpolation (its transpose) 8684 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8685 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8686 8687 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8688 @*/ 8689 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8690 { 8691 PetscFunctionBegin; 8692 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8693 PetscFunctionReturn(0); 8694 } 8695 8696 /*@ 8697 MatGetNullSpace - retrieves the null space of a matrix. 8698 8699 Logically Collective 8700 8701 Input Parameters: 8702 + mat - the matrix 8703 - nullsp - the null space object 8704 8705 Level: developer 8706 8707 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8708 @*/ 8709 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8710 { 8711 PetscFunctionBegin; 8712 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8713 PetscValidPointer(nullsp, 2); 8714 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8715 PetscFunctionReturn(0); 8716 } 8717 8718 /*@ 8719 MatSetNullSpace - attaches a null space to a matrix. 8720 8721 Logically Collective 8722 8723 Input Parameters: 8724 + mat - the matrix 8725 - nullsp - the null space object 8726 8727 Level: advanced 8728 8729 Notes: 8730 This null space is used by the `KSP` linear solvers to solve singular systems. 8731 8732 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 8733 8734 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 8735 to zero but the linear system will still be solved in a least squares sense. 8736 8737 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8738 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). 8739 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 8740 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 8741 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). 8742 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8743 8744 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8745 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8746 routine also automatically calls `MatSetTransposeNullSpace()`. 8747 8748 The user should call `MatNullSpaceDestroy()`. 8749 8750 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8751 `KSPSetPCSide()` 8752 @*/ 8753 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8754 { 8755 PetscFunctionBegin; 8756 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8757 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8758 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8759 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8760 mat->nullsp = nullsp; 8761 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8762 PetscFunctionReturn(0); 8763 } 8764 8765 /*@ 8766 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8767 8768 Logically Collective 8769 8770 Input Parameters: 8771 + mat - the matrix 8772 - nullsp - the null space object 8773 8774 Level: developer 8775 8776 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8777 @*/ 8778 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8779 { 8780 PetscFunctionBegin; 8781 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8782 PetscValidType(mat, 1); 8783 PetscValidPointer(nullsp, 2); 8784 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8785 PetscFunctionReturn(0); 8786 } 8787 8788 /*@ 8789 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8790 8791 Logically Collective 8792 8793 Input Parameters: 8794 + mat - the matrix 8795 - nullsp - the null space object 8796 8797 Level: advanced 8798 8799 Notes: 8800 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8801 8802 See `MatSetNullSpace()` 8803 8804 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8805 @*/ 8806 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8807 { 8808 PetscFunctionBegin; 8809 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8810 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8811 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8812 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8813 mat->transnullsp = nullsp; 8814 PetscFunctionReturn(0); 8815 } 8816 8817 /*@ 8818 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8819 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8820 8821 Logically Collective 8822 8823 Input Parameters: 8824 + mat - the matrix 8825 - nullsp - the null space object 8826 8827 Level: advanced 8828 8829 Notes: 8830 Overwrites any previous near null space that may have been attached 8831 8832 You can remove the null space by calling this routine with an nullsp of NULL 8833 8834 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8835 @*/ 8836 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8837 { 8838 PetscFunctionBegin; 8839 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8840 PetscValidType(mat, 1); 8841 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8842 MatCheckPreallocated(mat, 1); 8843 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8844 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8845 mat->nearnullsp = nullsp; 8846 PetscFunctionReturn(0); 8847 } 8848 8849 /*@ 8850 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8851 8852 Not Collective 8853 8854 Input Parameter: 8855 . mat - the matrix 8856 8857 Output Parameter: 8858 . nullsp - the null space object, NULL if not set 8859 8860 Level: advanced 8861 8862 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8863 @*/ 8864 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8865 { 8866 PetscFunctionBegin; 8867 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8868 PetscValidType(mat, 1); 8869 PetscValidPointer(nullsp, 2); 8870 MatCheckPreallocated(mat, 1); 8871 *nullsp = mat->nearnullsp; 8872 PetscFunctionReturn(0); 8873 } 8874 8875 /*@C 8876 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8877 8878 Collective 8879 8880 Input Parameters: 8881 + mat - the matrix 8882 . row - row/column permutation 8883 . fill - expected fill factor >= 1.0 8884 - level - level of fill, for ICC(k) 8885 8886 Notes: 8887 Probably really in-place only when level of fill is zero, otherwise allocates 8888 new space to store factored matrix and deletes previous memory. 8889 8890 Most users should employ the `KSP` interface for linear solvers 8891 instead of working directly with matrix algebra routines such as this. 8892 See, e.g., `KSPCreate()`. 8893 8894 Level: developer 8895 8896 Developer Note: 8897 The Fortran interface is not autogenerated as the 8898 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8899 8900 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8901 @*/ 8902 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8903 { 8904 PetscFunctionBegin; 8905 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8906 PetscValidType(mat, 1); 8907 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8908 PetscValidPointer(info, 3); 8909 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8910 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8911 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8912 MatCheckPreallocated(mat, 1); 8913 PetscUseTypeMethod(mat, iccfactor, row, info); 8914 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8915 PetscFunctionReturn(0); 8916 } 8917 8918 /*@ 8919 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8920 ghosted ones. 8921 8922 Not Collective 8923 8924 Input Parameters: 8925 + mat - the matrix 8926 - diag - the diagonal values, including ghost ones 8927 8928 Level: developer 8929 8930 Notes: 8931 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8932 8933 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8934 8935 .seealso: `MatDiagonalScale()` 8936 @*/ 8937 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8938 { 8939 PetscMPIInt size; 8940 8941 PetscFunctionBegin; 8942 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8943 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8944 PetscValidType(mat, 1); 8945 8946 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8947 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8948 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8949 if (size == 1) { 8950 PetscInt n, m; 8951 PetscCall(VecGetSize(diag, &n)); 8952 PetscCall(MatGetSize(mat, NULL, &m)); 8953 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 8954 PetscCall(MatDiagonalScale(mat, NULL, diag)); 8955 } else { 8956 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 8957 } 8958 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 8959 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8960 PetscFunctionReturn(0); 8961 } 8962 8963 /*@ 8964 MatGetInertia - Gets the inertia from a factored matrix 8965 8966 Collective 8967 8968 Input Parameter: 8969 . mat - the matrix 8970 8971 Output Parameters: 8972 + nneg - number of negative eigenvalues 8973 . nzero - number of zero eigenvalues 8974 - npos - number of positive eigenvalues 8975 8976 Level: advanced 8977 8978 Note: 8979 Matrix must have been factored by `MatCholeskyFactor()` 8980 8981 .seealso: `MatGetFactor()`, `MatCholeskyFactor()` 8982 @*/ 8983 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 8984 { 8985 PetscFunctionBegin; 8986 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8987 PetscValidType(mat, 1); 8988 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 8989 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 8990 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 8991 PetscFunctionReturn(0); 8992 } 8993 8994 /* ----------------------------------------------------------------*/ 8995 /*@C 8996 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 8997 8998 Neighbor-wise Collective 8999 9000 Input Parameters: 9001 + mat - the factored matrix obtained with `MatGetFactor()` 9002 - b - the right-hand-side vectors 9003 9004 Output Parameter: 9005 . x - the result vectors 9006 9007 Note: 9008 The vectors b and x cannot be the same. I.e., one cannot 9009 call `MatSolves`(A,x,x). 9010 9011 Level: developer 9012 9013 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9014 @*/ 9015 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9016 { 9017 PetscFunctionBegin; 9018 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9019 PetscValidType(mat, 1); 9020 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9021 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9022 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 9023 9024 MatCheckPreallocated(mat, 1); 9025 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9026 PetscUseTypeMethod(mat, solves, b, x); 9027 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9028 PetscFunctionReturn(0); 9029 } 9030 9031 /*@ 9032 MatIsSymmetric - Test whether a matrix is symmetric 9033 9034 Collective 9035 9036 Input Parameters: 9037 + A - the matrix to test 9038 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9039 9040 Output Parameters: 9041 . flg - the result 9042 9043 Notes: 9044 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9045 9046 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9047 9048 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9049 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9050 9051 Level: intermediate 9052 9053 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9054 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9055 @*/ 9056 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9057 { 9058 PetscFunctionBegin; 9059 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9060 PetscValidBoolPointer(flg, 3); 9061 9062 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9063 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9064 else { 9065 if (!A->ops->issymmetric) { 9066 MatType mattype; 9067 PetscCall(MatGetType(A, &mattype)); 9068 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype); 9069 } 9070 PetscUseTypeMethod(A, issymmetric, tol, flg); 9071 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9072 } 9073 PetscFunctionReturn(0); 9074 } 9075 9076 /*@ 9077 MatIsHermitian - Test whether a matrix is Hermitian 9078 9079 Collective on Mat 9080 9081 Input Parameters: 9082 + A - the matrix to test 9083 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9084 9085 Output Parameters: 9086 . flg - the result 9087 9088 Level: intermediate 9089 9090 Notes: 9091 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9092 9093 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9094 9095 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9096 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9097 9098 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9099 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9100 @*/ 9101 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9102 { 9103 PetscFunctionBegin; 9104 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9105 PetscValidBoolPointer(flg, 3); 9106 9107 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9108 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9109 else { 9110 if (!A->ops->ishermitian) { 9111 MatType mattype; 9112 PetscCall(MatGetType(A, &mattype)); 9113 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype); 9114 } 9115 PetscUseTypeMethod(A, ishermitian, tol, flg); 9116 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9117 } 9118 PetscFunctionReturn(0); 9119 } 9120 9121 /*@ 9122 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric 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 symmetry 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`). Use `MatIsSymmetric()` 9137 if you want it explicitly checked 9138 9139 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9140 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9141 9142 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9143 @*/ 9144 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9145 { 9146 PetscFunctionBegin; 9147 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9148 PetscValidBoolPointer(set, 2); 9149 PetscValidBoolPointer(flg, 3); 9150 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9151 *set = PETSC_TRUE; 9152 *flg = PetscBool3ToBool(A->symmetric); 9153 } else { 9154 *set = PETSC_FALSE; 9155 } 9156 PetscFunctionReturn(0); 9157 } 9158 9159 /*@ 9160 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9161 9162 Not Collective 9163 9164 Input Parameter: 9165 . A - the matrix to check 9166 9167 Output Parameters: 9168 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9169 - flg - the result (only valid if set is `PETSC_TRUE`) 9170 9171 Level: advanced 9172 9173 Notes: 9174 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9175 9176 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9177 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9178 9179 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9180 @*/ 9181 PetscErrorCode MatIsSPDKnown(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->spd != PETSC_BOOL3_UNKNOWN) { 9188 *set = PETSC_TRUE; 9189 *flg = PetscBool3ToBool(A->spd); 9190 } else { 9191 *set = PETSC_FALSE; 9192 } 9193 PetscFunctionReturn(0); 9194 } 9195 9196 /*@ 9197 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9198 9199 Not Collective 9200 9201 Input Parameter: 9202 . A - the matrix to check 9203 9204 Output Parameters: 9205 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9206 - flg - the result (only valid if set is `PETSC_TRUE`) 9207 9208 Level: advanced 9209 9210 Notes: 9211 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9212 if you want it explicitly checked 9213 9214 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9215 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9216 9217 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9218 @*/ 9219 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9220 { 9221 PetscFunctionBegin; 9222 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9223 PetscValidBoolPointer(set, 2); 9224 PetscValidBoolPointer(flg, 3); 9225 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9226 *set = PETSC_TRUE; 9227 *flg = PetscBool3ToBool(A->hermitian); 9228 } else { 9229 *set = PETSC_FALSE; 9230 } 9231 PetscFunctionReturn(0); 9232 } 9233 9234 /*@ 9235 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9236 9237 Collective on Mat 9238 9239 Input Parameter: 9240 . A - the matrix to test 9241 9242 Output Parameters: 9243 . flg - the result 9244 9245 Notes: 9246 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9247 9248 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 9249 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9250 9251 Level: intermediate 9252 9253 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9254 @*/ 9255 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9256 { 9257 PetscFunctionBegin; 9258 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9259 PetscValidBoolPointer(flg, 2); 9260 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9261 *flg = PetscBool3ToBool(A->structurally_symmetric); 9262 } else { 9263 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9264 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9265 } 9266 PetscFunctionReturn(0); 9267 } 9268 9269 /*@ 9270 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9271 9272 Not Collective 9273 9274 Input Parameter: 9275 . A - the matrix to check 9276 9277 Output Parameters: 9278 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9279 - flg - the result (only valid if set is PETSC_TRUE) 9280 9281 Level: advanced 9282 9283 Notes: 9284 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 9285 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9286 9287 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9288 9289 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9290 @*/ 9291 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9292 { 9293 PetscFunctionBegin; 9294 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9295 PetscValidBoolPointer(set, 2); 9296 PetscValidBoolPointer(flg, 3); 9297 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9298 *set = PETSC_TRUE; 9299 *flg = PetscBool3ToBool(A->structurally_symmetric); 9300 } else { 9301 *set = PETSC_FALSE; 9302 } 9303 PetscFunctionReturn(0); 9304 } 9305 9306 /*@ 9307 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9308 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9309 9310 Not collective 9311 9312 Input Parameter: 9313 . mat - the matrix 9314 9315 Output Parameters: 9316 + nstash - the size of the stash 9317 . reallocs - the number of additional mallocs incurred. 9318 . bnstash - the size of the block stash 9319 - breallocs - the number of additional mallocs incurred.in the block stash 9320 9321 Level: advanced 9322 9323 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9324 @*/ 9325 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9326 { 9327 PetscFunctionBegin; 9328 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9329 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9330 PetscFunctionReturn(0); 9331 } 9332 9333 /*@C 9334 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9335 parallel layout, `PetscLayout` for rows and columns 9336 9337 Collective 9338 9339 Input Parameter: 9340 . mat - the matrix 9341 9342 Output Parameters: 9343 + right - (optional) vector that the matrix can be multiplied against 9344 - left - (optional) vector that the matrix vector product can be stored in 9345 9346 Notes: 9347 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()`. 9348 9349 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9350 9351 Level: advanced 9352 9353 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9354 @*/ 9355 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9356 { 9357 PetscFunctionBegin; 9358 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9359 PetscValidType(mat, 1); 9360 if (mat->ops->getvecs) { 9361 PetscUseTypeMethod(mat, getvecs, right, left); 9362 } else { 9363 PetscInt rbs, cbs; 9364 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9365 if (right) { 9366 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9367 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9368 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9369 PetscCall(VecSetBlockSize(*right, cbs)); 9370 PetscCall(VecSetType(*right, mat->defaultvectype)); 9371 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9372 if (mat->boundtocpu && mat->bindingpropagates) { 9373 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9374 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9375 } 9376 #endif 9377 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9378 } 9379 if (left) { 9380 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9381 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9382 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9383 PetscCall(VecSetBlockSize(*left, rbs)); 9384 PetscCall(VecSetType(*left, mat->defaultvectype)); 9385 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9386 if (mat->boundtocpu && mat->bindingpropagates) { 9387 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9388 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9389 } 9390 #endif 9391 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9392 } 9393 } 9394 PetscFunctionReturn(0); 9395 } 9396 9397 /*@C 9398 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9399 with default values. 9400 9401 Not Collective 9402 9403 Input Parameters: 9404 . info - the `MatFactorInfo` data structure 9405 9406 Notes: 9407 The solvers are generally used through the `KSP` and `PC` objects, for example 9408 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9409 9410 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9411 9412 Level: developer 9413 9414 Developer Note: 9415 The Fortran interface is not autogenerated as the 9416 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9417 9418 .seealso: `MatGetFactor()`, `MatFactorInfo` 9419 @*/ 9420 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9421 { 9422 PetscFunctionBegin; 9423 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9424 PetscFunctionReturn(0); 9425 } 9426 9427 /*@ 9428 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9429 9430 Collective 9431 9432 Input Parameters: 9433 + mat - the factored matrix 9434 - is - the index set defining the Schur indices (0-based) 9435 9436 Notes: 9437 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9438 9439 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9440 9441 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9442 9443 Level: advanced 9444 9445 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9446 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9447 9448 @*/ 9449 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9450 { 9451 PetscErrorCode (*f)(Mat, IS); 9452 9453 PetscFunctionBegin; 9454 PetscValidType(mat, 1); 9455 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9456 PetscValidType(is, 2); 9457 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9458 PetscCheckSameComm(mat, 1, is, 2); 9459 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9460 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9461 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9462 PetscCall(MatDestroy(&mat->schur)); 9463 PetscCall((*f)(mat, is)); 9464 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9465 PetscFunctionReturn(0); 9466 } 9467 9468 /*@ 9469 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9470 9471 Logically Collective 9472 9473 Input Parameters: 9474 + F - the factored matrix obtained by calling `MatGetFactor()` 9475 . S - location where to return the Schur complement, can be NULL 9476 - status - the status of the Schur complement matrix, can be NULL 9477 9478 Notes: 9479 You must call `MatFactorSetSchurIS()` before calling this routine. 9480 9481 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9482 9483 The routine provides a copy of the Schur matrix stored within the solver data structures. 9484 The caller must destroy the object when it is no longer needed. 9485 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9486 9487 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) 9488 9489 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9490 9491 Developer Note: 9492 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9493 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9494 9495 Level: advanced 9496 9497 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9498 @*/ 9499 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9500 { 9501 PetscFunctionBegin; 9502 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9503 if (S) PetscValidPointer(S, 2); 9504 if (status) PetscValidPointer(status, 3); 9505 if (S) { 9506 PetscErrorCode (*f)(Mat, Mat *); 9507 9508 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9509 if (f) { 9510 PetscCall((*f)(F, S)); 9511 } else { 9512 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9513 } 9514 } 9515 if (status) *status = F->schur_status; 9516 PetscFunctionReturn(0); 9517 } 9518 9519 /*@ 9520 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9521 9522 Logically Collective 9523 9524 Input Parameters: 9525 + F - the factored matrix obtained by calling `MatGetFactor()` 9526 . *S - location where to return the Schur complement, can be NULL 9527 - status - the status of the Schur complement matrix, can be NULL 9528 9529 Notes: 9530 You must call `MatFactorSetSchurIS()` before calling this routine. 9531 9532 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9533 9534 The routine returns a the Schur Complement stored within the data strutures of the solver. 9535 9536 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9537 9538 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9539 9540 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9541 9542 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9543 9544 Level: advanced 9545 9546 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9547 @*/ 9548 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9549 { 9550 PetscFunctionBegin; 9551 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9552 if (S) PetscValidPointer(S, 2); 9553 if (status) PetscValidPointer(status, 3); 9554 if (S) *S = F->schur; 9555 if (status) *status = F->schur_status; 9556 PetscFunctionReturn(0); 9557 } 9558 9559 /*@ 9560 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9561 9562 Logically Collective 9563 9564 Input Parameters: 9565 + F - the factored matrix obtained by calling `MatGetFactor()` 9566 . *S - location where the Schur complement is stored 9567 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9568 9569 Level: advanced 9570 9571 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9572 @*/ 9573 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9574 { 9575 PetscFunctionBegin; 9576 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9577 if (S) { 9578 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9579 *S = NULL; 9580 } 9581 F->schur_status = status; 9582 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9583 PetscFunctionReturn(0); 9584 } 9585 9586 /*@ 9587 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9588 9589 Logically Collective 9590 9591 Input Parameters: 9592 + F - the factored matrix obtained by calling `MatGetFactor()` 9593 . rhs - location where the right hand side of the Schur complement system is stored 9594 - sol - location where the solution of the Schur complement system has to be returned 9595 9596 Notes: 9597 The sizes of the vectors should match the size of the Schur complement 9598 9599 Must be called after `MatFactorSetSchurIS()` 9600 9601 Level: advanced 9602 9603 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9604 @*/ 9605 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9606 { 9607 PetscFunctionBegin; 9608 PetscValidType(F, 1); 9609 PetscValidType(rhs, 2); 9610 PetscValidType(sol, 3); 9611 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9612 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9613 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9614 PetscCheckSameComm(F, 1, rhs, 2); 9615 PetscCheckSameComm(F, 1, sol, 3); 9616 PetscCall(MatFactorFactorizeSchurComplement(F)); 9617 switch (F->schur_status) { 9618 case MAT_FACTOR_SCHUR_FACTORED: 9619 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9620 break; 9621 case MAT_FACTOR_SCHUR_INVERTED: 9622 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9623 break; 9624 default: 9625 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9626 } 9627 PetscFunctionReturn(0); 9628 } 9629 9630 /*@ 9631 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9632 9633 Logically Collective 9634 9635 Input Parameters: 9636 + F - the factored matrix obtained by calling `MatGetFactor()` 9637 . rhs - location where the right hand side of the Schur complement system is stored 9638 - sol - location where the solution of the Schur complement system has to be returned 9639 9640 Notes: 9641 The sizes of the vectors should match the size of the Schur complement 9642 9643 Must be called after `MatFactorSetSchurIS()` 9644 9645 Level: advanced 9646 9647 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9648 @*/ 9649 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9650 { 9651 PetscFunctionBegin; 9652 PetscValidType(F, 1); 9653 PetscValidType(rhs, 2); 9654 PetscValidType(sol, 3); 9655 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9656 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9657 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9658 PetscCheckSameComm(F, 1, rhs, 2); 9659 PetscCheckSameComm(F, 1, sol, 3); 9660 PetscCall(MatFactorFactorizeSchurComplement(F)); 9661 switch (F->schur_status) { 9662 case MAT_FACTOR_SCHUR_FACTORED: 9663 PetscCall(MatSolve(F->schur, rhs, sol)); 9664 break; 9665 case MAT_FACTOR_SCHUR_INVERTED: 9666 PetscCall(MatMult(F->schur, rhs, sol)); 9667 break; 9668 default: 9669 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9670 } 9671 PetscFunctionReturn(0); 9672 } 9673 9674 /*@ 9675 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9676 9677 Logically Collective on F 9678 9679 Input Parameters: 9680 . F - the factored matrix obtained by calling `MatGetFactor()` 9681 9682 Notes: 9683 Must be called after `MatFactorSetSchurIS()`. 9684 9685 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9686 9687 Level: advanced 9688 9689 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9690 @*/ 9691 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9692 { 9693 PetscFunctionBegin; 9694 PetscValidType(F, 1); 9695 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9696 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0); 9697 PetscCall(MatFactorFactorizeSchurComplement(F)); 9698 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9699 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9700 PetscFunctionReturn(0); 9701 } 9702 9703 /*@ 9704 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9705 9706 Logically Collective 9707 9708 Input Parameters: 9709 . F - the factored matrix obtained by calling `MatGetFactor()` 9710 9711 Note: 9712 Must be called after `MatFactorSetSchurIS()` 9713 9714 Level: advanced 9715 9716 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9717 @*/ 9718 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9719 { 9720 PetscFunctionBegin; 9721 PetscValidType(F, 1); 9722 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9723 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0); 9724 PetscCall(MatFactorFactorizeSchurComplement_Private(F)); 9725 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9726 PetscFunctionReturn(0); 9727 } 9728 9729 /*@ 9730 MatPtAP - Creates the matrix product C = P^T * A * P 9731 9732 Neighbor-wise Collective on A 9733 9734 Input Parameters: 9735 + A - the matrix 9736 . P - the projection matrix 9737 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9738 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9739 if the result is a dense matrix this is irrelevant 9740 9741 Output Parameters: 9742 . C - the product matrix 9743 9744 Notes: 9745 C will be created and must be destroyed by the user with `MatDestroy()`. 9746 9747 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9748 9749 Developer Note: 9750 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9751 9752 Level: intermediate 9753 9754 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9755 @*/ 9756 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9757 { 9758 PetscFunctionBegin; 9759 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9760 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9761 9762 if (scall == MAT_INITIAL_MATRIX) { 9763 PetscCall(MatProductCreate(A, P, NULL, C)); 9764 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9765 PetscCall(MatProductSetAlgorithm(*C, "default")); 9766 PetscCall(MatProductSetFill(*C, fill)); 9767 9768 (*C)->product->api_user = PETSC_TRUE; 9769 PetscCall(MatProductSetFromOptions(*C)); 9770 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); 9771 PetscCall(MatProductSymbolic(*C)); 9772 } else { /* scall == MAT_REUSE_MATRIX */ 9773 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9774 } 9775 9776 PetscCall(MatProductNumeric(*C)); 9777 (*C)->symmetric = A->symmetric; 9778 (*C)->spd = A->spd; 9779 PetscFunctionReturn(0); 9780 } 9781 9782 /*@ 9783 MatRARt - Creates the matrix product C = R * A * R^T 9784 9785 Neighbor-wise Collective on A 9786 9787 Input Parameters: 9788 + A - the matrix 9789 . R - the projection matrix 9790 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9791 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9792 if the result is a dense matrix this is irrelevant 9793 9794 Output Parameters: 9795 . C - the product matrix 9796 9797 Notes: 9798 C will be created and must be destroyed by the user with `MatDestroy()`. 9799 9800 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9801 9802 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9803 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9804 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9805 We recommend using MatPtAP(). 9806 9807 Level: intermediate 9808 9809 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9810 @*/ 9811 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9812 { 9813 PetscFunctionBegin; 9814 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9815 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9816 9817 if (scall == MAT_INITIAL_MATRIX) { 9818 PetscCall(MatProductCreate(A, R, NULL, C)); 9819 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9820 PetscCall(MatProductSetAlgorithm(*C, "default")); 9821 PetscCall(MatProductSetFill(*C, fill)); 9822 9823 (*C)->product->api_user = PETSC_TRUE; 9824 PetscCall(MatProductSetFromOptions(*C)); 9825 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); 9826 PetscCall(MatProductSymbolic(*C)); 9827 } else { /* scall == MAT_REUSE_MATRIX */ 9828 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9829 } 9830 9831 PetscCall(MatProductNumeric(*C)); 9832 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9833 PetscFunctionReturn(0); 9834 } 9835 9836 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9837 { 9838 PetscFunctionBegin; 9839 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9840 9841 if (scall == MAT_INITIAL_MATRIX) { 9842 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9843 PetscCall(MatProductCreate(A, B, NULL, C)); 9844 PetscCall(MatProductSetType(*C, ptype)); 9845 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9846 PetscCall(MatProductSetFill(*C, fill)); 9847 9848 (*C)->product->api_user = PETSC_TRUE; 9849 PetscCall(MatProductSetFromOptions(*C)); 9850 PetscCall(MatProductSymbolic(*C)); 9851 } else { /* scall == MAT_REUSE_MATRIX */ 9852 Mat_Product *product = (*C)->product; 9853 PetscBool isdense; 9854 9855 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9856 if (isdense && product && product->type != ptype) { 9857 PetscCall(MatProductClear(*C)); 9858 product = NULL; 9859 } 9860 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9861 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9862 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9863 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9864 product = (*C)->product; 9865 product->fill = fill; 9866 product->api_user = PETSC_TRUE; 9867 product->clear = PETSC_TRUE; 9868 9869 PetscCall(MatProductSetType(*C, ptype)); 9870 PetscCall(MatProductSetFromOptions(*C)); 9871 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); 9872 PetscCall(MatProductSymbolic(*C)); 9873 } else { /* user may change input matrices A or B when REUSE */ 9874 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9875 } 9876 } 9877 PetscCall(MatProductNumeric(*C)); 9878 PetscFunctionReturn(0); 9879 } 9880 9881 /*@ 9882 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9883 9884 Neighbor-wise Collective on A 9885 9886 Input Parameters: 9887 + A - the left matrix 9888 . B - the right matrix 9889 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9890 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9891 if the result is a dense matrix this is irrelevant 9892 9893 Output Parameters: 9894 . C - the product matrix 9895 9896 Notes: 9897 Unless scall is `MAT_REUSE_MATRIX` C will be created. 9898 9899 `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 9900 call to this function with `MAT_INITIAL_MATRIX`. 9901 9902 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 9903 9904 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`, 9905 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 9906 9907 Example of Usage: 9908 .vb 9909 MatProductCreate(A,B,NULL,&C); 9910 MatProductSetType(C,MATPRODUCT_AB); 9911 MatProductSymbolic(C); 9912 MatProductNumeric(C); // compute C=A * B 9913 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 9914 MatProductNumeric(C); 9915 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 9916 MatProductNumeric(C); 9917 .ve 9918 9919 Level: intermediate 9920 9921 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 9922 @*/ 9923 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9924 { 9925 PetscFunctionBegin; 9926 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 9927 PetscFunctionReturn(0); 9928 } 9929 9930 /*@ 9931 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 9932 9933 Neighbor-wise Collective on A 9934 9935 Input Parameters: 9936 + A - the left matrix 9937 . B - the right matrix 9938 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9939 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9940 9941 Output Parameters: 9942 . C - the product matrix 9943 9944 Notes: 9945 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 9946 9947 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 9948 9949 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9950 actually needed. 9951 9952 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 9953 and for pairs of `MATMPIDENSE` matrices. 9954 9955 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 9956 9957 Options Database Keys: 9958 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 9959 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 9960 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 9961 9962 Level: intermediate 9963 9964 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 9965 @*/ 9966 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9967 { 9968 PetscFunctionBegin; 9969 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 9970 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9971 PetscFunctionReturn(0); 9972 } 9973 9974 /*@ 9975 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 9976 9977 Neighbor-wise Collective on A 9978 9979 Input Parameters: 9980 + A - the left matrix 9981 . B - the right matrix 9982 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9983 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9984 9985 Output Parameters: 9986 . C - the product matrix 9987 9988 Notes: 9989 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 9990 9991 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 9992 9993 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 9994 9995 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9996 actually needed. 9997 9998 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 9999 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10000 10001 Level: intermediate 10002 10003 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10004 @*/ 10005 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10006 { 10007 PetscFunctionBegin; 10008 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10009 PetscFunctionReturn(0); 10010 } 10011 10012 /*@ 10013 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10014 10015 Neighbor-wise Collective on A 10016 10017 Input Parameters: 10018 + A - the left matrix 10019 . B - the middle matrix 10020 . C - the right matrix 10021 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10022 - 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 10023 if the result is a dense matrix this is irrelevant 10024 10025 Output Parameters: 10026 . D - the product matrix 10027 10028 Notes: 10029 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10030 10031 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10032 10033 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10034 10035 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10036 actually needed. 10037 10038 If you have many matrices with the same non-zero structure to multiply, you 10039 should use `MAT_REUSE_MATRIX` in all calls but the first 10040 10041 Level: intermediate 10042 10043 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10044 @*/ 10045 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10046 { 10047 PetscFunctionBegin; 10048 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10049 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10050 10051 if (scall == MAT_INITIAL_MATRIX) { 10052 PetscCall(MatProductCreate(A, B, C, D)); 10053 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10054 PetscCall(MatProductSetAlgorithm(*D, "default")); 10055 PetscCall(MatProductSetFill(*D, fill)); 10056 10057 (*D)->product->api_user = PETSC_TRUE; 10058 PetscCall(MatProductSetFromOptions(*D)); 10059 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, 10060 ((PetscObject)C)->type_name); 10061 PetscCall(MatProductSymbolic(*D)); 10062 } else { /* user may change input matrices when REUSE */ 10063 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10064 } 10065 PetscCall(MatProductNumeric(*D)); 10066 PetscFunctionReturn(0); 10067 } 10068 10069 /*@ 10070 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10071 10072 Collective 10073 10074 Input Parameters: 10075 + mat - the matrix 10076 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10077 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10078 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10079 10080 Output Parameter: 10081 . matredundant - redundant matrix 10082 10083 Notes: 10084 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10085 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10086 10087 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10088 calling it. 10089 10090 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10091 10092 Level: advanced 10093 10094 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10095 @*/ 10096 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10097 { 10098 MPI_Comm comm; 10099 PetscMPIInt size; 10100 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10101 Mat_Redundant *redund = NULL; 10102 PetscSubcomm psubcomm = NULL; 10103 MPI_Comm subcomm_in = subcomm; 10104 Mat *matseq; 10105 IS isrow, iscol; 10106 PetscBool newsubcomm = PETSC_FALSE; 10107 10108 PetscFunctionBegin; 10109 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10110 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10111 PetscValidPointer(*matredundant, 5); 10112 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10113 } 10114 10115 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10116 if (size == 1 || nsubcomm == 1) { 10117 if (reuse == MAT_INITIAL_MATRIX) { 10118 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10119 } else { 10120 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"); 10121 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10122 } 10123 PetscFunctionReturn(0); 10124 } 10125 10126 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10127 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10128 MatCheckPreallocated(mat, 1); 10129 10130 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10131 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10132 /* create psubcomm, then get subcomm */ 10133 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10134 PetscCallMPI(MPI_Comm_size(comm, &size)); 10135 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10136 10137 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10138 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10139 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10140 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10141 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10142 newsubcomm = PETSC_TRUE; 10143 PetscCall(PetscSubcommDestroy(&psubcomm)); 10144 } 10145 10146 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10147 if (reuse == MAT_INITIAL_MATRIX) { 10148 mloc_sub = PETSC_DECIDE; 10149 nloc_sub = PETSC_DECIDE; 10150 if (bs < 1) { 10151 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10152 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10153 } else { 10154 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10155 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10156 } 10157 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10158 rstart = rend - mloc_sub; 10159 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10160 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10161 } else { /* reuse == MAT_REUSE_MATRIX */ 10162 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"); 10163 /* retrieve subcomm */ 10164 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10165 redund = (*matredundant)->redundant; 10166 isrow = redund->isrow; 10167 iscol = redund->iscol; 10168 matseq = redund->matseq; 10169 } 10170 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10171 10172 /* get matredundant over subcomm */ 10173 if (reuse == MAT_INITIAL_MATRIX) { 10174 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10175 10176 /* create a supporting struct and attach it to C for reuse */ 10177 PetscCall(PetscNew(&redund)); 10178 (*matredundant)->redundant = redund; 10179 redund->isrow = isrow; 10180 redund->iscol = iscol; 10181 redund->matseq = matseq; 10182 if (newsubcomm) { 10183 redund->subcomm = subcomm; 10184 } else { 10185 redund->subcomm = MPI_COMM_NULL; 10186 } 10187 } else { 10188 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10189 } 10190 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10191 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10192 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10193 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10194 } 10195 #endif 10196 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10197 PetscFunctionReturn(0); 10198 } 10199 10200 /*@C 10201 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10202 a given `Mat`. Each submatrix can span multiple procs. 10203 10204 Collective 10205 10206 Input Parameters: 10207 + mat - the matrix 10208 . subcomm - the subcommunicator obtained by MPI_Com_split(comm) 10209 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10210 10211 Output Parameter: 10212 . subMat - 'parallel submatrices each spans a given subcomm 10213 10214 Notes: 10215 The submatrix partition across processors is dictated by 'subComm' a 10216 communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm 10217 is not restriced to be grouped with consecutive original ranks. 10218 10219 Due the MPI_Comm_split() usage, the parallel layout of the submatrices 10220 map directly to the layout of the original matrix [wrt the local 10221 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10222 into the 'DiagonalMat' of the subMat, hence it is used directly from 10223 the subMat. However the offDiagMat looses some columns - and this is 10224 reconstructed with `MatSetValues()` 10225 10226 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10227 10228 Level: advanced 10229 10230 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10231 @*/ 10232 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10233 { 10234 PetscMPIInt commsize, subCommSize; 10235 10236 PetscFunctionBegin; 10237 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10238 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10239 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10240 10241 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"); 10242 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10243 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10244 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10245 PetscFunctionReturn(0); 10246 } 10247 10248 /*@ 10249 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10250 10251 Not Collective 10252 10253 Input Parameters: 10254 + mat - matrix to extract local submatrix from 10255 . isrow - local row indices for submatrix 10256 - iscol - local column indices for submatrix 10257 10258 Output Parameter: 10259 . submat - the submatrix 10260 10261 Level: intermediate 10262 10263 Notes: 10264 The submat should be returned with `MatRestoreLocalSubMatrix()`. 10265 10266 Depending on the format of mat, the returned submat may not implement `MatMult()`. Its communicator may be 10267 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's. 10268 10269 The submat always implements `MatSetValuesLocal()`. If isrow and iscol have the same block size, then 10270 `MatSetValuesBlockedLocal()` will also be implemented. 10271 10272 The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10273 Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided. 10274 10275 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10276 @*/ 10277 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10278 { 10279 PetscFunctionBegin; 10280 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10281 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10282 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10283 PetscCheckSameComm(isrow, 2, iscol, 3); 10284 PetscValidPointer(submat, 4); 10285 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10286 10287 if (mat->ops->getlocalsubmatrix) { 10288 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10289 } else { 10290 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10291 } 10292 PetscFunctionReturn(0); 10293 } 10294 10295 /*@ 10296 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10297 10298 Not Collective 10299 10300 Input Parameters: 10301 + mat - matrix to extract local submatrix from 10302 . isrow - local row indices for submatrix 10303 . iscol - local column indices for submatrix 10304 - submat - the submatrix 10305 10306 Level: intermediate 10307 10308 .seealso: `MatGetLocalSubMatrix()` 10309 @*/ 10310 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10311 { 10312 PetscFunctionBegin; 10313 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10314 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10315 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10316 PetscCheckSameComm(isrow, 2, iscol, 3); 10317 PetscValidPointer(submat, 4); 10318 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10319 10320 if (mat->ops->restorelocalsubmatrix) { 10321 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10322 } else { 10323 PetscCall(MatDestroy(submat)); 10324 } 10325 *submat = NULL; 10326 PetscFunctionReturn(0); 10327 } 10328 10329 /* --------------------------------------------------------*/ 10330 /*@ 10331 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10332 10333 Collective 10334 10335 Input Parameter: 10336 . mat - the matrix 10337 10338 Output Parameter: 10339 . is - if any rows have zero diagonals this contains the list of them 10340 10341 Level: developer 10342 10343 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10344 @*/ 10345 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10346 { 10347 PetscFunctionBegin; 10348 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10349 PetscValidType(mat, 1); 10350 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10351 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10352 10353 if (!mat->ops->findzerodiagonals) { 10354 Vec diag; 10355 const PetscScalar *a; 10356 PetscInt *rows; 10357 PetscInt rStart, rEnd, r, nrow = 0; 10358 10359 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10360 PetscCall(MatGetDiagonal(mat, diag)); 10361 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10362 PetscCall(VecGetArrayRead(diag, &a)); 10363 for (r = 0; r < rEnd - rStart; ++r) 10364 if (a[r] == 0.0) ++nrow; 10365 PetscCall(PetscMalloc1(nrow, &rows)); 10366 nrow = 0; 10367 for (r = 0; r < rEnd - rStart; ++r) 10368 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10369 PetscCall(VecRestoreArrayRead(diag, &a)); 10370 PetscCall(VecDestroy(&diag)); 10371 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10372 } else { 10373 PetscUseTypeMethod(mat, findzerodiagonals, is); 10374 } 10375 PetscFunctionReturn(0); 10376 } 10377 10378 /*@ 10379 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10380 10381 Collective 10382 10383 Input Parameter: 10384 . mat - the matrix 10385 10386 Output Parameter: 10387 . is - contains the list of rows with off block diagonal entries 10388 10389 Level: developer 10390 10391 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10392 @*/ 10393 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10394 { 10395 PetscFunctionBegin; 10396 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10397 PetscValidType(mat, 1); 10398 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10399 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10400 10401 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10402 PetscFunctionReturn(0); 10403 } 10404 10405 /*@C 10406 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10407 10408 Collective; No Fortran Support 10409 10410 Input Parameters: 10411 . mat - the matrix 10412 10413 Output Parameters: 10414 . values - the block inverses in column major order (FORTRAN-like) 10415 10416 Level: advanced 10417 10418 Notes: 10419 The size of the blocks is determined by the block size of the matrix. 10420 10421 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10422 10423 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10424 10425 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10426 @*/ 10427 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10428 { 10429 PetscFunctionBegin; 10430 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10431 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10432 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10433 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10434 PetscFunctionReturn(0); 10435 } 10436 10437 /*@C 10438 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10439 10440 Collective; No Fortran Support 10441 10442 Input Parameters: 10443 + mat - the matrix 10444 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10445 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10446 10447 Output Parameters: 10448 . values - the block inverses in column major order (FORTRAN-like) 10449 10450 Level: advanced 10451 10452 Notes: 10453 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10454 10455 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10456 10457 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10458 @*/ 10459 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10460 { 10461 PetscFunctionBegin; 10462 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10463 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10464 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10465 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10466 PetscFunctionReturn(0); 10467 } 10468 10469 /*@ 10470 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10471 10472 Collective on Mat 10473 10474 Input Parameters: 10475 + A - the matrix 10476 - C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 10477 10478 Note: 10479 The blocksize of the matrix is used to determine the blocks on the diagonal of C 10480 10481 Level: advanced 10482 10483 .seealso: `MatInvertBlockDiagonal()` 10484 @*/ 10485 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10486 { 10487 const PetscScalar *vals; 10488 PetscInt *dnnz; 10489 PetscInt m, rstart, rend, bs, i, j; 10490 10491 PetscFunctionBegin; 10492 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10493 PetscCall(MatGetBlockSize(A, &bs)); 10494 PetscCall(MatGetLocalSize(A, &m, NULL)); 10495 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10496 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10497 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10498 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10499 PetscCall(PetscFree(dnnz)); 10500 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10501 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10502 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10503 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10504 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10505 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10506 PetscFunctionReturn(0); 10507 } 10508 10509 /*@C 10510 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10511 via `MatTransposeColoringCreate()`. 10512 10513 Collective on c 10514 10515 Input Parameter: 10516 . c - coloring context 10517 10518 Level: intermediate 10519 10520 .seealso: `MatTransposeColoringCreate()` 10521 @*/ 10522 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10523 { 10524 MatTransposeColoring matcolor = *c; 10525 10526 PetscFunctionBegin; 10527 if (!matcolor) PetscFunctionReturn(0); 10528 if (--((PetscObject)matcolor)->refct > 0) { 10529 matcolor = NULL; 10530 PetscFunctionReturn(0); 10531 } 10532 10533 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10534 PetscCall(PetscFree(matcolor->rows)); 10535 PetscCall(PetscFree(matcolor->den2sp)); 10536 PetscCall(PetscFree(matcolor->colorforcol)); 10537 PetscCall(PetscFree(matcolor->columns)); 10538 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10539 PetscCall(PetscHeaderDestroy(c)); 10540 PetscFunctionReturn(0); 10541 } 10542 10543 /*@C 10544 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10545 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10546 `MatTransposeColoring` to sparse B. 10547 10548 Collective on coloring 10549 10550 Input Parameters: 10551 + B - sparse matrix B 10552 . Btdense - symbolic dense matrix B^T 10553 - coloring - coloring context created with `MatTransposeColoringCreate()` 10554 10555 Output Parameter: 10556 . Btdense - dense matrix B^T 10557 10558 Level: developer 10559 10560 Note: 10561 These are used internally for some implementations of `MatRARt()` 10562 10563 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10564 10565 @*/ 10566 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10567 { 10568 PetscFunctionBegin; 10569 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10570 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10571 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10572 10573 PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10574 PetscFunctionReturn(0); 10575 } 10576 10577 /*@C 10578 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10579 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10580 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10581 Csp from Cden. 10582 10583 Collective 10584 10585 Input Parameters: 10586 + coloring - coloring context created with `MatTransposeColoringCreate()` 10587 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10588 10589 Output Parameter: 10590 . Csp - sparse matrix 10591 10592 Level: developer 10593 10594 Note: 10595 These are used internally for some implementations of `MatRARt()` 10596 10597 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10598 10599 @*/ 10600 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10601 { 10602 PetscFunctionBegin; 10603 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10604 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10605 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10606 10607 PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10608 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10609 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10610 PetscFunctionReturn(0); 10611 } 10612 10613 /*@C 10614 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10615 10616 Collective 10617 10618 Input Parameters: 10619 + mat - the matrix product C 10620 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10621 10622 Output Parameter: 10623 . color - the new coloring context 10624 10625 Level: intermediate 10626 10627 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10628 `MatTransColoringApplyDenToSp()` 10629 @*/ 10630 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10631 { 10632 MatTransposeColoring c; 10633 MPI_Comm comm; 10634 10635 PetscFunctionBegin; 10636 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10637 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10638 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10639 10640 c->ctype = iscoloring->ctype; 10641 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10642 10643 *color = c; 10644 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10645 PetscFunctionReturn(0); 10646 } 10647 10648 /*@ 10649 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10650 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10651 same, otherwise it will be larger 10652 10653 Not Collective 10654 10655 Input Parameter: 10656 . A - the matrix 10657 10658 Output Parameter: 10659 . state - the current state 10660 10661 Notes: 10662 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10663 different matrices 10664 10665 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10666 10667 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10668 10669 Level: intermediate 10670 10671 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()` 10672 @*/ 10673 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10674 { 10675 PetscFunctionBegin; 10676 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10677 *state = mat->nonzerostate; 10678 PetscFunctionReturn(0); 10679 } 10680 10681 /*@ 10682 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10683 matrices from each processor 10684 10685 Collective 10686 10687 Input Parameters: 10688 + comm - the communicators the parallel matrix will live on 10689 . seqmat - the input sequential matrices 10690 . n - number of local columns (or `PETSC_DECIDE`) 10691 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10692 10693 Output Parameter: 10694 . mpimat - the parallel matrix generated 10695 10696 Level: developer 10697 10698 Note: 10699 The number of columns of the matrix in EACH processor MUST be the same. 10700 10701 .seealso: `Mat` 10702 @*/ 10703 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10704 { 10705 PetscMPIInt size; 10706 10707 PetscFunctionBegin; 10708 PetscCallMPI(MPI_Comm_size(comm, &size)); 10709 if (size == 1) { 10710 if (reuse == MAT_INITIAL_MATRIX) { 10711 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10712 } else { 10713 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10714 } 10715 PetscFunctionReturn(0); 10716 } 10717 10718 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"); 10719 10720 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10721 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10722 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10723 PetscFunctionReturn(0); 10724 } 10725 10726 /*@ 10727 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10728 10729 Collective on A 10730 10731 Input Parameters: 10732 + A - the matrix to create subdomains from 10733 - N - requested number of subdomains 10734 10735 Output Parameters: 10736 + n - number of subdomains resulting on this rank 10737 - iss - `IS` list with indices of subdomains on this rank 10738 10739 Level: advanced 10740 10741 Note: 10742 The number of subdomains must be smaller than the communicator size 10743 10744 .seealso: `Mat`, `IS` 10745 @*/ 10746 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10747 { 10748 MPI_Comm comm, subcomm; 10749 PetscMPIInt size, rank, color; 10750 PetscInt rstart, rend, k; 10751 10752 PetscFunctionBegin; 10753 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10754 PetscCallMPI(MPI_Comm_size(comm, &size)); 10755 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10756 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); 10757 *n = 1; 10758 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10759 color = rank / k; 10760 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10761 PetscCall(PetscMalloc1(1, iss)); 10762 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10763 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10764 PetscCallMPI(MPI_Comm_free(&subcomm)); 10765 PetscFunctionReturn(0); 10766 } 10767 10768 /*@ 10769 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10770 10771 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10772 If they are not the same, uses `MatMatMatMult()`. 10773 10774 Once the coarse grid problem is constructed, correct for interpolation operators 10775 that are not of full rank, which can legitimately happen in the case of non-nested 10776 geometric multigrid. 10777 10778 Input Parameters: 10779 + restrct - restriction operator 10780 . dA - fine grid matrix 10781 . interpolate - interpolation operator 10782 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10783 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10784 10785 Output Parameters: 10786 . A - the Galerkin coarse matrix 10787 10788 Options Database Key: 10789 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10790 10791 Level: developer 10792 10793 .seealso: `MatPtAP()`, `MatMatMatMult()` 10794 @*/ 10795 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10796 { 10797 IS zerorows; 10798 Vec diag; 10799 10800 PetscFunctionBegin; 10801 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10802 /* Construct the coarse grid matrix */ 10803 if (interpolate == restrct) { 10804 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10805 } else { 10806 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10807 } 10808 10809 /* If the interpolation matrix is not of full rank, A will have zero rows. 10810 This can legitimately happen in the case of non-nested geometric multigrid. 10811 In that event, we set the rows of the matrix to the rows of the identity, 10812 ignoring the equations (as the RHS will also be zero). */ 10813 10814 PetscCall(MatFindZeroRows(*A, &zerorows)); 10815 10816 if (zerorows != NULL) { /* if there are any zero rows */ 10817 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10818 PetscCall(MatGetDiagonal(*A, diag)); 10819 PetscCall(VecISSet(diag, zerorows, 1.0)); 10820 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10821 PetscCall(VecDestroy(&diag)); 10822 PetscCall(ISDestroy(&zerorows)); 10823 } 10824 PetscFunctionReturn(0); 10825 } 10826 10827 /*@C 10828 MatSetOperation - Allows user to set a matrix operation for any matrix type 10829 10830 Logically Collective 10831 10832 Input Parameters: 10833 + mat - the matrix 10834 . op - the name of the operation 10835 - f - the function that provides the operation 10836 10837 Level: developer 10838 10839 Usage: 10840 $ extern PetscErrorCode usermult(Mat,Vec,Vec); 10841 $ PetscCall(MatCreateXXX(comm,...&A); 10842 $ PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult); 10843 10844 Notes: 10845 See the file include/petscmat.h for a complete list of matrix 10846 operations, which all have the form MATOP_<OPERATION>, where 10847 <OPERATION> is the name (in all capital letters) of the 10848 user interface routine (e.g., MatMult() -> MATOP_MULT). 10849 10850 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10851 sequence as the usual matrix interface routines, since they 10852 are intended to be accessed via the usual matrix interface 10853 routines, e.g., 10854 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 10855 10856 In particular each function MUST return an error code of 0 on success and 10857 nonzero on failure. 10858 10859 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10860 10861 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10862 @*/ 10863 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10864 { 10865 PetscFunctionBegin; 10866 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10867 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10868 (((void (**)(void))mat->ops)[op]) = f; 10869 PetscFunctionReturn(0); 10870 } 10871 10872 /*@C 10873 MatGetOperation - Gets a matrix operation for any matrix type. 10874 10875 Not Collective 10876 10877 Input Parameters: 10878 + mat - the matrix 10879 - op - the name of the operation 10880 10881 Output Parameter: 10882 . f - the function that provides the operation 10883 10884 Level: developer 10885 10886 Usage: 10887 $ PetscErrorCode (*usermult)(Mat,Vec,Vec); 10888 $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult); 10889 10890 Notes: 10891 See the file include/petscmat.h for a complete list of matrix 10892 operations, which all have the form MATOP_<OPERATION>, where 10893 <OPERATION> is the name (in all capital letters) of the 10894 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10895 10896 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 10897 10898 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 10899 @*/ 10900 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 10901 { 10902 PetscFunctionBegin; 10903 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10904 *f = (((void (**)(void))mat->ops)[op]); 10905 PetscFunctionReturn(0); 10906 } 10907 10908 /*@ 10909 MatHasOperation - Determines whether the given matrix supports the particular operation. 10910 10911 Not Collective 10912 10913 Input Parameters: 10914 + mat - the matrix 10915 - op - the operation, for example, `MATOP_GET_DIAGONAL` 10916 10917 Output Parameter: 10918 . has - either `PETSC_TRUE` or `PETSC_FALSE` 10919 10920 Level: advanced 10921 10922 Note: 10923 See the file include/petscmat.h for a complete list of matrix 10924 operations, which all have the form MATOP_<OPERATION>, where 10925 <OPERATION> is the name (in all capital letters) of the 10926 user-level routine. E.g., `MatNorm()` -> `MATOP_NORM`. 10927 10928 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 10929 @*/ 10930 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 10931 { 10932 PetscFunctionBegin; 10933 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10934 PetscValidBoolPointer(has, 3); 10935 if (mat->ops->hasoperation) { 10936 PetscUseTypeMethod(mat, hasoperation, op, has); 10937 } else { 10938 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 10939 else { 10940 *has = PETSC_FALSE; 10941 if (op == MATOP_CREATE_SUBMATRIX) { 10942 PetscMPIInt size; 10943 10944 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10945 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 10946 } 10947 } 10948 } 10949 PetscFunctionReturn(0); 10950 } 10951 10952 /*@ 10953 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 10954 10955 Collective 10956 10957 Input Parameters: 10958 . mat - the matrix 10959 10960 Output Parameter: 10961 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 10962 10963 Level: beginner 10964 10965 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout` 10966 @*/ 10967 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 10968 { 10969 PetscFunctionBegin; 10970 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10971 PetscValidType(mat, 1); 10972 PetscValidBoolPointer(cong, 2); 10973 if (!mat->rmap || !mat->cmap) { 10974 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 10975 PetscFunctionReturn(0); 10976 } 10977 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 10978 PetscCall(PetscLayoutSetUp(mat->rmap)); 10979 PetscCall(PetscLayoutSetUp(mat->cmap)); 10980 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 10981 if (*cong) mat->congruentlayouts = 1; 10982 else mat->congruentlayouts = 0; 10983 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 10984 PetscFunctionReturn(0); 10985 } 10986 10987 PetscErrorCode MatSetInf(Mat A) 10988 { 10989 PetscFunctionBegin; 10990 PetscUseTypeMethod(A, setinf); 10991 PetscFunctionReturn(0); 10992 } 10993 10994 /*@C 10995 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 10996 and possibly removes small values from the graph structure. 10997 10998 Collective 10999 11000 Input Parameters: 11001 + A - the matrix 11002 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11003 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11004 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11005 11006 Output Parameter: 11007 . graph - the resulting graph 11008 11009 Level: advanced 11010 11011 .seealso: `MatCreate()`, `PCGAMG` 11012 @*/ 11013 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11014 { 11015 PetscFunctionBegin; 11016 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11017 PetscValidType(A, 1); 11018 PetscValidLogicalCollectiveBool(A, scale, 3); 11019 PetscValidPointer(graph, 5); 11020 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11021 PetscFunctionReturn(0); 11022 } 11023 11024 /*@ 11025 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11026 meaning the same memory is used for the matrix, and no new memory is allocated. 11027 11028 Collective on mat 11029 11030 Input Parameter: 11031 . A - the matrix 11032 11033 Output Parameter: 11034 . A - the matrix 11035 11036 Level: intermediate 11037 11038 .seealso: `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11039 @*/ 11040 PetscErrorCode MatEliminateZeros(Mat A) 11041 { 11042 PetscFunctionBegin; 11043 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11044 PetscUseTypeMethod(A, eliminatezeros); 11045 PetscFunctionReturn(0); 11046 } 11047