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