1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure; 36 PetscLogEvent MAT_GetMultiProcBlock; 37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 52 for sparse matrices that already have locations it fills the locations with random numbers 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and 59 it will create one internally. 60 61 Output Parameter: 62 . x - the matrix 63 64 Example of Usage: 65 .vb 66 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 67 MatSetRandom(x,rctx); 68 PetscRandomDestroy(rctx); 69 .ve 70 71 Level: intermediate 72 73 .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 74 @*/ 75 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 76 { 77 PetscRandom randObj = NULL; 78 79 PetscFunctionBegin; 80 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 81 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 82 PetscValidType(x, 1); 83 MatCheckPreallocated(x, 1); 84 85 if (!rctx) { 86 MPI_Comm comm; 87 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 88 PetscCall(PetscRandomCreate(comm, &randObj)); 89 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 90 PetscCall(PetscRandomSetFromOptions(randObj)); 91 rctx = randObj; 92 } 93 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 94 PetscUseTypeMethod(x, setrandom, rctx); 95 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 96 97 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 98 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 99 PetscCall(PetscRandomDestroy(&randObj)); 100 PetscFunctionReturn(0); 101 } 102 103 /*@ 104 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 105 106 Logically Collective 107 108 Input Parameter: 109 . mat - the factored matrix 110 111 Output Parameters: 112 + pivot - the pivot value computed 113 - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes 114 the share the matrix 115 116 Level: advanced 117 118 Notes: 119 This routine does not work for factorizations done with external packages. 120 121 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 122 123 This can be called on non-factored matrices that come from, for example, matrices used in SOR. 124 125 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 126 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 127 @*/ 128 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 129 { 130 PetscFunctionBegin; 131 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 132 PetscValidRealPointer(pivot, 2); 133 PetscValidIntPointer(row, 3); 134 *pivot = mat->factorerror_zeropivot_value; 135 *row = mat->factorerror_zeropivot_row; 136 PetscFunctionReturn(0); 137 } 138 139 /*@ 140 MatFactorGetError - gets the error code from a factorization 141 142 Logically Collective 143 144 Input Parameters: 145 . mat - the factored matrix 146 147 Output Parameter: 148 . err - the error code 149 150 Level: advanced 151 152 Note: 153 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 154 155 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 156 `MatFactorError` 157 @*/ 158 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 159 { 160 PetscFunctionBegin; 161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 162 PetscValidPointer(err, 2); 163 *err = mat->factorerrortype; 164 PetscFunctionReturn(0); 165 } 166 167 /*@ 168 MatFactorClearError - clears the error code in a factorization 169 170 Logically Collective 171 172 Input Parameter: 173 . mat - the factored matrix 174 175 Level: developer 176 177 Note: 178 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 179 180 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 181 `MatGetErrorCode()`, `MatFactorError` 182 @*/ 183 PetscErrorCode MatFactorClearError(Mat mat) 184 { 185 PetscFunctionBegin; 186 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 187 mat->factorerrortype = MAT_FACTOR_NOERROR; 188 mat->factorerror_zeropivot_value = 0.0; 189 mat->factorerror_zeropivot_row = 0; 190 PetscFunctionReturn(0); 191 } 192 193 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 194 { 195 Vec r, l; 196 const PetscScalar *al; 197 PetscInt i, nz, gnz, N, n; 198 199 PetscFunctionBegin; 200 PetscCall(MatCreateVecs(mat, &r, &l)); 201 if (!cols) { /* nonzero rows */ 202 PetscCall(MatGetSize(mat, &N, NULL)); 203 PetscCall(MatGetLocalSize(mat, &n, NULL)); 204 PetscCall(VecSet(l, 0.0)); 205 PetscCall(VecSetRandom(r, NULL)); 206 PetscCall(MatMult(mat, r, l)); 207 PetscCall(VecGetArrayRead(l, &al)); 208 } else { /* nonzero columns */ 209 PetscCall(MatGetSize(mat, NULL, &N)); 210 PetscCall(MatGetLocalSize(mat, NULL, &n)); 211 PetscCall(VecSet(r, 0.0)); 212 PetscCall(VecSetRandom(l, NULL)); 213 PetscCall(MatMultTranspose(mat, l, r)); 214 PetscCall(VecGetArrayRead(r, &al)); 215 } 216 if (tol <= 0.0) { 217 for (i = 0, nz = 0; i < n; i++) 218 if (al[i] != 0.0) nz++; 219 } else { 220 for (i = 0, nz = 0; i < n; i++) 221 if (PetscAbsScalar(al[i]) > tol) nz++; 222 } 223 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 224 if (gnz != N) { 225 PetscInt *nzr; 226 PetscCall(PetscMalloc1(nz, &nzr)); 227 if (nz) { 228 if (tol < 0) { 229 for (i = 0, nz = 0; i < n; i++) 230 if (al[i] != 0.0) nzr[nz++] = i; 231 } else { 232 for (i = 0, nz = 0; i < n; i++) 233 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 234 } 235 } 236 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 237 } else *nonzero = NULL; 238 if (!cols) { /* nonzero rows */ 239 PetscCall(VecRestoreArrayRead(l, &al)); 240 } else { 241 PetscCall(VecRestoreArrayRead(r, &al)); 242 } 243 PetscCall(VecDestroy(&l)); 244 PetscCall(VecDestroy(&r)); 245 PetscFunctionReturn(0); 246 } 247 248 /*@ 249 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 250 251 Input Parameter: 252 . A - the matrix 253 254 Output Parameter: 255 . keptrows - the rows that are not completely zero 256 257 Note: 258 keptrows is set to NULL if all rows are nonzero. 259 260 Level: intermediate 261 262 .seealso: `Mat`, `MatFindZeroRows()` 263 @*/ 264 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 265 { 266 PetscFunctionBegin; 267 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 268 PetscValidType(mat, 1); 269 PetscValidPointer(keptrows, 2); 270 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 271 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 272 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 273 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 274 PetscFunctionReturn(0); 275 } 276 277 /*@ 278 MatFindZeroRows - Locate all rows that are completely zero in the matrix 279 280 Input Parameter: 281 . A - the matrix 282 283 Output Parameter: 284 . zerorows - the rows that are completely zero 285 286 Note: 287 zerorows is set to NULL if no rows are zero. 288 289 Level: intermediate 290 291 .seealso: `Mat`, `MatFindNonzeroRows()` 292 @*/ 293 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 294 { 295 IS keptrows; 296 PetscInt m, n; 297 298 PetscFunctionBegin; 299 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 300 PetscValidType(mat, 1); 301 PetscValidPointer(zerorows, 2); 302 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 303 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 304 In keeping with this convention, we set zerorows to NULL if there are no zero 305 rows. */ 306 if (keptrows == NULL) { 307 *zerorows = NULL; 308 } else { 309 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 310 PetscCall(ISComplement(keptrows, m, n, zerorows)); 311 PetscCall(ISDestroy(&keptrows)); 312 } 313 PetscFunctionReturn(0); 314 } 315 316 /*@ 317 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 318 319 Not Collective 320 321 Input Parameters: 322 . A - the matrix 323 324 Output Parameters: 325 . a - the diagonal part (which is a SEQUENTIAL matrix) 326 327 Notes: 328 See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 329 330 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation. 331 332 Level: advanced 333 334 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 335 @*/ 336 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 337 { 338 PetscFunctionBegin; 339 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 340 PetscValidType(A, 1); 341 PetscValidPointer(a, 2); 342 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 343 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 344 else { 345 PetscMPIInt size; 346 347 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 348 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 349 *a = A; 350 } 351 PetscFunctionReturn(0); 352 } 353 354 /*@ 355 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 356 357 Collective 358 359 Input Parameters: 360 . mat - the matrix 361 362 Output Parameter: 363 . trace - the sum of the diagonal entries 364 365 Level: advanced 366 367 .seealso: `Mat` 368 @*/ 369 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 370 { 371 Vec diag; 372 373 PetscFunctionBegin; 374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 375 PetscValidScalarPointer(trace, 2); 376 PetscCall(MatCreateVecs(mat, &diag, NULL)); 377 PetscCall(MatGetDiagonal(mat, diag)); 378 PetscCall(VecSum(diag, trace)); 379 PetscCall(VecDestroy(&diag)); 380 PetscFunctionReturn(0); 381 } 382 383 /*@ 384 MatRealPart - Zeros out the imaginary part of the matrix 385 386 Logically Collective 387 388 Input Parameters: 389 . mat - the matrix 390 391 Level: advanced 392 393 .seealso: `MatImaginaryPart()` 394 @*/ 395 PetscErrorCode MatRealPart(Mat mat) 396 { 397 PetscFunctionBegin; 398 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 399 PetscValidType(mat, 1); 400 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 401 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 402 MatCheckPreallocated(mat, 1); 403 PetscUseTypeMethod(mat, realpart); 404 PetscFunctionReturn(0); 405 } 406 407 /*@C 408 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 409 410 Collective 411 412 Input Parameter: 413 . mat - the matrix 414 415 Output Parameters: 416 + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 417 - ghosts - the global indices of the ghost points 418 419 Note: 420 the nghosts and ghosts are suitable to pass into `VecCreateGhost()` 421 422 Level: advanced 423 424 .seealso: `Mat`, `VecCreateGhost()` 425 @*/ 426 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 427 { 428 PetscFunctionBegin; 429 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 430 PetscValidType(mat, 1); 431 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 432 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 433 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 434 else { 435 if (nghosts) *nghosts = 0; 436 if (ghosts) *ghosts = NULL; 437 } 438 PetscFunctionReturn(0); 439 } 440 441 /*@ 442 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 443 444 Logically Collective 445 446 Input Parameters: 447 . mat - the matrix 448 449 Level: advanced 450 451 .seealso: `MatRealPart()` 452 @*/ 453 PetscErrorCode MatImaginaryPart(Mat mat) 454 { 455 PetscFunctionBegin; 456 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 457 PetscValidType(mat, 1); 458 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 459 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 460 MatCheckPreallocated(mat, 1); 461 PetscUseTypeMethod(mat, imaginarypart); 462 PetscFunctionReturn(0); 463 } 464 465 /*@ 466 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 467 468 Not Collective 469 470 Input Parameter: 471 . mat - the matrix 472 473 Output Parameters: 474 + missing - is any diagonal missing 475 - dd - first diagonal entry that is missing (optional) on this process 476 477 Level: advanced 478 479 .seealso: `Mat` 480 @*/ 481 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 482 { 483 PetscFunctionBegin; 484 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 485 PetscValidType(mat, 1); 486 PetscValidBoolPointer(missing, 2); 487 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 488 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 489 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 490 PetscFunctionReturn(0); 491 } 492 493 /*@C 494 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 495 for each row that you get to ensure that your application does 496 not bleed memory. 497 498 Not Collective 499 500 Input Parameters: 501 + mat - the matrix 502 - row - the row to get 503 504 Output Parameters: 505 + ncols - if not NULL, the number of nonzeros in the row 506 . cols - if not NULL, the column numbers 507 - vals - if not NULL, the values 508 509 Notes: 510 This routine is provided for people who need to have direct access 511 to the structure of a matrix. We hope that we provide enough 512 high-level matrix routines that few users will need it. 513 514 `MatGetRow()` always returns 0-based column indices, regardless of 515 whether the internal representation is 0-based (default) or 1-based. 516 517 For better efficiency, set cols and/or vals to NULL if you do 518 not wish to extract these quantities. 519 520 The user can only examine the values extracted with `MatGetRow()`; 521 the values cannot be altered. To change the matrix entries, one 522 must use `MatSetValues()`. 523 524 You can only have one call to `MatGetRow()` outstanding for a particular 525 matrix at a time, per processor. `MatGetRow()` can only obtain rows 526 associated with the given processor, it cannot get rows from the 527 other processors; for that we suggest using `MatCreateSubMatrices()`, then 528 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 529 is in the global number of rows. 530 531 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 532 533 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 534 535 Fortran Note: 536 The calling sequence from Fortran is 537 .vb 538 MatGetRow(matrix,row,ncols,cols,values,ierr) 539 Mat matrix (input) 540 integer row (input) 541 integer ncols (output) 542 integer cols(maxcols) (output) 543 double precision (or double complex) values(maxcols) output 544 .ve 545 where maxcols >= maximum nonzeros in any row of the matrix. 546 547 Caution: 548 Do not try to change the contents of the output arrays (cols and vals). 549 In some cases, this may corrupt the matrix. 550 551 Level: advanced 552 553 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 554 @*/ 555 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 556 { 557 PetscInt incols; 558 559 PetscFunctionBegin; 560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 561 PetscValidType(mat, 1); 562 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 563 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 564 MatCheckPreallocated(mat, 1); 565 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 566 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 567 PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals)); 568 if (ncols) *ncols = incols; 569 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 570 PetscFunctionReturn(0); 571 } 572 573 /*@ 574 MatConjugate - replaces the matrix values with their complex conjugates 575 576 Logically Collective 577 578 Input Parameters: 579 . mat - the matrix 580 581 Level: advanced 582 583 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 584 @*/ 585 PetscErrorCode MatConjugate(Mat mat) 586 { 587 PetscFunctionBegin; 588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 589 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 590 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 591 PetscUseTypeMethod(mat, conjugate); 592 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 593 } 594 PetscFunctionReturn(0); 595 } 596 597 /*@C 598 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 599 600 Not Collective 601 602 Input Parameters: 603 + mat - the matrix 604 . row - the row to get 605 . ncols, cols - the number of nonzeros and their columns 606 - vals - if nonzero the column values 607 608 Notes: 609 This routine should be called after you have finished examining the entries. 610 611 This routine zeros out ncols, cols, and vals. This is to prevent accidental 612 us of the array after it has been restored. If you pass NULL, it will 613 not zero the pointers. Use of cols or vals after `MatRestoreRow()` is invalid. 614 615 Fortran Notes: 616 The calling sequence from Fortran is 617 .vb 618 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 619 Mat matrix (input) 620 integer row (input) 621 integer ncols (output) 622 integer cols(maxcols) (output) 623 double precision (or double complex) values(maxcols) output 624 .ve 625 Where maxcols >= maximum nonzeros in any row of the matrix. 626 627 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 628 before another call to `MatGetRow()` can be made. 629 630 Level: advanced 631 632 .seealso: `MatGetRow()` 633 @*/ 634 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 635 { 636 PetscFunctionBegin; 637 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 638 if (ncols) PetscValidIntPointer(ncols, 3); 639 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 640 if (!mat->ops->restorerow) PetscFunctionReturn(0); 641 PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals)); 642 if (ncols) *ncols = 0; 643 if (cols) *cols = NULL; 644 if (vals) *vals = NULL; 645 PetscFunctionReturn(0); 646 } 647 648 /*@ 649 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 650 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 651 652 Not Collective 653 654 Input Parameters: 655 . mat - the matrix 656 657 Note: 658 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 659 660 Level: advanced 661 662 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 663 @*/ 664 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 665 { 666 PetscFunctionBegin; 667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 668 PetscValidType(mat, 1); 669 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 670 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 671 MatCheckPreallocated(mat, 1); 672 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0); 673 PetscUseTypeMethod(mat, getrowuppertriangular); 674 PetscFunctionReturn(0); 675 } 676 677 /*@ 678 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 679 680 Not Collective 681 682 Input Parameters: 683 . mat - the matrix 684 685 Note: 686 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 687 688 Level: advanced 689 690 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0); 701 PetscUseTypeMethod(mat, restorerowuppertriangular); 702 PetscFunctionReturn(0); 703 } 704 705 /*@C 706 MatSetOptionsPrefix - Sets the prefix used for searching for all 707 `Mat` options in the database. 708 709 Logically Collective on A 710 711 Input Parameters: 712 + A - the matrix 713 - prefix - the prefix to prepend to all option names 714 715 Notes: 716 A hyphen (-) must NOT be given at the beginning of the prefix name. 717 The first character of all runtime options is AUTOMATICALLY the hyphen. 718 719 This is NOT used for options for the factorization of the matrix. Normally the 720 prefix is automatically passed in from the PC calling the factorization. To set 721 it directly use `MatSetOptionsPrefixFactor()` 722 723 Level: advanced 724 725 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 726 @*/ 727 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 728 { 729 PetscFunctionBegin; 730 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 731 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 732 PetscFunctionReturn(0); 733 } 734 735 /*@C 736 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 737 for matrices created with `MatGetFactor()` 738 739 Logically Collective on A 740 741 Input Parameters: 742 + A - the matrix 743 - prefix - the prefix to prepend to all option names for the factored matrix 744 745 Notes: 746 A hyphen (-) must NOT be given at the beginning of the prefix name. 747 The first character of all runtime options is AUTOMATICALLY the hyphen. 748 749 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 750 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 751 752 Level: developer 753 754 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 755 @*/ 756 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 757 { 758 PetscFunctionBegin; 759 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 760 if (prefix) { 761 PetscValidCharPointer(prefix, 2); 762 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 763 if (prefix != A->factorprefix) { 764 PetscCall(PetscFree(A->factorprefix)); 765 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 766 } 767 } else PetscCall(PetscFree(A->factorprefix)); 768 PetscFunctionReturn(0); 769 } 770 771 /*@C 772 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 773 for matrices created with `MatGetFactor()` 774 775 Logically Collective on A 776 777 Input Parameters: 778 + A - the matrix 779 - prefix - the prefix to prepend to all option names for the factored matrix 780 781 Notes: 782 A hyphen (-) must NOT be given at the beginning of the prefix name. 783 The first character of all runtime options is AUTOMATICALLY the hyphen. 784 785 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 786 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 787 788 Level: developer 789 790 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 791 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 792 `MatSetOptionsPrefix()` 793 @*/ 794 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 795 { 796 char *buf = A->factorprefix; 797 size_t len1, len2; 798 799 PetscFunctionBegin; 800 PetscValidHeader(A, 1); 801 if (!prefix) PetscFunctionReturn(0); 802 if (!buf) { 803 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 804 PetscFunctionReturn(0); 805 } 806 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 807 808 PetscCall(PetscStrlen(prefix, &len1)); 809 PetscCall(PetscStrlen(buf, &len2)); 810 PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix)); 811 PetscCall(PetscStrcpy(A->factorprefix, buf)); 812 PetscCall(PetscStrcat(A->factorprefix, prefix)); 813 PetscCall(PetscFree(buf)); 814 PetscFunctionReturn(0); 815 } 816 817 /*@C 818 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 819 matrix options in the database. 820 821 Logically Collective on A 822 823 Input Parameters: 824 + A - the matrix 825 - prefix - the prefix to prepend to all option names 826 827 Note: 828 A hyphen (-) must NOT be given at the beginning of the prefix name. 829 The first character of all runtime options is AUTOMATICALLY the hyphen. 830 831 Level: advanced 832 833 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 834 @*/ 835 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 836 { 837 PetscFunctionBegin; 838 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 839 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 840 PetscFunctionReturn(0); 841 } 842 843 /*@C 844 MatGetOptionsPrefix - Gets the prefix used for searching for all 845 matrix options in the database. 846 847 Not Collective 848 849 Input Parameter: 850 . A - the matrix 851 852 Output Parameter: 853 . prefix - pointer to the prefix string used 854 855 Level: advanced 856 857 Fortran Note: 858 On the fortran side, the user should pass in a string 'prefix' of 859 sufficient length to hold the prefix. 860 861 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 862 @*/ 863 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 864 { 865 PetscFunctionBegin; 866 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 867 PetscValidPointer(prefix, 2); 868 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 869 PetscFunctionReturn(0); 870 } 871 872 /*@ 873 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 874 875 Collective on A 876 877 Input Parameters: 878 . A - the matrix 879 880 Notes: 881 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 882 883 Users can reset the preallocation to access the original memory. 884 885 Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices. 886 887 Level: beginner 888 889 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 890 @*/ 891 PetscErrorCode MatResetPreallocation(Mat A) 892 { 893 PetscFunctionBegin; 894 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 895 PetscValidType(A, 1); 896 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 897 PetscFunctionReturn(0); 898 } 899 900 /*@ 901 MatSetUp - Sets up the internal matrix data structures for later use. 902 903 Collective on A 904 905 Input Parameters: 906 . A - the matrix 907 908 Notes: 909 If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used. 910 911 If a suitable preallocation routine is used, this function does not need to be called. 912 913 See the Performance chapter of the PETSc users manual for how to preallocate matrices 914 915 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 916 917 Level: intermediate 918 919 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()` 920 @*/ 921 PetscErrorCode MatSetUp(Mat A) 922 { 923 PetscFunctionBegin; 924 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 925 if (!((PetscObject)A)->type_name) { 926 PetscMPIInt size; 927 928 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 929 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 930 } 931 if (!A->preallocated && A->ops->setup) { 932 PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n")); 933 PetscUseTypeMethod(A, setup); 934 } 935 PetscCall(PetscLayoutSetUp(A->rmap)); 936 PetscCall(PetscLayoutSetUp(A->cmap)); 937 A->preallocated = PETSC_TRUE; 938 PetscFunctionReturn(0); 939 } 940 941 #if defined(PETSC_HAVE_SAWS) 942 #include <petscviewersaws.h> 943 #endif 944 945 /*@C 946 MatViewFromOptions - View properties of the matrix from the options database 947 948 Collective on A 949 950 Input Parameters: 951 + A - the matrix 952 . obj - optional additional object that provides the options prefix to use 953 - name - command line option 954 955 Options Database Key: 956 . -mat_view [viewertype]:... - the viewer and its options 957 958 Notes: 959 .vb 960 If no value is provided ascii:stdout is used 961 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 962 for example ascii::ascii_info prints just the information about the object not all details 963 unless :append is given filename opens in write mode, overwriting what was already there 964 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 965 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 966 socket[:port] defaults to the standard output port 967 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 968 .ve 969 970 Level: intermediate 971 972 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 973 @*/ 974 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 975 { 976 PetscFunctionBegin; 977 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 978 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 979 PetscFunctionReturn(0); 980 } 981 982 /*@C 983 MatView - display information about a matrix in a variety ways 984 985 Collective 986 987 Input Parameters: 988 + mat - the matrix 989 - viewer - visualization context 990 991 Notes: 992 The available visualization contexts include 993 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 994 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 995 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 996 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 997 998 The user can open alternative visualization contexts with 999 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1000 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1001 specified file; corresponding input uses MatLoad() 1002 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1003 an X window display 1004 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1005 Currently only the sequential dense and AIJ 1006 matrix types support the Socket viewer. 1007 1008 The user can call `PetscViewerPushFormat()` to specify the output 1009 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1010 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1011 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1012 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1013 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1014 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1015 format common among all matrix types 1016 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1017 format (which is in many cases the same as the default) 1018 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1019 size and structure (not the matrix entries) 1020 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1021 the matrix structure 1022 1023 Options Database Keys: 1024 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1025 . -mat_view ::ascii_info_detail - Prints more detailed info 1026 . -mat_view - Prints matrix in ASCII format 1027 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1028 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1029 . -display <name> - Sets display name (default is host) 1030 . -draw_pause <sec> - Sets number of seconds to pause after display 1031 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1032 . -viewer_socket_machine <machine> - 1033 . -viewer_socket_port <port> - 1034 . -mat_view binary - save matrix to file in binary format 1035 - -viewer_binary_filename <name> - 1036 1037 Level: beginner 1038 1039 Notes: 1040 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1041 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1042 1043 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1044 1045 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1046 viewer is used. 1047 1048 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1049 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1050 1051 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1052 and then use the following mouse functions. 1053 .vb 1054 left mouse: zoom in 1055 middle mouse: zoom out 1056 right mouse: continue with the simulation 1057 .ve 1058 1059 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`, 1060 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1061 @*/ 1062 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1063 { 1064 PetscInt rows, cols, rbs, cbs; 1065 PetscBool isascii, isstring, issaws; 1066 PetscViewerFormat format; 1067 PetscMPIInt size; 1068 1069 PetscFunctionBegin; 1070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1071 PetscValidType(mat, 1); 1072 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1073 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1074 PetscCheckSameComm(mat, 1, viewer, 2); 1075 1076 PetscCall(PetscViewerGetFormat(viewer, &format)); 1077 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1078 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0); 1079 1080 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1081 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1082 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1083 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1084 1085 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1086 if (isascii) { 1087 if (!mat->preallocated) { 1088 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1089 PetscFunctionReturn(0); 1090 } 1091 if (!mat->assembled) { 1092 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1093 PetscFunctionReturn(0); 1094 } 1095 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1096 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1097 MatNullSpace nullsp, transnullsp; 1098 1099 PetscCall(PetscViewerASCIIPushTab(viewer)); 1100 PetscCall(MatGetSize(mat, &rows, &cols)); 1101 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1102 if (rbs != 1 || cbs != 1) { 1103 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1104 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1105 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1106 if (mat->factortype) { 1107 MatSolverType solver; 1108 PetscCall(MatFactorGetSolverType(mat, &solver)); 1109 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1110 } 1111 if (mat->ops->getinfo) { 1112 MatInfo info; 1113 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1114 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1115 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1116 } 1117 PetscCall(MatGetNullSpace(mat, &nullsp)); 1118 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1119 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1120 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1121 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1122 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1123 PetscCall(PetscViewerASCIIPushTab(viewer)); 1124 PetscCall(MatProductView(mat, viewer)); 1125 PetscCall(PetscViewerASCIIPopTab(viewer)); 1126 } 1127 } else if (issaws) { 1128 #if defined(PETSC_HAVE_SAWS) 1129 PetscMPIInt rank; 1130 1131 PetscCall(PetscObjectName((PetscObject)mat)); 1132 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1133 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1134 #endif 1135 } else if (isstring) { 1136 const char *type; 1137 PetscCall(MatGetType(mat, &type)); 1138 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1139 PetscTryTypeMethod(mat, view, viewer); 1140 } 1141 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1142 PetscCall(PetscViewerASCIIPushTab(viewer)); 1143 PetscUseTypeMethod(mat, viewnative, viewer); 1144 PetscCall(PetscViewerASCIIPopTab(viewer)); 1145 } else if (mat->ops->view) { 1146 PetscCall(PetscViewerASCIIPushTab(viewer)); 1147 PetscUseTypeMethod(mat, view, viewer); 1148 PetscCall(PetscViewerASCIIPopTab(viewer)); 1149 } 1150 if (isascii) { 1151 PetscCall(PetscViewerGetFormat(viewer, &format)); 1152 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1153 } 1154 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1155 PetscFunctionReturn(0); 1156 } 1157 1158 #if defined(PETSC_USE_DEBUG) 1159 #include <../src/sys/totalview/tv_data_display.h> 1160 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1161 { 1162 TV_add_row("Local rows", "int", &mat->rmap->n); 1163 TV_add_row("Local columns", "int", &mat->cmap->n); 1164 TV_add_row("Global rows", "int", &mat->rmap->N); 1165 TV_add_row("Global columns", "int", &mat->cmap->N); 1166 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1167 return TV_format_OK; 1168 } 1169 #endif 1170 1171 /*@C 1172 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1173 with `MatView()`. The matrix format is determined from the options database. 1174 Generates a parallel MPI matrix if the communicator has more than one 1175 processor. The default matrix type is `MATAIJ`. 1176 1177 Collective 1178 1179 Input Parameters: 1180 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1181 or some related function before a call to `MatLoad()` 1182 - viewer - binary/HDF5 file viewer 1183 1184 Options Database Keys: 1185 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1186 block size 1187 . -matload_block_size <bs> - set block size 1188 1189 Level: beginner 1190 1191 Notes: 1192 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1193 `Mat` before calling this routine if you wish to set it from the options database. 1194 1195 `MatLoad()` automatically loads into the options database any options 1196 given in the file filename.info where filename is the name of the file 1197 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1198 file will be ignored if you use the -viewer_binary_skip_info option. 1199 1200 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1201 sets the default matrix type AIJ and sets the local and global sizes. 1202 If type and/or size is already set, then the same are used. 1203 1204 In parallel, each processor can load a subset of rows (or the 1205 entire matrix). This routine is especially useful when a large 1206 matrix is stored on disk and only part of it is desired on each 1207 processor. For example, a parallel solver may access only some of 1208 the rows from each processor. The algorithm used here reads 1209 relatively small blocks of data rather than reading the entire 1210 matrix and then subsetting it. 1211 1212 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1213 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1214 or the sequence like 1215 .vb 1216 `PetscViewer` v; 1217 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1218 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1219 `PetscViewerSetFromOptions`(v); 1220 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1221 `PetscViewerFileSetName`(v,"datafile"); 1222 .ve 1223 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1224 $ -viewer_type {binary,hdf5} 1225 1226 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1227 and src/mat/tutorials/ex10.c with the second approach. 1228 1229 Notes about the PETSc binary format: 1230 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1231 is read onto rank 0 and then shipped to its destination rank, one after another. 1232 Multiple objects, both matrices and vectors, can be stored within the same file. 1233 Their PetscObject name is ignored; they are loaded in the order of their storage. 1234 1235 Most users should not need to know the details of the binary storage 1236 format, since `MatLoad()` and `MatView()` completely hide these details. 1237 But for anyone who's interested, the standard binary matrix storage 1238 format is 1239 1240 $ PetscInt MAT_FILE_CLASSID 1241 $ PetscInt number of rows 1242 $ PetscInt number of columns 1243 $ PetscInt total number of nonzeros 1244 $ PetscInt *number nonzeros in each row 1245 $ PetscInt *column indices of all nonzeros (starting index is zero) 1246 $ PetscScalar *values of all nonzeros 1247 1248 PETSc automatically does the byte swapping for 1249 machines that store the bytes reversed, e.g. DEC alpha, freebsd, 1250 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary 1251 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1252 and `PetscBinaryWrite()` to see how this may be done. 1253 1254 Notes about the HDF5 (MATLAB MAT-File Version 7.3) format: 1255 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1256 Each processor's chunk is loaded independently by its owning rank. 1257 Multiple objects, both matrices and vectors, can be stored within the same file. 1258 They are looked up by their PetscObject name. 1259 1260 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1261 by default the same structure and naming of the AIJ arrays and column count 1262 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1263 $ save example.mat A b -v7.3 1264 can be directly read by this routine (see Reference 1 for details). 1265 Note that depending on your MATLAB version, this format might be a default, 1266 otherwise you can set it as default in Preferences. 1267 1268 Unless -nocompression flag is used to save the file in MATLAB, 1269 PETSc must be configured with ZLIB package. 1270 1271 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1272 1273 Current HDF5 (MAT-File) limitations: 1274 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices. 1275 1276 Corresponding `MatView()` is not yet implemented. 1277 1278 The loaded matrix is actually a transpose of the original one in MATLAB, 1279 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1280 With this format, matrix is automatically transposed by PETSc, 1281 unless the matrix is marked as SPD or symmetric 1282 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1283 1284 References: 1285 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1286 1287 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1288 @*/ 1289 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1290 { 1291 PetscBool flg; 1292 1293 PetscFunctionBegin; 1294 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1295 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1296 1297 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1298 1299 flg = PETSC_FALSE; 1300 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1301 if (flg) { 1302 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1303 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1304 } 1305 flg = PETSC_FALSE; 1306 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1307 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1308 1309 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1310 PetscUseTypeMethod(mat, load, viewer); 1311 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1312 PetscFunctionReturn(0); 1313 } 1314 1315 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1316 { 1317 Mat_Redundant *redund = *redundant; 1318 1319 PetscFunctionBegin; 1320 if (redund) { 1321 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1322 PetscCall(ISDestroy(&redund->isrow)); 1323 PetscCall(ISDestroy(&redund->iscol)); 1324 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1325 } else { 1326 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1327 PetscCall(PetscFree(redund->sbuf_j)); 1328 PetscCall(PetscFree(redund->sbuf_a)); 1329 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1330 PetscCall(PetscFree(redund->rbuf_j[i])); 1331 PetscCall(PetscFree(redund->rbuf_a[i])); 1332 } 1333 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1334 } 1335 1336 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1337 PetscCall(PetscFree(redund)); 1338 } 1339 PetscFunctionReturn(0); 1340 } 1341 1342 /*@C 1343 MatDestroy - Frees space taken by a matrix. 1344 1345 Collective on A 1346 1347 Input Parameter: 1348 . A - the matrix 1349 1350 Level: beginner 1351 1352 Developer Note: 1353 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1354 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1355 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1356 if changes are needed here. 1357 1358 .seealso: `Mat`, `MatCreate()` 1359 @*/ 1360 PetscErrorCode MatDestroy(Mat *A) 1361 { 1362 PetscFunctionBegin; 1363 if (!*A) PetscFunctionReturn(0); 1364 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1365 if (--((PetscObject)(*A))->refct > 0) { 1366 *A = NULL; 1367 PetscFunctionReturn(0); 1368 } 1369 1370 /* if memory was published with SAWs then destroy it */ 1371 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1372 PetscTryTypeMethod((*A), destroy); 1373 1374 PetscCall(PetscFree((*A)->factorprefix)); 1375 PetscCall(PetscFree((*A)->defaultvectype)); 1376 PetscCall(PetscFree((*A)->defaultrandtype)); 1377 PetscCall(PetscFree((*A)->bsizes)); 1378 PetscCall(PetscFree((*A)->solvertype)); 1379 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1380 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1381 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1382 PetscCall(MatProductClear(*A)); 1383 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1384 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1385 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1386 PetscCall(MatDestroy(&(*A)->schur)); 1387 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1388 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1389 PetscCall(PetscHeaderDestroy(A)); 1390 PetscFunctionReturn(0); 1391 } 1392 1393 /*@C 1394 MatSetValues - Inserts or adds a block of values into a matrix. 1395 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1396 MUST be called after all calls to `MatSetValues()` have been completed. 1397 1398 Not Collective 1399 1400 Input Parameters: 1401 + mat - the matrix 1402 . v - a logically two-dimensional array of values 1403 . m, idxm - the number of rows and their global indices 1404 . n, idxn - the number of columns and their global indices 1405 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1406 1407 Notes: 1408 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1409 `MatSetUp()` before using this routine 1410 1411 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1412 1413 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1414 options cannot be mixed without intervening calls to the assembly 1415 routines. 1416 1417 `MatSetValues()` uses 0-based row and column numbers in Fortran 1418 as well as in C. 1419 1420 Negative indices may be passed in idxm and idxn, these rows and columns are 1421 simply ignored. This allows easily inserting element stiffness matrices 1422 with homogeneous Dirchlet boundary conditions that you don't want represented 1423 in the matrix. 1424 1425 Efficiency Alert: 1426 The routine `MatSetValuesBlocked()` may offer much better efficiency 1427 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1428 1429 Level: beginner 1430 1431 Developer Note: 1432 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1433 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1434 1435 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1436 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1437 @*/ 1438 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1439 { 1440 PetscFunctionBeginHot; 1441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1442 PetscValidType(mat, 1); 1443 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1444 PetscValidIntPointer(idxm, 3); 1445 PetscValidIntPointer(idxn, 5); 1446 MatCheckPreallocated(mat, 1); 1447 1448 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1449 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1450 1451 if (PetscDefined(USE_DEBUG)) { 1452 PetscInt i, j; 1453 1454 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1455 for (i = 0; i < m; i++) { 1456 for (j = 0; j < n; j++) { 1457 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1458 #if defined(PETSC_USE_COMPLEX) 1459 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1460 #else 1461 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1462 #endif 1463 } 1464 } 1465 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1466 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1467 } 1468 1469 if (mat->assembled) { 1470 mat->was_assembled = PETSC_TRUE; 1471 mat->assembled = PETSC_FALSE; 1472 } 1473 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1474 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1475 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1476 PetscFunctionReturn(0); 1477 } 1478 1479 /*@C 1480 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1481 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1482 MUST be called after all calls to `MatSetValues()` have been completed. 1483 1484 Not Collective 1485 1486 Input Parameters: 1487 + mat - the matrix 1488 . v - a logically two-dimensional array of values 1489 . ism - the rows to provide 1490 . isn - the columns to provide 1491 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1492 1493 Level: beginner 1494 1495 Notes: 1496 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1497 `MatSetUp()` before using this routine 1498 1499 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1500 1501 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1502 options cannot be mixed without intervening calls to the assembly 1503 routines. 1504 1505 `MatSetValues()` uses 0-based row and column numbers in Fortran 1506 as well as in C. 1507 1508 Negative indices may be passed in ism and isn, these rows and columns are 1509 simply ignored. This allows easily inserting element stiffness matrices 1510 with homogeneous Dirchlet boundary conditions that you don't want represented 1511 in the matrix. 1512 1513 Efficiency Alert: 1514 The routine `MatSetValuesBlocked()` may offer much better efficiency 1515 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1516 1517 This is currently not optimized for any particular `ISType` 1518 1519 Developer Notes: 1520 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1521 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1522 1523 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1524 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1525 @*/ 1526 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1527 { 1528 PetscInt m, n; 1529 const PetscInt *rows, *cols; 1530 1531 PetscFunctionBeginHot; 1532 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1533 PetscCall(ISGetIndices(ism, &rows)); 1534 PetscCall(ISGetIndices(isn, &cols)); 1535 PetscCall(ISGetLocalSize(ism, &m)); 1536 PetscCall(ISGetLocalSize(isn, &n)); 1537 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1538 PetscCall(ISRestoreIndices(ism, &rows)); 1539 PetscCall(ISRestoreIndices(isn, &cols)); 1540 PetscFunctionReturn(0); 1541 } 1542 1543 /*@ 1544 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1545 values into a matrix 1546 1547 Not Collective 1548 1549 Input Parameters: 1550 + mat - the matrix 1551 . row - the (block) row to set 1552 - v - a logically two-dimensional array of values 1553 1554 Notes: 1555 By the values, v, are column-oriented (for the block version) and sorted 1556 1557 All the nonzeros in the row must be provided 1558 1559 The matrix must have previously had its column indices set 1560 1561 The row must belong to this process 1562 1563 Level: intermediate 1564 1565 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1566 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1567 @*/ 1568 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1569 { 1570 PetscInt globalrow; 1571 1572 PetscFunctionBegin; 1573 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1574 PetscValidType(mat, 1); 1575 PetscValidScalarPointer(v, 3); 1576 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1577 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1578 PetscFunctionReturn(0); 1579 } 1580 1581 /*@ 1582 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1583 values into a matrix 1584 1585 Not Collective 1586 1587 Input Parameters: 1588 + mat - the matrix 1589 . row - the (block) row to set 1590 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1591 1592 Notes: 1593 The values, v, are column-oriented for the block version. 1594 1595 All the nonzeros in the row must be provided 1596 1597 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1598 1599 The row must belong to this process 1600 1601 Level: advanced 1602 1603 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1604 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1605 @*/ 1606 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1607 { 1608 PetscFunctionBeginHot; 1609 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1610 PetscValidType(mat, 1); 1611 MatCheckPreallocated(mat, 1); 1612 PetscValidScalarPointer(v, 3); 1613 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1614 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1615 mat->insertmode = INSERT_VALUES; 1616 1617 if (mat->assembled) { 1618 mat->was_assembled = PETSC_TRUE; 1619 mat->assembled = PETSC_FALSE; 1620 } 1621 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1622 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1623 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1624 PetscFunctionReturn(0); 1625 } 1626 1627 /*@ 1628 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1629 Using structured grid indexing 1630 1631 Not Collective 1632 1633 Input Parameters: 1634 + mat - the matrix 1635 . m - number of rows being entered 1636 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1637 . n - number of columns being entered 1638 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1639 . v - a logically two-dimensional array of values 1640 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1641 1642 Level: beginner 1643 1644 Notes: 1645 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1646 1647 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1648 options cannot be mixed without intervening calls to the assembly 1649 routines. 1650 1651 The grid coordinates are across the entire grid, not just the local portion 1652 1653 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1654 as well as in C. 1655 1656 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1657 1658 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1659 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1660 1661 The columns and rows in the stencil passed in MUST be contained within the 1662 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1663 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1664 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1665 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1666 1667 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1668 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1669 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1670 `DM_BOUNDARY_PERIODIC` boundary type. 1671 1672 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1673 a single value per point) you can skip filling those indices. 1674 1675 Inspired by the structured grid interface to the HYPRE package 1676 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1677 1678 Efficiency Alert: 1679 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1680 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1681 1682 Fortran Note: 1683 In Fortran idxm and idxn should be declared as 1684 $ MatStencil idxm(4,m),idxn(4,n) 1685 and the values inserted using 1686 .vb 1687 idxm(MatStencil_i,1) = i 1688 idxm(MatStencil_j,1) = j 1689 idxm(MatStencil_k,1) = k 1690 idxm(MatStencil_c,1) = c 1691 etc 1692 .ve 1693 1694 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1695 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1696 @*/ 1697 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1698 { 1699 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1700 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1701 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1702 1703 PetscFunctionBegin; 1704 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1705 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1706 PetscValidType(mat, 1); 1707 PetscValidPointer(idxm, 3); 1708 PetscValidPointer(idxn, 5); 1709 1710 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1711 jdxm = buf; 1712 jdxn = buf + m; 1713 } else { 1714 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1715 jdxm = bufm; 1716 jdxn = bufn; 1717 } 1718 for (i = 0; i < m; i++) { 1719 for (j = 0; j < 3 - sdim; j++) dxm++; 1720 tmp = *dxm++ - starts[0]; 1721 for (j = 0; j < dim - 1; j++) { 1722 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1723 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1724 } 1725 if (mat->stencil.noc) dxm++; 1726 jdxm[i] = tmp; 1727 } 1728 for (i = 0; i < n; i++) { 1729 for (j = 0; j < 3 - sdim; j++) dxn++; 1730 tmp = *dxn++ - starts[0]; 1731 for (j = 0; j < dim - 1; j++) { 1732 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1733 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1734 } 1735 if (mat->stencil.noc) dxn++; 1736 jdxn[i] = tmp; 1737 } 1738 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1739 PetscCall(PetscFree2(bufm, bufn)); 1740 PetscFunctionReturn(0); 1741 } 1742 1743 /*@ 1744 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1745 Using structured grid indexing 1746 1747 Not Collective 1748 1749 Input Parameters: 1750 + mat - the matrix 1751 . m - number of rows being entered 1752 . idxm - grid coordinates for matrix rows being entered 1753 . n - number of columns being entered 1754 . idxn - grid coordinates for matrix columns being entered 1755 . v - a logically two-dimensional array of values 1756 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1757 1758 Level: beginner 1759 1760 Notes: 1761 By default the values, v, are row-oriented and unsorted. 1762 See `MatSetOption()` for other options. 1763 1764 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1765 options cannot be mixed without intervening calls to the assembly 1766 routines. 1767 1768 The grid coordinates are across the entire grid, not just the local portion 1769 1770 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1771 as well as in C. 1772 1773 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1774 1775 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1776 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1777 1778 The columns and rows in the stencil passed in MUST be contained within the 1779 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1780 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1781 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1782 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1783 1784 Negative indices may be passed in idxm and idxn, these rows and columns are 1785 simply ignored. This allows easily inserting element stiffness matrices 1786 with homogeneous Dirchlet boundary conditions that you don't want represented 1787 in the matrix. 1788 1789 Inspired by the structured grid interface to the HYPRE package 1790 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1791 1792 Fortran Note: 1793 In Fortran idxm and idxn should be declared as 1794 $ MatStencil idxm(4,m),idxn(4,n) 1795 and the values inserted using 1796 .vb 1797 idxm(MatStencil_i,1) = i 1798 idxm(MatStencil_j,1) = j 1799 idxm(MatStencil_k,1) = k 1800 etc 1801 .ve 1802 1803 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1804 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1805 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1806 @*/ 1807 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1808 { 1809 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1810 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1811 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1812 1813 PetscFunctionBegin; 1814 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1815 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1816 PetscValidType(mat, 1); 1817 PetscValidPointer(idxm, 3); 1818 PetscValidPointer(idxn, 5); 1819 PetscValidScalarPointer(v, 6); 1820 1821 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1822 jdxm = buf; 1823 jdxn = buf + m; 1824 } else { 1825 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1826 jdxm = bufm; 1827 jdxn = bufn; 1828 } 1829 for (i = 0; i < m; i++) { 1830 for (j = 0; j < 3 - sdim; j++) dxm++; 1831 tmp = *dxm++ - starts[0]; 1832 for (j = 0; j < sdim - 1; j++) { 1833 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1834 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1835 } 1836 dxm++; 1837 jdxm[i] = tmp; 1838 } 1839 for (i = 0; i < n; i++) { 1840 for (j = 0; j < 3 - sdim; j++) dxn++; 1841 tmp = *dxn++ - starts[0]; 1842 for (j = 0; j < sdim - 1; j++) { 1843 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1844 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1845 } 1846 dxn++; 1847 jdxn[i] = tmp; 1848 } 1849 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1850 PetscCall(PetscFree2(bufm, bufn)); 1851 PetscFunctionReturn(0); 1852 } 1853 1854 /*@ 1855 MatSetStencil - Sets the grid information for setting values into a matrix via 1856 `MatSetValuesStencil()` 1857 1858 Not Collective 1859 1860 Input Parameters: 1861 + mat - the matrix 1862 . dim - dimension of the grid 1, 2, or 3 1863 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1864 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1865 - dof - number of degrees of freedom per node 1866 1867 Notes: 1868 Inspired by the structured grid interface to the HYPRE package 1869 (www.llnl.gov/CASC/hyper) 1870 1871 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1872 user. 1873 1874 Level: beginner 1875 1876 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1877 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1878 @*/ 1879 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1880 { 1881 PetscFunctionBegin; 1882 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1883 PetscValidIntPointer(dims, 3); 1884 PetscValidIntPointer(starts, 4); 1885 1886 mat->stencil.dim = dim + (dof > 1); 1887 for (PetscInt i = 0; i < dim; i++) { 1888 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1889 mat->stencil.starts[i] = starts[dim - i - 1]; 1890 } 1891 mat->stencil.dims[dim] = dof; 1892 mat->stencil.starts[dim] = 0; 1893 mat->stencil.noc = (PetscBool)(dof == 1); 1894 PetscFunctionReturn(0); 1895 } 1896 1897 /*@C 1898 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1899 1900 Not Collective 1901 1902 Input Parameters: 1903 + mat - the matrix 1904 . v - a logically two-dimensional array of values 1905 . m, idxm - the number of block rows and their global block indices 1906 . n, idxn - the number of block columns and their global block indices 1907 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1908 1909 Level: intermediate 1910 1911 Notes: 1912 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1913 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1914 1915 The m and n count the NUMBER of blocks in the row direction and column direction, 1916 NOT the total number of rows/columns; for example, if the block size is 2 and 1917 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1918 The values in idxm would be 1 2; that is the first index for each block divided by 1919 the block size. 1920 1921 Note that you must call `MatSetBlockSize()` when constructing this matrix (before 1922 preallocating it). 1923 1924 By default the values, v, are row-oriented, so the layout of 1925 v is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1926 1927 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1928 options cannot be mixed without intervening calls to the assembly 1929 routines. 1930 1931 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1932 as well as in C. 1933 1934 Negative indices may be passed in idxm and idxn, these rows and columns are 1935 simply ignored. This allows easily inserting element stiffness matrices 1936 with homogeneous Dirchlet boundary conditions that you don't want represented 1937 in the matrix. 1938 1939 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1940 internal searching must be done to determine where to place the 1941 data in the matrix storage space. By instead inserting blocks of 1942 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1943 reduced. 1944 1945 Example: 1946 .vb 1947 Suppose m=n=2 and block size(bs) = 2 The array is 1948 1949 1 2 | 3 4 1950 5 6 | 7 8 1951 - - - | - - - 1952 9 10 | 11 12 1953 13 14 | 15 16 1954 1955 v[] should be passed in like 1956 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1957 1958 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1959 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1960 .ve 1961 1962 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1963 @*/ 1964 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1965 { 1966 PetscFunctionBeginHot; 1967 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1968 PetscValidType(mat, 1); 1969 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1970 PetscValidIntPointer(idxm, 3); 1971 PetscValidIntPointer(idxn, 5); 1972 MatCheckPreallocated(mat, 1); 1973 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1974 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1975 if (PetscDefined(USE_DEBUG)) { 1976 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1977 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1978 } 1979 if (PetscDefined(USE_DEBUG)) { 1980 PetscInt rbs, cbs, M, N, i; 1981 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1982 PetscCall(MatGetSize(mat, &M, &N)); 1983 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 1984 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 1985 } 1986 if (mat->assembled) { 1987 mat->was_assembled = PETSC_TRUE; 1988 mat->assembled = PETSC_FALSE; 1989 } 1990 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1991 if (mat->ops->setvaluesblocked) { 1992 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1993 } else { 1994 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1995 PetscInt i, j, bs, cbs; 1996 1997 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1998 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1999 iidxm = buf; 2000 iidxn = buf + m * bs; 2001 } else { 2002 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2003 iidxm = bufr; 2004 iidxn = bufc; 2005 } 2006 for (i = 0; i < m; i++) { 2007 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2008 } 2009 if (m != n || bs != cbs || idxm != idxn) { 2010 for (i = 0; i < n; i++) { 2011 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2012 } 2013 } else iidxn = iidxm; 2014 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2015 PetscCall(PetscFree2(bufr, bufc)); 2016 } 2017 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2018 PetscFunctionReturn(0); 2019 } 2020 2021 /*@C 2022 MatGetValues - Gets a block of local values from a matrix. 2023 2024 Not Collective; can only return values that are owned by the give process 2025 2026 Input Parameters: 2027 + mat - the matrix 2028 . v - a logically two-dimensional array for storing the values 2029 . m, idxm - the number of rows and their global indices 2030 - n, idxn - the number of columns and their global indices 2031 2032 Notes: 2033 The user must allocate space (m*n `PetscScalar`s) for the values, v. 2034 The values, v, are then returned in a row-oriented format, 2035 analogous to that used by default in `MatSetValues()`. 2036 2037 `MatGetValues()` uses 0-based row and column numbers in 2038 Fortran as well as in C. 2039 2040 `MatGetValues()` requires that the matrix has been assembled 2041 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2042 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2043 without intermediate matrix assembly. 2044 2045 Negative row or column indices will be ignored and those locations in v[] will be 2046 left unchanged. 2047 2048 For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank. 2049 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2050 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2051 2052 Level: advanced 2053 2054 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2055 @*/ 2056 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2057 { 2058 PetscFunctionBegin; 2059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2060 PetscValidType(mat, 1); 2061 if (!m || !n) PetscFunctionReturn(0); 2062 PetscValidIntPointer(idxm, 3); 2063 PetscValidIntPointer(idxn, 5); 2064 PetscValidScalarPointer(v, 6); 2065 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2066 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2067 MatCheckPreallocated(mat, 1); 2068 2069 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2070 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2071 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2072 PetscFunctionReturn(0); 2073 } 2074 2075 /*@C 2076 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2077 defined previously by `MatSetLocalToGlobalMapping()` 2078 2079 Not Collective 2080 2081 Input Parameters: 2082 + mat - the matrix 2083 . nrow, irow - number of rows and their local indices 2084 - ncol, icol - number of columns and their local indices 2085 2086 Output Parameter: 2087 . y - a logically two-dimensional array of values 2088 2089 Level: advanced 2090 2091 Notes: 2092 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2093 2094 This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering, 2095 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2096 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2097 with `MatSetLocalToGlobalMapping()`. 2098 2099 Developer Note: 2100 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2101 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2102 2103 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2104 `MatSetValuesLocal()`, `MatGetValues()` 2105 @*/ 2106 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2107 { 2108 PetscFunctionBeginHot; 2109 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2110 PetscValidType(mat, 1); 2111 MatCheckPreallocated(mat, 1); 2112 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */ 2113 PetscValidIntPointer(irow, 3); 2114 PetscValidIntPointer(icol, 5); 2115 if (PetscDefined(USE_DEBUG)) { 2116 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2117 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2118 } 2119 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2120 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2121 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2122 else { 2123 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2124 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2125 irowm = buf; 2126 icolm = buf + nrow; 2127 } else { 2128 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2129 irowm = bufr; 2130 icolm = bufc; 2131 } 2132 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2133 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2134 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2135 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2136 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2137 PetscCall(PetscFree2(bufr, bufc)); 2138 } 2139 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2140 PetscFunctionReturn(0); 2141 } 2142 2143 /*@ 2144 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2145 the same size. Currently, this can only be called once and creates the given matrix. 2146 2147 Not Collective 2148 2149 Input Parameters: 2150 + mat - the matrix 2151 . nb - the number of blocks 2152 . bs - the number of rows (and columns) in each block 2153 . rows - a concatenation of the rows for each block 2154 - v - a concatenation of logically two-dimensional arrays of values 2155 2156 Note: 2157 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2158 2159 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2160 2161 Level: advanced 2162 2163 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2164 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2165 @*/ 2166 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2167 { 2168 PetscFunctionBegin; 2169 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2170 PetscValidType(mat, 1); 2171 PetscValidIntPointer(rows, 4); 2172 PetscValidScalarPointer(v, 5); 2173 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2174 2175 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2176 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2177 else { 2178 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2179 } 2180 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2181 PetscFunctionReturn(0); 2182 } 2183 2184 /*@ 2185 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2186 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2187 using a local (per-processor) numbering. 2188 2189 Not Collective 2190 2191 Input Parameters: 2192 + x - the matrix 2193 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2194 - cmapping - column mapping 2195 2196 Level: intermediate 2197 2198 Note: 2199 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2200 2201 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2202 @*/ 2203 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2204 { 2205 PetscFunctionBegin; 2206 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2207 PetscValidType(x, 1); 2208 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2209 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2210 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2211 else { 2212 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2213 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2214 } 2215 PetscFunctionReturn(0); 2216 } 2217 2218 /*@ 2219 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2220 2221 Not Collective 2222 2223 Input Parameter: 2224 . A - the matrix 2225 2226 Output Parameters: 2227 + rmapping - row mapping 2228 - cmapping - column mapping 2229 2230 Level: advanced 2231 2232 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2233 @*/ 2234 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2235 { 2236 PetscFunctionBegin; 2237 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2238 PetscValidType(A, 1); 2239 if (rmapping) { 2240 PetscValidPointer(rmapping, 2); 2241 *rmapping = A->rmap->mapping; 2242 } 2243 if (cmapping) { 2244 PetscValidPointer(cmapping, 3); 2245 *cmapping = A->cmap->mapping; 2246 } 2247 PetscFunctionReturn(0); 2248 } 2249 2250 /*@ 2251 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2252 2253 Logically Collective on A 2254 2255 Input Parameters: 2256 + A - the matrix 2257 . rmap - row layout 2258 - cmap - column layout 2259 2260 Level: advanced 2261 2262 Note: 2263 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2264 2265 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2266 @*/ 2267 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2268 { 2269 PetscFunctionBegin; 2270 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2271 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2272 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2273 PetscFunctionReturn(0); 2274 } 2275 2276 /*@ 2277 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2278 2279 Not Collective 2280 2281 Input Parameter: 2282 . A - the matrix 2283 2284 Output Parameters: 2285 + rmap - row layout 2286 - cmap - column layout 2287 2288 Level: advanced 2289 2290 .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2291 @*/ 2292 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2293 { 2294 PetscFunctionBegin; 2295 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2296 PetscValidType(A, 1); 2297 if (rmap) { 2298 PetscValidPointer(rmap, 2); 2299 *rmap = A->rmap; 2300 } 2301 if (cmap) { 2302 PetscValidPointer(cmap, 3); 2303 *cmap = A->cmap; 2304 } 2305 PetscFunctionReturn(0); 2306 } 2307 2308 /*@C 2309 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2310 using a local numbering of the nodes. 2311 2312 Not Collective 2313 2314 Input Parameters: 2315 + mat - the matrix 2316 . nrow, irow - number of rows and their local indices 2317 . ncol, icol - number of columns and their local indices 2318 . y - a logically two-dimensional array of values 2319 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2320 2321 Notes: 2322 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2323 `MatSetUp()` before using this routine 2324 2325 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2326 2327 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2328 options cannot be mixed without intervening calls to the assembly 2329 routines. 2330 2331 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2332 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2333 2334 Level: intermediate 2335 2336 Developer Note: 2337 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2338 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2339 2340 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2341 `MatGetValuesLocal()` 2342 @*/ 2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2344 { 2345 PetscFunctionBeginHot; 2346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2347 PetscValidType(mat, 1); 2348 MatCheckPreallocated(mat, 1); 2349 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2350 PetscValidIntPointer(irow, 3); 2351 PetscValidIntPointer(icol, 5); 2352 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2353 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2354 if (PetscDefined(USE_DEBUG)) { 2355 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2356 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2357 } 2358 2359 if (mat->assembled) { 2360 mat->was_assembled = PETSC_TRUE; 2361 mat->assembled = PETSC_FALSE; 2362 } 2363 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2364 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2365 else { 2366 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2367 const PetscInt *irowm, *icolm; 2368 2369 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2370 bufr = buf; 2371 bufc = buf + nrow; 2372 irowm = bufr; 2373 icolm = bufc; 2374 } else { 2375 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2376 irowm = bufr; 2377 icolm = bufc; 2378 } 2379 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2380 else irowm = irow; 2381 if (mat->cmap->mapping) { 2382 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2383 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2384 } else icolm = irowm; 2385 } else icolm = icol; 2386 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2387 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2388 } 2389 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2390 PetscFunctionReturn(0); 2391 } 2392 2393 /*@C 2394 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2395 using a local ordering of the nodes a block at a time. 2396 2397 Not Collective 2398 2399 Input Parameters: 2400 + x - the matrix 2401 . nrow, irow - number of rows and their local indices 2402 . ncol, icol - number of columns and their local indices 2403 . y - a logically two-dimensional array of values 2404 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2405 2406 Notes: 2407 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2408 `MatSetUp()` before using this routine 2409 2410 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2411 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2412 2413 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2414 options cannot be mixed without intervening calls to the assembly 2415 routines. 2416 2417 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2418 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2419 2420 Level: intermediate 2421 2422 Developer Note: 2423 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2424 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2425 2426 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2427 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2428 @*/ 2429 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2430 { 2431 PetscFunctionBeginHot; 2432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2433 PetscValidType(mat, 1); 2434 MatCheckPreallocated(mat, 1); 2435 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2436 PetscValidIntPointer(irow, 3); 2437 PetscValidIntPointer(icol, 5); 2438 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2439 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2440 if (PetscDefined(USE_DEBUG)) { 2441 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2442 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2443 } 2444 2445 if (mat->assembled) { 2446 mat->was_assembled = PETSC_TRUE; 2447 mat->assembled = PETSC_FALSE; 2448 } 2449 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2450 PetscInt irbs, rbs; 2451 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2452 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2453 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2454 } 2455 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2456 PetscInt icbs, cbs; 2457 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2458 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2459 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2460 } 2461 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2462 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2463 else { 2464 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2465 const PetscInt *irowm, *icolm; 2466 2467 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2468 bufr = buf; 2469 bufc = buf + nrow; 2470 irowm = bufr; 2471 icolm = bufc; 2472 } else { 2473 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2474 irowm = bufr; 2475 icolm = bufc; 2476 } 2477 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2478 else irowm = irow; 2479 if (mat->cmap->mapping) { 2480 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2481 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2482 } else icolm = irowm; 2483 } else icolm = icol; 2484 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2485 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2486 } 2487 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2488 PetscFunctionReturn(0); 2489 } 2490 2491 /*@ 2492 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2493 2494 Collective 2495 2496 Input Parameters: 2497 + mat - the matrix 2498 - x - the vector to be multiplied 2499 2500 Output Parameters: 2501 . y - the result 2502 2503 Note: 2504 The vectors x and y cannot be the same. I.e., one cannot 2505 call `MatMultDiagonalBlock`(A,y,y). 2506 2507 Level: developer 2508 2509 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2510 @*/ 2511 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2512 { 2513 PetscFunctionBegin; 2514 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2515 PetscValidType(mat, 1); 2516 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2517 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2518 2519 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2520 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2521 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2522 MatCheckPreallocated(mat, 1); 2523 2524 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2525 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2526 PetscFunctionReturn(0); 2527 } 2528 2529 /* --------------------------------------------------------*/ 2530 /*@ 2531 MatMult - Computes the matrix-vector product, y = Ax. 2532 2533 Neighbor-wise Collective 2534 2535 Input Parameters: 2536 + mat - the matrix 2537 - x - the vector to be multiplied 2538 2539 Output Parameters: 2540 . y - the result 2541 2542 Note: 2543 The vectors x and y cannot be the same. I.e., one cannot 2544 call `MatMult`(A,y,y). 2545 2546 Level: beginner 2547 2548 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2549 @*/ 2550 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2551 { 2552 PetscFunctionBegin; 2553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2554 PetscValidType(mat, 1); 2555 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2556 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2557 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2558 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2559 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2560 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); 2561 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); 2562 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); 2563 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); 2564 PetscCall(VecSetErrorIfLocked(y, 3)); 2565 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2566 MatCheckPreallocated(mat, 1); 2567 2568 PetscCall(VecLockReadPush(x)); 2569 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2570 PetscUseTypeMethod(mat, mult, x, y); 2571 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2572 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2573 PetscCall(VecLockReadPop(x)); 2574 PetscFunctionReturn(0); 2575 } 2576 2577 /*@ 2578 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2579 2580 Neighbor-wise Collective 2581 2582 Input Parameters: 2583 + mat - the matrix 2584 - x - the vector to be multiplied 2585 2586 Output Parameters: 2587 . y - the result 2588 2589 Notes: 2590 The vectors x and y cannot be the same. I.e., one cannot 2591 call `MatMultTranspose`(A,y,y). 2592 2593 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2594 use `MatMultHermitianTranspose()` 2595 2596 Level: beginner 2597 2598 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2599 @*/ 2600 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2601 { 2602 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2603 2604 PetscFunctionBegin; 2605 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2606 PetscValidType(mat, 1); 2607 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2608 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2609 2610 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2611 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2612 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2613 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); 2614 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); 2615 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); 2616 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); 2617 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2618 MatCheckPreallocated(mat, 1); 2619 2620 if (!mat->ops->multtranspose) { 2621 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2622 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); 2623 } else op = mat->ops->multtranspose; 2624 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2625 PetscCall(VecLockReadPush(x)); 2626 PetscCall((*op)(mat, x, y)); 2627 PetscCall(VecLockReadPop(x)); 2628 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2629 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2630 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2631 PetscFunctionReturn(0); 2632 } 2633 2634 /*@ 2635 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2636 2637 Neighbor-wise Collective 2638 2639 Input Parameters: 2640 + mat - the matrix 2641 - x - the vector to be multilplied 2642 2643 Output Parameters: 2644 . y - the result 2645 2646 Notes: 2647 The vectors x and y cannot be the same. I.e., one cannot 2648 call `MatMultHermitianTranspose`(A,y,y). 2649 2650 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2651 2652 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2653 2654 Level: beginner 2655 2656 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2657 @*/ 2658 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2659 { 2660 PetscFunctionBegin; 2661 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2662 PetscValidType(mat, 1); 2663 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2664 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2665 2666 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2667 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2668 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2669 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); 2670 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); 2671 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); 2672 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); 2673 MatCheckPreallocated(mat, 1); 2674 2675 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2676 #if defined(PETSC_USE_COMPLEX) 2677 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2678 PetscCall(VecLockReadPush(x)); 2679 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2680 else PetscUseTypeMethod(mat, mult, x, y); 2681 PetscCall(VecLockReadPop(x)); 2682 } else { 2683 Vec w; 2684 PetscCall(VecDuplicate(x, &w)); 2685 PetscCall(VecCopy(x, w)); 2686 PetscCall(VecConjugate(w)); 2687 PetscCall(MatMultTranspose(mat, w, y)); 2688 PetscCall(VecDestroy(&w)); 2689 PetscCall(VecConjugate(y)); 2690 } 2691 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2692 #else 2693 PetscCall(MatMultTranspose(mat, x, y)); 2694 #endif 2695 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2696 PetscFunctionReturn(0); 2697 } 2698 2699 /*@ 2700 MatMultAdd - Computes v3 = v2 + A * v1. 2701 2702 Neighbor-wise Collective 2703 2704 Input Parameters: 2705 + mat - the matrix 2706 - v1, v2 - the vectors 2707 2708 Output Parameters: 2709 . v3 - the result 2710 2711 Note: 2712 The vectors v1 and v3 cannot be the same. I.e., one cannot 2713 call `MatMultAdd`(A,v1,v2,v1). 2714 2715 Level: beginner 2716 2717 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2718 @*/ 2719 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2720 { 2721 PetscFunctionBegin; 2722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2723 PetscValidType(mat, 1); 2724 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2725 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2726 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2727 2728 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2729 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2730 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); 2731 /* 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); 2732 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); */ 2733 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); 2734 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); 2735 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2736 MatCheckPreallocated(mat, 1); 2737 2738 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2739 PetscCall(VecLockReadPush(v1)); 2740 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2741 PetscCall(VecLockReadPop(v1)); 2742 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2743 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2744 PetscFunctionReturn(0); 2745 } 2746 2747 /*@ 2748 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2749 2750 Neighbor-wise Collective 2751 2752 Input Parameters: 2753 + mat - the matrix 2754 - v1, v2 - the vectors 2755 2756 Output Parameters: 2757 . v3 - the result 2758 2759 Note: 2760 The vectors v1 and v3 cannot be the same. I.e., one cannot 2761 call `MatMultTransposeAdd`(A,v1,v2,v1). 2762 2763 Level: beginner 2764 2765 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2766 @*/ 2767 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2768 { 2769 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2770 2771 PetscFunctionBegin; 2772 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2773 PetscValidType(mat, 1); 2774 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2775 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2776 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2777 2778 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2779 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2780 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); 2781 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); 2782 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); 2783 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2784 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2785 MatCheckPreallocated(mat, 1); 2786 2787 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2788 PetscCall(VecLockReadPush(v1)); 2789 PetscCall((*op)(mat, v1, v2, v3)); 2790 PetscCall(VecLockReadPop(v1)); 2791 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2792 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2793 PetscFunctionReturn(0); 2794 } 2795 2796 /*@ 2797 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2798 2799 Neighbor-wise Collective 2800 2801 Input Parameters: 2802 + mat - the matrix 2803 - v1, v2 - the vectors 2804 2805 Output Parameters: 2806 . v3 - the result 2807 2808 Note: 2809 The vectors v1 and v3 cannot be the same. I.e., one cannot 2810 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2811 2812 Level: beginner 2813 2814 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2815 @*/ 2816 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2817 { 2818 PetscFunctionBegin; 2819 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2820 PetscValidType(mat, 1); 2821 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2822 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2823 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2824 2825 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2826 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2827 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2828 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); 2829 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); 2830 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); 2831 MatCheckPreallocated(mat, 1); 2832 2833 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2834 PetscCall(VecLockReadPush(v1)); 2835 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2836 else { 2837 Vec w, z; 2838 PetscCall(VecDuplicate(v1, &w)); 2839 PetscCall(VecCopy(v1, w)); 2840 PetscCall(VecConjugate(w)); 2841 PetscCall(VecDuplicate(v3, &z)); 2842 PetscCall(MatMultTranspose(mat, w, z)); 2843 PetscCall(VecDestroy(&w)); 2844 PetscCall(VecConjugate(z)); 2845 if (v2 != v3) { 2846 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2847 } else { 2848 PetscCall(VecAXPY(v3, 1.0, z)); 2849 } 2850 PetscCall(VecDestroy(&z)); 2851 } 2852 PetscCall(VecLockReadPop(v1)); 2853 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2854 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2855 PetscFunctionReturn(0); 2856 } 2857 2858 /*@C 2859 MatGetFactorType - gets the type of factorization it is 2860 2861 Not Collective 2862 2863 Input Parameters: 2864 . mat - the matrix 2865 2866 Output Parameters: 2867 . 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` 2868 2869 Level: intermediate 2870 2871 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2872 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2873 @*/ 2874 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2875 { 2876 PetscFunctionBegin; 2877 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2878 PetscValidType(mat, 1); 2879 PetscValidPointer(t, 2); 2880 *t = mat->factortype; 2881 PetscFunctionReturn(0); 2882 } 2883 2884 /*@C 2885 MatSetFactorType - sets the type of factorization it is 2886 2887 Logically Collective 2888 2889 Input Parameters: 2890 + mat - the matrix 2891 - 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` 2892 2893 Level: intermediate 2894 2895 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2896 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2897 @*/ 2898 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2899 { 2900 PetscFunctionBegin; 2901 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2902 PetscValidType(mat, 1); 2903 mat->factortype = t; 2904 PetscFunctionReturn(0); 2905 } 2906 2907 /* ------------------------------------------------------------*/ 2908 /*@C 2909 MatGetInfo - Returns information about matrix storage (number of 2910 nonzeros, memory, etc.). 2911 2912 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2913 2914 Input Parameter: 2915 . mat - the matrix 2916 2917 Output Parameters: 2918 + flag - flag indicating the type of parameters to be returned 2919 (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, 2920 MAT_GLOBAL_SUM - sum over all processors) 2921 - info - matrix information context 2922 2923 Notes: 2924 The `MatInfo` context contains a variety of matrix data, including 2925 number of nonzeros allocated and used, number of mallocs during 2926 matrix assembly, etc. Additional information for factored matrices 2927 is provided (such as the fill ratio, number of mallocs during 2928 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2929 when using the runtime options 2930 $ -info -mat_view ::ascii_info 2931 2932 Example for C/C++ Users: 2933 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2934 data within the MatInfo context. For example, 2935 .vb 2936 MatInfo info; 2937 Mat A; 2938 double mal, nz_a, nz_u; 2939 2940 MatGetInfo(A,MAT_LOCAL,&info); 2941 mal = info.mallocs; 2942 nz_a = info.nz_allocated; 2943 .ve 2944 2945 Example for Fortran Users: 2946 Fortran users should declare info as a double precision 2947 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2948 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2949 a complete list of parameter names. 2950 .vb 2951 double precision info(MAT_INFO_SIZE) 2952 double precision mal, nz_a 2953 Mat A 2954 integer ierr 2955 2956 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2957 mal = info(MAT_INFO_MALLOCS) 2958 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2959 .ve 2960 2961 Level: intermediate 2962 2963 Developer Note: 2964 Fortran interface is not autogenerated as the 2965 interface definition cannot be generated correctly [due to MatInfo] 2966 2967 .seealso: `MatInfo`, `MatStashGetInfo()` 2968 @*/ 2969 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2970 { 2971 PetscFunctionBegin; 2972 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2973 PetscValidType(mat, 1); 2974 PetscValidPointer(info, 3); 2975 MatCheckPreallocated(mat, 1); 2976 PetscUseTypeMethod(mat, getinfo, flag, info); 2977 PetscFunctionReturn(0); 2978 } 2979 2980 /* 2981 This is used by external packages where it is not easy to get the info from the actual 2982 matrix factorization. 2983 */ 2984 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2985 { 2986 PetscFunctionBegin; 2987 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2988 PetscFunctionReturn(0); 2989 } 2990 2991 /* ----------------------------------------------------------*/ 2992 2993 /*@C 2994 MatLUFactor - Performs in-place LU factorization of matrix. 2995 2996 Collective 2997 2998 Input Parameters: 2999 + mat - the matrix 3000 . row - row permutation 3001 . col - column permutation 3002 - info - options for factorization, includes 3003 $ fill - expected fill as ratio of original fill. 3004 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3005 $ Run with the option -info to determine an optimal value to use 3006 3007 Notes: 3008 Most users should employ the `KSP` interface for linear solvers 3009 instead of working directly with matrix algebra routines such as this. 3010 See, e.g., `KSPCreate()`. 3011 3012 This changes the state of the matrix to a factored matrix; it cannot be used 3013 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3014 3015 This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3016 when not using `KSP`. 3017 3018 Level: developer 3019 3020 Developer Note: 3021 The Fortran interface is not autogenerated as the 3022 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3023 3024 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3025 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3026 @*/ 3027 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3028 { 3029 MatFactorInfo tinfo; 3030 3031 PetscFunctionBegin; 3032 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3033 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3034 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3035 if (info) PetscValidPointer(info, 4); 3036 PetscValidType(mat, 1); 3037 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3038 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3039 MatCheckPreallocated(mat, 1); 3040 if (!info) { 3041 PetscCall(MatFactorInfoInitialize(&tinfo)); 3042 info = &tinfo; 3043 } 3044 3045 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3046 PetscUseTypeMethod(mat, lufactor, row, col, info); 3047 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3048 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3049 PetscFunctionReturn(0); 3050 } 3051 3052 /*@C 3053 MatILUFactor - Performs in-place ILU factorization of matrix. 3054 3055 Collective 3056 3057 Input Parameters: 3058 + mat - the matrix 3059 . row - row permutation 3060 . col - column permutation 3061 - info - structure containing 3062 $ levels - number of levels of fill. 3063 $ expected fill - as ratio of original fill. 3064 $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3065 missing diagonal entries) 3066 3067 Level: developer 3068 3069 Notes: 3070 Most users should employ the `KSP` interface for linear solvers 3071 instead of working directly with matrix algebra routines such as this. 3072 See, e.g., `KSPCreate()`. 3073 3074 Probably really in-place only when level of fill is zero, otherwise allocates 3075 new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3076 when not using `KSP`. 3077 3078 Developer Note: 3079 The Fortran interface is not autogenerated as the 3080 interface definition cannot be generated correctly [due to MatFactorInfo] 3081 3082 .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3083 @*/ 3084 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3085 { 3086 PetscFunctionBegin; 3087 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3088 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3089 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3090 PetscValidPointer(info, 4); 3091 PetscValidType(mat, 1); 3092 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3093 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3094 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3095 MatCheckPreallocated(mat, 1); 3096 3097 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3098 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3099 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3100 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3101 PetscFunctionReturn(0); 3102 } 3103 3104 /*@C 3105 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3106 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3107 3108 Collective on fact 3109 3110 Input Parameters: 3111 + fact - the factor matrix obtained with `MatGetFactor()` 3112 . mat - the matrix 3113 . row, col - row and column permutations 3114 - info - options for factorization, includes 3115 .vb 3116 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3117 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3118 .ve 3119 3120 Level: developer 3121 3122 Notes: 3123 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3124 3125 Most users should employ the simplified `KSP` interface for linear solvers 3126 instead of working directly with matrix algebra routines such as this. 3127 See, e.g., `KSPCreate()`. 3128 3129 Developer Note: 3130 The Fortran interface is not autogenerated as the 3131 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3132 3133 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3134 @*/ 3135 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3136 { 3137 MatFactorInfo tinfo; 3138 3139 PetscFunctionBegin; 3140 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3141 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3142 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3143 if (info) PetscValidPointer(info, 5); 3144 PetscValidType(mat, 2); 3145 PetscValidPointer(fact, 1); 3146 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3147 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3148 if (!(fact)->ops->lufactorsymbolic) { 3149 MatSolverType stype; 3150 PetscCall(MatFactorGetSolverType(fact, &stype)); 3151 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype); 3152 } 3153 MatCheckPreallocated(mat, 2); 3154 if (!info) { 3155 PetscCall(MatFactorInfoInitialize(&tinfo)); 3156 info = &tinfo; 3157 } 3158 3159 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3160 PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info)); 3161 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3162 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3163 PetscFunctionReturn(0); 3164 } 3165 3166 /*@C 3167 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3168 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3169 3170 Collective on fact 3171 3172 Input Parameters: 3173 + fact - the factor matrix obtained with `MatGetFactor()` 3174 . mat - the matrix 3175 - info - options for factorization 3176 3177 Level: developer 3178 3179 Notes: 3180 See `MatLUFactor()` for in-place factorization. See 3181 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3182 3183 Most users should employ the `KSP` interface for linear solvers 3184 instead of working directly with matrix algebra routines such as this. 3185 See, e.g., `KSPCreate()`. 3186 3187 Developer Note: 3188 The Fortran interface is not autogenerated as the 3189 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3190 3191 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3192 @*/ 3193 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3194 { 3195 MatFactorInfo tinfo; 3196 3197 PetscFunctionBegin; 3198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3199 PetscValidType(mat, 2); 3200 PetscValidPointer(fact, 1); 3201 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3202 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3203 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, 3204 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3205 3206 PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name); 3207 MatCheckPreallocated(mat, 2); 3208 if (!info) { 3209 PetscCall(MatFactorInfoInitialize(&tinfo)); 3210 info = &tinfo; 3211 } 3212 3213 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3214 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3215 PetscCall((fact->ops->lufactornumeric)(fact, mat, info)); 3216 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3217 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3218 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3219 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3220 PetscFunctionReturn(0); 3221 } 3222 3223 /*@C 3224 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3225 symmetric matrix. 3226 3227 Collective 3228 3229 Input Parameters: 3230 + mat - the matrix 3231 . perm - row and column permutations 3232 - f - expected fill as ratio of original fill 3233 3234 Level: developer 3235 3236 Notes: 3237 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3238 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3239 3240 Most users should employ the `KSP` interface for linear solvers 3241 instead of working directly with matrix algebra routines such as this. 3242 See, e.g., `KSPCreate()`. 3243 3244 Developer Note: 3245 The Fortran interface is not autogenerated as the 3246 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3247 3248 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3249 `MatGetOrdering()` 3250 @*/ 3251 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3252 { 3253 MatFactorInfo tinfo; 3254 3255 PetscFunctionBegin; 3256 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3257 PetscValidType(mat, 1); 3258 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3259 if (info) PetscValidPointer(info, 3); 3260 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3262 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3263 MatCheckPreallocated(mat, 1); 3264 if (!info) { 3265 PetscCall(MatFactorInfoInitialize(&tinfo)); 3266 info = &tinfo; 3267 } 3268 3269 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3270 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3271 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3272 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3273 PetscFunctionReturn(0); 3274 } 3275 3276 /*@C 3277 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3278 of a symmetric matrix. 3279 3280 Collective on fact 3281 3282 Input Parameters: 3283 + fact - the factor matrix obtained with `MatGetFactor()` 3284 . mat - the matrix 3285 . perm - row and column permutations 3286 - info - options for factorization, includes 3287 .vb 3288 fill - expected fill as ratio of original fill. 3289 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3290 Run with the option -info to determine an optimal value to use 3291 .ve 3292 3293 Level: developer 3294 3295 Notes: 3296 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3297 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3298 3299 Most users should employ the `KSP` interface for linear solvers 3300 instead of working directly with matrix algebra routines such as this. 3301 See, e.g., `KSPCreate()`. 3302 3303 Developer Note: 3304 The Fortran interface is not autogenerated as the 3305 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3306 3307 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3308 `MatGetOrdering()` 3309 @*/ 3310 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3311 { 3312 MatFactorInfo tinfo; 3313 3314 PetscFunctionBegin; 3315 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3316 PetscValidType(mat, 2); 3317 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3318 if (info) PetscValidPointer(info, 4); 3319 PetscValidPointer(fact, 1); 3320 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3321 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3322 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3323 if (!(fact)->ops->choleskyfactorsymbolic) { 3324 MatSolverType stype; 3325 PetscCall(MatFactorGetSolverType(fact, &stype)); 3326 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype); 3327 } 3328 MatCheckPreallocated(mat, 2); 3329 if (!info) { 3330 PetscCall(MatFactorInfoInitialize(&tinfo)); 3331 info = &tinfo; 3332 } 3333 3334 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3335 PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info)); 3336 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3337 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3338 PetscFunctionReturn(0); 3339 } 3340 3341 /*@C 3342 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3343 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3344 `MatCholeskyFactorSymbolic()`. 3345 3346 Collective on fact 3347 3348 Input Parameters: 3349 + fact - the factor matrix obtained with `MatGetFactor()` 3350 . mat - the initial matrix 3351 . info - options for factorization 3352 - fact - the symbolic factor of mat 3353 3354 Level: developer 3355 3356 Note: 3357 Most users should employ the `KSP` interface for linear solvers 3358 instead of working directly with matrix algebra routines such as this. 3359 See, e.g., `KSPCreate()`. 3360 3361 Developer Note: 3362 The Fortran interface is not autogenerated as the 3363 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3364 3365 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3366 @*/ 3367 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3368 { 3369 MatFactorInfo tinfo; 3370 3371 PetscFunctionBegin; 3372 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3373 PetscValidType(mat, 2); 3374 PetscValidPointer(fact, 1); 3375 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3376 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3377 PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name); 3378 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, 3379 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3380 MatCheckPreallocated(mat, 2); 3381 if (!info) { 3382 PetscCall(MatFactorInfoInitialize(&tinfo)); 3383 info = &tinfo; 3384 } 3385 3386 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3387 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3388 PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info)); 3389 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3390 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3391 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3392 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3393 PetscFunctionReturn(0); 3394 } 3395 3396 /*@ 3397 MatQRFactor - Performs in-place QR factorization of matrix. 3398 3399 Collective 3400 3401 Input Parameters: 3402 + mat - the matrix 3403 . col - column permutation 3404 - info - options for factorization, includes 3405 .vb 3406 fill - expected fill as ratio of original fill. 3407 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3408 Run with the option -info to determine an optimal value to use 3409 .ve 3410 3411 Level: developer 3412 3413 Notes: 3414 Most users should employ the `KSP` interface for linear solvers 3415 instead of working directly with matrix algebra routines such as this. 3416 See, e.g., `KSPCreate()`. 3417 3418 This changes the state of the matrix to a factored matrix; it cannot be used 3419 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3420 3421 Developer Note: 3422 The Fortran interface is not autogenerated as the 3423 interface definition cannot be generated correctly [due to MatFactorInfo] 3424 3425 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3426 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3427 @*/ 3428 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3429 { 3430 PetscFunctionBegin; 3431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3432 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3433 if (info) PetscValidPointer(info, 3); 3434 PetscValidType(mat, 1); 3435 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3436 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3437 MatCheckPreallocated(mat, 1); 3438 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3439 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3440 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3441 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3442 PetscFunctionReturn(0); 3443 } 3444 3445 /*@ 3446 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3447 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3448 3449 Collective on fact 3450 3451 Input Parameters: 3452 + fact - the factor matrix obtained with `MatGetFactor()` 3453 . mat - the matrix 3454 . col - column permutation 3455 - info - options for factorization, includes 3456 .vb 3457 fill - expected fill as ratio of original fill. 3458 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3459 Run with the option -info to determine an optimal value to use 3460 .ve 3461 3462 Level: developer 3463 3464 Note: 3465 Most users should employ the `KSP` interface for linear solvers 3466 instead of working directly with matrix algebra routines such as this. 3467 See, e.g., `KSPCreate()`. 3468 3469 Developer Note: 3470 The Fortran interface is not autogenerated as the 3471 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3472 3473 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3474 @*/ 3475 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3476 { 3477 MatFactorInfo tinfo; 3478 3479 PetscFunctionBegin; 3480 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3481 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3482 if (info) PetscValidPointer(info, 4); 3483 PetscValidType(mat, 2); 3484 PetscValidPointer(fact, 1); 3485 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3486 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3487 MatCheckPreallocated(mat, 2); 3488 if (!info) { 3489 PetscCall(MatFactorInfoInitialize(&tinfo)); 3490 info = &tinfo; 3491 } 3492 3493 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3494 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3495 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3496 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3497 PetscFunctionReturn(0); 3498 } 3499 3500 /*@ 3501 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3502 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3503 3504 Collective on fact 3505 3506 Input Parameters: 3507 + fact - the factor matrix obtained with `MatGetFactor()` 3508 . mat - the matrix 3509 - info - options for factorization 3510 3511 Level: developer 3512 3513 Notes: 3514 See `MatQRFactor()` for in-place factorization. 3515 3516 Most users should employ the `KSP` interface for linear solvers 3517 instead of working directly with matrix algebra routines such as this. 3518 See, e.g., `KSPCreate()`. 3519 3520 Developer Note: 3521 The Fortran interface is not autogenerated as the 3522 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3523 3524 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3525 @*/ 3526 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3527 { 3528 MatFactorInfo tinfo; 3529 3530 PetscFunctionBegin; 3531 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3532 PetscValidType(mat, 2); 3533 PetscValidPointer(fact, 1); 3534 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3535 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3536 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, 3537 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3538 3539 MatCheckPreallocated(mat, 2); 3540 if (!info) { 3541 PetscCall(MatFactorInfoInitialize(&tinfo)); 3542 info = &tinfo; 3543 } 3544 3545 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3546 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3547 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3548 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3549 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3550 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3551 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3552 PetscFunctionReturn(0); 3553 } 3554 3555 /* ----------------------------------------------------------------*/ 3556 /*@ 3557 MatSolve - Solves A x = b, given a factored matrix. 3558 3559 Neighbor-wise Collective 3560 3561 Input Parameters: 3562 + mat - the factored matrix 3563 - b - the right-hand-side vector 3564 3565 Output Parameter: 3566 . x - the result vector 3567 3568 Notes: 3569 The vectors b and x cannot be the same. I.e., one cannot 3570 call `MatSolve`(A,x,x). 3571 3572 Most users should employ the `KSP` interface for linear solvers 3573 instead of working directly with matrix algebra routines such as this. 3574 See, e.g., `KSPCreate()`. 3575 3576 Level: developer 3577 3578 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3579 @*/ 3580 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3581 { 3582 PetscFunctionBegin; 3583 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3584 PetscValidType(mat, 1); 3585 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3586 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3587 PetscCheckSameComm(mat, 1, b, 2); 3588 PetscCheckSameComm(mat, 1, x, 3); 3589 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3590 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); 3591 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); 3592 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); 3593 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3594 MatCheckPreallocated(mat, 1); 3595 3596 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3597 if (mat->factorerrortype) { 3598 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3599 PetscCall(VecSetInf(x)); 3600 } else PetscUseTypeMethod(mat, solve, b, x); 3601 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3602 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3603 PetscFunctionReturn(0); 3604 } 3605 3606 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3607 { 3608 Vec b, x; 3609 PetscInt N, i; 3610 PetscErrorCode (*f)(Mat, Vec, Vec); 3611 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3612 3613 PetscFunctionBegin; 3614 if (A->factorerrortype) { 3615 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3616 PetscCall(MatSetInf(X)); 3617 PetscFunctionReturn(0); 3618 } 3619 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3620 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3621 PetscCall(MatBoundToCPU(A, &Abound)); 3622 if (!Abound) { 3623 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3624 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3625 } 3626 #if defined(PETSC_HAVE_CUDA) 3627 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3628 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3629 #elif (PETSC_HAVE_HIP) 3630 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3631 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3632 #endif 3633 PetscCall(MatGetSize(B, NULL, &N)); 3634 for (i = 0; i < N; i++) { 3635 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3636 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3637 PetscCall((*f)(A, b, x)); 3638 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3639 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3640 } 3641 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3642 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3643 PetscFunctionReturn(0); 3644 } 3645 3646 /*@ 3647 MatMatSolve - Solves A X = B, given a factored matrix. 3648 3649 Neighbor-wise Collective on A 3650 3651 Input Parameters: 3652 + A - the factored matrix 3653 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3654 3655 Output Parameter: 3656 . X - the result matrix (dense matrix) 3657 3658 Note: 3659 If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO; 3660 otherwise, B and X cannot be the same. 3661 3662 Level: developer 3663 3664 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3665 @*/ 3666 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3667 { 3668 PetscFunctionBegin; 3669 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3670 PetscValidType(A, 1); 3671 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3672 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3673 PetscCheckSameComm(A, 1, B, 2); 3674 PetscCheckSameComm(A, 1, X, 3); 3675 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); 3676 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); 3677 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"); 3678 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3679 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3680 MatCheckPreallocated(A, 1); 3681 3682 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3683 if (!A->ops->matsolve) { 3684 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3685 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3686 } else PetscUseTypeMethod(A, matsolve, B, X); 3687 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3688 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3689 PetscFunctionReturn(0); 3690 } 3691 3692 /*@ 3693 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3694 3695 Neighbor-wise Collective on A 3696 3697 Input Parameters: 3698 + A - the factored matrix 3699 - B - the right-hand-side matrix (`MATDENSE` matrix) 3700 3701 Output Parameter: 3702 . X - the result matrix (dense matrix) 3703 3704 Note: 3705 The matrices B and X cannot be the same. I.e., one cannot 3706 call `MatMatSolveTranspose`(A,X,X). 3707 3708 Level: developer 3709 3710 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3711 @*/ 3712 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3713 { 3714 PetscFunctionBegin; 3715 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3716 PetscValidType(A, 1); 3717 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3718 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3719 PetscCheckSameComm(A, 1, B, 2); 3720 PetscCheckSameComm(A, 1, X, 3); 3721 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3722 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); 3723 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); 3724 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); 3725 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"); 3726 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3727 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3728 MatCheckPreallocated(A, 1); 3729 3730 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3731 if (!A->ops->matsolvetranspose) { 3732 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3733 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3734 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3735 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3736 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3737 PetscFunctionReturn(0); 3738 } 3739 3740 /*@ 3741 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3742 3743 Neighbor-wise Collective on A 3744 3745 Input Parameters: 3746 + A - the factored matrix 3747 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3748 3749 Output Parameter: 3750 . X - the result matrix (dense matrix) 3751 3752 Note: 3753 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 3754 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3755 3756 Level: developer 3757 3758 .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3759 @*/ 3760 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3761 { 3762 PetscFunctionBegin; 3763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3764 PetscValidType(A, 1); 3765 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3766 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3767 PetscCheckSameComm(A, 1, Bt, 2); 3768 PetscCheckSameComm(A, 1, X, 3); 3769 3770 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3771 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); 3772 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); 3773 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"); 3774 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3775 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3776 MatCheckPreallocated(A, 1); 3777 3778 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3779 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3780 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3781 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3782 PetscFunctionReturn(0); 3783 } 3784 3785 /*@ 3786 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3787 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3788 3789 Neighbor-wise Collective 3790 3791 Input Parameters: 3792 + mat - the factored matrix 3793 - b - the right-hand-side vector 3794 3795 Output Parameter: 3796 . x - the result vector 3797 3798 Notes: 3799 `MatSolve()` should be used for most applications, as it performs 3800 a forward solve followed by a backward solve. 3801 3802 The vectors b and x cannot be the same, i.e., one cannot 3803 call `MatForwardSolve`(A,x,x). 3804 3805 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3806 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3807 `MatForwardSolve()` solves U^T*D y = b, and 3808 `MatBackwardSolve()` solves U x = y. 3809 Thus they do not provide a symmetric preconditioner. 3810 3811 Level: developer 3812 3813 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3814 @*/ 3815 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3816 { 3817 PetscFunctionBegin; 3818 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3819 PetscValidType(mat, 1); 3820 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3821 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3822 PetscCheckSameComm(mat, 1, b, 2); 3823 PetscCheckSameComm(mat, 1, x, 3); 3824 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3825 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); 3826 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); 3827 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); 3828 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3829 MatCheckPreallocated(mat, 1); 3830 3831 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3832 PetscUseTypeMethod(mat, forwardsolve, b, x); 3833 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3834 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3835 PetscFunctionReturn(0); 3836 } 3837 3838 /*@ 3839 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3840 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3841 3842 Neighbor-wise Collective 3843 3844 Input Parameters: 3845 + mat - the factored matrix 3846 - b - the right-hand-side vector 3847 3848 Output Parameter: 3849 . x - the result vector 3850 3851 Notes: 3852 `MatSolve()` should be used for most applications, as it performs 3853 a forward solve followed by a backward solve. 3854 3855 The vectors b and x cannot be the same. I.e., one cannot 3856 call `MatBackwardSolve`(A,x,x). 3857 3858 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3859 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3860 `MatForwardSolve()` solves U^T*D y = b, and 3861 `MatBackwardSolve()` solves U x = y. 3862 Thus they do not provide a symmetric preconditioner. 3863 3864 Level: developer 3865 3866 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3867 @*/ 3868 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3869 { 3870 PetscFunctionBegin; 3871 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3872 PetscValidType(mat, 1); 3873 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3874 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3875 PetscCheckSameComm(mat, 1, b, 2); 3876 PetscCheckSameComm(mat, 1, x, 3); 3877 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3878 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); 3879 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); 3880 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); 3881 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3882 MatCheckPreallocated(mat, 1); 3883 3884 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3885 PetscUseTypeMethod(mat, backwardsolve, b, x); 3886 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3887 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3888 PetscFunctionReturn(0); 3889 } 3890 3891 /*@ 3892 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3893 3894 Neighbor-wise Collective 3895 3896 Input Parameters: 3897 + mat - the factored matrix 3898 . b - the right-hand-side vector 3899 - y - the vector to be added to 3900 3901 Output Parameter: 3902 . x - the result vector 3903 3904 Note: 3905 The vectors b and x cannot be the same. I.e., one cannot 3906 call `MatSolveAdd`(A,x,y,x). 3907 3908 Level: developer 3909 3910 .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3911 @*/ 3912 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3913 { 3914 PetscScalar one = 1.0; 3915 Vec tmp; 3916 3917 PetscFunctionBegin; 3918 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3919 PetscValidType(mat, 1); 3920 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3921 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3922 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3923 PetscCheckSameComm(mat, 1, b, 2); 3924 PetscCheckSameComm(mat, 1, y, 3); 3925 PetscCheckSameComm(mat, 1, x, 4); 3926 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3927 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); 3928 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); 3929 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); 3930 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); 3931 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); 3932 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3933 MatCheckPreallocated(mat, 1); 3934 3935 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3936 if (mat->factorerrortype) { 3937 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3938 PetscCall(VecSetInf(x)); 3939 } else if (mat->ops->solveadd) { 3940 PetscUseTypeMethod(mat, solveadd, b, y, x); 3941 } else { 3942 /* do the solve then the add manually */ 3943 if (x != y) { 3944 PetscCall(MatSolve(mat, b, x)); 3945 PetscCall(VecAXPY(x, one, y)); 3946 } else { 3947 PetscCall(VecDuplicate(x, &tmp)); 3948 PetscCall(VecCopy(x, tmp)); 3949 PetscCall(MatSolve(mat, b, x)); 3950 PetscCall(VecAXPY(x, one, tmp)); 3951 PetscCall(VecDestroy(&tmp)); 3952 } 3953 } 3954 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3955 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3956 PetscFunctionReturn(0); 3957 } 3958 3959 /*@ 3960 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3961 3962 Neighbor-wise Collective 3963 3964 Input Parameters: 3965 + mat - the factored matrix 3966 - b - the right-hand-side vector 3967 3968 Output Parameter: 3969 . x - the result vector 3970 3971 Notes: 3972 The vectors b and x cannot be the same. I.e., one cannot 3973 call `MatSolveTranspose`(A,x,x). 3974 3975 Most users should employ the `KSP` interface for linear solvers 3976 instead of working directly with matrix algebra routines such as this. 3977 See, e.g., `KSPCreate()`. 3978 3979 Level: developer 3980 3981 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3982 @*/ 3983 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3984 { 3985 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3986 3987 PetscFunctionBegin; 3988 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3989 PetscValidType(mat, 1); 3990 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3991 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3992 PetscCheckSameComm(mat, 1, b, 2); 3993 PetscCheckSameComm(mat, 1, x, 3); 3994 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3995 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); 3996 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); 3997 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3998 MatCheckPreallocated(mat, 1); 3999 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4000 if (mat->factorerrortype) { 4001 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4002 PetscCall(VecSetInf(x)); 4003 } else { 4004 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4005 PetscCall((*f)(mat, b, x)); 4006 } 4007 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4008 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4009 PetscFunctionReturn(0); 4010 } 4011 4012 /*@ 4013 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4014 factored matrix. 4015 4016 Neighbor-wise Collective 4017 4018 Input Parameters: 4019 + mat - the factored matrix 4020 . b - the right-hand-side vector 4021 - y - the vector to be added to 4022 4023 Output Parameter: 4024 . x - the result vector 4025 4026 Note: 4027 The vectors b and x cannot be the same. I.e., one cannot 4028 call `MatSolveTransposeAdd`(A,x,y,x). 4029 4030 Level: developer 4031 4032 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4033 @*/ 4034 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4035 { 4036 PetscScalar one = 1.0; 4037 Vec tmp; 4038 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4039 4040 PetscFunctionBegin; 4041 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4042 PetscValidType(mat, 1); 4043 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4044 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4045 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4046 PetscCheckSameComm(mat, 1, b, 2); 4047 PetscCheckSameComm(mat, 1, y, 3); 4048 PetscCheckSameComm(mat, 1, x, 4); 4049 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4050 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); 4051 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); 4052 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); 4053 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); 4054 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 4055 MatCheckPreallocated(mat, 1); 4056 4057 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4058 if (mat->factorerrortype) { 4059 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4060 PetscCall(VecSetInf(x)); 4061 } else if (f) { 4062 PetscCall((*f)(mat, b, y, x)); 4063 } else { 4064 /* do the solve then the add manually */ 4065 if (x != y) { 4066 PetscCall(MatSolveTranspose(mat, b, x)); 4067 PetscCall(VecAXPY(x, one, y)); 4068 } else { 4069 PetscCall(VecDuplicate(x, &tmp)); 4070 PetscCall(VecCopy(x, tmp)); 4071 PetscCall(MatSolveTranspose(mat, b, x)); 4072 PetscCall(VecAXPY(x, one, tmp)); 4073 PetscCall(VecDestroy(&tmp)); 4074 } 4075 } 4076 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4077 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4078 PetscFunctionReturn(0); 4079 } 4080 /* ----------------------------------------------------------------*/ 4081 4082 /*@ 4083 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4084 4085 Neighbor-wise Collective 4086 4087 Input Parameters: 4088 + mat - the matrix 4089 . b - the right hand side 4090 . omega - the relaxation factor 4091 . flag - flag indicating the type of SOR (see below) 4092 . shift - diagonal shift 4093 . its - the number of iterations 4094 - lits - the number of local iterations 4095 4096 Output Parameter: 4097 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4098 4099 SOR Flags: 4100 + `SOR_FORWARD_SWEEP` - forward SOR 4101 . `SOR_BACKWARD_SWEEP` - backward SOR 4102 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4103 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4104 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4105 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4106 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4107 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4108 upper/lower triangular part of matrix to 4109 vector (with omega) 4110 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4111 4112 Notes: 4113 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4114 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4115 on each processor. 4116 4117 Application programmers will not generally use `MatSOR()` directly, 4118 but instead will employ the `KSP`/`PC` interface. 4119 4120 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4121 4122 Most users should employ the `KSP` interface for linear solvers 4123 instead of working directly with matrix algebra routines such as this. 4124 See, e.g., `KSPCreate()`. 4125 4126 Vectors x and b CANNOT be the same 4127 4128 Notes for Advanced Users: 4129 The flags are implemented as bitwise inclusive or operations. 4130 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4131 to specify a zero initial guess for SSOR. 4132 4133 Developer Note: 4134 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4135 4136 Level: developer 4137 4138 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4139 @*/ 4140 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4141 { 4142 PetscFunctionBegin; 4143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4144 PetscValidType(mat, 1); 4145 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4146 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4147 PetscCheckSameComm(mat, 1, b, 2); 4148 PetscCheckSameComm(mat, 1, x, 8); 4149 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4150 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4151 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); 4152 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); 4153 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); 4154 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4155 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4156 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4157 4158 MatCheckPreallocated(mat, 1); 4159 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4160 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4161 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4162 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4163 PetscFunctionReturn(0); 4164 } 4165 4166 /* 4167 Default matrix copy routine. 4168 */ 4169 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4170 { 4171 PetscInt i, rstart = 0, rend = 0, nz; 4172 const PetscInt *cwork; 4173 const PetscScalar *vwork; 4174 4175 PetscFunctionBegin; 4176 if (B->assembled) PetscCall(MatZeroEntries(B)); 4177 if (str == SAME_NONZERO_PATTERN) { 4178 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4179 for (i = rstart; i < rend; i++) { 4180 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4181 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4182 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4183 } 4184 } else { 4185 PetscCall(MatAYPX(B, 0.0, A, str)); 4186 } 4187 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4188 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4189 PetscFunctionReturn(0); 4190 } 4191 4192 /*@ 4193 MatCopy - Copies a matrix to another matrix. 4194 4195 Collective on A 4196 4197 Input Parameters: 4198 + A - the matrix 4199 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4200 4201 Output Parameter: 4202 . B - where the copy is put 4203 4204 Notes: 4205 If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash. 4206 4207 `MatCopy()` copies the matrix entries of a matrix to another existing 4208 matrix (after first zeroing the second matrix). A related routine is 4209 `MatConvert()`, which first creates a new matrix and then copies the data. 4210 4211 Level: intermediate 4212 4213 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()` 4214 @*/ 4215 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4216 { 4217 PetscInt i; 4218 4219 PetscFunctionBegin; 4220 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4221 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4222 PetscValidType(A, 1); 4223 PetscValidType(B, 2); 4224 PetscCheckSameComm(A, 1, B, 2); 4225 MatCheckPreallocated(B, 2); 4226 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4227 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4228 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, 4229 A->cmap->N, B->cmap->N); 4230 MatCheckPreallocated(A, 1); 4231 if (A == B) PetscFunctionReturn(0); 4232 4233 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4234 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4235 else PetscCall(MatCopy_Basic(A, B, str)); 4236 4237 B->stencil.dim = A->stencil.dim; 4238 B->stencil.noc = A->stencil.noc; 4239 for (i = 0; i <= A->stencil.dim; i++) { 4240 B->stencil.dims[i] = A->stencil.dims[i]; 4241 B->stencil.starts[i] = A->stencil.starts[i]; 4242 } 4243 4244 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4245 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4246 PetscFunctionReturn(0); 4247 } 4248 4249 /*@C 4250 MatConvert - Converts a matrix to another matrix, either of the same 4251 or different type. 4252 4253 Collective 4254 4255 Input Parameters: 4256 + mat - the matrix 4257 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4258 same type as the original matrix. 4259 - reuse - denotes if the destination matrix is to be created or reused. 4260 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 4261 `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). 4262 4263 Output Parameter: 4264 . M - pointer to place new matrix 4265 4266 Notes: 4267 `MatConvert()` first creates a new matrix and then copies the data from 4268 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4269 entries of one matrix to another already existing matrix context. 4270 4271 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4272 the MPI communicator of the generated matrix is always the same as the communicator 4273 of the input matrix. 4274 4275 Level: intermediate 4276 4277 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4278 @*/ 4279 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4280 { 4281 PetscBool sametype, issame, flg; 4282 PetscBool3 issymmetric, ishermitian; 4283 char convname[256], mtype[256]; 4284 Mat B; 4285 4286 PetscFunctionBegin; 4287 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4288 PetscValidType(mat, 1); 4289 PetscValidPointer(M, 4); 4290 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4291 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4292 MatCheckPreallocated(mat, 1); 4293 4294 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4295 if (flg) newtype = mtype; 4296 4297 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4298 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4299 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4300 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"); 4301 4302 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4303 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4304 PetscFunctionReturn(0); 4305 } 4306 4307 /* Cache Mat options because some converters use MatHeaderReplace */ 4308 issymmetric = mat->symmetric; 4309 ishermitian = mat->hermitian; 4310 4311 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4312 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4313 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4314 } else { 4315 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4316 const char *prefix[3] = {"seq", "mpi", ""}; 4317 PetscInt i; 4318 /* 4319 Order of precedence: 4320 0) See if newtype is a superclass of the current matrix. 4321 1) See if a specialized converter is known to the current matrix. 4322 2) See if a specialized converter is known to the desired matrix class. 4323 3) See if a good general converter is registered for the desired class 4324 (as of 6/27/03 only MATMPIADJ falls into this category). 4325 4) See if a good general converter is known for the current matrix. 4326 5) Use a really basic converter. 4327 */ 4328 4329 /* 0) See if newtype is a superclass of the current matrix. 4330 i.e mat is mpiaij and newtype is aij */ 4331 for (i = 0; i < 2; i++) { 4332 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4333 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4334 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4335 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4336 if (flg) { 4337 if (reuse == MAT_INPLACE_MATRIX) { 4338 PetscCall(PetscInfo(mat, "Early return\n")); 4339 PetscFunctionReturn(0); 4340 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4341 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4342 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4343 PetscFunctionReturn(0); 4344 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4345 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4346 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4347 PetscFunctionReturn(0); 4348 } 4349 } 4350 } 4351 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4352 for (i = 0; i < 3; i++) { 4353 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4354 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4355 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4356 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4357 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4358 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4359 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4360 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4361 if (conv) goto foundconv; 4362 } 4363 4364 /* 2) See if a specialized converter is known to the desired matrix class. */ 4365 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4366 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4367 PetscCall(MatSetType(B, newtype)); 4368 for (i = 0; i < 3; i++) { 4369 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4370 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4371 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4372 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4373 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4374 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4375 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4376 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4377 if (conv) { 4378 PetscCall(MatDestroy(&B)); 4379 goto foundconv; 4380 } 4381 } 4382 4383 /* 3) See if a good general converter is registered for the desired class */ 4384 conv = B->ops->convertfrom; 4385 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4386 PetscCall(MatDestroy(&B)); 4387 if (conv) goto foundconv; 4388 4389 /* 4) See if a good general converter is known for the current matrix */ 4390 if (mat->ops->convert) conv = mat->ops->convert; 4391 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4392 if (conv) goto foundconv; 4393 4394 /* 5) Use a really basic converter. */ 4395 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4396 conv = MatConvert_Basic; 4397 4398 foundconv: 4399 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4400 PetscCall((*conv)(mat, newtype, reuse, M)); 4401 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4402 /* the block sizes must be same if the mappings are copied over */ 4403 (*M)->rmap->bs = mat->rmap->bs; 4404 (*M)->cmap->bs = mat->cmap->bs; 4405 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4406 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4407 (*M)->rmap->mapping = mat->rmap->mapping; 4408 (*M)->cmap->mapping = mat->cmap->mapping; 4409 } 4410 (*M)->stencil.dim = mat->stencil.dim; 4411 (*M)->stencil.noc = mat->stencil.noc; 4412 for (i = 0; i <= mat->stencil.dim; i++) { 4413 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4414 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4415 } 4416 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4417 } 4418 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4419 4420 /* Copy Mat options */ 4421 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4422 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4423 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4424 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4425 PetscFunctionReturn(0); 4426 } 4427 4428 /*@C 4429 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4430 4431 Not Collective 4432 4433 Input Parameter: 4434 . mat - the matrix, must be a factored matrix 4435 4436 Output Parameter: 4437 . type - the string name of the package (do not free this string) 4438 4439 Level: intermediate 4440 4441 Note: 4442 In Fortran you pass in a empty string and the package name will be copied into it. 4443 (Make sure the string is long enough) 4444 4445 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4446 @*/ 4447 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4448 { 4449 PetscErrorCode (*conv)(Mat, MatSolverType *); 4450 4451 PetscFunctionBegin; 4452 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4453 PetscValidType(mat, 1); 4454 PetscValidPointer(type, 2); 4455 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4456 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4457 if (conv) PetscCall((*conv)(mat, type)); 4458 else *type = MATSOLVERPETSC; 4459 PetscFunctionReturn(0); 4460 } 4461 4462 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4463 struct _MatSolverTypeForSpecifcType { 4464 MatType mtype; 4465 /* no entry for MAT_FACTOR_NONE */ 4466 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4467 MatSolverTypeForSpecifcType next; 4468 }; 4469 4470 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4471 struct _MatSolverTypeHolder { 4472 char *name; 4473 MatSolverTypeForSpecifcType handlers; 4474 MatSolverTypeHolder next; 4475 }; 4476 4477 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4478 4479 /*@C 4480 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4481 4482 Input Parameters: 4483 + package - name of the package, for example petsc or superlu 4484 . mtype - the matrix type that works with this package 4485 . ftype - the type of factorization supported by the package 4486 - createfactor - routine that will create the factored matrix ready to be used 4487 4488 Level: developer 4489 4490 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4491 @*/ 4492 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4493 { 4494 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4495 PetscBool flg; 4496 MatSolverTypeForSpecifcType inext, iprev = NULL; 4497 4498 PetscFunctionBegin; 4499 PetscCall(MatInitializePackage()); 4500 if (!next) { 4501 PetscCall(PetscNew(&MatSolverTypeHolders)); 4502 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4503 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4504 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4505 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4506 PetscFunctionReturn(0); 4507 } 4508 while (next) { 4509 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4510 if (flg) { 4511 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4512 inext = next->handlers; 4513 while (inext) { 4514 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4515 if (flg) { 4516 inext->createfactor[(int)ftype - 1] = createfactor; 4517 PetscFunctionReturn(0); 4518 } 4519 iprev = inext; 4520 inext = inext->next; 4521 } 4522 PetscCall(PetscNew(&iprev->next)); 4523 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4524 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4525 PetscFunctionReturn(0); 4526 } 4527 prev = next; 4528 next = next->next; 4529 } 4530 PetscCall(PetscNew(&prev->next)); 4531 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4532 PetscCall(PetscNew(&prev->next->handlers)); 4533 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4534 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4535 PetscFunctionReturn(0); 4536 } 4537 4538 /*@C 4539 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4540 4541 Input Parameters: 4542 + type - name of the package, for example petsc or superlu 4543 . ftype - the type of factorization supported by the type 4544 - mtype - the matrix type that works with this type 4545 4546 Output Parameters: 4547 + foundtype - `PETSC_TRUE` if the type was registered 4548 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4549 - createfactor - routine that will create the factored matrix ready to be used or NULL if not found 4550 4551 Level: developer 4552 4553 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4554 @*/ 4555 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4556 { 4557 MatSolverTypeHolder next = MatSolverTypeHolders; 4558 PetscBool flg; 4559 MatSolverTypeForSpecifcType inext; 4560 4561 PetscFunctionBegin; 4562 if (foundtype) *foundtype = PETSC_FALSE; 4563 if (foundmtype) *foundmtype = PETSC_FALSE; 4564 if (createfactor) *createfactor = NULL; 4565 4566 if (type) { 4567 while (next) { 4568 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4569 if (flg) { 4570 if (foundtype) *foundtype = PETSC_TRUE; 4571 inext = next->handlers; 4572 while (inext) { 4573 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4574 if (flg) { 4575 if (foundmtype) *foundmtype = PETSC_TRUE; 4576 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4577 PetscFunctionReturn(0); 4578 } 4579 inext = inext->next; 4580 } 4581 } 4582 next = next->next; 4583 } 4584 } else { 4585 while (next) { 4586 inext = next->handlers; 4587 while (inext) { 4588 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4589 if (flg && inext->createfactor[(int)ftype - 1]) { 4590 if (foundtype) *foundtype = PETSC_TRUE; 4591 if (foundmtype) *foundmtype = PETSC_TRUE; 4592 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4593 PetscFunctionReturn(0); 4594 } 4595 inext = inext->next; 4596 } 4597 next = next->next; 4598 } 4599 /* try with base classes inext->mtype */ 4600 next = MatSolverTypeHolders; 4601 while (next) { 4602 inext = next->handlers; 4603 while (inext) { 4604 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4605 if (flg && inext->createfactor[(int)ftype - 1]) { 4606 if (foundtype) *foundtype = PETSC_TRUE; 4607 if (foundmtype) *foundmtype = PETSC_TRUE; 4608 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4609 PetscFunctionReturn(0); 4610 } 4611 inext = inext->next; 4612 } 4613 next = next->next; 4614 } 4615 } 4616 PetscFunctionReturn(0); 4617 } 4618 4619 PetscErrorCode MatSolverTypeDestroy(void) 4620 { 4621 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4622 MatSolverTypeForSpecifcType inext, iprev; 4623 4624 PetscFunctionBegin; 4625 while (next) { 4626 PetscCall(PetscFree(next->name)); 4627 inext = next->handlers; 4628 while (inext) { 4629 PetscCall(PetscFree(inext->mtype)); 4630 iprev = inext; 4631 inext = inext->next; 4632 PetscCall(PetscFree(iprev)); 4633 } 4634 prev = next; 4635 next = next->next; 4636 PetscCall(PetscFree(prev)); 4637 } 4638 MatSolverTypeHolders = NULL; 4639 PetscFunctionReturn(0); 4640 } 4641 4642 /*@C 4643 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4644 4645 Logically Collective 4646 4647 Input Parameters: 4648 . mat - the matrix 4649 4650 Output Parameters: 4651 . flg - `PETSC_TRUE` if uses the ordering 4652 4653 Note: 4654 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4655 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4656 4657 Level: developer 4658 4659 .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4660 @*/ 4661 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4662 { 4663 PetscFunctionBegin; 4664 *flg = mat->canuseordering; 4665 PetscFunctionReturn(0); 4666 } 4667 4668 /*@C 4669 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4670 4671 Logically Collective 4672 4673 Input Parameters: 4674 . mat - the matrix obtained with `MatGetFactor()` 4675 4676 Output Parameters: 4677 . otype - the preferred type 4678 4679 Level: developer 4680 4681 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4682 @*/ 4683 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4684 { 4685 PetscFunctionBegin; 4686 *otype = mat->preferredordering[ftype]; 4687 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4688 PetscFunctionReturn(0); 4689 } 4690 4691 /*@C 4692 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4693 4694 Collective 4695 4696 Input Parameters: 4697 + mat - the matrix 4698 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4699 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4700 4701 Output Parameters: 4702 . f - the factor matrix used with MatXXFactorSymbolic() calls 4703 4704 Options Database Key: 4705 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4706 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4707 4708 Notes: 4709 Users usually access the factorization solvers via `KSP` 4710 4711 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4712 such as pastix, superlu, mumps etc. 4713 4714 PETSc must have been ./configure to use the external solver, using the option --download-package 4715 4716 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4717 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4718 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4719 4720 Developer Note: 4721 This should actually be called `MatCreateFactor()` since it creates a new factor object 4722 4723 Level: intermediate 4724 4725 .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4726 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4727 @*/ 4728 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4729 { 4730 PetscBool foundtype, foundmtype; 4731 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4732 4733 PetscFunctionBegin; 4734 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4735 PetscValidType(mat, 1); 4736 4737 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4738 MatCheckPreallocated(mat, 1); 4739 4740 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4741 if (!foundtype) { 4742 if (type) { 4743 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], 4744 ((PetscObject)mat)->type_name, type); 4745 } else { 4746 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); 4747 } 4748 } 4749 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4750 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); 4751 4752 PetscCall((*conv)(mat, ftype, f)); 4753 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4754 PetscFunctionReturn(0); 4755 } 4756 4757 /*@C 4758 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4759 4760 Not Collective 4761 4762 Input Parameters: 4763 + mat - the matrix 4764 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4765 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4766 4767 Output Parameter: 4768 . flg - PETSC_TRUE if the factorization is available 4769 4770 Notes: 4771 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4772 such as pastix, superlu, mumps etc. 4773 4774 PETSc must have been ./configure to use the external solver, using the option --download-package 4775 4776 Developer Note: 4777 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4778 4779 Level: intermediate 4780 4781 .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4782 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4783 @*/ 4784 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4785 { 4786 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4787 4788 PetscFunctionBegin; 4789 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4790 PetscValidType(mat, 1); 4791 PetscValidBoolPointer(flg, 4); 4792 4793 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4794 MatCheckPreallocated(mat, 1); 4795 4796 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4797 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4798 PetscFunctionReturn(0); 4799 } 4800 4801 /*@ 4802 MatDuplicate - Duplicates a matrix including the non-zero structure. 4803 4804 Collective 4805 4806 Input Parameters: 4807 + mat - the matrix 4808 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4809 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4810 4811 Output Parameter: 4812 . M - pointer to place new matrix 4813 4814 Level: intermediate 4815 4816 Notes: 4817 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4818 4819 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. 4820 4821 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 4822 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4823 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4824 4825 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4826 @*/ 4827 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4828 { 4829 Mat B; 4830 VecType vtype; 4831 PetscInt i; 4832 PetscObject dm; 4833 void (*viewf)(void); 4834 4835 PetscFunctionBegin; 4836 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4837 PetscValidType(mat, 1); 4838 PetscValidPointer(M, 3); 4839 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4840 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4841 MatCheckPreallocated(mat, 1); 4842 4843 *M = NULL; 4844 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4845 PetscUseTypeMethod(mat, duplicate, op, M); 4846 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4847 B = *M; 4848 4849 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4850 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4851 PetscCall(MatGetVecType(mat, &vtype)); 4852 PetscCall(MatSetVecType(B, vtype)); 4853 4854 B->stencil.dim = mat->stencil.dim; 4855 B->stencil.noc = mat->stencil.noc; 4856 for (i = 0; i <= mat->stencil.dim; i++) { 4857 B->stencil.dims[i] = mat->stencil.dims[i]; 4858 B->stencil.starts[i] = mat->stencil.starts[i]; 4859 } 4860 4861 B->nooffproczerorows = mat->nooffproczerorows; 4862 B->nooffprocentries = mat->nooffprocentries; 4863 4864 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4865 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4866 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4867 PetscFunctionReturn(0); 4868 } 4869 4870 /*@ 4871 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4872 4873 Logically Collective 4874 4875 Input Parameters: 4876 + mat - the matrix 4877 - v - the vector for storing the diagonal 4878 4879 Output Parameter: 4880 . v - the diagonal of the matrix 4881 4882 Level: intermediate 4883 4884 Note: 4885 Currently only correct in parallel for square matrices. 4886 4887 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4888 @*/ 4889 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4890 { 4891 PetscFunctionBegin; 4892 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4893 PetscValidType(mat, 1); 4894 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4895 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4896 MatCheckPreallocated(mat, 1); 4897 4898 PetscUseTypeMethod(mat, getdiagonal, v); 4899 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4900 PetscFunctionReturn(0); 4901 } 4902 4903 /*@C 4904 MatGetRowMin - Gets the minimum value (of the real part) of each 4905 row of the matrix 4906 4907 Logically Collective 4908 4909 Input Parameter: 4910 . mat - the matrix 4911 4912 Output Parameters: 4913 + v - the vector for storing the maximums 4914 - idx - the indices of the column found for each row (optional) 4915 4916 Level: intermediate 4917 4918 Note: 4919 The result of this call are the same as if one converted the matrix to dense format 4920 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4921 4922 This code is only implemented for a couple of matrix formats. 4923 4924 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4925 `MatGetRowMax()` 4926 @*/ 4927 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4928 { 4929 PetscFunctionBegin; 4930 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4931 PetscValidType(mat, 1); 4932 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4933 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4934 4935 if (!mat->cmap->N) { 4936 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4937 if (idx) { 4938 PetscInt i, m = mat->rmap->n; 4939 for (i = 0; i < m; i++) idx[i] = -1; 4940 } 4941 } else { 4942 MatCheckPreallocated(mat, 1); 4943 } 4944 PetscUseTypeMethod(mat, getrowmin, v, idx); 4945 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4946 PetscFunctionReturn(0); 4947 } 4948 4949 /*@C 4950 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4951 row of the matrix 4952 4953 Logically Collective 4954 4955 Input Parameter: 4956 . mat - the matrix 4957 4958 Output Parameters: 4959 + v - the vector for storing the minimums 4960 - idx - the indices of the column found for each row (or NULL if not needed) 4961 4962 Level: intermediate 4963 4964 Notes: 4965 if a row is completely empty or has only 0.0 values then the idx[] value for that 4966 row is 0 (the first column). 4967 4968 This code is only implemented for a couple of matrix formats. 4969 4970 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4971 @*/ 4972 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4973 { 4974 PetscFunctionBegin; 4975 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4976 PetscValidType(mat, 1); 4977 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4978 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4979 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4980 4981 if (!mat->cmap->N) { 4982 PetscCall(VecSet(v, 0.0)); 4983 if (idx) { 4984 PetscInt i, m = mat->rmap->n; 4985 for (i = 0; i < m; i++) idx[i] = -1; 4986 } 4987 } else { 4988 MatCheckPreallocated(mat, 1); 4989 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4990 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4991 } 4992 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4993 PetscFunctionReturn(0); 4994 } 4995 4996 /*@C 4997 MatGetRowMax - Gets the maximum value (of the real part) of each 4998 row of the matrix 4999 5000 Logically Collective 5001 5002 Input Parameter: 5003 . mat - the matrix 5004 5005 Output Parameters: 5006 + v - the vector for storing the maximums 5007 - idx - the indices of the column found for each row (optional) 5008 5009 Level: intermediate 5010 5011 Notes: 5012 The result of this call are the same as if one converted the matrix to dense format 5013 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5014 5015 This code is only implemented for a couple of matrix formats. 5016 5017 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5018 @*/ 5019 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5020 { 5021 PetscFunctionBegin; 5022 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5023 PetscValidType(mat, 1); 5024 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5025 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5026 5027 if (!mat->cmap->N) { 5028 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5029 if (idx) { 5030 PetscInt i, m = mat->rmap->n; 5031 for (i = 0; i < m; i++) idx[i] = -1; 5032 } 5033 } else { 5034 MatCheckPreallocated(mat, 1); 5035 PetscUseTypeMethod(mat, getrowmax, v, idx); 5036 } 5037 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5038 PetscFunctionReturn(0); 5039 } 5040 5041 /*@C 5042 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5043 row of the matrix 5044 5045 Logically Collective 5046 5047 Input Parameter: 5048 . mat - the matrix 5049 5050 Output Parameters: 5051 + v - the vector for storing the maximums 5052 - idx - the indices of the column found for each row (or NULL if not needed) 5053 5054 Level: intermediate 5055 5056 Notes: 5057 if a row is completely empty or has only 0.0 values then the idx[] value for that 5058 row is 0 (the first column). 5059 5060 This code is only implemented for a couple of matrix formats. 5061 5062 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5063 @*/ 5064 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5065 { 5066 PetscFunctionBegin; 5067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5068 PetscValidType(mat, 1); 5069 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5070 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5071 5072 if (!mat->cmap->N) { 5073 PetscCall(VecSet(v, 0.0)); 5074 if (idx) { 5075 PetscInt i, m = mat->rmap->n; 5076 for (i = 0; i < m; i++) idx[i] = -1; 5077 } 5078 } else { 5079 MatCheckPreallocated(mat, 1); 5080 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5081 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5082 } 5083 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5084 PetscFunctionReturn(0); 5085 } 5086 5087 /*@ 5088 MatGetRowSum - Gets the sum of each row of the matrix 5089 5090 Logically or Neighborhood Collective 5091 5092 Input Parameters: 5093 . mat - the matrix 5094 5095 Output Parameter: 5096 . v - the vector for storing the sum of rows 5097 5098 Level: intermediate 5099 5100 Notes: 5101 This code is slow since it is not currently specialized for different formats 5102 5103 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5104 @*/ 5105 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5106 { 5107 Vec ones; 5108 5109 PetscFunctionBegin; 5110 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5111 PetscValidType(mat, 1); 5112 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5113 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5114 MatCheckPreallocated(mat, 1); 5115 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5116 PetscCall(VecSet(ones, 1.)); 5117 PetscCall(MatMult(mat, ones, v)); 5118 PetscCall(VecDestroy(&ones)); 5119 PetscFunctionReturn(0); 5120 } 5121 5122 /*@ 5123 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5124 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5125 5126 Collective 5127 5128 Input Parameter: 5129 . mat - the matrix to provide the transpose 5130 5131 Output Parameter: 5132 . 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 5133 5134 Level: advanced 5135 5136 Note: 5137 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 5138 routine allows bypassing that call. 5139 5140 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5141 @*/ 5142 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5143 { 5144 PetscContainer rB = NULL; 5145 MatParentState *rb = NULL; 5146 5147 PetscFunctionBegin; 5148 PetscCall(PetscNew(&rb)); 5149 rb->id = ((PetscObject)mat)->id; 5150 rb->state = 0; 5151 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5152 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5153 PetscCall(PetscContainerSetPointer(rB, rb)); 5154 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5155 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5156 PetscCall(PetscObjectDereference((PetscObject)rB)); 5157 PetscFunctionReturn(0); 5158 } 5159 5160 /*@ 5161 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5162 5163 Collective 5164 5165 Input Parameters: 5166 + mat - the matrix to transpose 5167 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5168 5169 Output Parameter: 5170 . B - the transpose 5171 5172 Notes: 5173 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5174 5175 `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 5176 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5177 5178 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. 5179 5180 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5181 5182 If mat is unchanged from the last call this function returns immediately without recomputing the result 5183 5184 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5185 5186 Level: intermediate 5187 5188 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5189 `MatTransposeSymbolic()` 5190 @*/ 5191 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5192 { 5193 PetscContainer rB = NULL; 5194 MatParentState *rb = NULL; 5195 5196 PetscFunctionBegin; 5197 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5198 PetscValidType(mat, 1); 5199 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5200 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5201 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5202 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5203 MatCheckPreallocated(mat, 1); 5204 if (reuse == MAT_REUSE_MATRIX) { 5205 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5206 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5207 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5208 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5209 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0); 5210 } 5211 5212 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5213 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5214 PetscUseTypeMethod(mat, transpose, reuse, B); 5215 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5216 } 5217 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5218 5219 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5220 if (reuse != MAT_INPLACE_MATRIX) { 5221 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5222 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5223 rb->state = ((PetscObject)mat)->state; 5224 rb->nonzerostate = mat->nonzerostate; 5225 } 5226 PetscFunctionReturn(0); 5227 } 5228 5229 /*@ 5230 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5231 5232 Collective on A 5233 5234 Input Parameters: 5235 . A - the matrix to transpose 5236 5237 Output Parameter: 5238 . 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 5239 numerical portion. 5240 5241 Level: intermediate 5242 5243 Note: 5244 This is not supported for many matrix types, use `MatTranspose()` in those cases 5245 5246 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5247 @*/ 5248 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5249 { 5250 PetscFunctionBegin; 5251 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5252 PetscValidType(A, 1); 5253 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5254 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5255 PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 5256 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5257 PetscCall((*A->ops->transposesymbolic)(A, B)); 5258 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5259 5260 PetscCall(MatTransposeSetPrecursor(A, *B)); 5261 PetscFunctionReturn(0); 5262 } 5263 5264 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5265 { 5266 PetscContainer rB; 5267 MatParentState *rb; 5268 5269 PetscFunctionBegin; 5270 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5271 PetscValidType(A, 1); 5272 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5273 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5274 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5275 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5276 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5277 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5278 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5279 PetscFunctionReturn(0); 5280 } 5281 5282 /*@ 5283 MatIsTranspose - Test whether a matrix is another one's transpose, 5284 or its own, in which case it tests symmetry. 5285 5286 Collective on A 5287 5288 Input Parameters: 5289 + A - the matrix to test 5290 - B - the matrix to test against, this can equal the first parameter 5291 5292 Output Parameters: 5293 . flg - the result 5294 5295 Notes: 5296 Only available for `MATAIJ` matrices. 5297 5298 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5299 test involves parallel copies of the block-offdiagonal parts of the matrix. 5300 5301 Level: intermediate 5302 5303 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5304 @*/ 5305 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5306 { 5307 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5308 5309 PetscFunctionBegin; 5310 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5311 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5312 PetscValidBoolPointer(flg, 4); 5313 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5314 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5315 *flg = PETSC_FALSE; 5316 if (f && g) { 5317 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5318 PetscCall((*f)(A, B, tol, flg)); 5319 } else { 5320 MatType mattype; 5321 5322 PetscCall(MatGetType(f ? B : A, &mattype)); 5323 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5324 } 5325 PetscFunctionReturn(0); 5326 } 5327 5328 /*@ 5329 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5330 5331 Collective 5332 5333 Input Parameters: 5334 + mat - the matrix to transpose and complex conjugate 5335 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5336 5337 Output Parameter: 5338 . B - the Hermitian transpose 5339 5340 Level: intermediate 5341 5342 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5343 @*/ 5344 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5345 { 5346 PetscFunctionBegin; 5347 PetscCall(MatTranspose(mat, reuse, B)); 5348 #if defined(PETSC_USE_COMPLEX) 5349 PetscCall(MatConjugate(*B)); 5350 #endif 5351 PetscFunctionReturn(0); 5352 } 5353 5354 /*@ 5355 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5356 5357 Collective on A 5358 5359 Input Parameters: 5360 + A - the matrix to test 5361 - B - the matrix to test against, this can equal the first parameter 5362 5363 Output Parameters: 5364 . flg - the result 5365 5366 Notes: 5367 Only available for `MATAIJ` matrices. 5368 5369 The sequential algorithm 5370 has a running time of the order of the number of nonzeros; the parallel 5371 test involves parallel copies of the block-offdiagonal parts of the matrix. 5372 5373 Level: intermediate 5374 5375 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5376 @*/ 5377 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5378 { 5379 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5380 5381 PetscFunctionBegin; 5382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5383 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5384 PetscValidBoolPointer(flg, 4); 5385 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5386 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5387 if (f && g) { 5388 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5389 PetscCall((*f)(A, B, tol, flg)); 5390 } 5391 PetscFunctionReturn(0); 5392 } 5393 5394 /*@ 5395 MatPermute - Creates a new matrix with rows and columns permuted from the 5396 original. 5397 5398 Collective 5399 5400 Input Parameters: 5401 + mat - the matrix to permute 5402 . row - row permutation, each processor supplies only the permutation for its rows 5403 - col - column permutation, each processor supplies only the permutation for its columns 5404 5405 Output Parameters: 5406 . B - the permuted matrix 5407 5408 Level: advanced 5409 5410 Note: 5411 The index sets map from row/col of permuted matrix to row/col of original matrix. 5412 The index sets should be on the same communicator as mat and have the same local sizes. 5413 5414 Developer Note: 5415 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5416 exploit the fact that row and col are permutations, consider implementing the 5417 more general `MatCreateSubMatrix()` instead. 5418 5419 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5420 @*/ 5421 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5422 { 5423 PetscFunctionBegin; 5424 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5425 PetscValidType(mat, 1); 5426 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5427 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5428 PetscValidPointer(B, 4); 5429 PetscCheckSameComm(mat, 1, row, 2); 5430 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5431 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5432 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5433 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5434 MatCheckPreallocated(mat, 1); 5435 5436 if (mat->ops->permute) { 5437 PetscUseTypeMethod(mat, permute, row, col, B); 5438 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5439 } else { 5440 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5441 } 5442 PetscFunctionReturn(0); 5443 } 5444 5445 /*@ 5446 MatEqual - Compares two matrices. 5447 5448 Collective on A 5449 5450 Input Parameters: 5451 + A - the first matrix 5452 - B - the second matrix 5453 5454 Output Parameter: 5455 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5456 5457 Level: intermediate 5458 5459 .seealso: `Mat` 5460 @*/ 5461 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5462 { 5463 PetscFunctionBegin; 5464 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5465 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5466 PetscValidType(A, 1); 5467 PetscValidType(B, 2); 5468 PetscValidBoolPointer(flg, 3); 5469 PetscCheckSameComm(A, 1, B, 2); 5470 MatCheckPreallocated(A, 1); 5471 MatCheckPreallocated(B, 2); 5472 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5473 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5474 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, 5475 B->cmap->N); 5476 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5477 PetscUseTypeMethod(A, equal, B, flg); 5478 } else { 5479 PetscCall(MatMultEqual(A, B, 10, flg)); 5480 } 5481 PetscFunctionReturn(0); 5482 } 5483 5484 /*@ 5485 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5486 matrices that are stored as vectors. Either of the two scaling 5487 matrices can be NULL. 5488 5489 Collective 5490 5491 Input Parameters: 5492 + mat - the matrix to be scaled 5493 . l - the left scaling vector (or NULL) 5494 - r - the right scaling vector (or NULL) 5495 5496 Note: 5497 `MatDiagonalScale()` computes A = LAR, where 5498 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5499 The L scales the rows of the matrix, the R scales the columns of the matrix. 5500 5501 Level: intermediate 5502 5503 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5504 @*/ 5505 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5506 { 5507 PetscFunctionBegin; 5508 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5509 PetscValidType(mat, 1); 5510 if (l) { 5511 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5512 PetscCheckSameComm(mat, 1, l, 2); 5513 } 5514 if (r) { 5515 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5516 PetscCheckSameComm(mat, 1, r, 3); 5517 } 5518 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5519 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5520 MatCheckPreallocated(mat, 1); 5521 if (!l && !r) PetscFunctionReturn(0); 5522 5523 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5524 PetscUseTypeMethod(mat, diagonalscale, l, r); 5525 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5526 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5527 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5528 PetscFunctionReturn(0); 5529 } 5530 5531 /*@ 5532 MatScale - Scales all elements of a matrix by a given number. 5533 5534 Logically Collective 5535 5536 Input Parameters: 5537 + mat - the matrix to be scaled 5538 - a - the scaling value 5539 5540 Output Parameter: 5541 . mat - the scaled matrix 5542 5543 Level: intermediate 5544 5545 .seealso: `Mat`, `MatDiagonalScale()` 5546 @*/ 5547 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5548 { 5549 PetscFunctionBegin; 5550 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5551 PetscValidType(mat, 1); 5552 PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 5553 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5554 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5555 PetscValidLogicalCollectiveScalar(mat, a, 2); 5556 MatCheckPreallocated(mat, 1); 5557 5558 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5559 if (a != (PetscScalar)1.0) { 5560 PetscUseTypeMethod(mat, scale, a); 5561 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5562 } 5563 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5564 PetscFunctionReturn(0); 5565 } 5566 5567 /*@ 5568 MatNorm - Calculates various norms of a matrix. 5569 5570 Collective 5571 5572 Input Parameters: 5573 + mat - the matrix 5574 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5575 5576 Output Parameter: 5577 . nrm - the resulting norm 5578 5579 Level: intermediate 5580 5581 .seealso: `Mat` 5582 @*/ 5583 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5584 { 5585 PetscFunctionBegin; 5586 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5587 PetscValidType(mat, 1); 5588 PetscValidRealPointer(nrm, 3); 5589 5590 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5591 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5592 MatCheckPreallocated(mat, 1); 5593 5594 PetscUseTypeMethod(mat, norm, type, nrm); 5595 PetscFunctionReturn(0); 5596 } 5597 5598 /* 5599 This variable is used to prevent counting of MatAssemblyBegin() that 5600 are called from within a MatAssemblyEnd(). 5601 */ 5602 static PetscInt MatAssemblyEnd_InUse = 0; 5603 /*@ 5604 MatAssemblyBegin - Begins assembling the matrix. This routine should 5605 be called after completing all calls to `MatSetValues()`. 5606 5607 Collective 5608 5609 Input Parameters: 5610 + mat - the matrix 5611 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5612 5613 Notes: 5614 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5615 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5616 5617 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5618 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5619 using the matrix. 5620 5621 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5622 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 5623 a global collective operation requiring all processes that share the matrix. 5624 5625 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5626 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5627 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5628 5629 Level: beginner 5630 5631 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5632 @*/ 5633 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5634 { 5635 PetscFunctionBegin; 5636 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5637 PetscValidType(mat, 1); 5638 MatCheckPreallocated(mat, 1); 5639 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5640 if (mat->assembled) { 5641 mat->was_assembled = PETSC_TRUE; 5642 mat->assembled = PETSC_FALSE; 5643 } 5644 5645 if (!MatAssemblyEnd_InUse) { 5646 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5647 PetscTryTypeMethod(mat, assemblybegin, type); 5648 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5649 } else PetscTryTypeMethod(mat, assemblybegin, type); 5650 PetscFunctionReturn(0); 5651 } 5652 5653 /*@ 5654 MatAssembled - Indicates if a matrix has been assembled and is ready for 5655 use; for example, in matrix-vector product. 5656 5657 Not Collective 5658 5659 Input Parameter: 5660 . mat - the matrix 5661 5662 Output Parameter: 5663 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5664 5665 Level: advanced 5666 5667 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5668 @*/ 5669 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5670 { 5671 PetscFunctionBegin; 5672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5673 PetscValidBoolPointer(assembled, 2); 5674 *assembled = mat->assembled; 5675 PetscFunctionReturn(0); 5676 } 5677 5678 /*@ 5679 MatAssemblyEnd - Completes assembling the matrix. This routine should 5680 be called after `MatAssemblyBegin()`. 5681 5682 Collective on Mat 5683 5684 Input Parameters: 5685 + mat - the matrix 5686 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5687 5688 Options Database Keys: 5689 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5690 . -mat_view ::ascii_info_detail - Prints more detailed info 5691 . -mat_view - Prints matrix in ASCII format 5692 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5693 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5694 . -display <name> - Sets display name (default is host) 5695 . -draw_pause <sec> - Sets number of seconds to pause after display 5696 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5697 . -viewer_socket_machine <machine> - Machine to use for socket 5698 . -viewer_socket_port <port> - Port number to use for socket 5699 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5700 5701 Level: beginner 5702 5703 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5704 @*/ 5705 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5706 { 5707 static PetscInt inassm = 0; 5708 PetscBool flg = PETSC_FALSE; 5709 5710 PetscFunctionBegin; 5711 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5712 PetscValidType(mat, 1); 5713 5714 inassm++; 5715 MatAssemblyEnd_InUse++; 5716 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5717 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5718 PetscTryTypeMethod(mat, assemblyend, type); 5719 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5720 } else PetscTryTypeMethod(mat, assemblyend, type); 5721 5722 /* Flush assembly is not a true assembly */ 5723 if (type != MAT_FLUSH_ASSEMBLY) { 5724 if (mat->num_ass) { 5725 if (!mat->symmetry_eternal) { 5726 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5727 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5728 } 5729 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5730 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5731 } 5732 mat->num_ass++; 5733 mat->assembled = PETSC_TRUE; 5734 mat->ass_nonzerostate = mat->nonzerostate; 5735 } 5736 5737 mat->insertmode = NOT_SET_VALUES; 5738 MatAssemblyEnd_InUse--; 5739 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5740 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5741 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5742 5743 if (mat->checksymmetryonassembly) { 5744 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5745 if (flg) { 5746 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5747 } else { 5748 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5749 } 5750 } 5751 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5752 } 5753 inassm--; 5754 PetscFunctionReturn(0); 5755 } 5756 5757 /*@ 5758 MatSetOption - Sets a parameter option for a matrix. Some options 5759 may be specific to certain storage formats. Some options 5760 determine how values will be inserted (or added). Sorted, 5761 row-oriented input will generally assemble the fastest. The default 5762 is row-oriented. 5763 5764 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5765 5766 Input Parameters: 5767 + mat - the matrix 5768 . option - the option, one of those listed below (and possibly others), 5769 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5770 5771 Options Describing Matrix Structure: 5772 + `MAT_SPD` - symmetric positive definite 5773 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5774 . `MAT_HERMITIAN` - transpose is the complex conjugation 5775 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5776 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5777 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5778 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5779 5780 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5781 do not need to be computed (usually at a high cost) 5782 5783 Options For Use with `MatSetValues()`: 5784 Insert a logically dense subblock, which can be 5785 . `MAT_ROW_ORIENTED` - row-oriented (default) 5786 5787 Note these options reflect the data you pass in with `MatSetValues()`; it has 5788 nothing to do with how the data is stored internally in the matrix 5789 data structure. 5790 5791 When (re)assembling a matrix, we can restrict the input for 5792 efficiency/debugging purposes. These options include 5793 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5794 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5795 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5796 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5797 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5798 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5799 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5800 performance for very large process counts. 5801 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5802 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5803 functions, instead sending only neighbor messages. 5804 5805 Notes: 5806 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5807 5808 Some options are relevant only for particular matrix types and 5809 are thus ignored by others. Other options are not supported by 5810 certain matrix types and will generate an error message if set. 5811 5812 If using Fortran to compute a matrix, one may need to 5813 use the column-oriented option (or convert to the row-oriented 5814 format). 5815 5816 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5817 that would generate a new entry in the nonzero structure is instead 5818 ignored. Thus, if memory has not alredy been allocated for this particular 5819 data, then the insertion is ignored. For dense matrices, in which 5820 the entire array is allocated, no entries are ever ignored. 5821 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5822 5823 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5824 that would generate a new entry in the nonzero structure instead produces 5825 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 5826 5827 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5828 that would generate a new entry that has not been preallocated will 5829 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5830 only.) This is a useful flag when debugging matrix memory preallocation. 5831 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5832 5833 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5834 other processors should be dropped, rather than stashed. 5835 This is useful if you know that the "owning" processor is also 5836 always generating the correct matrix entries, so that PETSc need 5837 not transfer duplicate entries generated on another processor. 5838 5839 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5840 searches during matrix assembly. When this flag is set, the hash table 5841 is created during the first matrix assembly. This hash table is 5842 used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()` 5843 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5844 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5845 supported by` MATMPIBAIJ` format only. 5846 5847 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5848 are kept in the nonzero structure 5849 5850 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5851 a zero location in the matrix 5852 5853 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5854 5855 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5856 zero row routines and thus improves performance for very large process counts. 5857 5858 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5859 part of the matrix (since they should match the upper triangular part). 5860 5861 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5862 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5863 with finite difference schemes with non-periodic boundary conditions. 5864 5865 Developer Note: 5866 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5867 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5868 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5869 not changed. 5870 5871 Level: intermediate 5872 5873 .seealso: `MatOption`, `Mat`, `MatGetOption()` 5874 @*/ 5875 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5876 { 5877 PetscFunctionBegin; 5878 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5879 if (op > 0) { 5880 PetscValidLogicalCollectiveEnum(mat, op, 2); 5881 PetscValidLogicalCollectiveBool(mat, flg, 3); 5882 } 5883 5884 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); 5885 5886 switch (op) { 5887 case MAT_FORCE_DIAGONAL_ENTRIES: 5888 mat->force_diagonals = flg; 5889 PetscFunctionReturn(0); 5890 case MAT_NO_OFF_PROC_ENTRIES: 5891 mat->nooffprocentries = flg; 5892 PetscFunctionReturn(0); 5893 case MAT_SUBSET_OFF_PROC_ENTRIES: 5894 mat->assembly_subset = flg; 5895 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5896 #if !defined(PETSC_HAVE_MPIUNI) 5897 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5898 #endif 5899 mat->stash.first_assembly_done = PETSC_FALSE; 5900 } 5901 PetscFunctionReturn(0); 5902 case MAT_NO_OFF_PROC_ZERO_ROWS: 5903 mat->nooffproczerorows = flg; 5904 PetscFunctionReturn(0); 5905 case MAT_SPD: 5906 if (flg) { 5907 mat->spd = PETSC_BOOL3_TRUE; 5908 mat->symmetric = PETSC_BOOL3_TRUE; 5909 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5910 } else { 5911 mat->spd = PETSC_BOOL3_FALSE; 5912 } 5913 break; 5914 case MAT_SYMMETRIC: 5915 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5916 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5917 #if !defined(PETSC_USE_COMPLEX) 5918 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5919 #endif 5920 break; 5921 case MAT_HERMITIAN: 5922 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5923 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5924 #if !defined(PETSC_USE_COMPLEX) 5925 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5926 #endif 5927 break; 5928 case MAT_STRUCTURALLY_SYMMETRIC: 5929 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5930 break; 5931 case MAT_SYMMETRY_ETERNAL: 5932 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"); 5933 mat->symmetry_eternal = flg; 5934 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5935 break; 5936 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5937 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"); 5938 mat->structural_symmetry_eternal = flg; 5939 break; 5940 case MAT_SPD_ETERNAL: 5941 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"); 5942 mat->spd_eternal = flg; 5943 if (flg) { 5944 mat->structural_symmetry_eternal = PETSC_TRUE; 5945 mat->symmetry_eternal = PETSC_TRUE; 5946 } 5947 break; 5948 case MAT_STRUCTURE_ONLY: 5949 mat->structure_only = flg; 5950 break; 5951 case MAT_SORTED_FULL: 5952 mat->sortedfull = flg; 5953 break; 5954 default: 5955 break; 5956 } 5957 PetscTryTypeMethod(mat, setoption, op, flg); 5958 PetscFunctionReturn(0); 5959 } 5960 5961 /*@ 5962 MatGetOption - Gets a parameter option that has been set for a matrix. 5963 5964 Logically Collective 5965 5966 Input Parameters: 5967 + mat - the matrix 5968 - option - the option, this only responds to certain options, check the code for which ones 5969 5970 Output Parameter: 5971 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5972 5973 Notes: 5974 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5975 5976 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5977 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5978 5979 Level: intermediate 5980 5981 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5982 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5983 @*/ 5984 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5985 { 5986 PetscFunctionBegin; 5987 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5988 PetscValidType(mat, 1); 5989 5990 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); 5991 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()"); 5992 5993 switch (op) { 5994 case MAT_NO_OFF_PROC_ENTRIES: 5995 *flg = mat->nooffprocentries; 5996 break; 5997 case MAT_NO_OFF_PROC_ZERO_ROWS: 5998 *flg = mat->nooffproczerorows; 5999 break; 6000 case MAT_SYMMETRIC: 6001 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6002 break; 6003 case MAT_HERMITIAN: 6004 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6005 break; 6006 case MAT_STRUCTURALLY_SYMMETRIC: 6007 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6008 break; 6009 case MAT_SPD: 6010 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6011 break; 6012 case MAT_SYMMETRY_ETERNAL: 6013 *flg = mat->symmetry_eternal; 6014 break; 6015 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6016 *flg = mat->symmetry_eternal; 6017 break; 6018 default: 6019 break; 6020 } 6021 PetscFunctionReturn(0); 6022 } 6023 6024 /*@ 6025 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6026 this routine retains the old nonzero structure. 6027 6028 Logically Collective 6029 6030 Input Parameters: 6031 . mat - the matrix 6032 6033 Level: intermediate 6034 6035 Note: 6036 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. 6037 See the Performance chapter of the users manual for information on preallocating matrices. 6038 6039 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6040 @*/ 6041 PetscErrorCode MatZeroEntries(Mat mat) 6042 { 6043 PetscFunctionBegin; 6044 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6045 PetscValidType(mat, 1); 6046 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6047 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"); 6048 MatCheckPreallocated(mat, 1); 6049 6050 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6051 PetscUseTypeMethod(mat, zeroentries); 6052 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6053 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6054 PetscFunctionReturn(0); 6055 } 6056 6057 /*@ 6058 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6059 of a set of rows and columns of a matrix. 6060 6061 Collective 6062 6063 Input Parameters: 6064 + mat - the matrix 6065 . numRows - the number of rows to remove 6066 . rows - the global row indices 6067 . diag - value put in the diagonal of the eliminated rows 6068 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6069 - b - optional vector of right hand side, that will be adjusted by provided solution 6070 6071 Notes: 6072 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6073 6074 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 6075 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 6076 6077 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6078 Krylov method to take advantage of the known solution on the zeroed rows. 6079 6080 For the parallel case, all processes that share the matrix (i.e., 6081 those in the communicator used for matrix creation) MUST call this 6082 routine, regardless of whether any rows being zeroed are owned by 6083 them. 6084 6085 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6086 6087 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6088 list only rows local to itself). 6089 6090 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6091 6092 Level: intermediate 6093 6094 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6095 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6096 @*/ 6097 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6098 { 6099 PetscFunctionBegin; 6100 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6101 PetscValidType(mat, 1); 6102 if (numRows) PetscValidIntPointer(rows, 3); 6103 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6104 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6105 MatCheckPreallocated(mat, 1); 6106 6107 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6108 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6109 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6110 PetscFunctionReturn(0); 6111 } 6112 6113 /*@ 6114 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6115 of a set of rows and columns of a matrix. 6116 6117 Collective 6118 6119 Input Parameters: 6120 + mat - the matrix 6121 . is - the rows to zero 6122 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6123 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6124 - b - optional vector of right hand side, that will be adjusted by provided solution 6125 6126 Note: 6127 See `MatZeroRowsColumns()` for details on how this routine operates. 6128 6129 Level: intermediate 6130 6131 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6132 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6133 @*/ 6134 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6135 { 6136 PetscInt numRows; 6137 const PetscInt *rows; 6138 6139 PetscFunctionBegin; 6140 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6141 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6142 PetscValidType(mat, 1); 6143 PetscValidType(is, 2); 6144 PetscCall(ISGetLocalSize(is, &numRows)); 6145 PetscCall(ISGetIndices(is, &rows)); 6146 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6147 PetscCall(ISRestoreIndices(is, &rows)); 6148 PetscFunctionReturn(0); 6149 } 6150 6151 /*@ 6152 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6153 of a set of rows of a matrix. 6154 6155 Collective 6156 6157 Input Parameters: 6158 + mat - the matrix 6159 . numRows - the number of rows to remove 6160 . rows - the global row indices 6161 . diag - value put in the diagonal of the eliminated rows 6162 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6163 - b - optional vector of right hand side, that will be adjusted by provided solution 6164 6165 Notes: 6166 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6167 6168 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 6169 6170 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6171 Krylov method to take advantage of the known solution on the zeroed rows. 6172 6173 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) 6174 from the matrix. 6175 6176 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6177 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 6178 formats this does not alter the nonzero structure. 6179 6180 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6181 of the matrix is not changed the values are 6182 merely zeroed. 6183 6184 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6185 formats can optionally remove the main diagonal entry from the 6186 nonzero structure as well, by passing 0.0 as the final argument). 6187 6188 For the parallel case, all processes that share the matrix (i.e., 6189 those in the communicator used for matrix creation) MUST call this 6190 routine, regardless of whether any rows being zeroed are owned by 6191 them. 6192 6193 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6194 list only rows local to itself). 6195 6196 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6197 owns that are to be zeroed. This saves a global synchronization in the implementation. 6198 6199 Level: intermediate 6200 6201 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6202 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6203 @*/ 6204 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6205 { 6206 PetscFunctionBegin; 6207 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6208 PetscValidType(mat, 1); 6209 if (numRows) PetscValidIntPointer(rows, 3); 6210 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6211 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6212 MatCheckPreallocated(mat, 1); 6213 6214 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6215 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6216 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6217 PetscFunctionReturn(0); 6218 } 6219 6220 /*@ 6221 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6222 of a set of rows of a matrix. 6223 6224 Collective on Mat 6225 6226 Input Parameters: 6227 + mat - the matrix 6228 . is - index set of rows to remove (if NULL then no row is removed) 6229 . diag - value put in all diagonals of eliminated rows 6230 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6231 - b - optional vector of right hand side, that will be adjusted by provided solution 6232 6233 Note: 6234 See `MatZeroRows()` for details on how this routine operates. 6235 6236 Level: intermediate 6237 6238 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6239 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6240 @*/ 6241 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6242 { 6243 PetscInt numRows = 0; 6244 const PetscInt *rows = NULL; 6245 6246 PetscFunctionBegin; 6247 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6248 PetscValidType(mat, 1); 6249 if (is) { 6250 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6251 PetscCall(ISGetLocalSize(is, &numRows)); 6252 PetscCall(ISGetIndices(is, &rows)); 6253 } 6254 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6255 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6256 PetscFunctionReturn(0); 6257 } 6258 6259 /*@ 6260 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6261 of a set of rows of a matrix. These rows must be local to the process. 6262 6263 Collective 6264 6265 Input Parameters: 6266 + mat - the matrix 6267 . numRows - the number of rows to remove 6268 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6269 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6270 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6271 - b - optional vector of right hand side, that will be adjusted by provided solution 6272 6273 Level: intermediate 6274 6275 Notes: 6276 See `MatZeroRows()` for details on how this routine operates. 6277 6278 The grid coordinates are across the entire grid, not just the local portion 6279 6280 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6281 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6282 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6283 `DM_BOUNDARY_PERIODIC` boundary type. 6284 6285 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 6286 a single value per point) you can skip filling those indices. 6287 6288 Fortran Note: 6289 idxm and idxn should be declared as 6290 $ MatStencil idxm(4,m) 6291 and the values inserted using 6292 .vb 6293 idxm(MatStencil_i,1) = i 6294 idxm(MatStencil_j,1) = j 6295 idxm(MatStencil_k,1) = k 6296 idxm(MatStencil_c,1) = c 6297 etc 6298 .ve 6299 6300 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6301 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6302 @*/ 6303 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6304 { 6305 PetscInt dim = mat->stencil.dim; 6306 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6307 PetscInt *dims = mat->stencil.dims + 1; 6308 PetscInt *starts = mat->stencil.starts; 6309 PetscInt *dxm = (PetscInt *)rows; 6310 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6311 6312 PetscFunctionBegin; 6313 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6314 PetscValidType(mat, 1); 6315 if (numRows) PetscValidPointer(rows, 3); 6316 6317 PetscCall(PetscMalloc1(numRows, &jdxm)); 6318 for (i = 0; i < numRows; ++i) { 6319 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6320 for (j = 0; j < 3 - sdim; ++j) dxm++; 6321 /* Local index in X dir */ 6322 tmp = *dxm++ - starts[0]; 6323 /* Loop over remaining dimensions */ 6324 for (j = 0; j < dim - 1; ++j) { 6325 /* If nonlocal, set index to be negative */ 6326 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6327 /* Update local index */ 6328 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6329 } 6330 /* Skip component slot if necessary */ 6331 if (mat->stencil.noc) dxm++; 6332 /* Local row number */ 6333 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6334 } 6335 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6336 PetscCall(PetscFree(jdxm)); 6337 PetscFunctionReturn(0); 6338 } 6339 6340 /*@ 6341 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6342 of a set of rows and columns of a matrix. 6343 6344 Collective 6345 6346 Input Parameters: 6347 + mat - the matrix 6348 . numRows - the number of rows/columns to remove 6349 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6350 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6351 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6352 - b - optional vector of right hand side, that will be adjusted by provided solution 6353 6354 Level: intermediate 6355 6356 Notes: 6357 See `MatZeroRowsColumns()` for details on how this routine operates. 6358 6359 The grid coordinates are across the entire grid, not just the local portion 6360 6361 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6362 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6363 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6364 `DM_BOUNDARY_PERIODIC` boundary type. 6365 6366 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 6367 a single value per point) you can skip filling those indices. 6368 6369 Fortran Note: 6370 In Fortran idxm and idxn should be declared as 6371 $ MatStencil idxm(4,m) 6372 and the values inserted using 6373 .vb 6374 idxm(MatStencil_i,1) = i 6375 idxm(MatStencil_j,1) = j 6376 idxm(MatStencil_k,1) = k 6377 idxm(MatStencil_c,1) = c 6378 etc 6379 .ve 6380 6381 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6382 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6383 @*/ 6384 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6385 { 6386 PetscInt dim = mat->stencil.dim; 6387 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6388 PetscInt *dims = mat->stencil.dims + 1; 6389 PetscInt *starts = mat->stencil.starts; 6390 PetscInt *dxm = (PetscInt *)rows; 6391 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6392 6393 PetscFunctionBegin; 6394 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6395 PetscValidType(mat, 1); 6396 if (numRows) PetscValidPointer(rows, 3); 6397 6398 PetscCall(PetscMalloc1(numRows, &jdxm)); 6399 for (i = 0; i < numRows; ++i) { 6400 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6401 for (j = 0; j < 3 - sdim; ++j) dxm++; 6402 /* Local index in X dir */ 6403 tmp = *dxm++ - starts[0]; 6404 /* Loop over remaining dimensions */ 6405 for (j = 0; j < dim - 1; ++j) { 6406 /* If nonlocal, set index to be negative */ 6407 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6408 /* Update local index */ 6409 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6410 } 6411 /* Skip component slot if necessary */ 6412 if (mat->stencil.noc) dxm++; 6413 /* Local row number */ 6414 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6415 } 6416 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6417 PetscCall(PetscFree(jdxm)); 6418 PetscFunctionReturn(0); 6419 } 6420 6421 /*@C 6422 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6423 of a set of rows of a matrix; using local numbering of rows. 6424 6425 Collective 6426 6427 Input Parameters: 6428 + mat - the matrix 6429 . numRows - the number of rows to remove 6430 . rows - the local row indices 6431 . diag - value put in all diagonals of eliminated rows 6432 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6433 - b - optional vector of right hand side, that will be adjusted by provided solution 6434 6435 Notes: 6436 Before calling `MatZeroRowsLocal()`, the user must first set the 6437 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6438 6439 See `MatZeroRows()` for details on how this routine operates. 6440 6441 Level: intermediate 6442 6443 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6444 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6445 @*/ 6446 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6447 { 6448 PetscFunctionBegin; 6449 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6450 PetscValidType(mat, 1); 6451 if (numRows) PetscValidIntPointer(rows, 3); 6452 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6453 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6454 MatCheckPreallocated(mat, 1); 6455 6456 if (mat->ops->zerorowslocal) { 6457 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6458 } else { 6459 IS is, newis; 6460 const PetscInt *newRows; 6461 6462 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6463 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6464 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6465 PetscCall(ISGetIndices(newis, &newRows)); 6466 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6467 PetscCall(ISRestoreIndices(newis, &newRows)); 6468 PetscCall(ISDestroy(&newis)); 6469 PetscCall(ISDestroy(&is)); 6470 } 6471 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6472 PetscFunctionReturn(0); 6473 } 6474 6475 /*@ 6476 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6477 of a set of rows of a matrix; using local numbering of rows. 6478 6479 Collective 6480 6481 Input Parameters: 6482 + mat - the matrix 6483 . is - index set of rows to remove 6484 . diag - value put in all diagonals of eliminated rows 6485 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6486 - b - optional vector of right hand side, that will be adjusted by provided solution 6487 6488 Notes: 6489 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6490 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6491 6492 See `MatZeroRows()` for details on how this routine operates. 6493 6494 Level: intermediate 6495 6496 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6497 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6498 @*/ 6499 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6500 { 6501 PetscInt numRows; 6502 const PetscInt *rows; 6503 6504 PetscFunctionBegin; 6505 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6506 PetscValidType(mat, 1); 6507 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6508 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6509 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6510 MatCheckPreallocated(mat, 1); 6511 6512 PetscCall(ISGetLocalSize(is, &numRows)); 6513 PetscCall(ISGetIndices(is, &rows)); 6514 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6515 PetscCall(ISRestoreIndices(is, &rows)); 6516 PetscFunctionReturn(0); 6517 } 6518 6519 /*@ 6520 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6521 of a set of rows and columns of a matrix; using local numbering of rows. 6522 6523 Collective 6524 6525 Input Parameters: 6526 + mat - the matrix 6527 . numRows - the number of rows to remove 6528 . rows - the global row indices 6529 . diag - value put in all diagonals of eliminated rows 6530 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6531 - b - optional vector of right hand side, that will be adjusted by provided solution 6532 6533 Notes: 6534 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6535 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6536 6537 See `MatZeroRowsColumns()` for details on how this routine operates. 6538 6539 Level: intermediate 6540 6541 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6542 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6543 @*/ 6544 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6545 { 6546 IS is, newis; 6547 const PetscInt *newRows; 6548 6549 PetscFunctionBegin; 6550 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6551 PetscValidType(mat, 1); 6552 if (numRows) PetscValidIntPointer(rows, 3); 6553 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6554 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6555 MatCheckPreallocated(mat, 1); 6556 6557 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6558 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6559 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6560 PetscCall(ISGetIndices(newis, &newRows)); 6561 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6562 PetscCall(ISRestoreIndices(newis, &newRows)); 6563 PetscCall(ISDestroy(&newis)); 6564 PetscCall(ISDestroy(&is)); 6565 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6566 PetscFunctionReturn(0); 6567 } 6568 6569 /*@ 6570 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6571 of a set of rows and columns of a matrix; using local numbering of rows. 6572 6573 Collective on Mat 6574 6575 Input Parameters: 6576 + mat - the matrix 6577 . is - index set of rows to remove 6578 . diag - value put in all diagonals of eliminated rows 6579 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6580 - b - optional vector of right hand side, that will be adjusted by provided solution 6581 6582 Notes: 6583 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6584 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6585 6586 See `MatZeroRowsColumns()` for details on how this routine operates. 6587 6588 Level: intermediate 6589 6590 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6591 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6592 @*/ 6593 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6594 { 6595 PetscInt numRows; 6596 const PetscInt *rows; 6597 6598 PetscFunctionBegin; 6599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6600 PetscValidType(mat, 1); 6601 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6602 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6603 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6604 MatCheckPreallocated(mat, 1); 6605 6606 PetscCall(ISGetLocalSize(is, &numRows)); 6607 PetscCall(ISGetIndices(is, &rows)); 6608 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6609 PetscCall(ISRestoreIndices(is, &rows)); 6610 PetscFunctionReturn(0); 6611 } 6612 6613 /*@C 6614 MatGetSize - Returns the numbers of rows and columns in a matrix. 6615 6616 Not Collective 6617 6618 Input Parameter: 6619 . mat - the matrix 6620 6621 Output Parameters: 6622 + m - the number of global rows 6623 - n - the number of global columns 6624 6625 Note: both output parameters can be NULL on input. 6626 6627 Level: beginner 6628 6629 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6630 @*/ 6631 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6632 { 6633 PetscFunctionBegin; 6634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6635 if (m) *m = mat->rmap->N; 6636 if (n) *n = mat->cmap->N; 6637 PetscFunctionReturn(0); 6638 } 6639 6640 /*@C 6641 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6642 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6643 6644 Not Collective 6645 6646 Input Parameter: 6647 . mat - the matrix 6648 6649 Output Parameters: 6650 + m - the number of local rows, use `NULL` to not obtain this value 6651 - n - the number of local columns, use `NULL` to not obtain this value 6652 6653 Level: beginner 6654 6655 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()` 6656 @*/ 6657 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6658 { 6659 PetscFunctionBegin; 6660 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6661 if (m) PetscValidIntPointer(m, 2); 6662 if (n) PetscValidIntPointer(n, 3); 6663 if (m) *m = mat->rmap->n; 6664 if (n) *n = mat->cmap->n; 6665 PetscFunctionReturn(0); 6666 } 6667 6668 /*@C 6669 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6670 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6671 6672 Not Collective, unless matrix has not been allocated, then collective 6673 6674 Input Parameter: 6675 . mat - the matrix 6676 6677 Output Parameters: 6678 + m - the global index of the first local column, use `NULL` to not obtain this value 6679 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6680 6681 Level: developer 6682 6683 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6684 @*/ 6685 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6686 { 6687 PetscFunctionBegin; 6688 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6689 PetscValidType(mat, 1); 6690 if (m) PetscValidIntPointer(m, 2); 6691 if (n) PetscValidIntPointer(n, 3); 6692 MatCheckPreallocated(mat, 1); 6693 if (m) *m = mat->cmap->rstart; 6694 if (n) *n = mat->cmap->rend; 6695 PetscFunctionReturn(0); 6696 } 6697 6698 /*@C 6699 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6700 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 6701 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6702 6703 Not Collective 6704 6705 Input Parameter: 6706 . mat - the matrix 6707 6708 Output Parameters: 6709 + m - the global index of the first local row, use `NULL` to not obtain this value 6710 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6711 6712 Note: 6713 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6714 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6715 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6716 6717 Level: beginner 6718 6719 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6720 `PetscLayout` 6721 @*/ 6722 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6723 { 6724 PetscFunctionBegin; 6725 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6726 PetscValidType(mat, 1); 6727 if (m) PetscValidIntPointer(m, 2); 6728 if (n) PetscValidIntPointer(n, 3); 6729 MatCheckPreallocated(mat, 1); 6730 if (m) *m = mat->rmap->rstart; 6731 if (n) *n = mat->rmap->rend; 6732 PetscFunctionReturn(0); 6733 } 6734 6735 /*@C 6736 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6737 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 6738 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6739 6740 Not Collective, unless matrix has not been allocated, then collective 6741 6742 Input Parameters: 6743 . mat - the matrix 6744 6745 Output Parameters: 6746 . ranges - start of each processors portion plus one more than the total length at the end 6747 6748 Level: beginner 6749 6750 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6751 @*/ 6752 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6753 { 6754 PetscFunctionBegin; 6755 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6756 PetscValidType(mat, 1); 6757 MatCheckPreallocated(mat, 1); 6758 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6759 PetscFunctionReturn(0); 6760 } 6761 6762 /*@C 6763 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6764 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6765 6766 Not Collective, unless matrix has not been allocated, then collective on Mat 6767 6768 Input Parameters: 6769 . mat - the matrix 6770 6771 Output Parameters: 6772 . ranges - start of each processors portion plus one more then the total length at the end 6773 6774 Level: beginner 6775 6776 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6777 @*/ 6778 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6779 { 6780 PetscFunctionBegin; 6781 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6782 PetscValidType(mat, 1); 6783 MatCheckPreallocated(mat, 1); 6784 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6785 PetscFunctionReturn(0); 6786 } 6787 6788 /*@C 6789 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6790 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6791 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6792 6793 Not Collective 6794 6795 Input Parameter: 6796 . A - matrix 6797 6798 Output Parameters: 6799 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6800 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6801 6802 Level: intermediate 6803 6804 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6805 @*/ 6806 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6807 { 6808 PetscErrorCode (*f)(Mat, IS *, IS *); 6809 6810 PetscFunctionBegin; 6811 MatCheckPreallocated(A, 1); 6812 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6813 if (f) { 6814 PetscCall((*f)(A, rows, cols)); 6815 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6816 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6817 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6818 } 6819 PetscFunctionReturn(0); 6820 } 6821 6822 /*@C 6823 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6824 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6825 to complete the factorization. 6826 6827 Collective on fact 6828 6829 Input Parameters: 6830 + fact - the factorized matrix obtained with `MatGetFactor()` 6831 . mat - the matrix 6832 . row - row permutation 6833 . column - column permutation 6834 - info - structure containing 6835 $ levels - number of levels of fill. 6836 $ expected fill - as ratio of original fill. 6837 $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6838 missing diagonal entries) 6839 6840 Output Parameters: 6841 . fact - new matrix that has been symbolically factored 6842 6843 Level: developer 6844 6845 Notes: 6846 See [Matrix Factorization](sec_matfactor) for additional information. 6847 6848 Most users should employ the `KSP` interface for linear solvers 6849 instead of working directly with matrix algebra routines such as this. 6850 See, e.g., `KSPCreate()`. 6851 6852 Uses the definition of level of fill as in Y. Saad, 2003 6853 6854 Developer Note: 6855 The Fortran interface is not autogenerated as the 6856 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6857 6858 References: 6859 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6860 6861 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6862 `MatGetOrdering()`, `MatFactorInfo` 6863 @*/ 6864 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6865 { 6866 PetscFunctionBegin; 6867 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6868 PetscValidType(mat, 2); 6869 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6870 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6871 PetscValidPointer(info, 5); 6872 PetscValidPointer(fact, 1); 6873 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6874 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6875 if (!fact->ops->ilufactorsymbolic) { 6876 MatSolverType stype; 6877 PetscCall(MatFactorGetSolverType(fact, &stype)); 6878 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype); 6879 } 6880 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6881 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6882 MatCheckPreallocated(mat, 2); 6883 6884 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6885 PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info)); 6886 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6887 PetscFunctionReturn(0); 6888 } 6889 6890 /*@C 6891 MatICCFactorSymbolic - Performs symbolic incomplete 6892 Cholesky factorization for a symmetric matrix. Use 6893 `MatCholeskyFactorNumeric()` to complete the factorization. 6894 6895 Collective on fact 6896 6897 Input Parameters: 6898 + fact - the factorized matrix obtained with `MatGetFactor()` 6899 . mat - the matrix to be factored 6900 . perm - row and column permutation 6901 - info - structure containing 6902 $ levels - number of levels of fill. 6903 $ expected fill - as ratio of original fill. 6904 6905 Output Parameter: 6906 . fact - the factored matrix 6907 6908 Level: developer 6909 6910 Notes: 6911 Most users should employ the `KSP` interface for linear solvers 6912 instead of working directly with matrix algebra routines such as this. 6913 See, e.g., `KSPCreate()`. 6914 6915 This uses the definition of level of fill as in Y. Saad, 2003 6916 6917 Developer Note: 6918 The Fortran interface is not autogenerated as the 6919 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6920 6921 References: 6922 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6923 6924 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6925 @*/ 6926 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6927 { 6928 PetscFunctionBegin; 6929 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6930 PetscValidType(mat, 2); 6931 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6932 PetscValidPointer(info, 4); 6933 PetscValidPointer(fact, 1); 6934 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6935 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6936 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6937 if (!(fact)->ops->iccfactorsymbolic) { 6938 MatSolverType stype; 6939 PetscCall(MatFactorGetSolverType(fact, &stype)); 6940 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype); 6941 } 6942 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6943 MatCheckPreallocated(mat, 2); 6944 6945 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6946 PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info)); 6947 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6948 PetscFunctionReturn(0); 6949 } 6950 6951 /*@C 6952 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6953 points to an array of valid matrices, they may be reused to store the new 6954 submatrices. 6955 6956 Collective 6957 6958 Input Parameters: 6959 + mat - the matrix 6960 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6961 . irow, icol - index sets of rows and columns to extract 6962 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6963 6964 Output Parameter: 6965 . submat - the array of submatrices 6966 6967 Notes: 6968 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6969 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6970 to extract a parallel submatrix. 6971 6972 Some matrix types place restrictions on the row and column 6973 indices, such as that they be sorted or that they be equal to each other. 6974 6975 The index sets may not have duplicate entries. 6976 6977 When extracting submatrices from a parallel matrix, each processor can 6978 form a different submatrix by setting the rows and columns of its 6979 individual index sets according to the local submatrix desired. 6980 6981 When finished using the submatrices, the user should destroy 6982 them with `MatDestroySubMatrices()`. 6983 6984 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6985 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6986 6987 This routine creates the matrices in submat; you should NOT create them before 6988 calling it. It also allocates the array of matrix pointers submat. 6989 6990 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6991 request one row/column in a block, they must request all rows/columns that are in 6992 that block. For example, if the block size is 2 you cannot request just row 0 and 6993 column 0. 6994 6995 Fortran Note: 6996 The Fortran interface is slightly different from that given below; it 6997 requires one to pass in as submat a `Mat` (integer) array of size at least n+1. 6998 6999 Level: advanced 7000 7001 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7002 @*/ 7003 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7004 { 7005 PetscInt i; 7006 PetscBool eq; 7007 7008 PetscFunctionBegin; 7009 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7010 PetscValidType(mat, 1); 7011 if (n) { 7012 PetscValidPointer(irow, 3); 7013 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7014 PetscValidPointer(icol, 4); 7015 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7016 } 7017 PetscValidPointer(submat, 6); 7018 if (n && scall == MAT_REUSE_MATRIX) { 7019 PetscValidPointer(*submat, 6); 7020 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7021 } 7022 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7023 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7024 MatCheckPreallocated(mat, 1); 7025 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7026 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7027 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7028 for (i = 0; i < n; i++) { 7029 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7030 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7031 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7032 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7033 if (mat->boundtocpu && mat->bindingpropagates) { 7034 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7035 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7036 } 7037 #endif 7038 } 7039 PetscFunctionReturn(0); 7040 } 7041 7042 /*@C 7043 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7044 7045 Collective 7046 7047 Input Parameters: 7048 + mat - the matrix 7049 . n - the number of submatrixes to be extracted 7050 . irow, icol - index sets of rows and columns to extract 7051 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7052 7053 Output Parameter: 7054 . submat - the array of submatrices 7055 7056 Level: advanced 7057 7058 Note: 7059 This is used by `PCGASM` 7060 7061 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7062 @*/ 7063 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7064 { 7065 PetscInt i; 7066 PetscBool eq; 7067 7068 PetscFunctionBegin; 7069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7070 PetscValidType(mat, 1); 7071 if (n) { 7072 PetscValidPointer(irow, 3); 7073 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7074 PetscValidPointer(icol, 4); 7075 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7076 } 7077 PetscValidPointer(submat, 6); 7078 if (n && scall == MAT_REUSE_MATRIX) { 7079 PetscValidPointer(*submat, 6); 7080 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7081 } 7082 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7083 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7084 MatCheckPreallocated(mat, 1); 7085 7086 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7087 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7088 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7089 for (i = 0; i < n; i++) { 7090 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7091 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7092 } 7093 PetscFunctionReturn(0); 7094 } 7095 7096 /*@C 7097 MatDestroyMatrices - Destroys an array of matrices. 7098 7099 Collective 7100 7101 Input Parameters: 7102 + n - the number of local matrices 7103 - mat - the matrices (note that this is a pointer to the array of matrices) 7104 7105 Level: advanced 7106 7107 Note: 7108 Frees not only the matrices, but also the array that contains the matrices 7109 In Fortran will not free the array. 7110 7111 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7112 @*/ 7113 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7114 { 7115 PetscInt i; 7116 7117 PetscFunctionBegin; 7118 if (!*mat) PetscFunctionReturn(0); 7119 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7120 PetscValidPointer(mat, 2); 7121 7122 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7123 7124 /* memory is allocated even if n = 0 */ 7125 PetscCall(PetscFree(*mat)); 7126 PetscFunctionReturn(0); 7127 } 7128 7129 /*@C 7130 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7131 7132 Collective 7133 7134 Input Parameters: 7135 + n - the number of local matrices 7136 - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling 7137 sequence of MatCreateSubMatrices()) 7138 7139 Level: advanced 7140 7141 Note: 7142 Frees not only the matrices, but also the array that contains the matrices 7143 In Fortran will not free the array. 7144 7145 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7146 @*/ 7147 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7148 { 7149 Mat mat0; 7150 7151 PetscFunctionBegin; 7152 if (!*mat) PetscFunctionReturn(0); 7153 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7154 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7155 PetscValidPointer(mat, 2); 7156 7157 mat0 = (*mat)[0]; 7158 if (mat0 && mat0->ops->destroysubmatrices) { 7159 PetscCall((mat0->ops->destroysubmatrices)(n, mat)); 7160 } else { 7161 PetscCall(MatDestroyMatrices(n, mat)); 7162 } 7163 PetscFunctionReturn(0); 7164 } 7165 7166 /*@C 7167 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7168 7169 Collective 7170 7171 Input Parameters: 7172 . mat - the matrix 7173 7174 Output Parameter: 7175 . matstruct - the sequential matrix with the nonzero structure of mat 7176 7177 Level: developer 7178 7179 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7180 @*/ 7181 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7182 { 7183 PetscFunctionBegin; 7184 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7185 PetscValidPointer(matstruct, 2); 7186 7187 PetscValidType(mat, 1); 7188 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7189 MatCheckPreallocated(mat, 1); 7190 7191 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7192 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7193 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7194 PetscFunctionReturn(0); 7195 } 7196 7197 /*@C 7198 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7199 7200 Collective 7201 7202 Input Parameters: 7203 . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling 7204 sequence of `MatGetSequentialNonzeroStructure()`) 7205 7206 Level: advanced 7207 7208 Note: 7209 Frees not only the matrices, but also the array that contains the matrices 7210 7211 .seealso: `Mat`, `MatGetSeqNonzeroStructure()` 7212 @*/ 7213 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7214 { 7215 PetscFunctionBegin; 7216 PetscValidPointer(mat, 1); 7217 PetscCall(MatDestroy(mat)); 7218 PetscFunctionReturn(0); 7219 } 7220 7221 /*@ 7222 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7223 replaces the index sets by larger ones that represent submatrices with 7224 additional overlap. 7225 7226 Collective 7227 7228 Input Parameters: 7229 + mat - the matrix 7230 . n - the number of index sets 7231 . is - the array of index sets (these index sets will changed during the call) 7232 - ov - the additional overlap requested 7233 7234 Options Database Key: 7235 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7236 7237 Level: developer 7238 7239 Developer Note: 7240 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. 7241 7242 .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7243 @*/ 7244 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7245 { 7246 PetscInt i, bs, cbs; 7247 7248 PetscFunctionBegin; 7249 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7250 PetscValidType(mat, 1); 7251 PetscValidLogicalCollectiveInt(mat, n, 2); 7252 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7253 if (n) { 7254 PetscValidPointer(is, 3); 7255 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7256 } 7257 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7258 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7259 MatCheckPreallocated(mat, 1); 7260 7261 if (!ov || !n) PetscFunctionReturn(0); 7262 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7263 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7264 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7265 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7266 if (bs == cbs) { 7267 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7268 } 7269 PetscFunctionReturn(0); 7270 } 7271 7272 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7273 7274 /*@ 7275 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7276 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7277 additional overlap. 7278 7279 Collective 7280 7281 Input Parameters: 7282 + mat - the matrix 7283 . n - the number of index sets 7284 . is - the array of index sets (these index sets will changed during the call) 7285 - ov - the additional overlap requested 7286 7287 ` Options Database Key: 7288 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7289 7290 Level: developer 7291 7292 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7293 @*/ 7294 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7295 { 7296 PetscInt i; 7297 7298 PetscFunctionBegin; 7299 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7300 PetscValidType(mat, 1); 7301 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7302 if (n) { 7303 PetscValidPointer(is, 3); 7304 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7305 } 7306 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7307 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7308 MatCheckPreallocated(mat, 1); 7309 if (!ov) PetscFunctionReturn(0); 7310 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7311 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7312 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7313 PetscFunctionReturn(0); 7314 } 7315 7316 /*@ 7317 MatGetBlockSize - Returns the matrix block size. 7318 7319 Not Collective 7320 7321 Input Parameter: 7322 . mat - the matrix 7323 7324 Output Parameter: 7325 . bs - block size 7326 7327 Notes: 7328 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7329 7330 If the block size has not been set yet this routine returns 1. 7331 7332 Level: intermediate 7333 7334 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7335 @*/ 7336 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7337 { 7338 PetscFunctionBegin; 7339 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7340 PetscValidIntPointer(bs, 2); 7341 *bs = PetscAbs(mat->rmap->bs); 7342 PetscFunctionReturn(0); 7343 } 7344 7345 /*@ 7346 MatGetBlockSizes - Returns the matrix block row and column sizes. 7347 7348 Not Collective 7349 7350 Input Parameter: 7351 . mat - the matrix 7352 7353 Output Parameters: 7354 + rbs - row block size 7355 - cbs - column block size 7356 7357 Notes: 7358 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7359 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7360 7361 If a block size has not been set yet this routine returns 1. 7362 7363 Level: intermediate 7364 7365 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7366 @*/ 7367 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7368 { 7369 PetscFunctionBegin; 7370 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7371 if (rbs) PetscValidIntPointer(rbs, 2); 7372 if (cbs) PetscValidIntPointer(cbs, 3); 7373 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7374 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7375 PetscFunctionReturn(0); 7376 } 7377 7378 /*@ 7379 MatSetBlockSize - Sets the matrix block size. 7380 7381 Logically Collective 7382 7383 Input Parameters: 7384 + mat - the matrix 7385 - bs - block size 7386 7387 Notes: 7388 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7389 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7390 7391 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7392 is compatible with the matrix local sizes. 7393 7394 Level: intermediate 7395 7396 .seealso: `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7397 @*/ 7398 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7399 { 7400 PetscFunctionBegin; 7401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7402 PetscValidLogicalCollectiveInt(mat, bs, 2); 7403 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7404 PetscFunctionReturn(0); 7405 } 7406 7407 typedef struct { 7408 PetscInt n; 7409 IS *is; 7410 Mat *mat; 7411 PetscObjectState nonzerostate; 7412 Mat C; 7413 } EnvelopeData; 7414 7415 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7416 { 7417 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7418 PetscCall(PetscFree(edata->is)); 7419 PetscCall(PetscFree(edata)); 7420 return 0; 7421 } 7422 7423 /* 7424 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7425 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7426 7427 Collective 7428 7429 Input Parameter: 7430 . mat - the matrix 7431 7432 Notes: 7433 There can be zeros within the blocks 7434 7435 The blocks can overlap between processes, including laying on more than two processes 7436 7437 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7438 */ 7439 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7440 { 7441 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7442 PetscInt *diag, *odiag, sc; 7443 VecScatter scatter; 7444 PetscScalar *seqv; 7445 const PetscScalar *parv; 7446 const PetscInt *ia, *ja; 7447 PetscBool set, flag, done; 7448 Mat AA = mat, A; 7449 MPI_Comm comm; 7450 PetscMPIInt rank, size, tag; 7451 MPI_Status status; 7452 PetscContainer container; 7453 EnvelopeData *edata; 7454 Vec seq, par; 7455 IS isglobal; 7456 7457 PetscFunctionBegin; 7458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7459 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7460 if (!set || !flag) { 7461 /* TOO: only needs nonzero structure of transpose */ 7462 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7463 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7464 } 7465 PetscCall(MatAIJGetLocalMat(AA, &A)); 7466 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7467 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7468 7469 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7470 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7471 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7472 PetscCallMPI(MPI_Comm_size(comm, &size)); 7473 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7474 7475 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7476 7477 if (rank > 0) { 7478 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7479 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7480 } 7481 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7482 for (i = 0; i < n; i++) { 7483 env = PetscMax(env, ja[ia[i + 1] - 1]); 7484 II = rstart + i; 7485 if (env == II) { 7486 starts[lblocks] = tbs; 7487 sizes[lblocks++] = 1 + II - tbs; 7488 tbs = 1 + II; 7489 } 7490 } 7491 if (rank < size - 1) { 7492 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7493 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7494 } 7495 7496 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7497 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7498 PetscCall(MatDestroy(&A)); 7499 7500 PetscCall(PetscNew(&edata)); 7501 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7502 edata->n = lblocks; 7503 /* create IS needed for extracting blocks from the original matrix */ 7504 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7505 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7506 7507 /* Create the resulting inverse matrix structure with preallocation information */ 7508 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7509 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7510 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7511 PetscCall(MatSetType(edata->C, MATAIJ)); 7512 7513 /* Communicate the start and end of each row, from each block to the correct rank */ 7514 /* TODO: Use PetscSF instead of VecScatter */ 7515 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7516 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7517 PetscCall(VecGetArrayWrite(seq, &seqv)); 7518 for (PetscInt i = 0; i < lblocks; i++) { 7519 for (PetscInt j = 0; j < sizes[i]; j++) { 7520 seqv[cnt] = starts[i]; 7521 seqv[cnt + 1] = starts[i] + sizes[i]; 7522 cnt += 2; 7523 } 7524 } 7525 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7526 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7527 sc -= cnt; 7528 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7529 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7530 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7531 PetscCall(ISDestroy(&isglobal)); 7532 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7533 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7534 PetscCall(VecScatterDestroy(&scatter)); 7535 PetscCall(VecDestroy(&seq)); 7536 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7537 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7538 PetscCall(VecGetArrayRead(par, &parv)); 7539 cnt = 0; 7540 PetscCall(MatGetSize(mat, NULL, &n)); 7541 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7542 PetscInt start, end, d = 0, od = 0; 7543 7544 start = (PetscInt)PetscRealPart(parv[cnt]); 7545 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7546 cnt += 2; 7547 7548 if (start < cstart) { 7549 od += cstart - start + n - cend; 7550 d += cend - cstart; 7551 } else if (start < cend) { 7552 od += n - cend; 7553 d += cend - start; 7554 } else od += n - start; 7555 if (end <= cstart) { 7556 od -= cstart - end + n - cend; 7557 d -= cend - cstart; 7558 } else if (end < cend) { 7559 od -= n - cend; 7560 d -= cend - end; 7561 } else od -= n - end; 7562 7563 odiag[i] = od; 7564 diag[i] = d; 7565 } 7566 PetscCall(VecRestoreArrayRead(par, &parv)); 7567 PetscCall(VecDestroy(&par)); 7568 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7569 PetscCall(PetscFree2(diag, odiag)); 7570 PetscCall(PetscFree2(sizes, starts)); 7571 7572 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7573 PetscCall(PetscContainerSetPointer(container, edata)); 7574 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7575 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7576 PetscCall(PetscObjectDereference((PetscObject)container)); 7577 PetscFunctionReturn(0); 7578 } 7579 7580 /*@ 7581 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7582 7583 Collective on A 7584 7585 Input Parameters: 7586 . A - the matrix 7587 7588 Output Parameters: 7589 . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 7590 7591 Note: 7592 For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal. 7593 7594 Level: advanced 7595 7596 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7597 @*/ 7598 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7599 { 7600 PetscContainer container; 7601 EnvelopeData *edata; 7602 PetscObjectState nonzerostate; 7603 7604 PetscFunctionBegin; 7605 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7606 if (!container) { 7607 PetscCall(MatComputeVariableBlockEnvelope(A)); 7608 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7609 } 7610 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7611 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7612 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7613 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7614 7615 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7616 *C = edata->C; 7617 7618 for (PetscInt i = 0; i < edata->n; i++) { 7619 Mat D; 7620 PetscScalar *dvalues; 7621 7622 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7623 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7624 PetscCall(MatSeqDenseInvert(D)); 7625 PetscCall(MatDenseGetArray(D, &dvalues)); 7626 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7627 PetscCall(MatDestroy(&D)); 7628 } 7629 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7630 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7631 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7632 PetscFunctionReturn(0); 7633 } 7634 7635 /*@ 7636 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7637 7638 Logically Collective 7639 7640 Input Parameters: 7641 + mat - the matrix 7642 . nblocks - the number of blocks on this process, each block can only exist on a single process 7643 - bsizes - the block sizes 7644 7645 Notes: 7646 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7647 7648 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. 7649 7650 Level: intermediate 7651 7652 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7653 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7654 @*/ 7655 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7656 { 7657 PetscInt i, ncnt = 0, nlocal; 7658 7659 PetscFunctionBegin; 7660 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7661 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7662 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7663 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7664 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); 7665 PetscCall(PetscFree(mat->bsizes)); 7666 mat->nblocks = nblocks; 7667 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7668 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7669 PetscFunctionReturn(0); 7670 } 7671 7672 /*@C 7673 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7674 7675 Logically Collective; No Fortran Support 7676 7677 Input Parameter: 7678 . mat - the matrix 7679 7680 Output Parameters: 7681 + nblocks - the number of blocks on this process 7682 - bsizes - the block sizes 7683 7684 Level: intermediate 7685 7686 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7687 @*/ 7688 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7689 { 7690 PetscFunctionBegin; 7691 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7692 *nblocks = mat->nblocks; 7693 *bsizes = mat->bsizes; 7694 PetscFunctionReturn(0); 7695 } 7696 7697 /*@ 7698 MatSetBlockSizes - Sets the matrix block row and column sizes. 7699 7700 Logically Collective 7701 7702 Input Parameters: 7703 + mat - the matrix 7704 . rbs - row block size 7705 - cbs - column block size 7706 7707 Notes: 7708 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7709 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7710 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7711 7712 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7713 are compatible with the matrix local sizes. 7714 7715 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7716 7717 Level: intermediate 7718 7719 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7720 @*/ 7721 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7722 { 7723 PetscFunctionBegin; 7724 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7725 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7726 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7727 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7728 if (mat->rmap->refcnt) { 7729 ISLocalToGlobalMapping l2g = NULL; 7730 PetscLayout nmap = NULL; 7731 7732 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7733 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7734 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7735 mat->rmap = nmap; 7736 mat->rmap->mapping = l2g; 7737 } 7738 if (mat->cmap->refcnt) { 7739 ISLocalToGlobalMapping l2g = NULL; 7740 PetscLayout nmap = NULL; 7741 7742 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7743 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7744 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7745 mat->cmap = nmap; 7746 mat->cmap->mapping = l2g; 7747 } 7748 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7749 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7750 PetscFunctionReturn(0); 7751 } 7752 7753 /*@ 7754 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7755 7756 Logically Collective 7757 7758 Input Parameters: 7759 + mat - the matrix 7760 . fromRow - matrix from which to copy row block size 7761 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7762 7763 Level: developer 7764 7765 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7766 @*/ 7767 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7768 { 7769 PetscFunctionBegin; 7770 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7771 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7772 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7773 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7774 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7775 PetscFunctionReturn(0); 7776 } 7777 7778 /*@ 7779 MatResidual - Default routine to calculate the residual r = b - Ax 7780 7781 Collective 7782 7783 Input Parameters: 7784 + mat - the matrix 7785 . b - the right-hand-side 7786 - x - the approximate solution 7787 7788 Output Parameter: 7789 . r - location to store the residual 7790 7791 Level: developer 7792 7793 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7794 @*/ 7795 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7796 { 7797 PetscFunctionBegin; 7798 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7799 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7800 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7801 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7802 PetscValidType(mat, 1); 7803 MatCheckPreallocated(mat, 1); 7804 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7805 if (!mat->ops->residual) { 7806 PetscCall(MatMult(mat, x, r)); 7807 PetscCall(VecAYPX(r, -1.0, b)); 7808 } else { 7809 PetscUseTypeMethod(mat, residual, b, x, r); 7810 } 7811 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7812 PetscFunctionReturn(0); 7813 } 7814 7815 /*@C 7816 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7817 7818 Collective 7819 7820 Input Parameters: 7821 + mat - the matrix 7822 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7823 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7824 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7825 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7826 always used. 7827 7828 Output Parameters: 7829 + n - number of local rows in the (possibly compressed) matrix, use NULL if not needed 7830 . 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 7831 . ja - the column indices, use NULL if not needed 7832 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7833 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7834 7835 Level: developer 7836 7837 Notes: 7838 You CANNOT change any of the ia[] or ja[] values. 7839 7840 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7841 7842 Fortran Notes: 7843 In Fortran use 7844 .vb 7845 PetscInt ia(1), ja(1) 7846 PetscOffset iia, jja 7847 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr) 7848 ! Access the ith and jth entries via ia(iia + i) and ja(jja + j) 7849 .ve 7850 or 7851 .vb 7852 PetscInt, pointer :: ia(:),ja(:) 7853 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7854 ! Access the ith and jth entries via ia(i) and ja(j) 7855 .ve 7856 7857 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7858 @*/ 7859 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7860 { 7861 PetscFunctionBegin; 7862 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7863 PetscValidType(mat, 1); 7864 if (n) PetscValidIntPointer(n, 5); 7865 if (ia) PetscValidPointer(ia, 6); 7866 if (ja) PetscValidPointer(ja, 7); 7867 if (done) PetscValidBoolPointer(done, 8); 7868 MatCheckPreallocated(mat, 1); 7869 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7870 else { 7871 if (done) *done = PETSC_TRUE; 7872 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7873 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7874 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7875 } 7876 PetscFunctionReturn(0); 7877 } 7878 7879 /*@C 7880 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7881 7882 Collective 7883 7884 Input Parameters: 7885 + mat - the matrix 7886 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7887 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7888 symmetrized 7889 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7890 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7891 always used. 7892 . n - number of columns in the (possibly compressed) matrix 7893 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7894 - ja - the row indices 7895 7896 Output Parameters: 7897 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7898 7899 Level: developer 7900 7901 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7902 @*/ 7903 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7904 { 7905 PetscFunctionBegin; 7906 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7907 PetscValidType(mat, 1); 7908 PetscValidIntPointer(n, 5); 7909 if (ia) PetscValidPointer(ia, 6); 7910 if (ja) PetscValidPointer(ja, 7); 7911 PetscValidBoolPointer(done, 8); 7912 MatCheckPreallocated(mat, 1); 7913 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7914 else { 7915 *done = PETSC_TRUE; 7916 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7917 } 7918 PetscFunctionReturn(0); 7919 } 7920 7921 /*@C 7922 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7923 7924 Collective 7925 7926 Input Parameters: 7927 + mat - the matrix 7928 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7929 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7930 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7931 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7932 always used. 7933 . n - size of (possibly compressed) matrix 7934 . ia - the row pointers 7935 - ja - the column indices 7936 7937 Output Parameters: 7938 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7939 7940 Note: 7941 This routine zeros out n, ia, and ja. This is to prevent accidental 7942 us of the array after it has been restored. If you pass NULL, it will 7943 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7944 7945 Level: developer 7946 7947 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7948 @*/ 7949 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7950 { 7951 PetscFunctionBegin; 7952 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7953 PetscValidType(mat, 1); 7954 if (ia) PetscValidPointer(ia, 6); 7955 if (ja) PetscValidPointer(ja, 7); 7956 if (done) PetscValidBoolPointer(done, 8); 7957 MatCheckPreallocated(mat, 1); 7958 7959 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 7960 else { 7961 if (done) *done = PETSC_TRUE; 7962 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7963 if (n) *n = 0; 7964 if (ia) *ia = NULL; 7965 if (ja) *ja = NULL; 7966 } 7967 PetscFunctionReturn(0); 7968 } 7969 7970 /*@C 7971 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 7972 7973 Collective on Mat 7974 7975 Input Parameters: 7976 + mat - the matrix 7977 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7978 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7979 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7980 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7981 always used. 7982 7983 Output Parameters: 7984 + n - size of (possibly compressed) matrix 7985 . ia - the column pointers 7986 . ja - the row indices 7987 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7988 7989 Level: developer 7990 7991 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()` 7992 @*/ 7993 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7994 { 7995 PetscFunctionBegin; 7996 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7997 PetscValidType(mat, 1); 7998 if (ia) PetscValidPointer(ia, 6); 7999 if (ja) PetscValidPointer(ja, 7); 8000 PetscValidBoolPointer(done, 8); 8001 MatCheckPreallocated(mat, 1); 8002 8003 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8004 else { 8005 *done = PETSC_TRUE; 8006 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8007 if (n) *n = 0; 8008 if (ia) *ia = NULL; 8009 if (ja) *ja = NULL; 8010 } 8011 PetscFunctionReturn(0); 8012 } 8013 8014 /*@C 8015 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8016 8017 Collective 8018 8019 Input Parameters: 8020 + mat - the matrix 8021 . ncolors - max color value 8022 . n - number of entries in colorarray 8023 - colorarray - array indicating color for each column 8024 8025 Output Parameters: 8026 . iscoloring - coloring generated using colorarray information 8027 8028 Level: developer 8029 8030 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()` 8031 @*/ 8032 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8033 { 8034 PetscFunctionBegin; 8035 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8036 PetscValidType(mat, 1); 8037 PetscValidIntPointer(colorarray, 4); 8038 PetscValidPointer(iscoloring, 5); 8039 MatCheckPreallocated(mat, 1); 8040 8041 if (!mat->ops->coloringpatch) { 8042 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8043 } else { 8044 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8045 } 8046 PetscFunctionReturn(0); 8047 } 8048 8049 /*@ 8050 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8051 8052 Logically Collective 8053 8054 Input Parameter: 8055 . mat - the factored matrix to be reset 8056 8057 Notes: 8058 This routine should be used only with factored matrices formed by in-place 8059 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8060 format). This option can save memory, for example, when solving nonlinear 8061 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8062 ILU(0) preconditioner. 8063 8064 Note that one can specify in-place ILU(0) factorization by calling 8065 .vb 8066 PCType(pc,PCILU); 8067 PCFactorSeUseInPlace(pc); 8068 .ve 8069 or by using the options -pc_type ilu -pc_factor_in_place 8070 8071 In-place factorization ILU(0) can also be used as a local 8072 solver for the blocks within the block Jacobi or additive Schwarz 8073 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8074 for details on setting local solver options. 8075 8076 Most users should employ the `KSP` interface for linear solvers 8077 instead of working directly with matrix algebra routines such as this. 8078 See, e.g., `KSPCreate()`. 8079 8080 Level: developer 8081 8082 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8083 @*/ 8084 PetscErrorCode MatSetUnfactored(Mat mat) 8085 { 8086 PetscFunctionBegin; 8087 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8088 PetscValidType(mat, 1); 8089 MatCheckPreallocated(mat, 1); 8090 mat->factortype = MAT_FACTOR_NONE; 8091 if (!mat->ops->setunfactored) PetscFunctionReturn(0); 8092 PetscUseTypeMethod(mat, setunfactored); 8093 PetscFunctionReturn(0); 8094 } 8095 8096 /*MC 8097 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8098 8099 Synopsis: 8100 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8101 8102 Not collective 8103 8104 Input Parameter: 8105 . x - matrix 8106 8107 Output Parameters: 8108 + xx_v - the Fortran pointer to the array 8109 - ierr - error code 8110 8111 Example of Usage: 8112 .vb 8113 PetscScalar, pointer xx_v(:,:) 8114 .... 8115 call MatDenseGetArrayF90(x,xx_v,ierr) 8116 a = xx_v(3) 8117 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8118 .ve 8119 8120 Level: advanced 8121 8122 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8123 8124 M*/ 8125 8126 /*MC 8127 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8128 accessed with `MatDenseGetArrayF90()`. 8129 8130 Synopsis: 8131 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8132 8133 Not collective 8134 8135 Input Parameters: 8136 + x - matrix 8137 - xx_v - the Fortran90 pointer to the array 8138 8139 Output Parameter: 8140 . ierr - error code 8141 8142 Example of Usage: 8143 .vb 8144 PetscScalar, pointer xx_v(:,:) 8145 .... 8146 call MatDenseGetArrayF90(x,xx_v,ierr) 8147 a = xx_v(3) 8148 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8149 .ve 8150 8151 Level: advanced 8152 8153 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8154 8155 M*/ 8156 8157 /*MC 8158 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8159 8160 Synopsis: 8161 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8162 8163 Not collective 8164 8165 Input Parameter: 8166 . x - matrix 8167 8168 Output Parameters: 8169 + xx_v - the Fortran pointer to the array 8170 - ierr - error code 8171 8172 Example of Usage: 8173 .vb 8174 PetscScalar, pointer xx_v(:) 8175 .... 8176 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8177 a = xx_v(3) 8178 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8179 .ve 8180 8181 Level: advanced 8182 8183 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8184 8185 M*/ 8186 8187 /*MC 8188 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8189 accessed with `MatSeqAIJGetArrayF90()`. 8190 8191 Synopsis: 8192 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8193 8194 Not collective 8195 8196 Input Parameters: 8197 + x - matrix 8198 - xx_v - the Fortran90 pointer to the array 8199 8200 Output Parameter: 8201 . ierr - error code 8202 8203 Example of Usage: 8204 .vb 8205 PetscScalar, pointer xx_v(:) 8206 .... 8207 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8208 a = xx_v(3) 8209 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8210 .ve 8211 8212 Level: advanced 8213 8214 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8215 8216 M*/ 8217 8218 /*@ 8219 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8220 as the original matrix. 8221 8222 Collective 8223 8224 Input Parameters: 8225 + mat - the original matrix 8226 . isrow - parallel IS containing the rows this processor should obtain 8227 . 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. 8228 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8229 8230 Output Parameter: 8231 . newmat - the new submatrix, of the same type as the old 8232 8233 Level: advanced 8234 8235 Notes: 8236 The submatrix will be able to be multiplied with vectors using the same layout as iscol. 8237 8238 Some matrix types place restrictions on the row and column indices, such 8239 as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block; 8240 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8241 8242 The index sets may not have duplicate entries. 8243 8244 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8245 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8246 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8247 will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when 8248 you are finished using it. 8249 8250 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8251 the input matrix. 8252 8253 If iscol is NULL then all columns are obtained (not supported in Fortran). 8254 8255 Example usage: 8256 Consider the following 8x8 matrix with 34 non-zero values, that is 8257 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8258 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8259 as follows: 8260 8261 .vb 8262 1 2 0 | 0 3 0 | 0 4 8263 Proc0 0 5 6 | 7 0 0 | 8 0 8264 9 0 10 | 11 0 0 | 12 0 8265 ------------------------------------- 8266 13 0 14 | 15 16 17 | 0 0 8267 Proc1 0 18 0 | 19 20 21 | 0 0 8268 0 0 0 | 22 23 0 | 24 0 8269 ------------------------------------- 8270 Proc2 25 26 27 | 0 0 28 | 29 0 8271 30 0 0 | 31 32 33 | 0 34 8272 .ve 8273 8274 Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8275 8276 .vb 8277 2 0 | 0 3 0 | 0 8278 Proc0 5 6 | 7 0 0 | 8 8279 ------------------------------- 8280 Proc1 18 0 | 19 20 21 | 0 8281 ------------------------------- 8282 Proc2 26 27 | 0 0 28 | 29 8283 0 0 | 31 32 33 | 0 8284 .ve 8285 8286 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8287 @*/ 8288 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8289 { 8290 PetscMPIInt size; 8291 Mat *local; 8292 IS iscoltmp; 8293 PetscBool flg; 8294 8295 PetscFunctionBegin; 8296 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8297 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8298 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8299 PetscValidPointer(newmat, 5); 8300 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8301 PetscValidType(mat, 1); 8302 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8303 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8304 8305 MatCheckPreallocated(mat, 1); 8306 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8307 8308 if (!iscol || isrow == iscol) { 8309 PetscBool stride; 8310 PetscMPIInt grabentirematrix = 0, grab; 8311 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8312 if (stride) { 8313 PetscInt first, step, n, rstart, rend; 8314 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8315 if (step == 1) { 8316 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8317 if (rstart == first) { 8318 PetscCall(ISGetLocalSize(isrow, &n)); 8319 if (n == rend - rstart) grabentirematrix = 1; 8320 } 8321 } 8322 } 8323 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8324 if (grab) { 8325 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8326 if (cll == MAT_INITIAL_MATRIX) { 8327 *newmat = mat; 8328 PetscCall(PetscObjectReference((PetscObject)mat)); 8329 } 8330 PetscFunctionReturn(0); 8331 } 8332 } 8333 8334 if (!iscol) { 8335 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8336 } else { 8337 iscoltmp = iscol; 8338 } 8339 8340 /* if original matrix is on just one processor then use submatrix generated */ 8341 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8342 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8343 goto setproperties; 8344 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8345 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8346 *newmat = *local; 8347 PetscCall(PetscFree(local)); 8348 goto setproperties; 8349 } else if (!mat->ops->createsubmatrix) { 8350 /* Create a new matrix type that implements the operation using the full matrix */ 8351 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8352 switch (cll) { 8353 case MAT_INITIAL_MATRIX: 8354 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8355 break; 8356 case MAT_REUSE_MATRIX: 8357 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8358 break; 8359 default: 8360 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8361 } 8362 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8363 goto setproperties; 8364 } 8365 8366 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8367 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8368 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8369 8370 setproperties: 8371 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8372 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8373 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8374 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8375 PetscFunctionReturn(0); 8376 } 8377 8378 /*@ 8379 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8380 8381 Not Collective 8382 8383 Input Parameters: 8384 + A - the matrix we wish to propagate options from 8385 - B - the matrix we wish to propagate options to 8386 8387 Level: beginner 8388 8389 Note: 8390 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8391 8392 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8393 @*/ 8394 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8395 { 8396 PetscFunctionBegin; 8397 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8398 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8399 B->symmetry_eternal = A->symmetry_eternal; 8400 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8401 B->symmetric = A->symmetric; 8402 B->structurally_symmetric = A->structurally_symmetric; 8403 B->spd = A->spd; 8404 B->hermitian = A->hermitian; 8405 PetscFunctionReturn(0); 8406 } 8407 8408 /*@ 8409 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8410 used during the assembly process to store values that belong to 8411 other processors. 8412 8413 Not Collective 8414 8415 Input Parameters: 8416 + mat - the matrix 8417 . size - the initial size of the stash. 8418 - bsize - the initial size of the block-stash(if used). 8419 8420 Options Database Keys: 8421 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8422 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8423 8424 Level: intermediate 8425 8426 Notes: 8427 The block-stash is used for values set with `MatSetValuesBlocked()` while 8428 the stash is used for values set with `MatSetValues()` 8429 8430 Run with the option -info and look for output of the form 8431 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8432 to determine the appropriate value, MM, to use for size and 8433 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8434 to determine the value, BMM to use for bsize 8435 8436 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8437 @*/ 8438 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8439 { 8440 PetscFunctionBegin; 8441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8442 PetscValidType(mat, 1); 8443 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8444 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8445 PetscFunctionReturn(0); 8446 } 8447 8448 /*@ 8449 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8450 the matrix 8451 8452 Neighbor-wise Collective 8453 8454 Input Parameters: 8455 + mat - the matrix 8456 . x,y - the vectors 8457 - w - where the result is stored 8458 8459 Level: intermediate 8460 8461 Notes: 8462 w may be the same vector as y. 8463 8464 This allows one to use either the restriction or interpolation (its transpose) 8465 matrix to do the interpolation 8466 8467 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8468 @*/ 8469 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8470 { 8471 PetscInt M, N, Ny; 8472 8473 PetscFunctionBegin; 8474 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8475 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8476 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8477 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8478 PetscCall(MatGetSize(A, &M, &N)); 8479 PetscCall(VecGetSize(y, &Ny)); 8480 if (M == Ny) { 8481 PetscCall(MatMultAdd(A, x, y, w)); 8482 } else { 8483 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8484 } 8485 PetscFunctionReturn(0); 8486 } 8487 8488 /*@ 8489 MatInterpolate - y = A*x or A'*x depending on the shape of 8490 the matrix 8491 8492 Neighbor-wise Collective 8493 8494 Input Parameters: 8495 + mat - the matrix 8496 - x,y - the vectors 8497 8498 Level: intermediate 8499 8500 Note: 8501 This allows one to use either the restriction or interpolation (its transpose) 8502 matrix to do the interpolation 8503 8504 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8505 @*/ 8506 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8507 { 8508 PetscInt M, N, Ny; 8509 8510 PetscFunctionBegin; 8511 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8512 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8513 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8514 PetscCall(MatGetSize(A, &M, &N)); 8515 PetscCall(VecGetSize(y, &Ny)); 8516 if (M == Ny) { 8517 PetscCall(MatMult(A, x, y)); 8518 } else { 8519 PetscCall(MatMultTranspose(A, x, y)); 8520 } 8521 PetscFunctionReturn(0); 8522 } 8523 8524 /*@ 8525 MatRestrict - y = A*x or A'*x 8526 8527 Neighbor-wise Collective on Mat 8528 8529 Input Parameters: 8530 + mat - the matrix 8531 - x,y - the vectors 8532 8533 Level: intermediate 8534 8535 Note: 8536 This allows one to use either the restriction or interpolation (its transpose) 8537 matrix to do the restriction 8538 8539 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8540 @*/ 8541 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8542 { 8543 PetscInt M, N, Ny; 8544 8545 PetscFunctionBegin; 8546 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8547 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8548 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8549 PetscCall(MatGetSize(A, &M, &N)); 8550 PetscCall(VecGetSize(y, &Ny)); 8551 if (M == Ny) { 8552 PetscCall(MatMult(A, x, y)); 8553 } else { 8554 PetscCall(MatMultTranspose(A, x, y)); 8555 } 8556 PetscFunctionReturn(0); 8557 } 8558 8559 /*@ 8560 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8561 8562 Neighbor-wise Collective on Mat 8563 8564 Input Parameters: 8565 + mat - the matrix 8566 - w, x - the input dense matrices 8567 8568 Output Parameters: 8569 . y - the output dense matrix 8570 8571 Level: intermediate 8572 8573 Note: 8574 This allows one to use either the restriction or interpolation (its transpose) 8575 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8576 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8577 8578 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8579 @*/ 8580 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8581 { 8582 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8583 PetscBool trans = PETSC_TRUE; 8584 MatReuse reuse = MAT_INITIAL_MATRIX; 8585 8586 PetscFunctionBegin; 8587 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8588 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8589 PetscValidType(x, 2); 8590 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8591 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8592 PetscCall(MatGetSize(A, &M, &N)); 8593 PetscCall(MatGetSize(x, &Mx, &Nx)); 8594 if (N == Mx) trans = PETSC_FALSE; 8595 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); 8596 Mo = trans ? N : M; 8597 if (*y) { 8598 PetscCall(MatGetSize(*y, &My, &Ny)); 8599 if (Mo == My && Nx == Ny) { 8600 reuse = MAT_REUSE_MATRIX; 8601 } else { 8602 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); 8603 PetscCall(MatDestroy(y)); 8604 } 8605 } 8606 8607 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8608 PetscBool flg; 8609 8610 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8611 if (w) { 8612 PetscInt My, Ny, Mw, Nw; 8613 8614 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8615 PetscCall(MatGetSize(*y, &My, &Ny)); 8616 PetscCall(MatGetSize(w, &Mw, &Nw)); 8617 if (!flg || My != Mw || Ny != Nw) w = NULL; 8618 } 8619 if (!w) { 8620 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8621 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8622 PetscCall(PetscObjectDereference((PetscObject)w)); 8623 } else { 8624 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8625 } 8626 } 8627 if (!trans) { 8628 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8629 } else { 8630 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8631 } 8632 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8633 PetscFunctionReturn(0); 8634 } 8635 8636 /*@ 8637 MatMatInterpolate - Y = A*X or A'*X 8638 8639 Neighbor-wise Collective on Mat 8640 8641 Input Parameters: 8642 + mat - the matrix 8643 - x - the input dense matrix 8644 8645 Output Parameters: 8646 . y - the output dense matrix 8647 8648 Level: intermediate 8649 8650 Note: 8651 This allows one to use either the restriction or interpolation (its transpose) 8652 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8653 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8654 8655 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8656 @*/ 8657 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8658 { 8659 PetscFunctionBegin; 8660 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8661 PetscFunctionReturn(0); 8662 } 8663 8664 /*@ 8665 MatMatRestrict - Y = A*X or A'*X 8666 8667 Neighbor-wise Collective on Mat 8668 8669 Input Parameters: 8670 + mat - the matrix 8671 - x - the input dense matrix 8672 8673 Output Parameters: 8674 . y - the output dense matrix 8675 8676 Level: intermediate 8677 8678 Note: 8679 This allows one to use either the restriction or interpolation (its transpose) 8680 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8681 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8682 8683 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8684 @*/ 8685 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8686 { 8687 PetscFunctionBegin; 8688 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8689 PetscFunctionReturn(0); 8690 } 8691 8692 /*@ 8693 MatGetNullSpace - retrieves the null space of a matrix. 8694 8695 Logically Collective 8696 8697 Input Parameters: 8698 + mat - the matrix 8699 - nullsp - the null space object 8700 8701 Level: developer 8702 8703 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8704 @*/ 8705 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8706 { 8707 PetscFunctionBegin; 8708 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8709 PetscValidPointer(nullsp, 2); 8710 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8711 PetscFunctionReturn(0); 8712 } 8713 8714 /*@ 8715 MatSetNullSpace - attaches a null space to a matrix. 8716 8717 Logically Collective 8718 8719 Input Parameters: 8720 + mat - the matrix 8721 - nullsp - the null space object 8722 8723 Level: advanced 8724 8725 Notes: 8726 This null space is used by the `KSP` linear solvers to solve singular systems. 8727 8728 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 8729 8730 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 8731 to zero but the linear system will still be solved in a least squares sense. 8732 8733 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8734 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). 8735 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 8736 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 8737 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). 8738 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8739 8740 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8741 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8742 routine also automatically calls `MatSetTransposeNullSpace()`. 8743 8744 The user should call `MatNullSpaceDestroy()`. 8745 8746 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8747 `KSPSetPCSide()` 8748 @*/ 8749 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8750 { 8751 PetscFunctionBegin; 8752 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8753 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8754 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8755 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8756 mat->nullsp = nullsp; 8757 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8758 PetscFunctionReturn(0); 8759 } 8760 8761 /*@ 8762 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8763 8764 Logically Collective 8765 8766 Input Parameters: 8767 + mat - the matrix 8768 - nullsp - the null space object 8769 8770 Level: developer 8771 8772 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8773 @*/ 8774 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8775 { 8776 PetscFunctionBegin; 8777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8778 PetscValidType(mat, 1); 8779 PetscValidPointer(nullsp, 2); 8780 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8781 PetscFunctionReturn(0); 8782 } 8783 8784 /*@ 8785 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8786 8787 Logically Collective 8788 8789 Input Parameters: 8790 + mat - the matrix 8791 - nullsp - the null space object 8792 8793 Level: advanced 8794 8795 Notes: 8796 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8797 8798 See `MatSetNullSpace()` 8799 8800 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8801 @*/ 8802 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8803 { 8804 PetscFunctionBegin; 8805 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8806 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8807 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8808 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8809 mat->transnullsp = nullsp; 8810 PetscFunctionReturn(0); 8811 } 8812 8813 /*@ 8814 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8815 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8816 8817 Logically Collective 8818 8819 Input Parameters: 8820 + mat - the matrix 8821 - nullsp - the null space object 8822 8823 Level: advanced 8824 8825 Notes: 8826 Overwrites any previous near null space that may have been attached 8827 8828 You can remove the null space by calling this routine with an nullsp of NULL 8829 8830 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8831 @*/ 8832 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8833 { 8834 PetscFunctionBegin; 8835 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8836 PetscValidType(mat, 1); 8837 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8838 MatCheckPreallocated(mat, 1); 8839 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8840 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8841 mat->nearnullsp = nullsp; 8842 PetscFunctionReturn(0); 8843 } 8844 8845 /*@ 8846 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8847 8848 Not Collective 8849 8850 Input Parameter: 8851 . mat - the matrix 8852 8853 Output Parameter: 8854 . nullsp - the null space object, NULL if not set 8855 8856 Level: advanced 8857 8858 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8859 @*/ 8860 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8861 { 8862 PetscFunctionBegin; 8863 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8864 PetscValidType(mat, 1); 8865 PetscValidPointer(nullsp, 2); 8866 MatCheckPreallocated(mat, 1); 8867 *nullsp = mat->nearnullsp; 8868 PetscFunctionReturn(0); 8869 } 8870 8871 /*@C 8872 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8873 8874 Collective 8875 8876 Input Parameters: 8877 + mat - the matrix 8878 . row - row/column permutation 8879 . fill - expected fill factor >= 1.0 8880 - level - level of fill, for ICC(k) 8881 8882 Notes: 8883 Probably really in-place only when level of fill is zero, otherwise allocates 8884 new space to store factored matrix and deletes previous memory. 8885 8886 Most users should employ the `KSP` interface for linear solvers 8887 instead of working directly with matrix algebra routines such as this. 8888 See, e.g., `KSPCreate()`. 8889 8890 Level: developer 8891 8892 Developer Note: 8893 The Fortran interface is not autogenerated as the 8894 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8895 8896 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8897 @*/ 8898 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8899 { 8900 PetscFunctionBegin; 8901 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8902 PetscValidType(mat, 1); 8903 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8904 PetscValidPointer(info, 3); 8905 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8906 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8907 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8908 MatCheckPreallocated(mat, 1); 8909 PetscUseTypeMethod(mat, iccfactor, row, info); 8910 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8911 PetscFunctionReturn(0); 8912 } 8913 8914 /*@ 8915 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8916 ghosted ones. 8917 8918 Not Collective 8919 8920 Input Parameters: 8921 + mat - the matrix 8922 - diag - the diagonal values, including ghost ones 8923 8924 Level: developer 8925 8926 Notes: 8927 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8928 8929 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8930 8931 .seealso: `MatDiagonalScale()` 8932 @*/ 8933 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8934 { 8935 PetscMPIInt size; 8936 8937 PetscFunctionBegin; 8938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8939 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8940 PetscValidType(mat, 1); 8941 8942 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8943 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8944 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8945 if (size == 1) { 8946 PetscInt n, m; 8947 PetscCall(VecGetSize(diag, &n)); 8948 PetscCall(MatGetSize(mat, NULL, &m)); 8949 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 8950 PetscCall(MatDiagonalScale(mat, NULL, diag)); 8951 } else { 8952 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 8953 } 8954 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 8955 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8956 PetscFunctionReturn(0); 8957 } 8958 8959 /*@ 8960 MatGetInertia - Gets the inertia from a factored matrix 8961 8962 Collective 8963 8964 Input Parameter: 8965 . mat - the matrix 8966 8967 Output Parameters: 8968 + nneg - number of negative eigenvalues 8969 . nzero - number of zero eigenvalues 8970 - npos - number of positive eigenvalues 8971 8972 Level: advanced 8973 8974 Note: 8975 Matrix must have been factored by `MatCholeskyFactor()` 8976 8977 .seealso: `MatGetFactor()`, `MatCholeskyFactor()` 8978 @*/ 8979 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 8980 { 8981 PetscFunctionBegin; 8982 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8983 PetscValidType(mat, 1); 8984 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 8985 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 8986 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 8987 PetscFunctionReturn(0); 8988 } 8989 8990 /* ----------------------------------------------------------------*/ 8991 /*@C 8992 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 8993 8994 Neighbor-wise Collective 8995 8996 Input Parameters: 8997 + mat - the factored matrix obtained with `MatGetFactor()` 8998 - b - the right-hand-side vectors 8999 9000 Output Parameter: 9001 . x - the result vectors 9002 9003 Note: 9004 The vectors b and x cannot be the same. I.e., one cannot 9005 call `MatSolves`(A,x,x). 9006 9007 Level: developer 9008 9009 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9010 @*/ 9011 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9012 { 9013 PetscFunctionBegin; 9014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9015 PetscValidType(mat, 1); 9016 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9017 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9018 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 9019 9020 MatCheckPreallocated(mat, 1); 9021 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9022 PetscUseTypeMethod(mat, solves, b, x); 9023 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9024 PetscFunctionReturn(0); 9025 } 9026 9027 /*@ 9028 MatIsSymmetric - Test whether a matrix is symmetric 9029 9030 Collective 9031 9032 Input Parameters: 9033 + A - the matrix to test 9034 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9035 9036 Output Parameters: 9037 . flg - the result 9038 9039 Notes: 9040 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9041 9042 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9043 9044 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9045 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9046 9047 Level: intermediate 9048 9049 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9050 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9051 @*/ 9052 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9053 { 9054 PetscFunctionBegin; 9055 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9056 PetscValidBoolPointer(flg, 3); 9057 9058 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9059 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9060 else { 9061 if (!A->ops->issymmetric) { 9062 MatType mattype; 9063 PetscCall(MatGetType(A, &mattype)); 9064 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype); 9065 } 9066 PetscUseTypeMethod(A, issymmetric, tol, flg); 9067 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9068 } 9069 PetscFunctionReturn(0); 9070 } 9071 9072 /*@ 9073 MatIsHermitian - Test whether a matrix is Hermitian 9074 9075 Collective on Mat 9076 9077 Input Parameters: 9078 + A - the matrix to test 9079 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9080 9081 Output Parameters: 9082 . flg - the result 9083 9084 Level: intermediate 9085 9086 Notes: 9087 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9088 9089 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9090 9091 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9092 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9093 9094 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9095 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9096 @*/ 9097 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9098 { 9099 PetscFunctionBegin; 9100 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9101 PetscValidBoolPointer(flg, 3); 9102 9103 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9104 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9105 else { 9106 if (!A->ops->ishermitian) { 9107 MatType mattype; 9108 PetscCall(MatGetType(A, &mattype)); 9109 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype); 9110 } 9111 PetscUseTypeMethod(A, ishermitian, tol, flg); 9112 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9113 } 9114 PetscFunctionReturn(0); 9115 } 9116 9117 /*@ 9118 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9119 9120 Not Collective 9121 9122 Input Parameter: 9123 . A - the matrix to check 9124 9125 Output Parameters: 9126 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9127 - flg - the result (only valid if set is `PETSC_TRUE`) 9128 9129 Level: advanced 9130 9131 Notes: 9132 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9133 if you want it explicitly checked 9134 9135 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9136 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9137 9138 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9139 @*/ 9140 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9141 { 9142 PetscFunctionBegin; 9143 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9144 PetscValidBoolPointer(set, 2); 9145 PetscValidBoolPointer(flg, 3); 9146 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9147 *set = PETSC_TRUE; 9148 *flg = PetscBool3ToBool(A->symmetric); 9149 } else { 9150 *set = PETSC_FALSE; 9151 } 9152 PetscFunctionReturn(0); 9153 } 9154 9155 /*@ 9156 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9157 9158 Not Collective 9159 9160 Input Parameter: 9161 . A - the matrix to check 9162 9163 Output Parameters: 9164 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9165 - flg - the result (only valid if set is `PETSC_TRUE`) 9166 9167 Level: advanced 9168 9169 Notes: 9170 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9171 9172 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9173 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9174 9175 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9176 @*/ 9177 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9178 { 9179 PetscFunctionBegin; 9180 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9181 PetscValidBoolPointer(set, 2); 9182 PetscValidBoolPointer(flg, 3); 9183 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9184 *set = PETSC_TRUE; 9185 *flg = PetscBool3ToBool(A->spd); 9186 } else { 9187 *set = PETSC_FALSE; 9188 } 9189 PetscFunctionReturn(0); 9190 } 9191 9192 /*@ 9193 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9194 9195 Not Collective 9196 9197 Input Parameter: 9198 . A - the matrix to check 9199 9200 Output Parameters: 9201 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9202 - flg - the result (only valid if set is `PETSC_TRUE`) 9203 9204 Level: advanced 9205 9206 Notes: 9207 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9208 if you want it explicitly checked 9209 9210 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9211 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9212 9213 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9214 @*/ 9215 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9216 { 9217 PetscFunctionBegin; 9218 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9219 PetscValidBoolPointer(set, 2); 9220 PetscValidBoolPointer(flg, 3); 9221 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9222 *set = PETSC_TRUE; 9223 *flg = PetscBool3ToBool(A->hermitian); 9224 } else { 9225 *set = PETSC_FALSE; 9226 } 9227 PetscFunctionReturn(0); 9228 } 9229 9230 /*@ 9231 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9232 9233 Collective on Mat 9234 9235 Input Parameter: 9236 . A - the matrix to test 9237 9238 Output Parameters: 9239 . flg - the result 9240 9241 Notes: 9242 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9243 9244 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 9245 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9246 9247 Level: intermediate 9248 9249 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9250 @*/ 9251 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9252 { 9253 PetscFunctionBegin; 9254 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9255 PetscValidBoolPointer(flg, 2); 9256 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9257 *flg = PetscBool3ToBool(A->structurally_symmetric); 9258 } else { 9259 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9260 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9261 } 9262 PetscFunctionReturn(0); 9263 } 9264 9265 /*@ 9266 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9267 9268 Not Collective 9269 9270 Input Parameter: 9271 . A - the matrix to check 9272 9273 Output Parameters: 9274 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9275 - flg - the result (only valid if set is PETSC_TRUE) 9276 9277 Level: advanced 9278 9279 Notes: 9280 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 9281 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9282 9283 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9284 9285 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9286 @*/ 9287 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9288 { 9289 PetscFunctionBegin; 9290 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9291 PetscValidBoolPointer(set, 2); 9292 PetscValidBoolPointer(flg, 3); 9293 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9294 *set = PETSC_TRUE; 9295 *flg = PetscBool3ToBool(A->structurally_symmetric); 9296 } else { 9297 *set = PETSC_FALSE; 9298 } 9299 PetscFunctionReturn(0); 9300 } 9301 9302 /*@ 9303 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9304 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9305 9306 Not collective 9307 9308 Input Parameter: 9309 . mat - the matrix 9310 9311 Output Parameters: 9312 + nstash - the size of the stash 9313 . reallocs - the number of additional mallocs incurred. 9314 . bnstash - the size of the block stash 9315 - breallocs - the number of additional mallocs incurred.in the block stash 9316 9317 Level: advanced 9318 9319 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9320 @*/ 9321 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9322 { 9323 PetscFunctionBegin; 9324 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9325 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9326 PetscFunctionReturn(0); 9327 } 9328 9329 /*@C 9330 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9331 parallel layout, `PetscLayout` for rows and columns 9332 9333 Collective 9334 9335 Input Parameter: 9336 . mat - the matrix 9337 9338 Output Parameters: 9339 + right - (optional) vector that the matrix can be multiplied against 9340 - left - (optional) vector that the matrix vector product can be stored in 9341 9342 Notes: 9343 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()`. 9344 9345 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9346 9347 Level: advanced 9348 9349 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9350 @*/ 9351 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9352 { 9353 PetscFunctionBegin; 9354 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9355 PetscValidType(mat, 1); 9356 if (mat->ops->getvecs) { 9357 PetscUseTypeMethod(mat, getvecs, right, left); 9358 } else { 9359 PetscInt rbs, cbs; 9360 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9361 if (right) { 9362 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9363 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9364 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9365 PetscCall(VecSetBlockSize(*right, cbs)); 9366 PetscCall(VecSetType(*right, mat->defaultvectype)); 9367 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9368 if (mat->boundtocpu && mat->bindingpropagates) { 9369 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9370 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9371 } 9372 #endif 9373 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9374 } 9375 if (left) { 9376 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9377 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9378 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9379 PetscCall(VecSetBlockSize(*left, rbs)); 9380 PetscCall(VecSetType(*left, mat->defaultvectype)); 9381 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9382 if (mat->boundtocpu && mat->bindingpropagates) { 9383 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9384 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9385 } 9386 #endif 9387 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9388 } 9389 } 9390 PetscFunctionReturn(0); 9391 } 9392 9393 /*@C 9394 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9395 with default values. 9396 9397 Not Collective 9398 9399 Input Parameters: 9400 . info - the `MatFactorInfo` data structure 9401 9402 Notes: 9403 The solvers are generally used through the `KSP` and `PC` objects, for example 9404 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9405 9406 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9407 9408 Level: developer 9409 9410 Developer Note: 9411 The Fortran interface is not autogenerated as the 9412 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9413 9414 .seealso: `MatGetFactor()`, `MatFactorInfo` 9415 @*/ 9416 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9417 { 9418 PetscFunctionBegin; 9419 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9420 PetscFunctionReturn(0); 9421 } 9422 9423 /*@ 9424 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9425 9426 Collective 9427 9428 Input Parameters: 9429 + mat - the factored matrix 9430 - is - the index set defining the Schur indices (0-based) 9431 9432 Notes: 9433 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9434 9435 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9436 9437 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9438 9439 Level: advanced 9440 9441 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9442 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9443 9444 @*/ 9445 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9446 { 9447 PetscErrorCode (*f)(Mat, IS); 9448 9449 PetscFunctionBegin; 9450 PetscValidType(mat, 1); 9451 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9452 PetscValidType(is, 2); 9453 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9454 PetscCheckSameComm(mat, 1, is, 2); 9455 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9456 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9457 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9458 PetscCall(MatDestroy(&mat->schur)); 9459 PetscCall((*f)(mat, is)); 9460 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9461 PetscFunctionReturn(0); 9462 } 9463 9464 /*@ 9465 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9466 9467 Logically Collective 9468 9469 Input Parameters: 9470 + F - the factored matrix obtained by calling `MatGetFactor()` 9471 . S - location where to return the Schur complement, can be NULL 9472 - status - the status of the Schur complement matrix, can be NULL 9473 9474 Notes: 9475 You must call `MatFactorSetSchurIS()` before calling this routine. 9476 9477 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9478 9479 The routine provides a copy of the Schur matrix stored within the solver data structures. 9480 The caller must destroy the object when it is no longer needed. 9481 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9482 9483 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) 9484 9485 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9486 9487 Developer Note: 9488 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9489 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9490 9491 Level: advanced 9492 9493 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9494 @*/ 9495 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9496 { 9497 PetscFunctionBegin; 9498 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9499 if (S) PetscValidPointer(S, 2); 9500 if (status) PetscValidPointer(status, 3); 9501 if (S) { 9502 PetscErrorCode (*f)(Mat, Mat *); 9503 9504 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9505 if (f) { 9506 PetscCall((*f)(F, S)); 9507 } else { 9508 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9509 } 9510 } 9511 if (status) *status = F->schur_status; 9512 PetscFunctionReturn(0); 9513 } 9514 9515 /*@ 9516 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9517 9518 Logically Collective 9519 9520 Input Parameters: 9521 + F - the factored matrix obtained by calling `MatGetFactor()` 9522 . *S - location where to return the Schur complement, can be NULL 9523 - status - the status of the Schur complement matrix, can be NULL 9524 9525 Notes: 9526 You must call `MatFactorSetSchurIS()` before calling this routine. 9527 9528 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9529 9530 The routine returns a the Schur Complement stored within the data strutures of the solver. 9531 9532 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9533 9534 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9535 9536 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9537 9538 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9539 9540 Level: advanced 9541 9542 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9543 @*/ 9544 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9545 { 9546 PetscFunctionBegin; 9547 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9548 if (S) PetscValidPointer(S, 2); 9549 if (status) PetscValidPointer(status, 3); 9550 if (S) *S = F->schur; 9551 if (status) *status = F->schur_status; 9552 PetscFunctionReturn(0); 9553 } 9554 9555 /*@ 9556 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9557 9558 Logically Collective 9559 9560 Input Parameters: 9561 + F - the factored matrix obtained by calling `MatGetFactor()` 9562 . *S - location where the Schur complement is stored 9563 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9564 9565 Level: advanced 9566 9567 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9568 @*/ 9569 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9570 { 9571 PetscFunctionBegin; 9572 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9573 if (S) { 9574 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9575 *S = NULL; 9576 } 9577 F->schur_status = status; 9578 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9579 PetscFunctionReturn(0); 9580 } 9581 9582 /*@ 9583 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9584 9585 Logically Collective 9586 9587 Input Parameters: 9588 + F - the factored matrix obtained by calling `MatGetFactor()` 9589 . rhs - location where the right hand side of the Schur complement system is stored 9590 - sol - location where the solution of the Schur complement system has to be returned 9591 9592 Notes: 9593 The sizes of the vectors should match the size of the Schur complement 9594 9595 Must be called after `MatFactorSetSchurIS()` 9596 9597 Level: advanced 9598 9599 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9600 @*/ 9601 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9602 { 9603 PetscFunctionBegin; 9604 PetscValidType(F, 1); 9605 PetscValidType(rhs, 2); 9606 PetscValidType(sol, 3); 9607 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9608 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9609 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9610 PetscCheckSameComm(F, 1, rhs, 2); 9611 PetscCheckSameComm(F, 1, sol, 3); 9612 PetscCall(MatFactorFactorizeSchurComplement(F)); 9613 switch (F->schur_status) { 9614 case MAT_FACTOR_SCHUR_FACTORED: 9615 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9616 break; 9617 case MAT_FACTOR_SCHUR_INVERTED: 9618 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9619 break; 9620 default: 9621 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9622 } 9623 PetscFunctionReturn(0); 9624 } 9625 9626 /*@ 9627 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9628 9629 Logically Collective 9630 9631 Input Parameters: 9632 + F - the factored matrix obtained by calling `MatGetFactor()` 9633 . rhs - location where the right hand side of the Schur complement system is stored 9634 - sol - location where the solution of the Schur complement system has to be returned 9635 9636 Notes: 9637 The sizes of the vectors should match the size of the Schur complement 9638 9639 Must be called after `MatFactorSetSchurIS()` 9640 9641 Level: advanced 9642 9643 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9644 @*/ 9645 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9646 { 9647 PetscFunctionBegin; 9648 PetscValidType(F, 1); 9649 PetscValidType(rhs, 2); 9650 PetscValidType(sol, 3); 9651 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9652 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9653 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9654 PetscCheckSameComm(F, 1, rhs, 2); 9655 PetscCheckSameComm(F, 1, sol, 3); 9656 PetscCall(MatFactorFactorizeSchurComplement(F)); 9657 switch (F->schur_status) { 9658 case MAT_FACTOR_SCHUR_FACTORED: 9659 PetscCall(MatSolve(F->schur, rhs, sol)); 9660 break; 9661 case MAT_FACTOR_SCHUR_INVERTED: 9662 PetscCall(MatMult(F->schur, rhs, sol)); 9663 break; 9664 default: 9665 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9666 } 9667 PetscFunctionReturn(0); 9668 } 9669 9670 /*@ 9671 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9672 9673 Logically Collective on F 9674 9675 Input Parameters: 9676 . F - the factored matrix obtained by calling `MatGetFactor()` 9677 9678 Notes: 9679 Must be called after `MatFactorSetSchurIS()`. 9680 9681 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9682 9683 Level: advanced 9684 9685 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9686 @*/ 9687 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9688 { 9689 PetscFunctionBegin; 9690 PetscValidType(F, 1); 9691 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9692 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0); 9693 PetscCall(MatFactorFactorizeSchurComplement(F)); 9694 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9695 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9696 PetscFunctionReturn(0); 9697 } 9698 9699 /*@ 9700 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9701 9702 Logically Collective 9703 9704 Input Parameters: 9705 . F - the factored matrix obtained by calling `MatGetFactor()` 9706 9707 Note: 9708 Must be called after `MatFactorSetSchurIS()` 9709 9710 Level: advanced 9711 9712 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9713 @*/ 9714 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9715 { 9716 PetscFunctionBegin; 9717 PetscValidType(F, 1); 9718 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9719 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0); 9720 PetscCall(MatFactorFactorizeSchurComplement_Private(F)); 9721 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9722 PetscFunctionReturn(0); 9723 } 9724 9725 /*@ 9726 MatPtAP - Creates the matrix product C = P^T * A * P 9727 9728 Neighbor-wise Collective on A 9729 9730 Input Parameters: 9731 + A - the matrix 9732 . P - the projection matrix 9733 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9734 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9735 if the result is a dense matrix this is irrelevant 9736 9737 Output Parameters: 9738 . C - the product matrix 9739 9740 Notes: 9741 C will be created and must be destroyed by the user with `MatDestroy()`. 9742 9743 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9744 9745 Developer Note: 9746 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9747 9748 Level: intermediate 9749 9750 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9751 @*/ 9752 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9753 { 9754 PetscFunctionBegin; 9755 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9756 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9757 9758 if (scall == MAT_INITIAL_MATRIX) { 9759 PetscCall(MatProductCreate(A, P, NULL, C)); 9760 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9761 PetscCall(MatProductSetAlgorithm(*C, "default")); 9762 PetscCall(MatProductSetFill(*C, fill)); 9763 9764 (*C)->product->api_user = PETSC_TRUE; 9765 PetscCall(MatProductSetFromOptions(*C)); 9766 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); 9767 PetscCall(MatProductSymbolic(*C)); 9768 } else { /* scall == MAT_REUSE_MATRIX */ 9769 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9770 } 9771 9772 PetscCall(MatProductNumeric(*C)); 9773 (*C)->symmetric = A->symmetric; 9774 (*C)->spd = A->spd; 9775 PetscFunctionReturn(0); 9776 } 9777 9778 /*@ 9779 MatRARt - Creates the matrix product C = R * A * R^T 9780 9781 Neighbor-wise Collective on A 9782 9783 Input Parameters: 9784 + A - the matrix 9785 . R - the projection matrix 9786 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9787 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9788 if the result is a dense matrix this is irrelevant 9789 9790 Output Parameters: 9791 . C - the product matrix 9792 9793 Notes: 9794 C will be created and must be destroyed by the user with `MatDestroy()`. 9795 9796 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9797 9798 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9799 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9800 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9801 We recommend using MatPtAP(). 9802 9803 Level: intermediate 9804 9805 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9806 @*/ 9807 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9808 { 9809 PetscFunctionBegin; 9810 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9811 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9812 9813 if (scall == MAT_INITIAL_MATRIX) { 9814 PetscCall(MatProductCreate(A, R, NULL, C)); 9815 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9816 PetscCall(MatProductSetAlgorithm(*C, "default")); 9817 PetscCall(MatProductSetFill(*C, fill)); 9818 9819 (*C)->product->api_user = PETSC_TRUE; 9820 PetscCall(MatProductSetFromOptions(*C)); 9821 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); 9822 PetscCall(MatProductSymbolic(*C)); 9823 } else { /* scall == MAT_REUSE_MATRIX */ 9824 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9825 } 9826 9827 PetscCall(MatProductNumeric(*C)); 9828 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9829 PetscFunctionReturn(0); 9830 } 9831 9832 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9833 { 9834 PetscFunctionBegin; 9835 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9836 9837 if (scall == MAT_INITIAL_MATRIX) { 9838 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9839 PetscCall(MatProductCreate(A, B, NULL, C)); 9840 PetscCall(MatProductSetType(*C, ptype)); 9841 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9842 PetscCall(MatProductSetFill(*C, fill)); 9843 9844 (*C)->product->api_user = PETSC_TRUE; 9845 PetscCall(MatProductSetFromOptions(*C)); 9846 PetscCall(MatProductSymbolic(*C)); 9847 } else { /* scall == MAT_REUSE_MATRIX */ 9848 Mat_Product *product = (*C)->product; 9849 PetscBool isdense; 9850 9851 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9852 if (isdense && product && product->type != ptype) { 9853 PetscCall(MatProductClear(*C)); 9854 product = NULL; 9855 } 9856 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9857 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9858 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9859 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9860 product = (*C)->product; 9861 product->fill = fill; 9862 product->api_user = PETSC_TRUE; 9863 product->clear = PETSC_TRUE; 9864 9865 PetscCall(MatProductSetType(*C, ptype)); 9866 PetscCall(MatProductSetFromOptions(*C)); 9867 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); 9868 PetscCall(MatProductSymbolic(*C)); 9869 } else { /* user may change input matrices A or B when REUSE */ 9870 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9871 } 9872 } 9873 PetscCall(MatProductNumeric(*C)); 9874 PetscFunctionReturn(0); 9875 } 9876 9877 /*@ 9878 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9879 9880 Neighbor-wise Collective on A 9881 9882 Input Parameters: 9883 + A - the left matrix 9884 . B - the right matrix 9885 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9886 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9887 if the result is a dense matrix this is irrelevant 9888 9889 Output Parameters: 9890 . C - the product matrix 9891 9892 Notes: 9893 Unless scall is `MAT_REUSE_MATRIX` C will be created. 9894 9895 `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 9896 call to this function with `MAT_INITIAL_MATRIX`. 9897 9898 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 9899 9900 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`, 9901 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 9902 9903 Example of Usage: 9904 .vb 9905 MatProductCreate(A,B,NULL,&C); 9906 MatProductSetType(C,MATPRODUCT_AB); 9907 MatProductSymbolic(C); 9908 MatProductNumeric(C); // compute C=A * B 9909 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 9910 MatProductNumeric(C); 9911 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 9912 MatProductNumeric(C); 9913 .ve 9914 9915 Level: intermediate 9916 9917 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 9918 @*/ 9919 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9920 { 9921 PetscFunctionBegin; 9922 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 9923 PetscFunctionReturn(0); 9924 } 9925 9926 /*@ 9927 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 9928 9929 Neighbor-wise Collective on A 9930 9931 Input Parameters: 9932 + A - the left matrix 9933 . B - the right matrix 9934 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9935 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9936 9937 Output Parameters: 9938 . C - the product matrix 9939 9940 Notes: 9941 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 9942 9943 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 9944 9945 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9946 actually needed. 9947 9948 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 9949 and for pairs of `MATMPIDENSE` matrices. 9950 9951 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 9952 9953 Options Database Keys: 9954 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 9955 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 9956 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 9957 9958 Level: intermediate 9959 9960 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 9961 @*/ 9962 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9963 { 9964 PetscFunctionBegin; 9965 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 9966 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9967 PetscFunctionReturn(0); 9968 } 9969 9970 /*@ 9971 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 9972 9973 Neighbor-wise Collective on A 9974 9975 Input Parameters: 9976 + A - the left matrix 9977 . B - the right matrix 9978 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9979 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9980 9981 Output Parameters: 9982 . C - the product matrix 9983 9984 Notes: 9985 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 9986 9987 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 9988 9989 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 9990 9991 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9992 actually needed. 9993 9994 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 9995 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 9996 9997 Level: intermediate 9998 9999 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10000 @*/ 10001 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10002 { 10003 PetscFunctionBegin; 10004 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10005 PetscFunctionReturn(0); 10006 } 10007 10008 /*@ 10009 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10010 10011 Neighbor-wise Collective on A 10012 10013 Input Parameters: 10014 + A - the left matrix 10015 . B - the middle matrix 10016 . C - the right matrix 10017 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10018 - 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 10019 if the result is a dense matrix this is irrelevant 10020 10021 Output Parameters: 10022 . D - the product matrix 10023 10024 Notes: 10025 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10026 10027 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10028 10029 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10030 10031 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10032 actually needed. 10033 10034 If you have many matrices with the same non-zero structure to multiply, you 10035 should use `MAT_REUSE_MATRIX` in all calls but the first 10036 10037 Level: intermediate 10038 10039 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10040 @*/ 10041 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10042 { 10043 PetscFunctionBegin; 10044 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10045 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10046 10047 if (scall == MAT_INITIAL_MATRIX) { 10048 PetscCall(MatProductCreate(A, B, C, D)); 10049 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10050 PetscCall(MatProductSetAlgorithm(*D, "default")); 10051 PetscCall(MatProductSetFill(*D, fill)); 10052 10053 (*D)->product->api_user = PETSC_TRUE; 10054 PetscCall(MatProductSetFromOptions(*D)); 10055 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, 10056 ((PetscObject)C)->type_name); 10057 PetscCall(MatProductSymbolic(*D)); 10058 } else { /* user may change input matrices when REUSE */ 10059 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10060 } 10061 PetscCall(MatProductNumeric(*D)); 10062 PetscFunctionReturn(0); 10063 } 10064 10065 /*@ 10066 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10067 10068 Collective 10069 10070 Input Parameters: 10071 + mat - the matrix 10072 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10073 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10074 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10075 10076 Output Parameter: 10077 . matredundant - redundant matrix 10078 10079 Notes: 10080 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10081 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10082 10083 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10084 calling it. 10085 10086 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10087 10088 Level: advanced 10089 10090 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10091 @*/ 10092 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10093 { 10094 MPI_Comm comm; 10095 PetscMPIInt size; 10096 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10097 Mat_Redundant *redund = NULL; 10098 PetscSubcomm psubcomm = NULL; 10099 MPI_Comm subcomm_in = subcomm; 10100 Mat *matseq; 10101 IS isrow, iscol; 10102 PetscBool newsubcomm = PETSC_FALSE; 10103 10104 PetscFunctionBegin; 10105 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10106 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10107 PetscValidPointer(*matredundant, 5); 10108 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10109 } 10110 10111 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10112 if (size == 1 || nsubcomm == 1) { 10113 if (reuse == MAT_INITIAL_MATRIX) { 10114 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10115 } else { 10116 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"); 10117 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10118 } 10119 PetscFunctionReturn(0); 10120 } 10121 10122 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10123 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10124 MatCheckPreallocated(mat, 1); 10125 10126 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10127 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10128 /* create psubcomm, then get subcomm */ 10129 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10130 PetscCallMPI(MPI_Comm_size(comm, &size)); 10131 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10132 10133 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10134 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10135 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10136 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10137 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10138 newsubcomm = PETSC_TRUE; 10139 PetscCall(PetscSubcommDestroy(&psubcomm)); 10140 } 10141 10142 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10143 if (reuse == MAT_INITIAL_MATRIX) { 10144 mloc_sub = PETSC_DECIDE; 10145 nloc_sub = PETSC_DECIDE; 10146 if (bs < 1) { 10147 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10148 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10149 } else { 10150 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10151 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10152 } 10153 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10154 rstart = rend - mloc_sub; 10155 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10156 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10157 } else { /* reuse == MAT_REUSE_MATRIX */ 10158 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"); 10159 /* retrieve subcomm */ 10160 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10161 redund = (*matredundant)->redundant; 10162 isrow = redund->isrow; 10163 iscol = redund->iscol; 10164 matseq = redund->matseq; 10165 } 10166 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10167 10168 /* get matredundant over subcomm */ 10169 if (reuse == MAT_INITIAL_MATRIX) { 10170 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10171 10172 /* create a supporting struct and attach it to C for reuse */ 10173 PetscCall(PetscNew(&redund)); 10174 (*matredundant)->redundant = redund; 10175 redund->isrow = isrow; 10176 redund->iscol = iscol; 10177 redund->matseq = matseq; 10178 if (newsubcomm) { 10179 redund->subcomm = subcomm; 10180 } else { 10181 redund->subcomm = MPI_COMM_NULL; 10182 } 10183 } else { 10184 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10185 } 10186 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10187 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10188 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10189 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10190 } 10191 #endif 10192 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10193 PetscFunctionReturn(0); 10194 } 10195 10196 /*@C 10197 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10198 a given `Mat`. Each submatrix can span multiple procs. 10199 10200 Collective 10201 10202 Input Parameters: 10203 + mat - the matrix 10204 . subcomm - the subcommunicator obtained by MPI_Com_split(comm) 10205 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10206 10207 Output Parameter: 10208 . subMat - 'parallel submatrices each spans a given subcomm 10209 10210 Notes: 10211 The submatrix partition across processors is dictated by 'subComm' a 10212 communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm 10213 is not restriced to be grouped with consecutive original ranks. 10214 10215 Due the MPI_Comm_split() usage, the parallel layout of the submatrices 10216 map directly to the layout of the original matrix [wrt the local 10217 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10218 into the 'DiagonalMat' of the subMat, hence it is used directly from 10219 the subMat. However the offDiagMat looses some columns - and this is 10220 reconstructed with `MatSetValues()` 10221 10222 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10223 10224 Level: advanced 10225 10226 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10227 @*/ 10228 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10229 { 10230 PetscMPIInt commsize, subCommSize; 10231 10232 PetscFunctionBegin; 10233 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10234 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10235 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10236 10237 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"); 10238 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10239 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10240 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10241 PetscFunctionReturn(0); 10242 } 10243 10244 /*@ 10245 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10246 10247 Not Collective 10248 10249 Input Parameters: 10250 + mat - matrix to extract local submatrix from 10251 . isrow - local row indices for submatrix 10252 - iscol - local column indices for submatrix 10253 10254 Output Parameter: 10255 . submat - the submatrix 10256 10257 Level: intermediate 10258 10259 Notes: 10260 The submat should be returned with `MatRestoreLocalSubMatrix()`. 10261 10262 Depending on the format of mat, the returned submat may not implement `MatMult()`. Its communicator may be 10263 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's. 10264 10265 The submat always implements `MatSetValuesLocal()`. If isrow and iscol have the same block size, then 10266 `MatSetValuesBlockedLocal()` will also be implemented. 10267 10268 The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10269 Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided. 10270 10271 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10272 @*/ 10273 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10274 { 10275 PetscFunctionBegin; 10276 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10277 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10278 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10279 PetscCheckSameComm(isrow, 2, iscol, 3); 10280 PetscValidPointer(submat, 4); 10281 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10282 10283 if (mat->ops->getlocalsubmatrix) { 10284 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10285 } else { 10286 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10287 } 10288 PetscFunctionReturn(0); 10289 } 10290 10291 /*@ 10292 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10293 10294 Not Collective 10295 10296 Input Parameters: 10297 + mat - matrix to extract local submatrix from 10298 . isrow - local row indices for submatrix 10299 . iscol - local column indices for submatrix 10300 - submat - the submatrix 10301 10302 Level: intermediate 10303 10304 .seealso: `MatGetLocalSubMatrix()` 10305 @*/ 10306 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10307 { 10308 PetscFunctionBegin; 10309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10310 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10311 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10312 PetscCheckSameComm(isrow, 2, iscol, 3); 10313 PetscValidPointer(submat, 4); 10314 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10315 10316 if (mat->ops->restorelocalsubmatrix) { 10317 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10318 } else { 10319 PetscCall(MatDestroy(submat)); 10320 } 10321 *submat = NULL; 10322 PetscFunctionReturn(0); 10323 } 10324 10325 /* --------------------------------------------------------*/ 10326 /*@ 10327 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10328 10329 Collective 10330 10331 Input Parameter: 10332 . mat - the matrix 10333 10334 Output Parameter: 10335 . is - if any rows have zero diagonals this contains the list of them 10336 10337 Level: developer 10338 10339 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10340 @*/ 10341 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10342 { 10343 PetscFunctionBegin; 10344 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10345 PetscValidType(mat, 1); 10346 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10347 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10348 10349 if (!mat->ops->findzerodiagonals) { 10350 Vec diag; 10351 const PetscScalar *a; 10352 PetscInt *rows; 10353 PetscInt rStart, rEnd, r, nrow = 0; 10354 10355 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10356 PetscCall(MatGetDiagonal(mat, diag)); 10357 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10358 PetscCall(VecGetArrayRead(diag, &a)); 10359 for (r = 0; r < rEnd - rStart; ++r) 10360 if (a[r] == 0.0) ++nrow; 10361 PetscCall(PetscMalloc1(nrow, &rows)); 10362 nrow = 0; 10363 for (r = 0; r < rEnd - rStart; ++r) 10364 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10365 PetscCall(VecRestoreArrayRead(diag, &a)); 10366 PetscCall(VecDestroy(&diag)); 10367 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10368 } else { 10369 PetscUseTypeMethod(mat, findzerodiagonals, is); 10370 } 10371 PetscFunctionReturn(0); 10372 } 10373 10374 /*@ 10375 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10376 10377 Collective 10378 10379 Input Parameter: 10380 . mat - the matrix 10381 10382 Output Parameter: 10383 . is - contains the list of rows with off block diagonal entries 10384 10385 Level: developer 10386 10387 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10388 @*/ 10389 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10390 { 10391 PetscFunctionBegin; 10392 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10393 PetscValidType(mat, 1); 10394 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10395 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10396 10397 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10398 PetscFunctionReturn(0); 10399 } 10400 10401 /*@C 10402 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10403 10404 Collective; No Fortran Support 10405 10406 Input Parameters: 10407 . mat - the matrix 10408 10409 Output Parameters: 10410 . values - the block inverses in column major order (FORTRAN-like) 10411 10412 Level: advanced 10413 10414 Notes: 10415 The size of the blocks is determined by the block size of the matrix. 10416 10417 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10418 10419 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10420 10421 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10422 @*/ 10423 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10424 { 10425 PetscFunctionBegin; 10426 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10427 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10428 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10429 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10430 PetscFunctionReturn(0); 10431 } 10432 10433 /*@C 10434 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10435 10436 Collective; No Fortran Support 10437 10438 Input Parameters: 10439 + mat - the matrix 10440 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10441 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10442 10443 Output Parameters: 10444 . values - the block inverses in column major order (FORTRAN-like) 10445 10446 Level: advanced 10447 10448 Notes: 10449 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10450 10451 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10452 10453 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10454 @*/ 10455 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10456 { 10457 PetscFunctionBegin; 10458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10459 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10460 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10461 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10462 PetscFunctionReturn(0); 10463 } 10464 10465 /*@ 10466 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10467 10468 Collective on Mat 10469 10470 Input Parameters: 10471 + A - the matrix 10472 - C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 10473 10474 Note: 10475 The blocksize of the matrix is used to determine the blocks on the diagonal of C 10476 10477 Level: advanced 10478 10479 .seealso: `MatInvertBlockDiagonal()` 10480 @*/ 10481 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10482 { 10483 const PetscScalar *vals; 10484 PetscInt *dnnz; 10485 PetscInt m, rstart, rend, bs, i, j; 10486 10487 PetscFunctionBegin; 10488 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10489 PetscCall(MatGetBlockSize(A, &bs)); 10490 PetscCall(MatGetLocalSize(A, &m, NULL)); 10491 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10492 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10493 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10494 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10495 PetscCall(PetscFree(dnnz)); 10496 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10497 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10498 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10499 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10500 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10501 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10502 PetscFunctionReturn(0); 10503 } 10504 10505 /*@C 10506 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10507 via `MatTransposeColoringCreate()`. 10508 10509 Collective on c 10510 10511 Input Parameter: 10512 . c - coloring context 10513 10514 Level: intermediate 10515 10516 .seealso: `MatTransposeColoringCreate()` 10517 @*/ 10518 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10519 { 10520 MatTransposeColoring matcolor = *c; 10521 10522 PetscFunctionBegin; 10523 if (!matcolor) PetscFunctionReturn(0); 10524 if (--((PetscObject)matcolor)->refct > 0) { 10525 matcolor = NULL; 10526 PetscFunctionReturn(0); 10527 } 10528 10529 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10530 PetscCall(PetscFree(matcolor->rows)); 10531 PetscCall(PetscFree(matcolor->den2sp)); 10532 PetscCall(PetscFree(matcolor->colorforcol)); 10533 PetscCall(PetscFree(matcolor->columns)); 10534 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10535 PetscCall(PetscHeaderDestroy(c)); 10536 PetscFunctionReturn(0); 10537 } 10538 10539 /*@C 10540 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10541 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10542 `MatTransposeColoring` to sparse B. 10543 10544 Collective on coloring 10545 10546 Input Parameters: 10547 + B - sparse matrix B 10548 . Btdense - symbolic dense matrix B^T 10549 - coloring - coloring context created with `MatTransposeColoringCreate()` 10550 10551 Output Parameter: 10552 . Btdense - dense matrix B^T 10553 10554 Level: developer 10555 10556 Note: 10557 These are used internally for some implementations of `MatRARt()` 10558 10559 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10560 10561 @*/ 10562 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10563 { 10564 PetscFunctionBegin; 10565 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10566 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10567 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10568 10569 PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10570 PetscFunctionReturn(0); 10571 } 10572 10573 /*@C 10574 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10575 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10576 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10577 Csp from Cden. 10578 10579 Collective 10580 10581 Input Parameters: 10582 + coloring - coloring context created with `MatTransposeColoringCreate()` 10583 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10584 10585 Output Parameter: 10586 . Csp - sparse matrix 10587 10588 Level: developer 10589 10590 Note: 10591 These are used internally for some implementations of `MatRARt()` 10592 10593 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10594 10595 @*/ 10596 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10597 { 10598 PetscFunctionBegin; 10599 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10600 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10601 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10602 10603 PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10604 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10605 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10606 PetscFunctionReturn(0); 10607 } 10608 10609 /*@C 10610 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10611 10612 Collective 10613 10614 Input Parameters: 10615 + mat - the matrix product C 10616 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10617 10618 Output Parameter: 10619 . color - the new coloring context 10620 10621 Level: intermediate 10622 10623 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10624 `MatTransColoringApplyDenToSp()` 10625 @*/ 10626 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10627 { 10628 MatTransposeColoring c; 10629 MPI_Comm comm; 10630 10631 PetscFunctionBegin; 10632 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10633 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10634 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10635 10636 c->ctype = iscoloring->ctype; 10637 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10638 10639 *color = c; 10640 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10641 PetscFunctionReturn(0); 10642 } 10643 10644 /*@ 10645 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10646 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10647 same, otherwise it will be larger 10648 10649 Not Collective 10650 10651 Input Parameter: 10652 . A - the matrix 10653 10654 Output Parameter: 10655 . state - the current state 10656 10657 Notes: 10658 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10659 different matrices 10660 10661 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10662 10663 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10664 10665 Level: intermediate 10666 10667 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()` 10668 @*/ 10669 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10670 { 10671 PetscFunctionBegin; 10672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10673 *state = mat->nonzerostate; 10674 PetscFunctionReturn(0); 10675 } 10676 10677 /*@ 10678 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10679 matrices from each processor 10680 10681 Collective 10682 10683 Input Parameters: 10684 + comm - the communicators the parallel matrix will live on 10685 . seqmat - the input sequential matrices 10686 . n - number of local columns (or `PETSC_DECIDE`) 10687 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10688 10689 Output Parameter: 10690 . mpimat - the parallel matrix generated 10691 10692 Level: developer 10693 10694 Note: 10695 The number of columns of the matrix in EACH processor MUST be the same. 10696 10697 .seealso: `Mat` 10698 @*/ 10699 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10700 { 10701 PetscMPIInt size; 10702 10703 PetscFunctionBegin; 10704 PetscCallMPI(MPI_Comm_size(comm, &size)); 10705 if (size == 1) { 10706 if (reuse == MAT_INITIAL_MATRIX) { 10707 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10708 } else { 10709 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10710 } 10711 PetscFunctionReturn(0); 10712 } 10713 10714 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"); 10715 10716 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10717 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10718 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10719 PetscFunctionReturn(0); 10720 } 10721 10722 /*@ 10723 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10724 10725 Collective on A 10726 10727 Input Parameters: 10728 + A - the matrix to create subdomains from 10729 - N - requested number of subdomains 10730 10731 Output Parameters: 10732 + n - number of subdomains resulting on this rank 10733 - iss - `IS` list with indices of subdomains on this rank 10734 10735 Level: advanced 10736 10737 Note: 10738 The number of subdomains must be smaller than the communicator size 10739 10740 .seealso: `Mat`, `IS` 10741 @*/ 10742 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10743 { 10744 MPI_Comm comm, subcomm; 10745 PetscMPIInt size, rank, color; 10746 PetscInt rstart, rend, k; 10747 10748 PetscFunctionBegin; 10749 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10750 PetscCallMPI(MPI_Comm_size(comm, &size)); 10751 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10752 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); 10753 *n = 1; 10754 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10755 color = rank / k; 10756 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10757 PetscCall(PetscMalloc1(1, iss)); 10758 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10759 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10760 PetscCallMPI(MPI_Comm_free(&subcomm)); 10761 PetscFunctionReturn(0); 10762 } 10763 10764 /*@ 10765 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10766 10767 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10768 If they are not the same, uses `MatMatMatMult()`. 10769 10770 Once the coarse grid problem is constructed, correct for interpolation operators 10771 that are not of full rank, which can legitimately happen in the case of non-nested 10772 geometric multigrid. 10773 10774 Input Parameters: 10775 + restrct - restriction operator 10776 . dA - fine grid matrix 10777 . interpolate - interpolation operator 10778 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10779 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10780 10781 Output Parameters: 10782 . A - the Galerkin coarse matrix 10783 10784 Options Database Key: 10785 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10786 10787 Level: developer 10788 10789 .seealso: `MatPtAP()`, `MatMatMatMult()` 10790 @*/ 10791 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10792 { 10793 IS zerorows; 10794 Vec diag; 10795 10796 PetscFunctionBegin; 10797 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10798 /* Construct the coarse grid matrix */ 10799 if (interpolate == restrct) { 10800 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10801 } else { 10802 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10803 } 10804 10805 /* If the interpolation matrix is not of full rank, A will have zero rows. 10806 This can legitimately happen in the case of non-nested geometric multigrid. 10807 In that event, we set the rows of the matrix to the rows of the identity, 10808 ignoring the equations (as the RHS will also be zero). */ 10809 10810 PetscCall(MatFindZeroRows(*A, &zerorows)); 10811 10812 if (zerorows != NULL) { /* if there are any zero rows */ 10813 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10814 PetscCall(MatGetDiagonal(*A, diag)); 10815 PetscCall(VecISSet(diag, zerorows, 1.0)); 10816 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10817 PetscCall(VecDestroy(&diag)); 10818 PetscCall(ISDestroy(&zerorows)); 10819 } 10820 PetscFunctionReturn(0); 10821 } 10822 10823 /*@C 10824 MatSetOperation - Allows user to set a matrix operation for any matrix type 10825 10826 Logically Collective 10827 10828 Input Parameters: 10829 + mat - the matrix 10830 . op - the name of the operation 10831 - f - the function that provides the operation 10832 10833 Level: developer 10834 10835 Usage: 10836 $ extern PetscErrorCode usermult(Mat,Vec,Vec); 10837 $ PetscCall(MatCreateXXX(comm,...&A); 10838 $ PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult); 10839 10840 Notes: 10841 See the file include/petscmat.h for a complete list of matrix 10842 operations, which all have the form MATOP_<OPERATION>, where 10843 <OPERATION> is the name (in all capital letters) of the 10844 user interface routine (e.g., MatMult() -> MATOP_MULT). 10845 10846 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10847 sequence as the usual matrix interface routines, since they 10848 are intended to be accessed via the usual matrix interface 10849 routines, e.g., 10850 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 10851 10852 In particular each function MUST return an error code of 0 on success and 10853 nonzero on failure. 10854 10855 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10856 10857 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10858 @*/ 10859 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10860 { 10861 PetscFunctionBegin; 10862 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10863 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10864 (((void (**)(void))mat->ops)[op]) = f; 10865 PetscFunctionReturn(0); 10866 } 10867 10868 /*@C 10869 MatGetOperation - Gets a matrix operation for any matrix type. 10870 10871 Not Collective 10872 10873 Input Parameters: 10874 + mat - the matrix 10875 - op - the name of the operation 10876 10877 Output Parameter: 10878 . f - the function that provides the operation 10879 10880 Level: developer 10881 10882 Usage: 10883 $ PetscErrorCode (*usermult)(Mat,Vec,Vec); 10884 $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult); 10885 10886 Notes: 10887 See the file include/petscmat.h for a complete list of matrix 10888 operations, which all have the form MATOP_<OPERATION>, where 10889 <OPERATION> is the name (in all capital letters) of the 10890 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10891 10892 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 10893 10894 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 10895 @*/ 10896 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 10897 { 10898 PetscFunctionBegin; 10899 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10900 *f = (((void (**)(void))mat->ops)[op]); 10901 PetscFunctionReturn(0); 10902 } 10903 10904 /*@ 10905 MatHasOperation - Determines whether the given matrix supports the particular operation. 10906 10907 Not Collective 10908 10909 Input Parameters: 10910 + mat - the matrix 10911 - op - the operation, for example, `MATOP_GET_DIAGONAL` 10912 10913 Output Parameter: 10914 . has - either `PETSC_TRUE` or `PETSC_FALSE` 10915 10916 Level: advanced 10917 10918 Note: 10919 See the file include/petscmat.h for a complete list of matrix 10920 operations, which all have the form MATOP_<OPERATION>, where 10921 <OPERATION> is the name (in all capital letters) of the 10922 user-level routine. E.g., `MatNorm()` -> `MATOP_NORM`. 10923 10924 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 10925 @*/ 10926 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 10927 { 10928 PetscFunctionBegin; 10929 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10930 PetscValidBoolPointer(has, 3); 10931 if (mat->ops->hasoperation) { 10932 PetscUseTypeMethod(mat, hasoperation, op, has); 10933 } else { 10934 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 10935 else { 10936 *has = PETSC_FALSE; 10937 if (op == MATOP_CREATE_SUBMATRIX) { 10938 PetscMPIInt size; 10939 10940 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10941 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 10942 } 10943 } 10944 } 10945 PetscFunctionReturn(0); 10946 } 10947 10948 /*@ 10949 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 10950 10951 Collective 10952 10953 Input Parameters: 10954 . mat - the matrix 10955 10956 Output Parameter: 10957 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 10958 10959 Level: beginner 10960 10961 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout` 10962 @*/ 10963 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 10964 { 10965 PetscFunctionBegin; 10966 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10967 PetscValidType(mat, 1); 10968 PetscValidBoolPointer(cong, 2); 10969 if (!mat->rmap || !mat->cmap) { 10970 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 10971 PetscFunctionReturn(0); 10972 } 10973 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 10974 PetscCall(PetscLayoutSetUp(mat->rmap)); 10975 PetscCall(PetscLayoutSetUp(mat->cmap)); 10976 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 10977 if (*cong) mat->congruentlayouts = 1; 10978 else mat->congruentlayouts = 0; 10979 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 10980 PetscFunctionReturn(0); 10981 } 10982 10983 PetscErrorCode MatSetInf(Mat A) 10984 { 10985 PetscFunctionBegin; 10986 PetscUseTypeMethod(A, setinf); 10987 PetscFunctionReturn(0); 10988 } 10989 10990 /*@C 10991 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 10992 and possibly removes small values from the graph structure. 10993 10994 Collective 10995 10996 Input Parameters: 10997 + A - the matrix 10998 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 10999 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11000 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11001 11002 Output Parameter: 11003 . graph - the resulting graph 11004 11005 Level: advanced 11006 11007 .seealso: `MatCreate()`, `PCGAMG` 11008 @*/ 11009 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11010 { 11011 PetscFunctionBegin; 11012 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11013 PetscValidType(A, 1); 11014 PetscValidLogicalCollectiveBool(A, scale, 3); 11015 PetscValidPointer(graph, 5); 11016 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11017 PetscFunctionReturn(0); 11018 } 11019 11020 /*@ 11021 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11022 meaning the same memory is used for the matrix, and no new memory is allocated. 11023 11024 Collective on mat 11025 11026 Input Parameter: 11027 . A - the matrix 11028 11029 Output Parameter: 11030 . A - the matrix 11031 11032 Level: intermediate 11033 11034 .seealso: `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11035 @*/ 11036 PetscErrorCode MatEliminateZeros(Mat A) 11037 { 11038 PetscFunctionBegin; 11039 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11040 PetscUseTypeMethod(A, eliminatezeros); 11041 PetscFunctionReturn(0); 11042 } 11043