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