1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure; 36 PetscLogEvent MAT_GetMultiProcBlock; 37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 52 for sparse matrices that already have locations it fills the locations with random numbers 53 54 Logically Collective on mat 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and 59 it will create one internally. 60 61 Output Parameter: 62 . x - the matrix 63 64 Example of Usage: 65 .vb 66 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 67 MatSetRandom(x,rctx); 68 PetscRandomDestroy(rctx); 69 .ve 70 71 Level: intermediate 72 73 .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 74 @*/ 75 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 76 { 77 PetscRandom randObj = NULL; 78 79 PetscFunctionBegin; 80 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 81 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 82 PetscValidType(x, 1); 83 MatCheckPreallocated(x, 1); 84 85 if (!rctx) { 86 MPI_Comm comm; 87 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 88 PetscCall(PetscRandomCreate(comm, &randObj)); 89 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 90 PetscCall(PetscRandomSetFromOptions(randObj)); 91 rctx = randObj; 92 } 93 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 94 PetscUseTypeMethod(x, setrandom, rctx); 95 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 96 97 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 98 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 99 PetscCall(PetscRandomDestroy(&randObj)); 100 PetscFunctionReturn(0); 101 } 102 103 /*@ 104 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 105 106 Logically Collective on mat 107 108 Input Parameter: 109 . mat - the factored matrix 110 111 Output Parameters: 112 + pivot - the pivot value computed 113 - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes 114 the share the matrix 115 116 Level: advanced 117 118 Notes: 119 This routine does not work for factorizations done with external packages. 120 121 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 122 123 This can be called on non-factored matrices that come from, for example, matrices used in SOR. 124 125 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 126 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 127 @*/ 128 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 129 { 130 PetscFunctionBegin; 131 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 132 PetscValidRealPointer(pivot, 2); 133 PetscValidIntPointer(row, 3); 134 *pivot = mat->factorerror_zeropivot_value; 135 *row = mat->factorerror_zeropivot_row; 136 PetscFunctionReturn(0); 137 } 138 139 /*@ 140 MatFactorGetError - gets the error code from a factorization 141 142 Logically Collective on mat 143 144 Input Parameters: 145 . mat - the factored matrix 146 147 Output Parameter: 148 . err - the error code 149 150 Level: advanced 151 152 Note: 153 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 154 155 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 156 `MatFactorError` 157 @*/ 158 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 159 { 160 PetscFunctionBegin; 161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 162 PetscValidPointer(err, 2); 163 *err = mat->factorerrortype; 164 PetscFunctionReturn(0); 165 } 166 167 /*@ 168 MatFactorClearError - clears the error code in a factorization 169 170 Logically Collective on mat 171 172 Input Parameter: 173 . mat - the factored matrix 174 175 Level: developer 176 177 Note: 178 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 179 180 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 181 `MatGetErrorCode()`, `MatFactorError` 182 @*/ 183 PetscErrorCode MatFactorClearError(Mat mat) 184 { 185 PetscFunctionBegin; 186 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 187 mat->factorerrortype = MAT_FACTOR_NOERROR; 188 mat->factorerror_zeropivot_value = 0.0; 189 mat->factorerror_zeropivot_row = 0; 190 PetscFunctionReturn(0); 191 } 192 193 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 194 { 195 Vec r, l; 196 const PetscScalar *al; 197 PetscInt i, nz, gnz, N, n; 198 199 PetscFunctionBegin; 200 PetscCall(MatCreateVecs(mat, &r, &l)); 201 if (!cols) { /* nonzero rows */ 202 PetscCall(MatGetSize(mat, &N, NULL)); 203 PetscCall(MatGetLocalSize(mat, &n, NULL)); 204 PetscCall(VecSet(l, 0.0)); 205 PetscCall(VecSetRandom(r, NULL)); 206 PetscCall(MatMult(mat, r, l)); 207 PetscCall(VecGetArrayRead(l, &al)); 208 } else { /* nonzero columns */ 209 PetscCall(MatGetSize(mat, NULL, &N)); 210 PetscCall(MatGetLocalSize(mat, NULL, &n)); 211 PetscCall(VecSet(r, 0.0)); 212 PetscCall(VecSetRandom(l, NULL)); 213 PetscCall(MatMultTranspose(mat, l, r)); 214 PetscCall(VecGetArrayRead(r, &al)); 215 } 216 if (tol <= 0.0) { 217 for (i = 0, nz = 0; i < n; i++) 218 if (al[i] != 0.0) nz++; 219 } else { 220 for (i = 0, nz = 0; i < n; i++) 221 if (PetscAbsScalar(al[i]) > tol) nz++; 222 } 223 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 224 if (gnz != N) { 225 PetscInt *nzr; 226 PetscCall(PetscMalloc1(nz, &nzr)); 227 if (nz) { 228 if (tol < 0) { 229 for (i = 0, nz = 0; i < n; i++) 230 if (al[i] != 0.0) nzr[nz++] = i; 231 } else { 232 for (i = 0, nz = 0; i < n; i++) 233 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 234 } 235 } 236 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 237 } else *nonzero = NULL; 238 if (!cols) { /* nonzero rows */ 239 PetscCall(VecRestoreArrayRead(l, &al)); 240 } else { 241 PetscCall(VecRestoreArrayRead(r, &al)); 242 } 243 PetscCall(VecDestroy(&l)); 244 PetscCall(VecDestroy(&r)); 245 PetscFunctionReturn(0); 246 } 247 248 /*@ 249 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 250 251 Input Parameter: 252 . A - the matrix 253 254 Output Parameter: 255 . keptrows - the rows that are not completely zero 256 257 Note: 258 keptrows is set to NULL if all rows are nonzero. 259 260 Level: intermediate 261 262 .seealso: `Mat`, `MatFindZeroRows()` 263 @*/ 264 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 265 { 266 PetscFunctionBegin; 267 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 268 PetscValidType(mat, 1); 269 PetscValidPointer(keptrows, 2); 270 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 271 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 272 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 273 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 274 PetscFunctionReturn(0); 275 } 276 277 /*@ 278 MatFindZeroRows - Locate all rows that are completely zero in the matrix 279 280 Input Parameter: 281 . A - the matrix 282 283 Output Parameter: 284 . zerorows - the rows that are completely zero 285 286 Note: 287 zerorows is set to NULL if no rows are zero. 288 289 Level: intermediate 290 291 .seealso: `Mat`, `MatFindNonzeroRows()` 292 @*/ 293 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 294 { 295 IS keptrows; 296 PetscInt m, n; 297 298 PetscFunctionBegin; 299 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 300 PetscValidType(mat, 1); 301 PetscValidPointer(zerorows, 2); 302 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 303 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 304 In keeping with this convention, we set zerorows to NULL if there are no zero 305 rows. */ 306 if (keptrows == NULL) { 307 *zerorows = NULL; 308 } else { 309 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 310 PetscCall(ISComplement(keptrows, m, n, zerorows)); 311 PetscCall(ISDestroy(&keptrows)); 312 } 313 PetscFunctionReturn(0); 314 } 315 316 /*@ 317 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 318 319 Not Collective 320 321 Input Parameters: 322 . A - the matrix 323 324 Output Parameters: 325 . a - the diagonal part (which is a SEQUENTIAL matrix) 326 327 Notes: 328 See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 329 330 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation. 331 332 Level: advanced 333 334 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 335 @*/ 336 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 337 { 338 PetscFunctionBegin; 339 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 340 PetscValidType(A, 1); 341 PetscValidPointer(a, 2); 342 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 343 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 344 else { 345 PetscMPIInt size; 346 347 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 348 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 349 *a = A; 350 } 351 PetscFunctionReturn(0); 352 } 353 354 /*@ 355 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 356 357 Collective on mat 358 359 Input Parameters: 360 . mat - the matrix 361 362 Output Parameter: 363 . trace - the sum of the diagonal entries 364 365 Level: advanced 366 367 .seealso: `Mat` 368 @*/ 369 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 370 { 371 Vec diag; 372 373 PetscFunctionBegin; 374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 375 PetscValidScalarPointer(trace, 2); 376 PetscCall(MatCreateVecs(mat, &diag, NULL)); 377 PetscCall(MatGetDiagonal(mat, diag)); 378 PetscCall(VecSum(diag, trace)); 379 PetscCall(VecDestroy(&diag)); 380 PetscFunctionReturn(0); 381 } 382 383 /*@ 384 MatRealPart - Zeros out the imaginary part of the matrix 385 386 Logically Collective on mat 387 388 Input Parameters: 389 . mat - the matrix 390 391 Level: advanced 392 393 .seealso: `MatImaginaryPart()` 394 @*/ 395 PetscErrorCode MatRealPart(Mat mat) 396 { 397 PetscFunctionBegin; 398 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 399 PetscValidType(mat, 1); 400 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 401 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 402 MatCheckPreallocated(mat, 1); 403 PetscUseTypeMethod(mat, realpart); 404 PetscFunctionReturn(0); 405 } 406 407 /*@C 408 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 409 410 Collective on mat 411 412 Input Parameter: 413 . mat - the matrix 414 415 Output Parameters: 416 + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 417 - ghosts - the global indices of the ghost points 418 419 Note: 420 the nghosts and ghosts are suitable to pass into `VecCreateGhost()` 421 422 Level: advanced 423 424 .seealso: `Mat`, `VecCreateGhost()` 425 @*/ 426 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 427 { 428 PetscFunctionBegin; 429 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 430 PetscValidType(mat, 1); 431 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 432 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 433 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 434 else { 435 if (nghosts) *nghosts = 0; 436 if (ghosts) *ghosts = NULL; 437 } 438 PetscFunctionReturn(0); 439 } 440 441 /*@ 442 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 443 444 Logically Collective on mat 445 446 Input Parameters: 447 . mat - the matrix 448 449 Level: advanced 450 451 .seealso: `MatRealPart()` 452 @*/ 453 PetscErrorCode MatImaginaryPart(Mat mat) 454 { 455 PetscFunctionBegin; 456 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 457 PetscValidType(mat, 1); 458 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 459 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 460 MatCheckPreallocated(mat, 1); 461 PetscUseTypeMethod(mat, imaginarypart); 462 PetscFunctionReturn(0); 463 } 464 465 /*@ 466 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 467 468 Not Collective 469 470 Input Parameter: 471 . mat - the matrix 472 473 Output Parameters: 474 + missing - is any diagonal missing 475 - dd - first diagonal entry that is missing (optional) on this process 476 477 Level: advanced 478 479 .seealso: `Mat` 480 @*/ 481 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 482 { 483 PetscFunctionBegin; 484 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 485 PetscValidType(mat, 1); 486 PetscValidBoolPointer(missing, 2); 487 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 488 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 489 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 490 PetscFunctionReturn(0); 491 } 492 493 /*@C 494 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 495 for each row that you get to ensure that your application does 496 not bleed memory. 497 498 Not Collective 499 500 Input Parameters: 501 + mat - the matrix 502 - row - the row to get 503 504 Output Parameters: 505 + ncols - if not NULL, the number of nonzeros in the row 506 . cols - if not NULL, the column numbers 507 - vals - if not NULL, the values 508 509 Notes: 510 This routine is provided for people who need to have direct access 511 to the structure of a matrix. We hope that we provide enough 512 high-level matrix routines that few users will need it. 513 514 `MatGetRow()` always returns 0-based column indices, regardless of 515 whether the internal representation is 0-based (default) or 1-based. 516 517 For better efficiency, set cols and/or vals to NULL if you do 518 not wish to extract these quantities. 519 520 The user can only examine the values extracted with `MatGetRow()`; 521 the values cannot be altered. To change the matrix entries, one 522 must use `MatSetValues()`. 523 524 You can only have one call to `MatGetRow()` outstanding for a particular 525 matrix at a time, per processor. `MatGetRow()` can only obtain rows 526 associated with the given processor, it cannot get rows from the 527 other processors; for that we suggest using `MatCreateSubMatrices()`, then 528 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 529 is in the global number of rows. 530 531 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 532 533 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 534 535 Fortran Note: 536 The calling sequence from Fortran is 537 .vb 538 MatGetRow(matrix,row,ncols,cols,values,ierr) 539 Mat matrix (input) 540 integer row (input) 541 integer ncols (output) 542 integer cols(maxcols) (output) 543 double precision (or double complex) values(maxcols) output 544 .ve 545 where maxcols >= maximum nonzeros in any row of the matrix. 546 547 Caution: 548 Do not try to change the contents of the output arrays (cols and vals). 549 In some cases, this may corrupt the matrix. 550 551 Level: advanced 552 553 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 554 @*/ 555 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 556 { 557 PetscInt incols; 558 559 PetscFunctionBegin; 560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 561 PetscValidType(mat, 1); 562 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 563 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 564 MatCheckPreallocated(mat, 1); 565 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 566 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 567 PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals)); 568 if (ncols) *ncols = incols; 569 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 570 PetscFunctionReturn(0); 571 } 572 573 /*@ 574 MatConjugate - replaces the matrix values with their complex conjugates 575 576 Logically Collective on mat 577 578 Input Parameters: 579 . mat - the matrix 580 581 Level: advanced 582 583 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 584 @*/ 585 PetscErrorCode MatConjugate(Mat mat) 586 { 587 PetscFunctionBegin; 588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 589 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 590 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 591 PetscUseTypeMethod(mat, conjugate); 592 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 593 } 594 PetscFunctionReturn(0); 595 } 596 597 /*@C 598 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 599 600 Not Collective 601 602 Input Parameters: 603 + mat - the matrix 604 . row - the row to get 605 . ncols, cols - the number of nonzeros and their columns 606 - vals - if nonzero the column values 607 608 Notes: 609 This routine should be called after you have finished examining the entries. 610 611 This routine zeros out ncols, cols, and vals. This is to prevent accidental 612 us of the array after it has been restored. If you pass NULL, it will 613 not zero the pointers. Use of cols or vals after `MatRestoreRow()` is invalid. 614 615 Fortran Notes: 616 The calling sequence from Fortran is 617 .vb 618 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 619 Mat matrix (input) 620 integer row (input) 621 integer ncols (output) 622 integer cols(maxcols) (output) 623 double precision (or double complex) values(maxcols) output 624 .ve 625 Where maxcols >= maximum nonzeros in any row of the matrix. 626 627 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 628 before another call to `MatGetRow()` can be made. 629 630 Level: advanced 631 632 .seealso: `MatGetRow()` 633 @*/ 634 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 635 { 636 PetscFunctionBegin; 637 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 638 if (ncols) PetscValidIntPointer(ncols, 3); 639 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 640 if (!mat->ops->restorerow) PetscFunctionReturn(0); 641 PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals)); 642 if (ncols) *ncols = 0; 643 if (cols) *cols = NULL; 644 if (vals) *vals = NULL; 645 PetscFunctionReturn(0); 646 } 647 648 /*@ 649 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 650 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 651 652 Not Collective 653 654 Input Parameters: 655 . mat - the matrix 656 657 Note: 658 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 659 660 Level: advanced 661 662 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 663 @*/ 664 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 665 { 666 PetscFunctionBegin; 667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 668 PetscValidType(mat, 1); 669 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 670 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 671 MatCheckPreallocated(mat, 1); 672 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0); 673 PetscUseTypeMethod(mat, getrowuppertriangular); 674 PetscFunctionReturn(0); 675 } 676 677 /*@ 678 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 679 680 Not Collective 681 682 Input Parameters: 683 . mat - the matrix 684 685 Note: 686 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 687 688 Level: advanced 689 690 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0); 701 PetscUseTypeMethod(mat, restorerowuppertriangular); 702 PetscFunctionReturn(0); 703 } 704 705 /*@C 706 MatSetOptionsPrefix - Sets the prefix used for searching for all 707 `Mat` options in the database. 708 709 Logically Collective on A 710 711 Input Parameters: 712 + A - the matrix 713 - prefix - the prefix to prepend to all option names 714 715 Notes: 716 A hyphen (-) must NOT be given at the beginning of the prefix name. 717 The first character of all runtime options is AUTOMATICALLY the hyphen. 718 719 This is NOT used for options for the factorization of the matrix. Normally the 720 prefix is automatically passed in from the PC calling the factorization. To set 721 it directly use `MatSetOptionsPrefixFactor()` 722 723 Level: advanced 724 725 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 726 @*/ 727 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 728 { 729 PetscFunctionBegin; 730 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 731 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 732 PetscFunctionReturn(0); 733 } 734 735 /*@C 736 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 737 for matrices created with `MatGetFactor()` 738 739 Logically Collective on A 740 741 Input Parameters: 742 + A - the matrix 743 - prefix - the prefix to prepend to all option names for the factored matrix 744 745 Notes: 746 A hyphen (-) must NOT be given at the beginning of the prefix name. 747 The first character of all runtime options is AUTOMATICALLY the hyphen. 748 749 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 750 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 751 752 Level: developer 753 754 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 755 @*/ 756 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 757 { 758 PetscFunctionBegin; 759 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 760 if (prefix) { 761 PetscValidCharPointer(prefix, 2); 762 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 763 if (prefix != A->factorprefix) { 764 PetscCall(PetscFree(A->factorprefix)); 765 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 766 } 767 } else PetscCall(PetscFree(A->factorprefix)); 768 PetscFunctionReturn(0); 769 } 770 771 /*@C 772 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 773 for matrices created with `MatGetFactor()` 774 775 Logically Collective on A 776 777 Input Parameters: 778 + A - the matrix 779 - prefix - the prefix to prepend to all option names for the factored matrix 780 781 Notes: 782 A hyphen (-) must NOT be given at the beginning of the prefix name. 783 The first character of all runtime options is AUTOMATICALLY the hyphen. 784 785 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 786 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 787 788 Level: developer 789 790 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 791 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 792 `MatSetOptionsPrefix()` 793 @*/ 794 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 795 { 796 char *buf = A->factorprefix; 797 size_t len1, len2; 798 799 PetscFunctionBegin; 800 PetscValidHeader(A, 1); 801 if (!prefix) PetscFunctionReturn(0); 802 if (!buf) { 803 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 804 PetscFunctionReturn(0); 805 } 806 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 807 808 PetscCall(PetscStrlen(prefix, &len1)); 809 PetscCall(PetscStrlen(buf, &len2)); 810 PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix)); 811 PetscCall(PetscStrcpy(A->factorprefix, buf)); 812 PetscCall(PetscStrcat(A->factorprefix, prefix)); 813 PetscCall(PetscFree(buf)); 814 PetscFunctionReturn(0); 815 } 816 817 /*@C 818 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 819 matrix options in the database. 820 821 Logically Collective on A 822 823 Input Parameters: 824 + A - the matrix 825 - prefix - the prefix to prepend to all option names 826 827 Note: 828 A hyphen (-) must NOT be given at the beginning of the prefix name. 829 The first character of all runtime options is AUTOMATICALLY the hyphen. 830 831 Level: advanced 832 833 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 834 @*/ 835 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 836 { 837 PetscFunctionBegin; 838 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 839 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 840 PetscFunctionReturn(0); 841 } 842 843 /*@C 844 MatGetOptionsPrefix - Gets the prefix used for searching for all 845 matrix options in the database. 846 847 Not Collective 848 849 Input Parameter: 850 . A - the matrix 851 852 Output Parameter: 853 . prefix - pointer to the prefix string used 854 855 Fortran Note: 856 On the fortran side, the user should pass in a string 'prefix' of 857 sufficient length to hold the prefix. 858 859 Level: advanced 860 861 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 862 @*/ 863 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 864 { 865 PetscFunctionBegin; 866 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 867 PetscValidPointer(prefix, 2); 868 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 869 PetscFunctionReturn(0); 870 } 871 872 /*@ 873 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 874 875 Collective on A 876 877 Input Parameters: 878 . A - the matrix 879 880 Notes: 881 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 882 883 Users can reset the preallocation to access the original memory. 884 885 Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices. 886 887 Level: beginner 888 889 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 890 @*/ 891 PetscErrorCode MatResetPreallocation(Mat A) 892 { 893 PetscFunctionBegin; 894 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 895 PetscValidType(A, 1); 896 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 897 PetscFunctionReturn(0); 898 } 899 900 /*@ 901 MatSetUp - Sets up the internal matrix data structures for later use. 902 903 Collective on A 904 905 Input Parameters: 906 . A - the matrix 907 908 Notes: 909 If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used. 910 911 If a suitable preallocation routine is used, this function does not need to be called. 912 913 See the Performance chapter of the PETSc users manual for how to preallocate matrices 914 915 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 916 917 Level: intermediate 918 919 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()` 920 @*/ 921 PetscErrorCode MatSetUp(Mat A) 922 { 923 PetscFunctionBegin; 924 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 925 if (!((PetscObject)A)->type_name) { 926 PetscMPIInt size; 927 928 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 929 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 930 } 931 if (!A->preallocated && A->ops->setup) { 932 PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n")); 933 PetscUseTypeMethod(A, setup); 934 } 935 PetscCall(PetscLayoutSetUp(A->rmap)); 936 PetscCall(PetscLayoutSetUp(A->cmap)); 937 A->preallocated = PETSC_TRUE; 938 PetscFunctionReturn(0); 939 } 940 941 #if defined(PETSC_HAVE_SAWS) 942 #include <petscviewersaws.h> 943 #endif 944 945 /*@C 946 MatViewFromOptions - View properties of the matrix from the options database 947 948 Collective on A 949 950 Input Parameters: 951 + A - the matrix 952 . obj - optional additional object that provides the options prefix to use 953 - name - command line option 954 955 Options Database: 956 . -mat_view [viewertype]:... - the viewer and its options 957 958 Notes: 959 .vb 960 If no value is provided ascii:stdout is used 961 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 962 for example ascii::ascii_info prints just the information about the object not all details 963 unless :append is given filename opens in write mode, overwriting what was already there 964 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 965 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 966 socket[:port] defaults to the standard output port 967 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 968 .ve 969 970 Level: intermediate 971 972 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 973 @*/ 974 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 975 { 976 PetscFunctionBegin; 977 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 978 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 979 PetscFunctionReturn(0); 980 } 981 982 /*@C 983 MatView - display information about a matrix in a variety ways 984 985 Collective on mat 986 987 Input Parameters: 988 + mat - the matrix 989 - viewer - visualization context 990 991 Notes: 992 The available visualization contexts include 993 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 994 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 995 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 996 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 997 998 The user can open alternative visualization contexts with 999 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1000 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1001 specified file; corresponding input uses MatLoad() 1002 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1003 an X window display 1004 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1005 Currently only the sequential dense and AIJ 1006 matrix types support the Socket viewer. 1007 1008 The user can call `PetscViewerPushFormat()` to specify the output 1009 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1010 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1011 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1012 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1013 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1014 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1015 format common among all matrix types 1016 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1017 format (which is in many cases the same as the default) 1018 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1019 size and structure (not the matrix entries) 1020 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1021 the matrix structure 1022 1023 Options Database Keys: 1024 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1025 . -mat_view ::ascii_info_detail - Prints more detailed info 1026 . -mat_view - Prints matrix in ASCII format 1027 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1028 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1029 . -display <name> - Sets display name (default is host) 1030 . -draw_pause <sec> - Sets number of seconds to pause after display 1031 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1032 . -viewer_socket_machine <machine> - 1033 . -viewer_socket_port <port> - 1034 . -mat_view binary - save matrix to file in binary format 1035 - -viewer_binary_filename <name> - 1036 1037 Level: beginner 1038 1039 Notes: 1040 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1041 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1042 1043 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1044 1045 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1046 viewer is used. 1047 1048 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1049 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1050 1051 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1052 and then use the following mouse functions. 1053 .vb 1054 left mouse: zoom in 1055 middle mouse: zoom out 1056 right mouse: continue with the simulation 1057 .ve 1058 1059 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`, 1060 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1061 @*/ 1062 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1063 { 1064 PetscInt rows, cols, rbs, cbs; 1065 PetscBool isascii, isstring, issaws; 1066 PetscViewerFormat format; 1067 PetscMPIInt size; 1068 1069 PetscFunctionBegin; 1070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1071 PetscValidType(mat, 1); 1072 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1073 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1074 PetscCheckSameComm(mat, 1, viewer, 2); 1075 MatCheckPreallocated(mat, 1); 1076 1077 PetscCall(PetscViewerGetFormat(viewer, &format)); 1078 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1079 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0); 1080 1081 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1082 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1083 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1084 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1085 1086 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1087 if (isascii) { 1088 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Must call MatAssemblyBegin/End() before viewing matrix"); 1089 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1090 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1091 MatNullSpace nullsp, transnullsp; 1092 1093 PetscCall(PetscViewerASCIIPushTab(viewer)); 1094 PetscCall(MatGetSize(mat, &rows, &cols)); 1095 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1096 if (rbs != 1 || cbs != 1) { 1097 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1098 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1099 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1100 if (mat->factortype) { 1101 MatSolverType solver; 1102 PetscCall(MatFactorGetSolverType(mat, &solver)); 1103 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1104 } 1105 if (mat->ops->getinfo) { 1106 MatInfo info; 1107 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1108 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1109 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1110 } 1111 PetscCall(MatGetNullSpace(mat, &nullsp)); 1112 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1113 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1114 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1115 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1116 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1117 PetscCall(PetscViewerASCIIPushTab(viewer)); 1118 PetscCall(MatProductView(mat, viewer)); 1119 PetscCall(PetscViewerASCIIPopTab(viewer)); 1120 } 1121 } else if (issaws) { 1122 #if defined(PETSC_HAVE_SAWS) 1123 PetscMPIInt rank; 1124 1125 PetscCall(PetscObjectName((PetscObject)mat)); 1126 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1127 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1128 #endif 1129 } else if (isstring) { 1130 const char *type; 1131 PetscCall(MatGetType(mat, &type)); 1132 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1133 PetscTryTypeMethod(mat, view, viewer); 1134 } 1135 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1136 PetscCall(PetscViewerASCIIPushTab(viewer)); 1137 PetscUseTypeMethod(mat, viewnative, viewer); 1138 PetscCall(PetscViewerASCIIPopTab(viewer)); 1139 } else if (mat->ops->view) { 1140 PetscCall(PetscViewerASCIIPushTab(viewer)); 1141 PetscUseTypeMethod(mat, view, viewer); 1142 PetscCall(PetscViewerASCIIPopTab(viewer)); 1143 } 1144 if (isascii) { 1145 PetscCall(PetscViewerGetFormat(viewer, &format)); 1146 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1147 } 1148 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1149 PetscFunctionReturn(0); 1150 } 1151 1152 #if defined(PETSC_USE_DEBUG) 1153 #include <../src/sys/totalview/tv_data_display.h> 1154 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1155 { 1156 TV_add_row("Local rows", "int", &mat->rmap->n); 1157 TV_add_row("Local columns", "int", &mat->cmap->n); 1158 TV_add_row("Global rows", "int", &mat->rmap->N); 1159 TV_add_row("Global columns", "int", &mat->cmap->N); 1160 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1161 return TV_format_OK; 1162 } 1163 #endif 1164 1165 /*@C 1166 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1167 with `MatView()`. The matrix format is determined from the options database. 1168 Generates a parallel MPI matrix if the communicator has more than one 1169 processor. The default matrix type is `MATAIJ`. 1170 1171 Collective on mat 1172 1173 Input Parameters: 1174 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1175 or some related function before a call to `MatLoad()` 1176 - viewer - binary/HDF5 file viewer 1177 1178 Options Database Keys: 1179 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1180 block size 1181 . -matload_block_size <bs> - set block size 1182 1183 Level: beginner 1184 1185 Notes: 1186 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1187 `Mat` before calling this routine if you wish to set it from the options database. 1188 1189 `MatLoad()` automatically loads into the options database any options 1190 given in the file filename.info where filename is the name of the file 1191 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1192 file will be ignored if you use the -viewer_binary_skip_info option. 1193 1194 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1195 sets the default matrix type AIJ and sets the local and global sizes. 1196 If type and/or size is already set, then the same are used. 1197 1198 In parallel, each processor can load a subset of rows (or the 1199 entire matrix). This routine is especially useful when a large 1200 matrix is stored on disk and only part of it is desired on each 1201 processor. For example, a parallel solver may access only some of 1202 the rows from each processor. The algorithm used here reads 1203 relatively small blocks of data rather than reading the entire 1204 matrix and then subsetting it. 1205 1206 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1207 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1208 or the sequence like 1209 .vb 1210 `PetscViewer` v; 1211 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1212 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1213 `PetscViewerSetFromOptions`(v); 1214 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1215 `PetscViewerFileSetName`(v,"datafile"); 1216 .ve 1217 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1218 $ -viewer_type {binary,hdf5} 1219 1220 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1221 and src/mat/tutorials/ex10.c with the second approach. 1222 1223 Notes about the PETSc binary format: 1224 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1225 is read onto rank 0 and then shipped to its destination rank, one after another. 1226 Multiple objects, both matrices and vectors, can be stored within the same file. 1227 Their PetscObject name is ignored; they are loaded in the order of their storage. 1228 1229 Most users should not need to know the details of the binary storage 1230 format, since `MatLoad()` and `MatView()` completely hide these details. 1231 But for anyone who's interested, the standard binary matrix storage 1232 format is 1233 1234 $ PetscInt MAT_FILE_CLASSID 1235 $ PetscInt number of rows 1236 $ PetscInt number of columns 1237 $ PetscInt total number of nonzeros 1238 $ PetscInt *number nonzeros in each row 1239 $ PetscInt *column indices of all nonzeros (starting index is zero) 1240 $ PetscScalar *values of all nonzeros 1241 1242 PETSc automatically does the byte swapping for 1243 machines that store the bytes reversed, e.g. DEC alpha, freebsd, 1244 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary 1245 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1246 and `PetscBinaryWrite()` to see how this may be done. 1247 1248 Notes about the HDF5 (MATLAB MAT-File Version 7.3) format: 1249 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1250 Each processor's chunk is loaded independently by its owning rank. 1251 Multiple objects, both matrices and vectors, can be stored within the same file. 1252 They are looked up by their PetscObject name. 1253 1254 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1255 by default the same structure and naming of the AIJ arrays and column count 1256 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1257 $ save example.mat A b -v7.3 1258 can be directly read by this routine (see Reference 1 for details). 1259 Note that depending on your MATLAB version, this format might be a default, 1260 otherwise you can set it as default in Preferences. 1261 1262 Unless -nocompression flag is used to save the file in MATLAB, 1263 PETSc must be configured with ZLIB package. 1264 1265 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1266 1267 Current HDF5 (MAT-File) limitations: 1268 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices. 1269 1270 Corresponding `MatView()` is not yet implemented. 1271 1272 The loaded matrix is actually a transpose of the original one in MATLAB, 1273 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1274 With this format, matrix is automatically transposed by PETSc, 1275 unless the matrix is marked as SPD or symmetric 1276 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1277 1278 References: 1279 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1280 1281 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1282 @*/ 1283 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1284 { 1285 PetscBool flg; 1286 1287 PetscFunctionBegin; 1288 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1289 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1290 1291 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1292 1293 flg = PETSC_FALSE; 1294 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1295 if (flg) { 1296 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1297 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1298 } 1299 flg = PETSC_FALSE; 1300 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1301 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1302 1303 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1304 PetscUseTypeMethod(mat, load, viewer); 1305 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1306 PetscFunctionReturn(0); 1307 } 1308 1309 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1310 { 1311 Mat_Redundant *redund = *redundant; 1312 1313 PetscFunctionBegin; 1314 if (redund) { 1315 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1316 PetscCall(ISDestroy(&redund->isrow)); 1317 PetscCall(ISDestroy(&redund->iscol)); 1318 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1319 } else { 1320 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1321 PetscCall(PetscFree(redund->sbuf_j)); 1322 PetscCall(PetscFree(redund->sbuf_a)); 1323 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1324 PetscCall(PetscFree(redund->rbuf_j[i])); 1325 PetscCall(PetscFree(redund->rbuf_a[i])); 1326 } 1327 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1328 } 1329 1330 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1331 PetscCall(PetscFree(redund)); 1332 } 1333 PetscFunctionReturn(0); 1334 } 1335 1336 /*@C 1337 MatDestroy - Frees space taken by a matrix. 1338 1339 Collective on A 1340 1341 Input Parameter: 1342 . A - the matrix 1343 1344 Level: beginner 1345 1346 Developer Note: 1347 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1348 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1349 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1350 if changes are needed here. 1351 1352 .seealso: `Mat`, `MatCreate()` 1353 @*/ 1354 PetscErrorCode MatDestroy(Mat *A) 1355 { 1356 PetscFunctionBegin; 1357 if (!*A) PetscFunctionReturn(0); 1358 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1359 if (--((PetscObject)(*A))->refct > 0) { 1360 *A = NULL; 1361 PetscFunctionReturn(0); 1362 } 1363 1364 /* if memory was published with SAWs then destroy it */ 1365 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1366 PetscTryTypeMethod((*A), destroy); 1367 1368 PetscCall(PetscFree((*A)->factorprefix)); 1369 PetscCall(PetscFree((*A)->defaultvectype)); 1370 PetscCall(PetscFree((*A)->defaultrandtype)); 1371 PetscCall(PetscFree((*A)->bsizes)); 1372 PetscCall(PetscFree((*A)->solvertype)); 1373 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1374 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1375 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1376 PetscCall(MatProductClear(*A)); 1377 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1378 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1379 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1380 PetscCall(MatDestroy(&(*A)->schur)); 1381 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1382 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1383 PetscCall(PetscHeaderDestroy(A)); 1384 PetscFunctionReturn(0); 1385 } 1386 1387 /*@C 1388 MatSetValues - Inserts or adds a block of values into a matrix. 1389 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1390 MUST be called after all calls to `MatSetValues()` have been completed. 1391 1392 Not Collective 1393 1394 Input Parameters: 1395 + mat - the matrix 1396 . v - a logically two-dimensional array of values 1397 . m, idxm - the number of rows and their global indices 1398 . n, idxn - the number of columns and their global indices 1399 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1400 1401 Notes: 1402 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1403 `MatSetUp()` before using this routine 1404 1405 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1406 1407 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1408 options cannot be mixed without intervening calls to the assembly 1409 routines. 1410 1411 `MatSetValues()` uses 0-based row and column numbers in Fortran 1412 as well as in C. 1413 1414 Negative indices may be passed in idxm and idxn, these rows and columns are 1415 simply ignored. This allows easily inserting element stiffness matrices 1416 with homogeneous Dirchlet boundary conditions that you don't want represented 1417 in the matrix. 1418 1419 Efficiency Alert: 1420 The routine `MatSetValuesBlocked()` may offer much better efficiency 1421 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1422 1423 Level: beginner 1424 1425 Developer Note: 1426 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1427 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1428 1429 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1430 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1431 @*/ 1432 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1433 { 1434 PetscFunctionBeginHot; 1435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1436 PetscValidType(mat, 1); 1437 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1438 PetscValidIntPointer(idxm, 3); 1439 PetscValidIntPointer(idxn, 5); 1440 MatCheckPreallocated(mat, 1); 1441 1442 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1443 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1444 1445 if (PetscDefined(USE_DEBUG)) { 1446 PetscInt i, j; 1447 1448 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1449 for (i = 0; i < m; i++) { 1450 for (j = 0; j < n; j++) { 1451 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1452 #if defined(PETSC_USE_COMPLEX) 1453 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1454 #else 1455 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1456 #endif 1457 } 1458 } 1459 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1460 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1461 } 1462 1463 if (mat->assembled) { 1464 mat->was_assembled = PETSC_TRUE; 1465 mat->assembled = PETSC_FALSE; 1466 } 1467 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1468 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1469 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1470 PetscFunctionReturn(0); 1471 } 1472 1473 /*@C 1474 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1475 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1476 MUST be called after all calls to `MatSetValues()` have been completed. 1477 1478 Not Collective 1479 1480 Input Parameters: 1481 + mat - the matrix 1482 . v - a logically two-dimensional array of values 1483 . ism - the rows to provide 1484 . isn - the columns to provide 1485 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1486 1487 Notes: 1488 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1489 `MatSetUp()` before using this routine 1490 1491 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1492 1493 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1494 options cannot be mixed without intervening calls to the assembly 1495 routines. 1496 1497 MatSetValues() uses 0-based row and column numbers in Fortran 1498 as well as in C. 1499 1500 Negative indices may be passed in ism and isn, these rows and columns are 1501 simply ignored. This allows easily inserting element stiffness matrices 1502 with homogeneous Dirchlet boundary conditions that you don't want represented 1503 in the matrix. 1504 1505 Efficiency Alert: 1506 The routine `MatSetValuesBlocked()` may offer much better efficiency 1507 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1508 1509 Level: beginner 1510 1511 Developer Notes: 1512 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1513 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1514 1515 This is currently not optimized for any particular `ISType` 1516 1517 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1518 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1519 @*/ 1520 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1521 { 1522 PetscInt m, n; 1523 const PetscInt *rows, *cols; 1524 1525 PetscFunctionBeginHot; 1526 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1527 PetscCall(ISGetIndices(ism, &rows)); 1528 PetscCall(ISGetIndices(isn, &cols)); 1529 PetscCall(ISGetLocalSize(ism, &m)); 1530 PetscCall(ISGetLocalSize(isn, &n)); 1531 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1532 PetscCall(ISRestoreIndices(ism, &rows)); 1533 PetscCall(ISRestoreIndices(isn, &cols)); 1534 PetscFunctionReturn(0); 1535 } 1536 1537 /*@ 1538 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1539 values into a matrix 1540 1541 Not Collective 1542 1543 Input Parameters: 1544 + mat - the matrix 1545 . row - the (block) row to set 1546 - v - a logically two-dimensional array of values 1547 1548 Notes: 1549 By the values, v, are column-oriented (for the block version) and sorted 1550 1551 All the nonzeros in the row must be provided 1552 1553 The matrix must have previously had its column indices set 1554 1555 The row must belong to this process 1556 1557 Level: intermediate 1558 1559 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1560 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1561 @*/ 1562 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1563 { 1564 PetscInt globalrow; 1565 1566 PetscFunctionBegin; 1567 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1568 PetscValidType(mat, 1); 1569 PetscValidScalarPointer(v, 3); 1570 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1571 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1572 PetscFunctionReturn(0); 1573 } 1574 1575 /*@ 1576 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1577 values into a matrix 1578 1579 Not Collective 1580 1581 Input Parameters: 1582 + mat - the matrix 1583 . row - the (block) row to set 1584 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1585 1586 Notes: 1587 The values, v, are column-oriented for the block version. 1588 1589 All the nonzeros in the row must be provided 1590 1591 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1592 1593 The row must belong to this process 1594 1595 Level: advanced 1596 1597 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1598 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1599 @*/ 1600 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1601 { 1602 PetscFunctionBeginHot; 1603 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1604 PetscValidType(mat, 1); 1605 MatCheckPreallocated(mat, 1); 1606 PetscValidScalarPointer(v, 3); 1607 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1608 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1609 mat->insertmode = INSERT_VALUES; 1610 1611 if (mat->assembled) { 1612 mat->was_assembled = PETSC_TRUE; 1613 mat->assembled = PETSC_FALSE; 1614 } 1615 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1616 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1617 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1618 PetscFunctionReturn(0); 1619 } 1620 1621 /*@ 1622 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1623 Using structured grid indexing 1624 1625 Not Collective 1626 1627 Input Parameters: 1628 + mat - the matrix 1629 . m - number of rows being entered 1630 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1631 . n - number of columns being entered 1632 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1633 . v - a logically two-dimensional array of values 1634 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1635 1636 Notes: 1637 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1638 1639 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1640 options cannot be mixed without intervening calls to the assembly 1641 routines. 1642 1643 The grid coordinates are across the entire grid, not just the local portion 1644 1645 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1646 as well as in C. 1647 1648 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1649 1650 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1651 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1652 1653 The columns and rows in the stencil passed in MUST be contained within the 1654 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1655 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1656 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1657 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1658 1659 In Fortran idxm and idxn should be declared as 1660 $ MatStencil idxm(4,m),idxn(4,n) 1661 and the values inserted using 1662 $ idxm(MatStencil_i,1) = i 1663 $ idxm(MatStencil_j,1) = j 1664 $ idxm(MatStencil_k,1) = k 1665 $ idxm(MatStencil_c,1) = c 1666 etc 1667 1668 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1669 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1670 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1671 `DM_BOUNDARY_PERIODIC` boundary type. 1672 1673 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1674 a single value per point) you can skip filling those indices. 1675 1676 Inspired by the structured grid interface to the HYPRE package 1677 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1678 1679 Efficiency Alert: 1680 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1681 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1682 1683 Level: beginner 1684 1685 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1686 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1687 @*/ 1688 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1689 { 1690 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1691 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1692 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1693 1694 PetscFunctionBegin; 1695 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1696 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1697 PetscValidType(mat, 1); 1698 PetscValidPointer(idxm, 3); 1699 PetscValidPointer(idxn, 5); 1700 1701 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1702 jdxm = buf; 1703 jdxn = buf + m; 1704 } else { 1705 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1706 jdxm = bufm; 1707 jdxn = bufn; 1708 } 1709 for (i = 0; i < m; i++) { 1710 for (j = 0; j < 3 - sdim; j++) dxm++; 1711 tmp = *dxm++ - starts[0]; 1712 for (j = 0; j < dim - 1; j++) { 1713 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1714 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1715 } 1716 if (mat->stencil.noc) dxm++; 1717 jdxm[i] = tmp; 1718 } 1719 for (i = 0; i < n; i++) { 1720 for (j = 0; j < 3 - sdim; j++) dxn++; 1721 tmp = *dxn++ - starts[0]; 1722 for (j = 0; j < dim - 1; j++) { 1723 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1724 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1725 } 1726 if (mat->stencil.noc) dxn++; 1727 jdxn[i] = tmp; 1728 } 1729 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1730 PetscCall(PetscFree2(bufm, bufn)); 1731 PetscFunctionReturn(0); 1732 } 1733 1734 /*@ 1735 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1736 Using structured grid indexing 1737 1738 Not Collective 1739 1740 Input Parameters: 1741 + mat - the matrix 1742 . m - number of rows being entered 1743 . idxm - grid coordinates for matrix rows being entered 1744 . n - number of columns being entered 1745 . idxn - grid coordinates for matrix columns being entered 1746 . v - a logically two-dimensional array of values 1747 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1748 1749 Notes: 1750 By default the values, v, are row-oriented and unsorted. 1751 See `MatSetOption()` for other options. 1752 1753 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1754 options cannot be mixed without intervening calls to the assembly 1755 routines. 1756 1757 The grid coordinates are across the entire grid, not just the local portion 1758 1759 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1760 as well as in C. 1761 1762 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1763 1764 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1765 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1766 1767 The columns and rows in the stencil passed in MUST be contained within the 1768 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1769 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1770 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1771 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1772 1773 In Fortran idxm and idxn should be declared as 1774 $ MatStencil idxm(4,m),idxn(4,n) 1775 and the values inserted using 1776 $ idxm(MatStencil_i,1) = i 1777 $ idxm(MatStencil_j,1) = j 1778 $ idxm(MatStencil_k,1) = k 1779 etc 1780 1781 Negative indices may be passed in idxm and idxn, these rows and columns are 1782 simply ignored. This allows easily inserting element stiffness matrices 1783 with homogeneous Dirchlet boundary conditions that you don't want represented 1784 in the matrix. 1785 1786 Inspired by the structured grid interface to the HYPRE package 1787 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1788 1789 Level: beginner 1790 1791 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1792 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1793 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1794 @*/ 1795 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1796 { 1797 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1798 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1799 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1800 1801 PetscFunctionBegin; 1802 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1803 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1804 PetscValidType(mat, 1); 1805 PetscValidPointer(idxm, 3); 1806 PetscValidPointer(idxn, 5); 1807 PetscValidScalarPointer(v, 6); 1808 1809 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1810 jdxm = buf; 1811 jdxn = buf + m; 1812 } else { 1813 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1814 jdxm = bufm; 1815 jdxn = bufn; 1816 } 1817 for (i = 0; i < m; i++) { 1818 for (j = 0; j < 3 - sdim; j++) dxm++; 1819 tmp = *dxm++ - starts[0]; 1820 for (j = 0; j < sdim - 1; j++) { 1821 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1822 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1823 } 1824 dxm++; 1825 jdxm[i] = tmp; 1826 } 1827 for (i = 0; i < n; i++) { 1828 for (j = 0; j < 3 - sdim; j++) dxn++; 1829 tmp = *dxn++ - starts[0]; 1830 for (j = 0; j < sdim - 1; j++) { 1831 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1832 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1833 } 1834 dxn++; 1835 jdxn[i] = tmp; 1836 } 1837 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1838 PetscCall(PetscFree2(bufm, bufn)); 1839 PetscFunctionReturn(0); 1840 } 1841 1842 /*@ 1843 MatSetStencil - Sets the grid information for setting values into a matrix via 1844 `MatSetValuesStencil()` 1845 1846 Not Collective 1847 1848 Input Parameters: 1849 + mat - the matrix 1850 . dim - dimension of the grid 1, 2, or 3 1851 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1852 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1853 - dof - number of degrees of freedom per node 1854 1855 Notes: 1856 Inspired by the structured grid interface to the HYPRE package 1857 (www.llnl.gov/CASC/hyper) 1858 1859 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1860 user. 1861 1862 Level: beginner 1863 1864 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1865 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1866 @*/ 1867 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1868 { 1869 PetscFunctionBegin; 1870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1871 PetscValidIntPointer(dims, 3); 1872 PetscValidIntPointer(starts, 4); 1873 1874 mat->stencil.dim = dim + (dof > 1); 1875 for (PetscInt i = 0; i < dim; i++) { 1876 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1877 mat->stencil.starts[i] = starts[dim - i - 1]; 1878 } 1879 mat->stencil.dims[dim] = dof; 1880 mat->stencil.starts[dim] = 0; 1881 mat->stencil.noc = (PetscBool)(dof == 1); 1882 PetscFunctionReturn(0); 1883 } 1884 1885 /*@C 1886 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1887 1888 Not Collective 1889 1890 Input Parameters: 1891 + mat - the matrix 1892 . v - a logically two-dimensional array of values 1893 . m, idxm - the number of block rows and their global block indices 1894 . n, idxn - the number of block columns and their global block indices 1895 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1896 1897 Notes: 1898 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1899 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1900 1901 The m and n count the NUMBER of blocks in the row direction and column direction, 1902 NOT the total number of rows/columns; for example, if the block size is 2 and 1903 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1904 The values in idxm would be 1 2; that is the first index for each block divided by 1905 the block size. 1906 1907 Note that you must call `MatSetBlockSize()` when constructing this matrix (before 1908 preallocating it). 1909 1910 By default the values, v, are row-oriented, so the layout of 1911 v is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1912 1913 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1914 options cannot be mixed without intervening calls to the assembly 1915 routines. 1916 1917 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1918 as well as in C. 1919 1920 Negative indices may be passed in idxm and idxn, these rows and columns are 1921 simply ignored. This allows easily inserting element stiffness matrices 1922 with homogeneous Dirchlet boundary conditions that you don't want represented 1923 in the matrix. 1924 1925 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1926 internal searching must be done to determine where to place the 1927 data in the matrix storage space. By instead inserting blocks of 1928 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1929 reduced. 1930 1931 Example: 1932 $ Suppose m=n=2 and block size(bs) = 2 The array is 1933 $ 1934 $ 1 2 | 3 4 1935 $ 5 6 | 7 8 1936 $ - - - | - - - 1937 $ 9 10 | 11 12 1938 $ 13 14 | 15 16 1939 $ 1940 $ v[] should be passed in like 1941 $ v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1942 $ 1943 $ If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1944 $ v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1945 1946 Level: intermediate 1947 1948 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1949 @*/ 1950 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1951 { 1952 PetscFunctionBeginHot; 1953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1954 PetscValidType(mat, 1); 1955 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1956 PetscValidIntPointer(idxm, 3); 1957 PetscValidIntPointer(idxn, 5); 1958 MatCheckPreallocated(mat, 1); 1959 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1960 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1961 if (PetscDefined(USE_DEBUG)) { 1962 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1963 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1964 } 1965 if (PetscDefined(USE_DEBUG)) { 1966 PetscInt rbs, cbs, M, N, i; 1967 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1968 PetscCall(MatGetSize(mat, &M, &N)); 1969 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 1970 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 1971 } 1972 if (mat->assembled) { 1973 mat->was_assembled = PETSC_TRUE; 1974 mat->assembled = PETSC_FALSE; 1975 } 1976 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1977 if (mat->ops->setvaluesblocked) { 1978 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1979 } else { 1980 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1981 PetscInt i, j, bs, cbs; 1982 1983 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1984 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1985 iidxm = buf; 1986 iidxn = buf + m * bs; 1987 } else { 1988 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 1989 iidxm = bufr; 1990 iidxn = bufc; 1991 } 1992 for (i = 0; i < m; i++) { 1993 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 1994 } 1995 if (m != n || bs != cbs || idxm != idxn) { 1996 for (i = 0; i < n; i++) { 1997 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 1998 } 1999 } else iidxn = iidxm; 2000 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2001 PetscCall(PetscFree2(bufr, bufc)); 2002 } 2003 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2004 PetscFunctionReturn(0); 2005 } 2006 2007 /*@C 2008 MatGetValues - Gets a block of local values from a matrix. 2009 2010 Not Collective; can only return values that are owned by the give process 2011 2012 Input Parameters: 2013 + mat - the matrix 2014 . v - a logically two-dimensional array for storing the values 2015 . m, idxm - the number of rows and their global indices 2016 - n, idxn - the number of columns and their global indices 2017 2018 Notes: 2019 The user must allocate space (m*n `PetscScalar`s) for the values, v. 2020 The values, v, are then returned in a row-oriented format, 2021 analogous to that used by default in `MatSetValues()`. 2022 2023 `MatGetValues()` uses 0-based row and column numbers in 2024 Fortran as well as in C. 2025 2026 `MatGetValues()` requires that the matrix has been assembled 2027 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2028 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2029 without intermediate matrix assembly. 2030 2031 Negative row or column indices will be ignored and those locations in v[] will be 2032 left unchanged. 2033 2034 For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank. 2035 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2036 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2037 2038 Level: advanced 2039 2040 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2041 @*/ 2042 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2043 { 2044 PetscFunctionBegin; 2045 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2046 PetscValidType(mat, 1); 2047 if (!m || !n) PetscFunctionReturn(0); 2048 PetscValidIntPointer(idxm, 3); 2049 PetscValidIntPointer(idxn, 5); 2050 PetscValidScalarPointer(v, 6); 2051 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2052 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2053 MatCheckPreallocated(mat, 1); 2054 2055 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2056 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2057 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2058 PetscFunctionReturn(0); 2059 } 2060 2061 /*@C 2062 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2063 defined previously by `MatSetLocalToGlobalMapping()` 2064 2065 Not Collective 2066 2067 Input Parameters: 2068 + mat - the matrix 2069 . nrow, irow - number of rows and their local indices 2070 - ncol, icol - number of columns and their local indices 2071 2072 Output Parameter: 2073 . y - a logically two-dimensional array of values 2074 2075 Notes: 2076 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2077 2078 This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering, 2079 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2080 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2081 with `MatSetLocalToGlobalMapping()`. 2082 2083 Developer Note: 2084 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2085 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2086 2087 Level: advanced 2088 2089 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2090 `MatSetValuesLocal()`, `MatGetValues()` 2091 @*/ 2092 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2093 { 2094 PetscFunctionBeginHot; 2095 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2096 PetscValidType(mat, 1); 2097 MatCheckPreallocated(mat, 1); 2098 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */ 2099 PetscValidIntPointer(irow, 3); 2100 PetscValidIntPointer(icol, 5); 2101 if (PetscDefined(USE_DEBUG)) { 2102 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2103 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2104 } 2105 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2106 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2107 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2108 else { 2109 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2110 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2111 irowm = buf; 2112 icolm = buf + nrow; 2113 } else { 2114 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2115 irowm = bufr; 2116 icolm = bufc; 2117 } 2118 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2119 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2120 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2121 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2122 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2123 PetscCall(PetscFree2(bufr, bufc)); 2124 } 2125 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2126 PetscFunctionReturn(0); 2127 } 2128 2129 /*@ 2130 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2131 the same size. Currently, this can only be called once and creates the given matrix. 2132 2133 Not Collective 2134 2135 Input Parameters: 2136 + mat - the matrix 2137 . nb - the number of blocks 2138 . bs - the number of rows (and columns) in each block 2139 . rows - a concatenation of the rows for each block 2140 - v - a concatenation of logically two-dimensional arrays of values 2141 2142 Note: 2143 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2144 2145 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2146 2147 Level: advanced 2148 2149 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2150 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2151 @*/ 2152 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2153 { 2154 PetscFunctionBegin; 2155 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2156 PetscValidType(mat, 1); 2157 PetscValidIntPointer(rows, 4); 2158 PetscValidScalarPointer(v, 5); 2159 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2160 2161 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2162 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2163 else { 2164 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2165 } 2166 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2167 PetscFunctionReturn(0); 2168 } 2169 2170 /*@ 2171 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2172 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2173 using a local (per-processor) numbering. 2174 2175 Not Collective 2176 2177 Input Parameters: 2178 + x - the matrix 2179 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2180 - cmapping - column mapping 2181 2182 Level: intermediate 2183 2184 Note: 2185 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2186 2187 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2188 @*/ 2189 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2190 { 2191 PetscFunctionBegin; 2192 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2193 PetscValidType(x, 1); 2194 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2195 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2196 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2197 else { 2198 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2199 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2200 } 2201 PetscFunctionReturn(0); 2202 } 2203 2204 /*@ 2205 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2206 2207 Not Collective 2208 2209 Input Parameter: 2210 . A - the matrix 2211 2212 Output Parameters: 2213 + rmapping - row mapping 2214 - cmapping - column mapping 2215 2216 Level: advanced 2217 2218 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2219 @*/ 2220 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2221 { 2222 PetscFunctionBegin; 2223 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2224 PetscValidType(A, 1); 2225 if (rmapping) { 2226 PetscValidPointer(rmapping, 2); 2227 *rmapping = A->rmap->mapping; 2228 } 2229 if (cmapping) { 2230 PetscValidPointer(cmapping, 3); 2231 *cmapping = A->cmap->mapping; 2232 } 2233 PetscFunctionReturn(0); 2234 } 2235 2236 /*@ 2237 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2238 2239 Logically Collective on A 2240 2241 Input Parameters: 2242 + A - the matrix 2243 . rmap - row layout 2244 - cmap - column layout 2245 2246 Level: advanced 2247 2248 Note: 2249 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2250 2251 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2252 @*/ 2253 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2254 { 2255 PetscFunctionBegin; 2256 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2257 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2258 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2259 PetscFunctionReturn(0); 2260 } 2261 2262 /*@ 2263 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2264 2265 Not Collective 2266 2267 Input Parameter: 2268 . A - the matrix 2269 2270 Output Parameters: 2271 + rmap - row layout 2272 - cmap - column layout 2273 2274 Level: advanced 2275 2276 .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2277 @*/ 2278 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2279 { 2280 PetscFunctionBegin; 2281 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2282 PetscValidType(A, 1); 2283 if (rmap) { 2284 PetscValidPointer(rmap, 2); 2285 *rmap = A->rmap; 2286 } 2287 if (cmap) { 2288 PetscValidPointer(cmap, 3); 2289 *cmap = A->cmap; 2290 } 2291 PetscFunctionReturn(0); 2292 } 2293 2294 /*@C 2295 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2296 using a local numbering of the nodes. 2297 2298 Not Collective 2299 2300 Input Parameters: 2301 + mat - the matrix 2302 . nrow, irow - number of rows and their local indices 2303 . ncol, icol - number of columns and their local indices 2304 . y - a logically two-dimensional array of values 2305 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2306 2307 Notes: 2308 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2309 `MatSetUp()` before using this routine 2310 2311 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2312 2313 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2314 options cannot be mixed without intervening calls to the assembly 2315 routines. 2316 2317 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2318 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2319 2320 Level: intermediate 2321 2322 Developer Note: 2323 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2324 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2325 2326 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2327 `MatGetValuesLocal()` 2328 @*/ 2329 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2330 { 2331 PetscFunctionBeginHot; 2332 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2333 PetscValidType(mat, 1); 2334 MatCheckPreallocated(mat, 1); 2335 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2336 PetscValidIntPointer(irow, 3); 2337 PetscValidIntPointer(icol, 5); 2338 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2339 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2340 if (PetscDefined(USE_DEBUG)) { 2341 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2342 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2343 } 2344 2345 if (mat->assembled) { 2346 mat->was_assembled = PETSC_TRUE; 2347 mat->assembled = PETSC_FALSE; 2348 } 2349 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2350 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2351 else { 2352 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2353 const PetscInt *irowm, *icolm; 2354 2355 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2356 bufr = buf; 2357 bufc = buf + nrow; 2358 irowm = bufr; 2359 icolm = bufc; 2360 } else { 2361 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2362 irowm = bufr; 2363 icolm = bufc; 2364 } 2365 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2366 else irowm = irow; 2367 if (mat->cmap->mapping) { 2368 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2369 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2370 } else icolm = irowm; 2371 } else icolm = icol; 2372 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2373 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2374 } 2375 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2376 PetscFunctionReturn(0); 2377 } 2378 2379 /*@C 2380 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2381 using a local ordering of the nodes a block at a time. 2382 2383 Not Collective 2384 2385 Input Parameters: 2386 + x - the matrix 2387 . nrow, irow - number of rows and their local indices 2388 . ncol, icol - number of columns and their local indices 2389 . y - a logically two-dimensional array of values 2390 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2391 2392 Notes: 2393 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2394 `MatSetUp()` before using this routine 2395 2396 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2397 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2398 2399 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2400 options cannot be mixed without intervening calls to the assembly 2401 routines. 2402 2403 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2404 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2405 2406 Level: intermediate 2407 2408 Developer Note: 2409 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2410 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2411 2412 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2413 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2414 @*/ 2415 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2416 { 2417 PetscFunctionBeginHot; 2418 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2419 PetscValidType(mat, 1); 2420 MatCheckPreallocated(mat, 1); 2421 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2422 PetscValidIntPointer(irow, 3); 2423 PetscValidIntPointer(icol, 5); 2424 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2425 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2426 if (PetscDefined(USE_DEBUG)) { 2427 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2428 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2429 } 2430 2431 if (mat->assembled) { 2432 mat->was_assembled = PETSC_TRUE; 2433 mat->assembled = PETSC_FALSE; 2434 } 2435 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2436 PetscInt irbs, rbs; 2437 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2438 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2439 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2440 } 2441 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2442 PetscInt icbs, cbs; 2443 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2444 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2445 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2446 } 2447 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2448 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2449 else { 2450 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2451 const PetscInt *irowm, *icolm; 2452 2453 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2454 bufr = buf; 2455 bufc = buf + nrow; 2456 irowm = bufr; 2457 icolm = bufc; 2458 } else { 2459 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2460 irowm = bufr; 2461 icolm = bufc; 2462 } 2463 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2464 else irowm = irow; 2465 if (mat->cmap->mapping) { 2466 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2467 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2468 } else icolm = irowm; 2469 } else icolm = icol; 2470 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2471 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2472 } 2473 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2474 PetscFunctionReturn(0); 2475 } 2476 2477 /*@ 2478 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2479 2480 Collective on mat 2481 2482 Input Parameters: 2483 + mat - the matrix 2484 - x - the vector to be multiplied 2485 2486 Output Parameters: 2487 . y - the result 2488 2489 Note: 2490 The vectors x and y cannot be the same. I.e., one cannot 2491 call `MatMultDiagonalBlock`(A,y,y). 2492 2493 Level: developer 2494 2495 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2496 @*/ 2497 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2498 { 2499 PetscFunctionBegin; 2500 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2501 PetscValidType(mat, 1); 2502 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2503 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2504 2505 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2506 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2507 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2508 MatCheckPreallocated(mat, 1); 2509 2510 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2511 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2512 PetscFunctionReturn(0); 2513 } 2514 2515 /* --------------------------------------------------------*/ 2516 /*@ 2517 MatMult - Computes the matrix-vector product, y = Ax. 2518 2519 Neighbor-wise Collective on mat 2520 2521 Input Parameters: 2522 + mat - the matrix 2523 - x - the vector to be multiplied 2524 2525 Output Parameters: 2526 . y - the result 2527 2528 Note: 2529 The vectors x and y cannot be the same. I.e., one cannot 2530 call `MatMult`(A,y,y). 2531 2532 Level: beginner 2533 2534 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2535 @*/ 2536 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2537 { 2538 PetscFunctionBegin; 2539 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2540 PetscValidType(mat, 1); 2541 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2542 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2543 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2544 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2545 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2546 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2547 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2548 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2549 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2550 PetscCall(VecSetErrorIfLocked(y, 3)); 2551 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2552 MatCheckPreallocated(mat, 1); 2553 2554 PetscCall(VecLockReadPush(x)); 2555 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2556 PetscUseTypeMethod(mat, mult, x, y); 2557 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2558 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2559 PetscCall(VecLockReadPop(x)); 2560 PetscFunctionReturn(0); 2561 } 2562 2563 /*@ 2564 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2565 2566 Neighbor-wise Collective on mat 2567 2568 Input Parameters: 2569 + mat - the matrix 2570 - x - the vector to be multiplied 2571 2572 Output Parameters: 2573 . y - the result 2574 2575 Notes: 2576 The vectors x and y cannot be the same. I.e., one cannot 2577 call `MatMultTranspose`(A,y,y). 2578 2579 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2580 use `MatMultHermitianTranspose()` 2581 2582 Level: beginner 2583 2584 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2585 @*/ 2586 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2587 { 2588 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2589 2590 PetscFunctionBegin; 2591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2592 PetscValidType(mat, 1); 2593 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2594 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2595 2596 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2597 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2598 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2599 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2600 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2601 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2602 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2603 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2604 MatCheckPreallocated(mat, 1); 2605 2606 if (!mat->ops->multtranspose) { 2607 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2608 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2609 } else op = mat->ops->multtranspose; 2610 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2611 PetscCall(VecLockReadPush(x)); 2612 PetscCall((*op)(mat, x, y)); 2613 PetscCall(VecLockReadPop(x)); 2614 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2615 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2616 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2617 PetscFunctionReturn(0); 2618 } 2619 2620 /*@ 2621 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2622 2623 Neighbor-wise Collective on mat 2624 2625 Input Parameters: 2626 + mat - the matrix 2627 - x - the vector to be multilplied 2628 2629 Output Parameters: 2630 . y - the result 2631 2632 Notes: 2633 The vectors x and y cannot be the same. I.e., one cannot 2634 call `MatMultHermitianTranspose`(A,y,y). 2635 2636 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2637 2638 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2639 2640 Level: beginner 2641 2642 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2643 @*/ 2644 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2645 { 2646 PetscFunctionBegin; 2647 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2648 PetscValidType(mat, 1); 2649 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2650 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2651 2652 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2653 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2654 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2655 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2656 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2657 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2658 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2659 MatCheckPreallocated(mat, 1); 2660 2661 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2662 #if defined(PETSC_USE_COMPLEX) 2663 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2664 PetscCall(VecLockReadPush(x)); 2665 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2666 else PetscUseTypeMethod(mat, mult, x, y); 2667 PetscCall(VecLockReadPop(x)); 2668 } else { 2669 Vec w; 2670 PetscCall(VecDuplicate(x, &w)); 2671 PetscCall(VecCopy(x, w)); 2672 PetscCall(VecConjugate(w)); 2673 PetscCall(MatMultTranspose(mat, w, y)); 2674 PetscCall(VecDestroy(&w)); 2675 PetscCall(VecConjugate(y)); 2676 } 2677 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2678 #else 2679 PetscCall(MatMultTranspose(mat, x, y)); 2680 #endif 2681 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2682 PetscFunctionReturn(0); 2683 } 2684 2685 /*@ 2686 MatMultAdd - Computes v3 = v2 + A * v1. 2687 2688 Neighbor-wise Collective on mat 2689 2690 Input Parameters: 2691 + mat - the matrix 2692 - v1, v2 - the vectors 2693 2694 Output Parameters: 2695 . v3 - the result 2696 2697 Note: 2698 The vectors v1 and v3 cannot be the same. I.e., one cannot 2699 call `MatMultAdd`(A,v1,v2,v1). 2700 2701 Level: beginner 2702 2703 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2704 @*/ 2705 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2706 { 2707 PetscFunctionBegin; 2708 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2709 PetscValidType(mat, 1); 2710 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2711 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2712 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2713 2714 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2715 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2716 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2717 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2718 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2719 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2720 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2721 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2722 MatCheckPreallocated(mat, 1); 2723 2724 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2725 PetscCall(VecLockReadPush(v1)); 2726 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2727 PetscCall(VecLockReadPop(v1)); 2728 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2729 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2730 PetscFunctionReturn(0); 2731 } 2732 2733 /*@ 2734 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2735 2736 Neighbor-wise Collective on mat 2737 2738 Input Parameters: 2739 + mat - the matrix 2740 - v1, v2 - the vectors 2741 2742 Output Parameters: 2743 . v3 - the result 2744 2745 Note: 2746 The vectors v1 and v3 cannot be the same. I.e., one cannot 2747 call `MatMultTransposeAdd`(A,v1,v2,v1). 2748 2749 Level: beginner 2750 2751 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2752 @*/ 2753 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2754 { 2755 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2756 2757 PetscFunctionBegin; 2758 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2759 PetscValidType(mat, 1); 2760 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2761 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2762 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2763 2764 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2765 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2766 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2767 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2768 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2769 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2770 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2771 MatCheckPreallocated(mat, 1); 2772 2773 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2774 PetscCall(VecLockReadPush(v1)); 2775 PetscCall((*op)(mat, v1, v2, v3)); 2776 PetscCall(VecLockReadPop(v1)); 2777 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2778 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2779 PetscFunctionReturn(0); 2780 } 2781 2782 /*@ 2783 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2784 2785 Neighbor-wise Collective on mat 2786 2787 Input Parameters: 2788 + mat - the matrix 2789 - v1, v2 - the vectors 2790 2791 Output Parameters: 2792 . v3 - the result 2793 2794 Note: 2795 The vectors v1 and v3 cannot be the same. I.e., one cannot 2796 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2797 2798 Level: beginner 2799 2800 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2801 @*/ 2802 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2803 { 2804 PetscFunctionBegin; 2805 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2806 PetscValidType(mat, 1); 2807 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2808 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2809 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2810 2811 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2812 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2813 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2814 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2815 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2816 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2817 MatCheckPreallocated(mat, 1); 2818 2819 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2820 PetscCall(VecLockReadPush(v1)); 2821 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2822 else { 2823 Vec w, z; 2824 PetscCall(VecDuplicate(v1, &w)); 2825 PetscCall(VecCopy(v1, w)); 2826 PetscCall(VecConjugate(w)); 2827 PetscCall(VecDuplicate(v3, &z)); 2828 PetscCall(MatMultTranspose(mat, w, z)); 2829 PetscCall(VecDestroy(&w)); 2830 PetscCall(VecConjugate(z)); 2831 if (v2 != v3) { 2832 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2833 } else { 2834 PetscCall(VecAXPY(v3, 1.0, z)); 2835 } 2836 PetscCall(VecDestroy(&z)); 2837 } 2838 PetscCall(VecLockReadPop(v1)); 2839 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2840 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2841 PetscFunctionReturn(0); 2842 } 2843 2844 /*@C 2845 MatGetFactorType - gets the type of factorization it is 2846 2847 Not Collective 2848 2849 Input Parameters: 2850 . mat - the matrix 2851 2852 Output Parameters: 2853 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2854 2855 Level: intermediate 2856 2857 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2858 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2859 @*/ 2860 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2861 { 2862 PetscFunctionBegin; 2863 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2864 PetscValidType(mat, 1); 2865 PetscValidPointer(t, 2); 2866 *t = mat->factortype; 2867 PetscFunctionReturn(0); 2868 } 2869 2870 /*@C 2871 MatSetFactorType - sets the type of factorization it is 2872 2873 Logically Collective on mat 2874 2875 Input Parameters: 2876 + mat - the matrix 2877 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2878 2879 Level: intermediate 2880 2881 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2882 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2883 @*/ 2884 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2885 { 2886 PetscFunctionBegin; 2887 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2888 PetscValidType(mat, 1); 2889 mat->factortype = t; 2890 PetscFunctionReturn(0); 2891 } 2892 2893 /* ------------------------------------------------------------*/ 2894 /*@C 2895 MatGetInfo - Returns information about matrix storage (number of 2896 nonzeros, memory, etc.). 2897 2898 Collective on mat if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2899 2900 Input Parameter: 2901 . mat - the matrix 2902 2903 Output Parameters: 2904 + flag - flag indicating the type of parameters to be returned 2905 (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, 2906 MAT_GLOBAL_SUM - sum over all processors) 2907 - info - matrix information context 2908 2909 Notes: 2910 The `MatInfo` context contains a variety of matrix data, including 2911 number of nonzeros allocated and used, number of mallocs during 2912 matrix assembly, etc. Additional information for factored matrices 2913 is provided (such as the fill ratio, number of mallocs during 2914 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2915 when using the runtime options 2916 $ -info -mat_view ::ascii_info 2917 2918 Example for C/C++ Users: 2919 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2920 data within the MatInfo context. For example, 2921 .vb 2922 MatInfo info; 2923 Mat A; 2924 double mal, nz_a, nz_u; 2925 2926 MatGetInfo(A,MAT_LOCAL,&info); 2927 mal = info.mallocs; 2928 nz_a = info.nz_allocated; 2929 .ve 2930 2931 Example for Fortran Users: 2932 Fortran users should declare info as a double precision 2933 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2934 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2935 a complete list of parameter names. 2936 .vb 2937 double precision info(MAT_INFO_SIZE) 2938 double precision mal, nz_a 2939 Mat A 2940 integer ierr 2941 2942 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2943 mal = info(MAT_INFO_MALLOCS) 2944 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2945 .ve 2946 2947 Level: intermediate 2948 2949 Developer Note: fortran interface is not autogenerated as the f90 2950 interface definition cannot be generated correctly [due to MatInfo] 2951 2952 .seealso: `MatInfo`, `MatStashGetInfo()` 2953 @*/ 2954 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2955 { 2956 PetscFunctionBegin; 2957 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2958 PetscValidType(mat, 1); 2959 PetscValidPointer(info, 3); 2960 MatCheckPreallocated(mat, 1); 2961 PetscUseTypeMethod(mat, getinfo, flag, info); 2962 PetscFunctionReturn(0); 2963 } 2964 2965 /* 2966 This is used by external packages where it is not easy to get the info from the actual 2967 matrix factorization. 2968 */ 2969 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2970 { 2971 PetscFunctionBegin; 2972 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2973 PetscFunctionReturn(0); 2974 } 2975 2976 /* ----------------------------------------------------------*/ 2977 2978 /*@C 2979 MatLUFactor - Performs in-place LU factorization of matrix. 2980 2981 Collective on mat 2982 2983 Input Parameters: 2984 + mat - the matrix 2985 . row - row permutation 2986 . col - column permutation 2987 - info - options for factorization, includes 2988 $ fill - expected fill as ratio of original fill. 2989 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 2990 $ Run with the option -info to determine an optimal value to use 2991 2992 Notes: 2993 Most users should employ the `KSP` interface for linear solvers 2994 instead of working directly with matrix algebra routines such as this. 2995 See, e.g., `KSPCreate()`. 2996 2997 This changes the state of the matrix to a factored matrix; it cannot be used 2998 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 2999 3000 This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3001 when not using `KSP`. 3002 3003 Level: developer 3004 3005 Developer Note: 3006 The Fortran interface is not autogenerated as the f90 3007 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3008 3009 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3010 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3011 @*/ 3012 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3013 { 3014 MatFactorInfo tinfo; 3015 3016 PetscFunctionBegin; 3017 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3018 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3019 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3020 if (info) PetscValidPointer(info, 4); 3021 PetscValidType(mat, 1); 3022 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3023 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3024 MatCheckPreallocated(mat, 1); 3025 if (!info) { 3026 PetscCall(MatFactorInfoInitialize(&tinfo)); 3027 info = &tinfo; 3028 } 3029 3030 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3031 PetscUseTypeMethod(mat, lufactor, row, col, info); 3032 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3033 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3034 PetscFunctionReturn(0); 3035 } 3036 3037 /*@C 3038 MatILUFactor - Performs in-place ILU factorization of matrix. 3039 3040 Collective on mat 3041 3042 Input Parameters: 3043 + mat - the matrix 3044 . row - row permutation 3045 . col - column permutation 3046 - info - structure containing 3047 $ levels - number of levels of fill. 3048 $ expected fill - as ratio of original fill. 3049 $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3050 missing diagonal entries) 3051 3052 Notes: 3053 Most users should employ the `KSP` interface for linear solvers 3054 instead of working directly with matrix algebra routines such as this. 3055 See, e.g., `KSPCreate()`. 3056 3057 Probably really in-place only when level of fill is zero, otherwise allocates 3058 new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3059 when not using `KSP`. 3060 3061 Level: developer 3062 3063 Developer Note: 3064 The Fortran interface is not autogenerated as the f90 3065 interface definition cannot be generated correctly [due to MatFactorInfo] 3066 3067 .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3068 @*/ 3069 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3070 { 3071 PetscFunctionBegin; 3072 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3073 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3074 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3075 PetscValidPointer(info, 4); 3076 PetscValidType(mat, 1); 3077 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3078 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3079 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3080 MatCheckPreallocated(mat, 1); 3081 3082 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3083 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3084 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3085 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3086 PetscFunctionReturn(0); 3087 } 3088 3089 /*@C 3090 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3091 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3092 3093 Collective on fact 3094 3095 Input Parameters: 3096 + fact - the factor matrix obtained with `MatGetFactor()` 3097 . mat - the matrix 3098 . row, col - row and column permutations 3099 - info - options for factorization, includes 3100 .vb 3101 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3102 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3103 .ve 3104 3105 Notes: 3106 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3107 3108 Most users should employ the simplified `KSP` interface for linear solvers 3109 instead of working directly with matrix algebra routines such as this. 3110 See, e.g., `KSPCreate()`. 3111 3112 Level: developer 3113 3114 Developer Note: 3115 The Fortran interface is not autogenerated as the f90 3116 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3117 3118 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3119 @*/ 3120 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3121 { 3122 MatFactorInfo tinfo; 3123 3124 PetscFunctionBegin; 3125 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3126 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3127 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3128 if (info) PetscValidPointer(info, 5); 3129 PetscValidType(mat, 2); 3130 PetscValidPointer(fact, 1); 3131 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3132 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3133 if (!(fact)->ops->lufactorsymbolic) { 3134 MatSolverType stype; 3135 PetscCall(MatFactorGetSolverType(fact, &stype)); 3136 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype); 3137 } 3138 MatCheckPreallocated(mat, 2); 3139 if (!info) { 3140 PetscCall(MatFactorInfoInitialize(&tinfo)); 3141 info = &tinfo; 3142 } 3143 3144 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3145 PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info)); 3146 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3147 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3148 PetscFunctionReturn(0); 3149 } 3150 3151 /*@C 3152 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3153 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3154 3155 Collective on fact 3156 3157 Input Parameters: 3158 + fact - the factor matrix obtained with `MatGetFactor()` 3159 . mat - the matrix 3160 - info - options for factorization 3161 3162 Notes: 3163 See `MatLUFactor()` for in-place factorization. See 3164 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3165 3166 Most users should employ the `KSP` interface for linear solvers 3167 instead of working directly with matrix algebra routines such as this. 3168 See, e.g., `KSPCreate()`. 3169 3170 Level: developer 3171 3172 Developer Note: 3173 The Fortran interface is not autogenerated as the f90 3174 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3175 3176 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3177 @*/ 3178 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3179 { 3180 MatFactorInfo tinfo; 3181 3182 PetscFunctionBegin; 3183 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3184 PetscValidType(mat, 2); 3185 PetscValidPointer(fact, 1); 3186 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3187 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3188 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3189 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3190 3191 PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name); 3192 MatCheckPreallocated(mat, 2); 3193 if (!info) { 3194 PetscCall(MatFactorInfoInitialize(&tinfo)); 3195 info = &tinfo; 3196 } 3197 3198 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3199 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3200 PetscCall((fact->ops->lufactornumeric)(fact, mat, info)); 3201 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3202 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3203 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3204 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3205 PetscFunctionReturn(0); 3206 } 3207 3208 /*@C 3209 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3210 symmetric matrix. 3211 3212 Collective on mat 3213 3214 Input Parameters: 3215 + mat - the matrix 3216 . perm - row and column permutations 3217 - f - expected fill as ratio of original fill 3218 3219 Notes: 3220 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3221 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3222 3223 Most users should employ the `KSP` interface for linear solvers 3224 instead of working directly with matrix algebra routines such as this. 3225 See, e.g., `KSPCreate()`. 3226 3227 Level: developer 3228 3229 Developer Note: 3230 The Fortran interface is not autogenerated as the f90 3231 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3232 3233 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3234 `MatGetOrdering()` 3235 @*/ 3236 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3237 { 3238 MatFactorInfo tinfo; 3239 3240 PetscFunctionBegin; 3241 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3242 PetscValidType(mat, 1); 3243 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3244 if (info) PetscValidPointer(info, 3); 3245 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3246 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3247 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3248 MatCheckPreallocated(mat, 1); 3249 if (!info) { 3250 PetscCall(MatFactorInfoInitialize(&tinfo)); 3251 info = &tinfo; 3252 } 3253 3254 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3255 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3256 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3257 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3258 PetscFunctionReturn(0); 3259 } 3260 3261 /*@C 3262 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3263 of a symmetric matrix. 3264 3265 Collective on fact 3266 3267 Input Parameters: 3268 + fact - the factor matrix obtained with `MatGetFactor()` 3269 . mat - the matrix 3270 . perm - row and column permutations 3271 - info - options for factorization, includes 3272 $ fill - expected fill as ratio of original fill. 3273 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3274 $ Run with the option -info to determine an optimal value to use 3275 3276 Notes: 3277 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3278 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3279 3280 Most users should employ the `KSP` interface for linear solvers 3281 instead of working directly with matrix algebra routines such as this. 3282 See, e.g., `KSPCreate()`. 3283 3284 Level: developer 3285 3286 Developer Note: 3287 The Fortran interface is not autogenerated as the f90 3288 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3289 3290 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3291 `MatGetOrdering()` 3292 @*/ 3293 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3294 { 3295 MatFactorInfo tinfo; 3296 3297 PetscFunctionBegin; 3298 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3299 PetscValidType(mat, 2); 3300 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3301 if (info) PetscValidPointer(info, 4); 3302 PetscValidPointer(fact, 1); 3303 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3304 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3305 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3306 if (!(fact)->ops->choleskyfactorsymbolic) { 3307 MatSolverType stype; 3308 PetscCall(MatFactorGetSolverType(fact, &stype)); 3309 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype); 3310 } 3311 MatCheckPreallocated(mat, 2); 3312 if (!info) { 3313 PetscCall(MatFactorInfoInitialize(&tinfo)); 3314 info = &tinfo; 3315 } 3316 3317 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3318 PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info)); 3319 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3320 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3321 PetscFunctionReturn(0); 3322 } 3323 3324 /*@C 3325 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3326 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3327 `MatCholeskyFactorSymbolic()`. 3328 3329 Collective on fact 3330 3331 Input Parameters: 3332 + fact - the factor matrix obtained with `MatGetFactor()` 3333 . mat - the initial matrix 3334 . info - options for factorization 3335 - fact - the symbolic factor of mat 3336 3337 Note: 3338 Most users should employ the `KSP` interface for linear solvers 3339 instead of working directly with matrix algebra routines such as this. 3340 See, e.g., `KSPCreate()`. 3341 3342 Level: developer 3343 3344 Developer Note: 3345 The Fortran interface is not autogenerated as the f90 3346 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3347 3348 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3349 @*/ 3350 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3351 { 3352 MatFactorInfo tinfo; 3353 3354 PetscFunctionBegin; 3355 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3356 PetscValidType(mat, 2); 3357 PetscValidPointer(fact, 1); 3358 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3359 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3360 PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name); 3361 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3362 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3363 MatCheckPreallocated(mat, 2); 3364 if (!info) { 3365 PetscCall(MatFactorInfoInitialize(&tinfo)); 3366 info = &tinfo; 3367 } 3368 3369 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3370 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3371 PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info)); 3372 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3373 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3374 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3375 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3376 PetscFunctionReturn(0); 3377 } 3378 3379 /*@ 3380 MatQRFactor - Performs in-place QR factorization of matrix. 3381 3382 Collective on mat 3383 3384 Input Parameters: 3385 + mat - the matrix 3386 . col - column permutation 3387 - info - options for factorization, includes 3388 $ fill - expected fill as ratio of original fill. 3389 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3390 $ Run with the option -info to determine an optimal value to use 3391 3392 Notes: 3393 Most users should employ the `KSP` interface for linear solvers 3394 instead of working directly with matrix algebra routines such as this. 3395 See, e.g., `KSPCreate()`. 3396 3397 This changes the state of the matrix to a factored matrix; it cannot be used 3398 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3399 3400 Level: developer 3401 3402 Developer Note: 3403 The Fortran interface is not autogenerated as the f90 3404 interface definition cannot be generated correctly [due to MatFactorInfo] 3405 3406 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3407 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3408 @*/ 3409 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3410 { 3411 PetscFunctionBegin; 3412 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3413 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3414 if (info) PetscValidPointer(info, 3); 3415 PetscValidType(mat, 1); 3416 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3417 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3418 MatCheckPreallocated(mat, 1); 3419 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3420 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3421 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3422 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3423 PetscFunctionReturn(0); 3424 } 3425 3426 /*@ 3427 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3428 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3429 3430 Collective on fact 3431 3432 Input Parameters: 3433 + fact - the factor matrix obtained with `MatGetFactor()` 3434 . mat - the matrix 3435 . col - column permutation 3436 - info - options for factorization, includes 3437 $ fill - expected fill as ratio of original fill. 3438 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3439 $ Run with the option -info to determine an optimal value to use 3440 3441 Most users should employ the `KSP` interface for linear solvers 3442 instead of working directly with matrix algebra routines such as this. 3443 See, e.g., `KSPCreate()`. 3444 3445 Level: developer 3446 3447 Developer Note: 3448 The Fortran interface is not autogenerated as the f90 3449 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3450 3451 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3452 @*/ 3453 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3454 { 3455 MatFactorInfo tinfo; 3456 3457 PetscFunctionBegin; 3458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3459 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3460 if (info) PetscValidPointer(info, 4); 3461 PetscValidType(mat, 2); 3462 PetscValidPointer(fact, 1); 3463 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3464 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3465 MatCheckPreallocated(mat, 2); 3466 if (!info) { 3467 PetscCall(MatFactorInfoInitialize(&tinfo)); 3468 info = &tinfo; 3469 } 3470 3471 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3472 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3473 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3474 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3475 PetscFunctionReturn(0); 3476 } 3477 3478 /*@ 3479 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3480 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3481 3482 Collective on fact 3483 3484 Input Parameters: 3485 + fact - the factor matrix obtained with `MatGetFactor()` 3486 . mat - the matrix 3487 - info - options for factorization 3488 3489 Notes: 3490 See `MatQRFactor()` for in-place factorization. 3491 3492 Most users should employ the `KSP` interface for linear solvers 3493 instead of working directly with matrix algebra routines such as this. 3494 See, e.g., `KSPCreate()`. 3495 3496 Level: developer 3497 3498 Developer Note: 3499 The Fortran interface is not autogenerated as the f90 3500 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3501 3502 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3503 @*/ 3504 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3505 { 3506 MatFactorInfo tinfo; 3507 3508 PetscFunctionBegin; 3509 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3510 PetscValidType(mat, 2); 3511 PetscValidPointer(fact, 1); 3512 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3513 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3514 PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3515 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3516 3517 MatCheckPreallocated(mat, 2); 3518 if (!info) { 3519 PetscCall(MatFactorInfoInitialize(&tinfo)); 3520 info = &tinfo; 3521 } 3522 3523 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3524 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3525 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3526 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3527 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3528 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3529 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3530 PetscFunctionReturn(0); 3531 } 3532 3533 /* ----------------------------------------------------------------*/ 3534 /*@ 3535 MatSolve - Solves A x = b, given a factored matrix. 3536 3537 Neighbor-wise Collective on mat 3538 3539 Input Parameters: 3540 + mat - the factored matrix 3541 - b - the right-hand-side vector 3542 3543 Output Parameter: 3544 . x - the result vector 3545 3546 Notes: 3547 The vectors b and x cannot be the same. I.e., one cannot 3548 call `MatSolve`(A,x,x). 3549 3550 Most users should employ the `KSP` interface for linear solvers 3551 instead of working directly with matrix algebra routines such as this. 3552 See, e.g., `KSPCreate()`. 3553 3554 Level: developer 3555 3556 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3557 @*/ 3558 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3559 { 3560 PetscFunctionBegin; 3561 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3562 PetscValidType(mat, 1); 3563 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3564 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3565 PetscCheckSameComm(mat, 1, b, 2); 3566 PetscCheckSameComm(mat, 1, x, 3); 3567 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3568 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3569 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3570 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3571 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3572 MatCheckPreallocated(mat, 1); 3573 3574 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3575 if (mat->factorerrortype) { 3576 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3577 PetscCall(VecSetInf(x)); 3578 } else PetscUseTypeMethod(mat, solve, b, x); 3579 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3580 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3581 PetscFunctionReturn(0); 3582 } 3583 3584 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3585 { 3586 Vec b, x; 3587 PetscInt N, i; 3588 PetscErrorCode (*f)(Mat, Vec, Vec); 3589 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3590 3591 PetscFunctionBegin; 3592 if (A->factorerrortype) { 3593 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3594 PetscCall(MatSetInf(X)); 3595 PetscFunctionReturn(0); 3596 } 3597 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3598 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3599 PetscCall(MatBoundToCPU(A, &Abound)); 3600 if (!Abound) { 3601 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3602 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3603 } 3604 #if defined(PETSC_HAVE_CUDA) 3605 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3606 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3607 #elif (PETSC_HAVE_HIP) 3608 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3609 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3610 #endif 3611 PetscCall(MatGetSize(B, NULL, &N)); 3612 for (i = 0; i < N; i++) { 3613 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3614 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3615 PetscCall((*f)(A, b, x)); 3616 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3617 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3618 } 3619 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3620 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3621 PetscFunctionReturn(0); 3622 } 3623 3624 /*@ 3625 MatMatSolve - Solves A X = B, given a factored matrix. 3626 3627 Neighbor-wise Collective on A 3628 3629 Input Parameters: 3630 + A - the factored matrix 3631 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3632 3633 Output Parameter: 3634 . X - the result matrix (dense matrix) 3635 3636 Note: 3637 If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO; 3638 otherwise, B and X cannot be the same. 3639 3640 Level: developer 3641 3642 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3643 @*/ 3644 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3645 { 3646 PetscFunctionBegin; 3647 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3648 PetscValidType(A, 1); 3649 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3650 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3651 PetscCheckSameComm(A, 1, B, 2); 3652 PetscCheckSameComm(A, 1, X, 3); 3653 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3654 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3655 PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3656 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3657 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3658 MatCheckPreallocated(A, 1); 3659 3660 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3661 if (!A->ops->matsolve) { 3662 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3663 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3664 } else PetscUseTypeMethod(A, matsolve, B, X); 3665 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3666 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3667 PetscFunctionReturn(0); 3668 } 3669 3670 /*@ 3671 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3672 3673 Neighbor-wise Collective on A 3674 3675 Input Parameters: 3676 + A - the factored matrix 3677 - B - the right-hand-side matrix (`MATDENSE` matrix) 3678 3679 Output Parameter: 3680 . X - the result matrix (dense matrix) 3681 3682 Note: 3683 The matrices B and X cannot be the same. I.e., one cannot 3684 call `MatMatSolveTranspose`(A,X,X). 3685 3686 Level: developer 3687 3688 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3689 @*/ 3690 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3691 { 3692 PetscFunctionBegin; 3693 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3694 PetscValidType(A, 1); 3695 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3696 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3697 PetscCheckSameComm(A, 1, B, 2); 3698 PetscCheckSameComm(A, 1, X, 3); 3699 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3700 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3701 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3702 PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n); 3703 PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3704 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3705 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3706 MatCheckPreallocated(A, 1); 3707 3708 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3709 if (!A->ops->matsolvetranspose) { 3710 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3711 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3712 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3713 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3714 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3715 PetscFunctionReturn(0); 3716 } 3717 3718 /*@ 3719 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3720 3721 Neighbor-wise Collective on A 3722 3723 Input Parameters: 3724 + A - the factored matrix 3725 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3726 3727 Output Parameter: 3728 . X - the result matrix (dense matrix) 3729 3730 Note: 3731 For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row 3732 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3733 3734 Level: developer 3735 3736 .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3737 @*/ 3738 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3739 { 3740 PetscFunctionBegin; 3741 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3742 PetscValidType(A, 1); 3743 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3744 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3745 PetscCheckSameComm(A, 1, Bt, 2); 3746 PetscCheckSameComm(A, 1, X, 3); 3747 3748 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3749 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3750 PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N); 3751 PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix"); 3752 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3753 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3754 MatCheckPreallocated(A, 1); 3755 3756 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3757 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3758 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3759 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3760 PetscFunctionReturn(0); 3761 } 3762 3763 /*@ 3764 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3765 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3766 3767 Neighbor-wise Collective on mat 3768 3769 Input Parameters: 3770 + mat - the factored matrix 3771 - b - the right-hand-side vector 3772 3773 Output Parameter: 3774 . x - the result vector 3775 3776 Notes: 3777 `MatSolve()` should be used for most applications, as it performs 3778 a forward solve followed by a backward solve. 3779 3780 The vectors b and x cannot be the same, i.e., one cannot 3781 call `MatForwardSolve`(A,x,x). 3782 3783 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3784 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3785 `MatForwardSolve()` solves U^T*D y = b, and 3786 `MatBackwardSolve()` solves U x = y. 3787 Thus they do not provide a symmetric preconditioner. 3788 3789 Level: developer 3790 3791 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3792 @*/ 3793 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3794 { 3795 PetscFunctionBegin; 3796 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3797 PetscValidType(mat, 1); 3798 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3799 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3800 PetscCheckSameComm(mat, 1, b, 2); 3801 PetscCheckSameComm(mat, 1, x, 3); 3802 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3803 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3804 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3805 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3806 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3807 MatCheckPreallocated(mat, 1); 3808 3809 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3810 PetscUseTypeMethod(mat, forwardsolve, b, x); 3811 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3812 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3813 PetscFunctionReturn(0); 3814 } 3815 3816 /*@ 3817 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3818 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3819 3820 Neighbor-wise Collective on mat 3821 3822 Input Parameters: 3823 + mat - the factored matrix 3824 - b - the right-hand-side vector 3825 3826 Output Parameter: 3827 . x - the result vector 3828 3829 Notes: 3830 `MatSolve()` should be used for most applications, as it performs 3831 a forward solve followed by a backward solve. 3832 3833 The vectors b and x cannot be the same. I.e., one cannot 3834 call `MatBackwardSolve`(A,x,x). 3835 3836 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3837 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3838 `MatForwardSolve()` solves U^T*D y = b, and 3839 `MatBackwardSolve()` solves U x = y. 3840 Thus they do not provide a symmetric preconditioner. 3841 3842 Level: developer 3843 3844 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3845 @*/ 3846 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3847 { 3848 PetscFunctionBegin; 3849 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3850 PetscValidType(mat, 1); 3851 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3852 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3853 PetscCheckSameComm(mat, 1, b, 2); 3854 PetscCheckSameComm(mat, 1, x, 3); 3855 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3856 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3857 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3858 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3859 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3860 MatCheckPreallocated(mat, 1); 3861 3862 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3863 PetscUseTypeMethod(mat, backwardsolve, b, x); 3864 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3865 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3866 PetscFunctionReturn(0); 3867 } 3868 3869 /*@ 3870 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3871 3872 Neighbor-wise Collective on mat 3873 3874 Input Parameters: 3875 + mat - the factored matrix 3876 . b - the right-hand-side vector 3877 - y - the vector to be added to 3878 3879 Output Parameter: 3880 . x - the result vector 3881 3882 Note: 3883 The vectors b and x cannot be the same. I.e., one cannot 3884 call `MatSolveAdd`(A,x,y,x). 3885 3886 Level: developer 3887 3888 .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3889 @*/ 3890 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3891 { 3892 PetscScalar one = 1.0; 3893 Vec tmp; 3894 3895 PetscFunctionBegin; 3896 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3897 PetscValidType(mat, 1); 3898 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3899 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3900 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3901 PetscCheckSameComm(mat, 1, b, 2); 3902 PetscCheckSameComm(mat, 1, y, 3); 3903 PetscCheckSameComm(mat, 1, x, 4); 3904 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3905 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3906 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3907 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 3908 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3909 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 3910 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3911 MatCheckPreallocated(mat, 1); 3912 3913 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3914 if (mat->factorerrortype) { 3915 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3916 PetscCall(VecSetInf(x)); 3917 } else if (mat->ops->solveadd) { 3918 PetscUseTypeMethod(mat, solveadd, b, y, x); 3919 } else { 3920 /* do the solve then the add manually */ 3921 if (x != y) { 3922 PetscCall(MatSolve(mat, b, x)); 3923 PetscCall(VecAXPY(x, one, y)); 3924 } else { 3925 PetscCall(VecDuplicate(x, &tmp)); 3926 PetscCall(VecCopy(x, tmp)); 3927 PetscCall(MatSolve(mat, b, x)); 3928 PetscCall(VecAXPY(x, one, tmp)); 3929 PetscCall(VecDestroy(&tmp)); 3930 } 3931 } 3932 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3933 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3934 PetscFunctionReturn(0); 3935 } 3936 3937 /*@ 3938 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3939 3940 Neighbor-wise Collective on mat 3941 3942 Input Parameters: 3943 + mat - the factored matrix 3944 - b - the right-hand-side vector 3945 3946 Output Parameter: 3947 . x - the result vector 3948 3949 Notes: 3950 The vectors b and x cannot be the same. I.e., one cannot 3951 call `MatSolveTranspose`(A,x,x). 3952 3953 Most users should employ the `KSP` interface for linear solvers 3954 instead of working directly with matrix algebra routines such as this. 3955 See, e.g., `KSPCreate()`. 3956 3957 Level: developer 3958 3959 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3960 @*/ 3961 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3962 { 3963 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3964 3965 PetscFunctionBegin; 3966 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3967 PetscValidType(mat, 1); 3968 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3969 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3970 PetscCheckSameComm(mat, 1, b, 2); 3971 PetscCheckSameComm(mat, 1, x, 3); 3972 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3973 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 3974 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 3975 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3976 MatCheckPreallocated(mat, 1); 3977 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 3978 if (mat->factorerrortype) { 3979 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3980 PetscCall(VecSetInf(x)); 3981 } else { 3982 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 3983 PetscCall((*f)(mat, b, x)); 3984 } 3985 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 3986 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3987 PetscFunctionReturn(0); 3988 } 3989 3990 /*@ 3991 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 3992 factored matrix. 3993 3994 Neighbor-wise Collective on mat 3995 3996 Input Parameters: 3997 + mat - the factored matrix 3998 . b - the right-hand-side vector 3999 - y - the vector to be added to 4000 4001 Output Parameter: 4002 . x - the result vector 4003 4004 Note: 4005 The vectors b and x cannot be the same. I.e., one cannot 4006 call `MatSolveTransposeAdd`(A,x,y,x). 4007 4008 Level: developer 4009 4010 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4011 @*/ 4012 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4013 { 4014 PetscScalar one = 1.0; 4015 Vec tmp; 4016 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4017 4018 PetscFunctionBegin; 4019 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4020 PetscValidType(mat, 1); 4021 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4022 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4023 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4024 PetscCheckSameComm(mat, 1, b, 2); 4025 PetscCheckSameComm(mat, 1, y, 3); 4026 PetscCheckSameComm(mat, 1, x, 4); 4027 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4028 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4029 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4030 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 4031 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 4032 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 4033 MatCheckPreallocated(mat, 1); 4034 4035 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4036 if (mat->factorerrortype) { 4037 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4038 PetscCall(VecSetInf(x)); 4039 } else if (f) { 4040 PetscCall((*f)(mat, b, y, x)); 4041 } else { 4042 /* do the solve then the add manually */ 4043 if (x != y) { 4044 PetscCall(MatSolveTranspose(mat, b, x)); 4045 PetscCall(VecAXPY(x, one, y)); 4046 } else { 4047 PetscCall(VecDuplicate(x, &tmp)); 4048 PetscCall(VecCopy(x, tmp)); 4049 PetscCall(MatSolveTranspose(mat, b, x)); 4050 PetscCall(VecAXPY(x, one, tmp)); 4051 PetscCall(VecDestroy(&tmp)); 4052 } 4053 } 4054 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4055 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4056 PetscFunctionReturn(0); 4057 } 4058 /* ----------------------------------------------------------------*/ 4059 4060 /*@ 4061 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4062 4063 Neighbor-wise Collective on mat 4064 4065 Input Parameters: 4066 + mat - the matrix 4067 . b - the right hand side 4068 . omega - the relaxation factor 4069 . flag - flag indicating the type of SOR (see below) 4070 . shift - diagonal shift 4071 . its - the number of iterations 4072 - lits - the number of local iterations 4073 4074 Output Parameter: 4075 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4076 4077 SOR Flags: 4078 + `SOR_FORWARD_SWEEP` - forward SOR 4079 . `SOR_BACKWARD_SWEEP` - backward SOR 4080 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4081 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4082 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4083 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4084 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4085 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4086 upper/lower triangular part of matrix to 4087 vector (with omega) 4088 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4089 4090 Notes: 4091 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4092 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4093 on each processor. 4094 4095 Application programmers will not generally use `MatSOR()` directly, 4096 but instead will employ the `KSP`/`PC` interface. 4097 4098 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4099 4100 Most users should employ the `KSP` interface for linear solvers 4101 instead of working directly with matrix algebra routines such as this. 4102 See, e.g., `KSPCreate()`. 4103 4104 Vectors x and b CANNOT be the same 4105 4106 Notes for Advanced Users: 4107 The flags are implemented as bitwise inclusive or operations. 4108 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4109 to specify a zero initial guess for SSOR. 4110 4111 Developer Note: 4112 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4113 4114 Level: developer 4115 4116 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4117 @*/ 4118 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4119 { 4120 PetscFunctionBegin; 4121 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4122 PetscValidType(mat, 1); 4123 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4124 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4125 PetscCheckSameComm(mat, 1, b, 2); 4126 PetscCheckSameComm(mat, 1, x, 8); 4127 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4128 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4129 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 4130 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 4131 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 4132 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4133 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4134 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4135 4136 MatCheckPreallocated(mat, 1); 4137 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4138 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4139 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4140 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4141 PetscFunctionReturn(0); 4142 } 4143 4144 /* 4145 Default matrix copy routine. 4146 */ 4147 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4148 { 4149 PetscInt i, rstart = 0, rend = 0, nz; 4150 const PetscInt *cwork; 4151 const PetscScalar *vwork; 4152 4153 PetscFunctionBegin; 4154 if (B->assembled) PetscCall(MatZeroEntries(B)); 4155 if (str == SAME_NONZERO_PATTERN) { 4156 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4157 for (i = rstart; i < rend; i++) { 4158 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4159 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4160 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4161 } 4162 } else { 4163 PetscCall(MatAYPX(B, 0.0, A, str)); 4164 } 4165 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4166 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4167 PetscFunctionReturn(0); 4168 } 4169 4170 /*@ 4171 MatCopy - Copies a matrix to another matrix. 4172 4173 Collective on A 4174 4175 Input Parameters: 4176 + A - the matrix 4177 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4178 4179 Output Parameter: 4180 . B - where the copy is put 4181 4182 Notes: 4183 If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash. 4184 4185 `MatCopy()` copies the matrix entries of a matrix to another existing 4186 matrix (after first zeroing the second matrix). A related routine is 4187 `MatConvert()`, which first creates a new matrix and then copies the data. 4188 4189 Level: intermediate 4190 4191 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()` 4192 @*/ 4193 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4194 { 4195 PetscInt i; 4196 4197 PetscFunctionBegin; 4198 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4199 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4200 PetscValidType(A, 1); 4201 PetscValidType(B, 2); 4202 PetscCheckSameComm(A, 1, B, 2); 4203 MatCheckPreallocated(B, 2); 4204 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4205 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4206 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N, 4207 A->cmap->N, B->cmap->N); 4208 MatCheckPreallocated(A, 1); 4209 if (A == B) PetscFunctionReturn(0); 4210 4211 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4212 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4213 else PetscCall(MatCopy_Basic(A, B, str)); 4214 4215 B->stencil.dim = A->stencil.dim; 4216 B->stencil.noc = A->stencil.noc; 4217 for (i = 0; i <= A->stencil.dim; i++) { 4218 B->stencil.dims[i] = A->stencil.dims[i]; 4219 B->stencil.starts[i] = A->stencil.starts[i]; 4220 } 4221 4222 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4223 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4224 PetscFunctionReturn(0); 4225 } 4226 4227 /*@C 4228 MatConvert - Converts a matrix to another matrix, either of the same 4229 or different type. 4230 4231 Collective on mat 4232 4233 Input Parameters: 4234 + mat - the matrix 4235 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4236 same type as the original matrix. 4237 - reuse - denotes if the destination matrix is to be created or reused. 4238 Use `MAT_INPLACE_MATRIX` for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use 4239 `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` (can only be used after the first call was made with `MAT_INITIAL_MATRIX`, causes the matrix space in M to be reused). 4240 4241 Output Parameter: 4242 . M - pointer to place new matrix 4243 4244 Notes: 4245 `MatConvert()` first creates a new matrix and then copies the data from 4246 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4247 entries of one matrix to another already existing matrix context. 4248 4249 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4250 the MPI communicator of the generated matrix is always the same as the communicator 4251 of the input matrix. 4252 4253 Level: intermediate 4254 4255 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4256 @*/ 4257 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4258 { 4259 PetscBool sametype, issame, flg; 4260 PetscBool3 issymmetric, ishermitian; 4261 char convname[256], mtype[256]; 4262 Mat B; 4263 4264 PetscFunctionBegin; 4265 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4266 PetscValidType(mat, 1); 4267 PetscValidPointer(M, 4); 4268 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4269 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4270 MatCheckPreallocated(mat, 1); 4271 4272 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4273 if (flg) newtype = mtype; 4274 4275 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4276 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4277 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4278 PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4279 4280 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4281 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4282 PetscFunctionReturn(0); 4283 } 4284 4285 /* Cache Mat options because some converters use MatHeaderReplace */ 4286 issymmetric = mat->symmetric; 4287 ishermitian = mat->hermitian; 4288 4289 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4290 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4291 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4292 } else { 4293 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4294 const char *prefix[3] = {"seq", "mpi", ""}; 4295 PetscInt i; 4296 /* 4297 Order of precedence: 4298 0) See if newtype is a superclass of the current matrix. 4299 1) See if a specialized converter is known to the current matrix. 4300 2) See if a specialized converter is known to the desired matrix class. 4301 3) See if a good general converter is registered for the desired class 4302 (as of 6/27/03 only MATMPIADJ falls into this category). 4303 4) See if a good general converter is known for the current matrix. 4304 5) Use a really basic converter. 4305 */ 4306 4307 /* 0) See if newtype is a superclass of the current matrix. 4308 i.e mat is mpiaij and newtype is aij */ 4309 for (i = 0; i < 2; i++) { 4310 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4311 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4312 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4313 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4314 if (flg) { 4315 if (reuse == MAT_INPLACE_MATRIX) { 4316 PetscCall(PetscInfo(mat, "Early return\n")); 4317 PetscFunctionReturn(0); 4318 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4319 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4320 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4321 PetscFunctionReturn(0); 4322 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4323 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4324 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4325 PetscFunctionReturn(0); 4326 } 4327 } 4328 } 4329 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4330 for (i = 0; i < 3; i++) { 4331 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4332 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4333 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4334 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4335 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4336 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4337 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4338 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4339 if (conv) goto foundconv; 4340 } 4341 4342 /* 2) See if a specialized converter is known to the desired matrix class. */ 4343 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4344 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4345 PetscCall(MatSetType(B, newtype)); 4346 for (i = 0; i < 3; i++) { 4347 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4348 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4349 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4350 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4351 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4352 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4353 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4354 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4355 if (conv) { 4356 PetscCall(MatDestroy(&B)); 4357 goto foundconv; 4358 } 4359 } 4360 4361 /* 3) See if a good general converter is registered for the desired class */ 4362 conv = B->ops->convertfrom; 4363 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4364 PetscCall(MatDestroy(&B)); 4365 if (conv) goto foundconv; 4366 4367 /* 4) See if a good general converter is known for the current matrix */ 4368 if (mat->ops->convert) conv = mat->ops->convert; 4369 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4370 if (conv) goto foundconv; 4371 4372 /* 5) Use a really basic converter. */ 4373 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4374 conv = MatConvert_Basic; 4375 4376 foundconv: 4377 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4378 PetscCall((*conv)(mat, newtype, reuse, M)); 4379 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4380 /* the block sizes must be same if the mappings are copied over */ 4381 (*M)->rmap->bs = mat->rmap->bs; 4382 (*M)->cmap->bs = mat->cmap->bs; 4383 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4384 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4385 (*M)->rmap->mapping = mat->rmap->mapping; 4386 (*M)->cmap->mapping = mat->cmap->mapping; 4387 } 4388 (*M)->stencil.dim = mat->stencil.dim; 4389 (*M)->stencil.noc = mat->stencil.noc; 4390 for (i = 0; i <= mat->stencil.dim; i++) { 4391 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4392 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4393 } 4394 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4395 } 4396 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4397 4398 /* Copy Mat options */ 4399 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4400 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4401 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4402 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4403 PetscFunctionReturn(0); 4404 } 4405 4406 /*@C 4407 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4408 4409 Not Collective 4410 4411 Input Parameter: 4412 . mat - the matrix, must be a factored matrix 4413 4414 Output Parameter: 4415 . type - the string name of the package (do not free this string) 4416 4417 Note: 4418 In Fortran you pass in a empty string and the package name will be copied into it. 4419 (Make sure the string is long enough) 4420 4421 Level: intermediate 4422 4423 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4424 @*/ 4425 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4426 { 4427 PetscErrorCode (*conv)(Mat, MatSolverType *); 4428 4429 PetscFunctionBegin; 4430 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4431 PetscValidType(mat, 1); 4432 PetscValidPointer(type, 2); 4433 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4434 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4435 if (conv) PetscCall((*conv)(mat, type)); 4436 else *type = MATSOLVERPETSC; 4437 PetscFunctionReturn(0); 4438 } 4439 4440 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4441 struct _MatSolverTypeForSpecifcType { 4442 MatType mtype; 4443 /* no entry for MAT_FACTOR_NONE */ 4444 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4445 MatSolverTypeForSpecifcType next; 4446 }; 4447 4448 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4449 struct _MatSolverTypeHolder { 4450 char *name; 4451 MatSolverTypeForSpecifcType handlers; 4452 MatSolverTypeHolder next; 4453 }; 4454 4455 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4456 4457 /*@C 4458 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4459 4460 Input Parameters: 4461 + package - name of the package, for example petsc or superlu 4462 . mtype - the matrix type that works with this package 4463 . ftype - the type of factorization supported by the package 4464 - createfactor - routine that will create the factored matrix ready to be used 4465 4466 Level: developer 4467 4468 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4469 @*/ 4470 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4471 { 4472 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4473 PetscBool flg; 4474 MatSolverTypeForSpecifcType inext, iprev = NULL; 4475 4476 PetscFunctionBegin; 4477 PetscCall(MatInitializePackage()); 4478 if (!next) { 4479 PetscCall(PetscNew(&MatSolverTypeHolders)); 4480 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4481 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4482 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4483 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4484 PetscFunctionReturn(0); 4485 } 4486 while (next) { 4487 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4488 if (flg) { 4489 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4490 inext = next->handlers; 4491 while (inext) { 4492 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4493 if (flg) { 4494 inext->createfactor[(int)ftype - 1] = createfactor; 4495 PetscFunctionReturn(0); 4496 } 4497 iprev = inext; 4498 inext = inext->next; 4499 } 4500 PetscCall(PetscNew(&iprev->next)); 4501 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4502 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4503 PetscFunctionReturn(0); 4504 } 4505 prev = next; 4506 next = next->next; 4507 } 4508 PetscCall(PetscNew(&prev->next)); 4509 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4510 PetscCall(PetscNew(&prev->next->handlers)); 4511 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4512 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4513 PetscFunctionReturn(0); 4514 } 4515 4516 /*@C 4517 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4518 4519 Input Parameters: 4520 + type - name of the package, for example petsc or superlu 4521 . ftype - the type of factorization supported by the type 4522 - mtype - the matrix type that works with this type 4523 4524 Output Parameters: 4525 + foundtype - `PETSC_TRUE` if the type was registered 4526 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4527 - createfactor - routine that will create the factored matrix ready to be used or NULL if not found 4528 4529 Level: developer 4530 4531 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4532 @*/ 4533 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4534 { 4535 MatSolverTypeHolder next = MatSolverTypeHolders; 4536 PetscBool flg; 4537 MatSolverTypeForSpecifcType inext; 4538 4539 PetscFunctionBegin; 4540 if (foundtype) *foundtype = PETSC_FALSE; 4541 if (foundmtype) *foundmtype = PETSC_FALSE; 4542 if (createfactor) *createfactor = NULL; 4543 4544 if (type) { 4545 while (next) { 4546 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4547 if (flg) { 4548 if (foundtype) *foundtype = PETSC_TRUE; 4549 inext = next->handlers; 4550 while (inext) { 4551 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4552 if (flg) { 4553 if (foundmtype) *foundmtype = PETSC_TRUE; 4554 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4555 PetscFunctionReturn(0); 4556 } 4557 inext = inext->next; 4558 } 4559 } 4560 next = next->next; 4561 } 4562 } else { 4563 while (next) { 4564 inext = next->handlers; 4565 while (inext) { 4566 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4567 if (flg && inext->createfactor[(int)ftype - 1]) { 4568 if (foundtype) *foundtype = PETSC_TRUE; 4569 if (foundmtype) *foundmtype = PETSC_TRUE; 4570 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4571 PetscFunctionReturn(0); 4572 } 4573 inext = inext->next; 4574 } 4575 next = next->next; 4576 } 4577 /* try with base classes inext->mtype */ 4578 next = MatSolverTypeHolders; 4579 while (next) { 4580 inext = next->handlers; 4581 while (inext) { 4582 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4583 if (flg && inext->createfactor[(int)ftype - 1]) { 4584 if (foundtype) *foundtype = PETSC_TRUE; 4585 if (foundmtype) *foundmtype = PETSC_TRUE; 4586 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4587 PetscFunctionReturn(0); 4588 } 4589 inext = inext->next; 4590 } 4591 next = next->next; 4592 } 4593 } 4594 PetscFunctionReturn(0); 4595 } 4596 4597 PetscErrorCode MatSolverTypeDestroy(void) 4598 { 4599 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4600 MatSolverTypeForSpecifcType inext, iprev; 4601 4602 PetscFunctionBegin; 4603 while (next) { 4604 PetscCall(PetscFree(next->name)); 4605 inext = next->handlers; 4606 while (inext) { 4607 PetscCall(PetscFree(inext->mtype)); 4608 iprev = inext; 4609 inext = inext->next; 4610 PetscCall(PetscFree(iprev)); 4611 } 4612 prev = next; 4613 next = next->next; 4614 PetscCall(PetscFree(prev)); 4615 } 4616 MatSolverTypeHolders = NULL; 4617 PetscFunctionReturn(0); 4618 } 4619 4620 /*@C 4621 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4622 4623 Logically Collective on mat 4624 4625 Input Parameters: 4626 . mat - the matrix 4627 4628 Output Parameters: 4629 . flg - `PETSC_TRUE` if uses the ordering 4630 4631 Note: 4632 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4633 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4634 4635 Level: developer 4636 4637 .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4638 @*/ 4639 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4640 { 4641 PetscFunctionBegin; 4642 *flg = mat->canuseordering; 4643 PetscFunctionReturn(0); 4644 } 4645 4646 /*@C 4647 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4648 4649 Logically Collective on mat 4650 4651 Input Parameters: 4652 . mat - the matrix obtained with `MatGetFactor()` 4653 4654 Output Parameters: 4655 . otype - the preferred type 4656 4657 Level: developer 4658 4659 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4660 @*/ 4661 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4662 { 4663 PetscFunctionBegin; 4664 *otype = mat->preferredordering[ftype]; 4665 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4666 PetscFunctionReturn(0); 4667 } 4668 4669 /*@C 4670 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4671 4672 Collective on mat 4673 4674 Input Parameters: 4675 + mat - the matrix 4676 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4677 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4678 4679 Output Parameters: 4680 . f - the factor matrix used with MatXXFactorSymbolic() calls 4681 4682 Options Database Key: 4683 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4684 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4685 4686 Notes: 4687 Users usually access the factorization solvers via `KSP` 4688 4689 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4690 such as pastix, superlu, mumps etc. 4691 4692 PETSc must have been ./configure to use the external solver, using the option --download-package 4693 4694 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4695 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4696 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4697 4698 Developer Note: 4699 This should actually be called `MatCreateFactor()` since it creates a new factor object 4700 4701 Level: intermediate 4702 4703 .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4704 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4705 @*/ 4706 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4707 { 4708 PetscBool foundtype, foundmtype; 4709 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4710 4711 PetscFunctionBegin; 4712 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4713 PetscValidType(mat, 1); 4714 4715 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4716 MatCheckPreallocated(mat, 1); 4717 4718 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4719 if (!foundtype) { 4720 if (type) { 4721 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate solver type %s for factorization type %s and matrix type %s. Perhaps you must ./configure with --download-%s", type, MatFactorTypes[ftype], 4722 ((PetscObject)mat)->type_name, type); 4723 } else { 4724 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate a solver type for factorization type %s and matrix type %s.", MatFactorTypes[ftype], ((PetscObject)mat)->type_name); 4725 } 4726 } 4727 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4728 PetscCheck(conv, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support factorization type %s for matrix type %s", type, MatFactorTypes[ftype], ((PetscObject)mat)->type_name); 4729 4730 PetscCall((*conv)(mat, ftype, f)); 4731 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4732 PetscFunctionReturn(0); 4733 } 4734 4735 /*@C 4736 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4737 4738 Not Collective 4739 4740 Input Parameters: 4741 + mat - the matrix 4742 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4743 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4744 4745 Output Parameter: 4746 . flg - PETSC_TRUE if the factorization is available 4747 4748 Notes: 4749 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4750 such as pastix, superlu, mumps etc. 4751 4752 PETSc must have been ./configure to use the external solver, using the option --download-package 4753 4754 Developer Note: 4755 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4756 4757 Level: intermediate 4758 4759 .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4760 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4761 @*/ 4762 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4763 { 4764 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4765 4766 PetscFunctionBegin; 4767 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4768 PetscValidType(mat, 1); 4769 PetscValidBoolPointer(flg, 4); 4770 4771 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4772 MatCheckPreallocated(mat, 1); 4773 4774 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4775 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4776 PetscFunctionReturn(0); 4777 } 4778 4779 /*@ 4780 MatDuplicate - Duplicates a matrix including the non-zero structure. 4781 4782 Collective on mat 4783 4784 Input Parameters: 4785 + mat - the matrix 4786 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4787 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4788 4789 Output Parameter: 4790 . M - pointer to place new matrix 4791 4792 Level: intermediate 4793 4794 Notes: 4795 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4796 4797 May be called with an unassembled input `Mat` if `MAT_DO_NOT_COPY_VALUES` is used, in which case the output `Mat` is unassembled as well. 4798 4799 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the simple matrix data structure of mat 4800 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4801 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4802 4803 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4804 @*/ 4805 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4806 { 4807 Mat B; 4808 VecType vtype; 4809 PetscInt i; 4810 PetscObject dm; 4811 void (*viewf)(void); 4812 4813 PetscFunctionBegin; 4814 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4815 PetscValidType(mat, 1); 4816 PetscValidPointer(M, 3); 4817 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4818 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4819 MatCheckPreallocated(mat, 1); 4820 4821 *M = NULL; 4822 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4823 PetscUseTypeMethod(mat, duplicate, op, M); 4824 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4825 B = *M; 4826 4827 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4828 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4829 PetscCall(MatGetVecType(mat, &vtype)); 4830 PetscCall(MatSetVecType(B, vtype)); 4831 4832 B->stencil.dim = mat->stencil.dim; 4833 B->stencil.noc = mat->stencil.noc; 4834 for (i = 0; i <= mat->stencil.dim; i++) { 4835 B->stencil.dims[i] = mat->stencil.dims[i]; 4836 B->stencil.starts[i] = mat->stencil.starts[i]; 4837 } 4838 4839 B->nooffproczerorows = mat->nooffproczerorows; 4840 B->nooffprocentries = mat->nooffprocentries; 4841 4842 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4843 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4844 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4845 PetscFunctionReturn(0); 4846 } 4847 4848 /*@ 4849 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4850 4851 Logically Collective on mat 4852 4853 Input Parameters: 4854 + mat - the matrix 4855 - v - the vector for storing the diagonal 4856 4857 Output Parameter: 4858 . v - the diagonal of the matrix 4859 4860 Level: intermediate 4861 4862 Note: 4863 Currently only correct in parallel for square matrices. 4864 4865 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4866 @*/ 4867 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4868 { 4869 PetscFunctionBegin; 4870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4871 PetscValidType(mat, 1); 4872 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4873 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4874 MatCheckPreallocated(mat, 1); 4875 4876 PetscUseTypeMethod(mat, getdiagonal, v); 4877 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4878 PetscFunctionReturn(0); 4879 } 4880 4881 /*@C 4882 MatGetRowMin - Gets the minimum value (of the real part) of each 4883 row of the matrix 4884 4885 Logically Collective on mat 4886 4887 Input Parameter: 4888 . mat - the matrix 4889 4890 Output Parameters: 4891 + v - the vector for storing the maximums 4892 - idx - the indices of the column found for each row (optional) 4893 4894 Level: intermediate 4895 4896 Note: 4897 The result of this call are the same as if one converted the matrix to dense format 4898 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4899 4900 This code is only implemented for a couple of matrix formats. 4901 4902 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4903 `MatGetRowMax()` 4904 @*/ 4905 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4906 { 4907 PetscFunctionBegin; 4908 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4909 PetscValidType(mat, 1); 4910 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4911 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4912 4913 if (!mat->cmap->N) { 4914 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4915 if (idx) { 4916 PetscInt i, m = mat->rmap->n; 4917 for (i = 0; i < m; i++) idx[i] = -1; 4918 } 4919 } else { 4920 MatCheckPreallocated(mat, 1); 4921 } 4922 PetscUseTypeMethod(mat, getrowmin, v, idx); 4923 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4924 PetscFunctionReturn(0); 4925 } 4926 4927 /*@C 4928 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4929 row of the matrix 4930 4931 Logically Collective on mat 4932 4933 Input Parameter: 4934 . mat - the matrix 4935 4936 Output Parameters: 4937 + v - the vector for storing the minimums 4938 - idx - the indices of the column found for each row (or NULL if not needed) 4939 4940 Level: intermediate 4941 4942 Notes: 4943 if a row is completely empty or has only 0.0 values then the idx[] value for that 4944 row is 0 (the first column). 4945 4946 This code is only implemented for a couple of matrix formats. 4947 4948 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4949 @*/ 4950 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4951 { 4952 PetscFunctionBegin; 4953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4954 PetscValidType(mat, 1); 4955 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4956 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4957 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4958 4959 if (!mat->cmap->N) { 4960 PetscCall(VecSet(v, 0.0)); 4961 if (idx) { 4962 PetscInt i, m = mat->rmap->n; 4963 for (i = 0; i < m; i++) idx[i] = -1; 4964 } 4965 } else { 4966 MatCheckPreallocated(mat, 1); 4967 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4968 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4969 } 4970 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4971 PetscFunctionReturn(0); 4972 } 4973 4974 /*@C 4975 MatGetRowMax - Gets the maximum value (of the real part) of each 4976 row of the matrix 4977 4978 Logically Collective on mat 4979 4980 Input Parameter: 4981 . mat - the matrix 4982 4983 Output Parameters: 4984 + v - the vector for storing the maximums 4985 - idx - the indices of the column found for each row (optional) 4986 4987 Level: intermediate 4988 4989 Notes: 4990 The result of this call are the same as if one converted the matrix to dense format 4991 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4992 4993 This code is only implemented for a couple of matrix formats. 4994 4995 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 4996 @*/ 4997 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 4998 { 4999 PetscFunctionBegin; 5000 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5001 PetscValidType(mat, 1); 5002 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5003 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5004 5005 if (!mat->cmap->N) { 5006 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5007 if (idx) { 5008 PetscInt i, m = mat->rmap->n; 5009 for (i = 0; i < m; i++) idx[i] = -1; 5010 } 5011 } else { 5012 MatCheckPreallocated(mat, 1); 5013 PetscUseTypeMethod(mat, getrowmax, v, idx); 5014 } 5015 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5016 PetscFunctionReturn(0); 5017 } 5018 5019 /*@C 5020 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5021 row of the matrix 5022 5023 Logically Collective on mat 5024 5025 Input Parameter: 5026 . mat - the matrix 5027 5028 Output Parameters: 5029 + v - the vector for storing the maximums 5030 - idx - the indices of the column found for each row (or NULL if not needed) 5031 5032 Level: intermediate 5033 5034 Notes: 5035 if a row is completely empty or has only 0.0 values then the idx[] value for that 5036 row is 0 (the first column). 5037 5038 This code is only implemented for a couple of matrix formats. 5039 5040 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5041 @*/ 5042 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5043 { 5044 PetscFunctionBegin; 5045 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5046 PetscValidType(mat, 1); 5047 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5048 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5049 5050 if (!mat->cmap->N) { 5051 PetscCall(VecSet(v, 0.0)); 5052 if (idx) { 5053 PetscInt i, m = mat->rmap->n; 5054 for (i = 0; i < m; i++) idx[i] = -1; 5055 } 5056 } else { 5057 MatCheckPreallocated(mat, 1); 5058 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5059 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5060 } 5061 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5062 PetscFunctionReturn(0); 5063 } 5064 5065 /*@ 5066 MatGetRowSum - Gets the sum of each row of the matrix 5067 5068 Logically or Neighborhood Collective on mat 5069 5070 Input Parameters: 5071 . mat - the matrix 5072 5073 Output Parameter: 5074 . v - the vector for storing the sum of rows 5075 5076 Level: intermediate 5077 5078 Notes: 5079 This code is slow since it is not currently specialized for different formats 5080 5081 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5082 @*/ 5083 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5084 { 5085 Vec ones; 5086 5087 PetscFunctionBegin; 5088 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5089 PetscValidType(mat, 1); 5090 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5091 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5092 MatCheckPreallocated(mat, 1); 5093 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5094 PetscCall(VecSet(ones, 1.)); 5095 PetscCall(MatMult(mat, ones, v)); 5096 PetscCall(VecDestroy(&ones)); 5097 PetscFunctionReturn(0); 5098 } 5099 5100 /*@ 5101 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5102 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5103 5104 Collective on mat 5105 5106 Input Parameter: 5107 . mat - the matrix to provide the transpose 5108 5109 Output Parameter: 5110 . mat - the matrix to contain the transpose; it MUST have the nonzero structure of the transpose of A or the code will crash or generate incorrect results 5111 5112 Level: advanced 5113 5114 Note: 5115 Normally he use of `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) requires that B was obtained with a call to `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B). This 5116 routine allows bypassing that call. 5117 5118 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5119 @*/ 5120 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5121 { 5122 PetscContainer rB = NULL; 5123 MatParentState *rb = NULL; 5124 5125 PetscFunctionBegin; 5126 PetscCall(PetscNew(&rb)); 5127 rb->id = ((PetscObject)mat)->id; 5128 rb->state = 0; 5129 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5130 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5131 PetscCall(PetscContainerSetPointer(rB, rb)); 5132 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5133 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5134 PetscCall(PetscObjectDereference((PetscObject)rB)); 5135 PetscFunctionReturn(0); 5136 } 5137 5138 /*@ 5139 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5140 5141 Collective on mat 5142 5143 Input Parameters: 5144 + mat - the matrix to transpose 5145 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5146 5147 Output Parameter: 5148 . B - the transpose 5149 5150 Notes: 5151 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5152 5153 `MAT_REUSE_MATRIX` uses the B matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the 5154 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5155 5156 If the nonzero structure of mat changed from the previous call to this function with the same matrices an error will be generated for some matrix types. 5157 5158 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5159 5160 If mat is unchanged from the last call this function returns immediately without recomputing the result 5161 5162 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5163 5164 Level: intermediate 5165 5166 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5167 `MatTransposeSymbolic()` 5168 @*/ 5169 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5170 { 5171 PetscContainer rB = NULL; 5172 MatParentState *rb = NULL; 5173 5174 PetscFunctionBegin; 5175 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5176 PetscValidType(mat, 1); 5177 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5178 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5179 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5180 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5181 MatCheckPreallocated(mat, 1); 5182 if (reuse == MAT_REUSE_MATRIX) { 5183 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5184 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5185 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5186 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5187 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0); 5188 } 5189 5190 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5191 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5192 PetscUseTypeMethod(mat, transpose, reuse, B); 5193 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5194 } 5195 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5196 5197 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5198 if (reuse != MAT_INPLACE_MATRIX) { 5199 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5200 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5201 rb->state = ((PetscObject)mat)->state; 5202 rb->nonzerostate = mat->nonzerostate; 5203 } 5204 PetscFunctionReturn(0); 5205 } 5206 5207 /*@ 5208 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5209 5210 Collective on A 5211 5212 Input Parameters: 5213 . A - the matrix to transpose 5214 5215 Output Parameter: 5216 . B - the transpose. This is a complete matrix but the numerical portion is invalid. One can call `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) to compute the 5217 numerical portion. 5218 5219 Level: intermediate 5220 5221 Note: 5222 This is not supported for many matrix types, use `MatTranspose()` in those cases 5223 5224 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5225 @*/ 5226 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5227 { 5228 PetscFunctionBegin; 5229 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5230 PetscValidType(A, 1); 5231 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5232 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5233 PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 5234 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5235 PetscCall((*A->ops->transposesymbolic)(A, B)); 5236 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5237 5238 PetscCall(MatTransposeSetPrecursor(A, *B)); 5239 PetscFunctionReturn(0); 5240 } 5241 5242 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5243 { 5244 PetscContainer rB; 5245 MatParentState *rb; 5246 5247 PetscFunctionBegin; 5248 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5249 PetscValidType(A, 1); 5250 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5251 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5252 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5253 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5254 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5255 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5256 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5257 PetscFunctionReturn(0); 5258 } 5259 5260 /*@ 5261 MatIsTranspose - Test whether a matrix is another one's transpose, 5262 or its own, in which case it tests symmetry. 5263 5264 Collective on A 5265 5266 Input Parameters: 5267 + A - the matrix to test 5268 - B - the matrix to test against, this can equal the first parameter 5269 5270 Output Parameters: 5271 . flg - the result 5272 5273 Notes: 5274 Only available for `MATAIJ` matrices. 5275 5276 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5277 test involves parallel copies of the block-offdiagonal parts of the matrix. 5278 5279 Level: intermediate 5280 5281 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5282 @*/ 5283 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5284 { 5285 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5286 5287 PetscFunctionBegin; 5288 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5289 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5290 PetscValidBoolPointer(flg, 4); 5291 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5292 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5293 *flg = PETSC_FALSE; 5294 if (f && g) { 5295 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5296 PetscCall((*f)(A, B, tol, flg)); 5297 } else { 5298 MatType mattype; 5299 5300 PetscCall(MatGetType(f ? B : A, &mattype)); 5301 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5302 } 5303 PetscFunctionReturn(0); 5304 } 5305 5306 /*@ 5307 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5308 5309 Collective on mat 5310 5311 Input Parameters: 5312 + mat - the matrix to transpose and complex conjugate 5313 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5314 5315 Output Parameter: 5316 . B - the Hermitian transpose 5317 5318 Level: intermediate 5319 5320 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5321 @*/ 5322 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5323 { 5324 PetscFunctionBegin; 5325 PetscCall(MatTranspose(mat, reuse, B)); 5326 #if defined(PETSC_USE_COMPLEX) 5327 PetscCall(MatConjugate(*B)); 5328 #endif 5329 PetscFunctionReturn(0); 5330 } 5331 5332 /*@ 5333 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5334 5335 Collective on A 5336 5337 Input Parameters: 5338 + A - the matrix to test 5339 - B - the matrix to test against, this can equal the first parameter 5340 5341 Output Parameters: 5342 . flg - the result 5343 5344 Notes: 5345 Only available for `MATAIJ` matrices. 5346 5347 The sequential algorithm 5348 has a running time of the order of the number of nonzeros; the parallel 5349 test involves parallel copies of the block-offdiagonal parts of the matrix. 5350 5351 Level: intermediate 5352 5353 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5354 @*/ 5355 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5356 { 5357 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5358 5359 PetscFunctionBegin; 5360 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5361 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5362 PetscValidBoolPointer(flg, 4); 5363 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5364 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5365 if (f && g) { 5366 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5367 PetscCall((*f)(A, B, tol, flg)); 5368 } 5369 PetscFunctionReturn(0); 5370 } 5371 5372 /*@ 5373 MatPermute - Creates a new matrix with rows and columns permuted from the 5374 original. 5375 5376 Collective on mat 5377 5378 Input Parameters: 5379 + mat - the matrix to permute 5380 . row - row permutation, each processor supplies only the permutation for its rows 5381 - col - column permutation, each processor supplies only the permutation for its columns 5382 5383 Output Parameters: 5384 . B - the permuted matrix 5385 5386 Level: advanced 5387 5388 Note: 5389 The index sets map from row/col of permuted matrix to row/col of original matrix. 5390 The index sets should be on the same communicator as mat and have the same local sizes. 5391 5392 Developer Note: 5393 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5394 exploit the fact that row and col are permutations, consider implementing the 5395 more general `MatCreateSubMatrix()` instead. 5396 5397 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5398 @*/ 5399 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5400 { 5401 PetscFunctionBegin; 5402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5403 PetscValidType(mat, 1); 5404 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5405 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5406 PetscValidPointer(B, 4); 5407 PetscCheckSameComm(mat, 1, row, 2); 5408 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5409 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5410 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5411 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5412 MatCheckPreallocated(mat, 1); 5413 5414 if (mat->ops->permute) { 5415 PetscUseTypeMethod(mat, permute, row, col, B); 5416 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5417 } else { 5418 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5419 } 5420 PetscFunctionReturn(0); 5421 } 5422 5423 /*@ 5424 MatEqual - Compares two matrices. 5425 5426 Collective on A 5427 5428 Input Parameters: 5429 + A - the first matrix 5430 - B - the second matrix 5431 5432 Output Parameter: 5433 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5434 5435 Level: intermediate 5436 5437 .seealso: `Mat` 5438 @*/ 5439 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5440 { 5441 PetscFunctionBegin; 5442 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5443 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5444 PetscValidType(A, 1); 5445 PetscValidType(B, 2); 5446 PetscValidBoolPointer(flg, 3); 5447 PetscCheckSameComm(A, 1, B, 2); 5448 MatCheckPreallocated(A, 1); 5449 MatCheckPreallocated(B, 2); 5450 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5451 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5452 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N, 5453 B->cmap->N); 5454 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5455 PetscUseTypeMethod(A, equal, B, flg); 5456 } else { 5457 PetscCall(MatMultEqual(A, B, 10, flg)); 5458 } 5459 PetscFunctionReturn(0); 5460 } 5461 5462 /*@ 5463 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5464 matrices that are stored as vectors. Either of the two scaling 5465 matrices can be NULL. 5466 5467 Collective on mat 5468 5469 Input Parameters: 5470 + mat - the matrix to be scaled 5471 . l - the left scaling vector (or NULL) 5472 - r - the right scaling vector (or NULL) 5473 5474 Note: 5475 `MatDiagonalScale()` computes A = LAR, where 5476 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5477 The L scales the rows of the matrix, the R scales the columns of the matrix. 5478 5479 Level: intermediate 5480 5481 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5482 @*/ 5483 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5484 { 5485 PetscFunctionBegin; 5486 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5487 PetscValidType(mat, 1); 5488 if (l) { 5489 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5490 PetscCheckSameComm(mat, 1, l, 2); 5491 } 5492 if (r) { 5493 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5494 PetscCheckSameComm(mat, 1, r, 3); 5495 } 5496 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5497 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5498 MatCheckPreallocated(mat, 1); 5499 if (!l && !r) PetscFunctionReturn(0); 5500 5501 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5502 PetscUseTypeMethod(mat, diagonalscale, l, r); 5503 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5504 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5505 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5506 PetscFunctionReturn(0); 5507 } 5508 5509 /*@ 5510 MatScale - Scales all elements of a matrix by a given number. 5511 5512 Logically Collective on mat 5513 5514 Input Parameters: 5515 + mat - the matrix to be scaled 5516 - a - the scaling value 5517 5518 Output Parameter: 5519 . mat - the scaled matrix 5520 5521 Level: intermediate 5522 5523 .seealso: `Mat`, `MatDiagonalScale()` 5524 @*/ 5525 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5526 { 5527 PetscFunctionBegin; 5528 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5529 PetscValidType(mat, 1); 5530 PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 5531 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5532 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5533 PetscValidLogicalCollectiveScalar(mat, a, 2); 5534 MatCheckPreallocated(mat, 1); 5535 5536 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5537 if (a != (PetscScalar)1.0) { 5538 PetscUseTypeMethod(mat, scale, a); 5539 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5540 } 5541 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5542 PetscFunctionReturn(0); 5543 } 5544 5545 /*@ 5546 MatNorm - Calculates various norms of a matrix. 5547 5548 Collective on mat 5549 5550 Input Parameters: 5551 + mat - the matrix 5552 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5553 5554 Output Parameter: 5555 . nrm - the resulting norm 5556 5557 Level: intermediate 5558 5559 .seealso: `Mat` 5560 @*/ 5561 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5562 { 5563 PetscFunctionBegin; 5564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5565 PetscValidType(mat, 1); 5566 PetscValidRealPointer(nrm, 3); 5567 5568 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5569 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5570 MatCheckPreallocated(mat, 1); 5571 5572 PetscUseTypeMethod(mat, norm, type, nrm); 5573 PetscFunctionReturn(0); 5574 } 5575 5576 /* 5577 This variable is used to prevent counting of MatAssemblyBegin() that 5578 are called from within a MatAssemblyEnd(). 5579 */ 5580 static PetscInt MatAssemblyEnd_InUse = 0; 5581 /*@ 5582 MatAssemblyBegin - Begins assembling the matrix. This routine should 5583 be called after completing all calls to `MatSetValues()`. 5584 5585 Collective on mat 5586 5587 Input Parameters: 5588 + mat - the matrix 5589 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5590 5591 Notes: 5592 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5593 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5594 5595 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5596 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5597 using the matrix. 5598 5599 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5600 same flag of `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` for all processes. Thus you CANNOT locally change from `ADD_VALUES` to `INSERT_VALUES`, that is 5601 a global collective operation requiring all processes that share the matrix. 5602 5603 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5604 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5605 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5606 5607 Level: beginner 5608 5609 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5610 @*/ 5611 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5612 { 5613 PetscFunctionBegin; 5614 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5615 PetscValidType(mat, 1); 5616 MatCheckPreallocated(mat, 1); 5617 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5618 if (mat->assembled) { 5619 mat->was_assembled = PETSC_TRUE; 5620 mat->assembled = PETSC_FALSE; 5621 } 5622 5623 if (!MatAssemblyEnd_InUse) { 5624 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5625 PetscTryTypeMethod(mat, assemblybegin, type); 5626 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5627 } else PetscTryTypeMethod(mat, assemblybegin, type); 5628 PetscFunctionReturn(0); 5629 } 5630 5631 /*@ 5632 MatAssembled - Indicates if a matrix has been assembled and is ready for 5633 use; for example, in matrix-vector product. 5634 5635 Not Collective 5636 5637 Input Parameter: 5638 . mat - the matrix 5639 5640 Output Parameter: 5641 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5642 5643 Level: advanced 5644 5645 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5646 @*/ 5647 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5648 { 5649 PetscFunctionBegin; 5650 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5651 PetscValidBoolPointer(assembled, 2); 5652 *assembled = mat->assembled; 5653 PetscFunctionReturn(0); 5654 } 5655 5656 /*@ 5657 MatAssemblyEnd - Completes assembling the matrix. This routine should 5658 be called after `MatAssemblyBegin()`. 5659 5660 Collective on Mat 5661 5662 Input Parameters: 5663 + mat - the matrix 5664 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5665 5666 Options Database Keys: 5667 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5668 . -mat_view ::ascii_info_detail - Prints more detailed info 5669 . -mat_view - Prints matrix in ASCII format 5670 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5671 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5672 . -display <name> - Sets display name (default is host) 5673 . -draw_pause <sec> - Sets number of seconds to pause after display 5674 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5675 . -viewer_socket_machine <machine> - Machine to use for socket 5676 . -viewer_socket_port <port> - Port number to use for socket 5677 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5678 5679 Level: beginner 5680 5681 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5682 @*/ 5683 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5684 { 5685 static PetscInt inassm = 0; 5686 PetscBool flg = PETSC_FALSE; 5687 5688 PetscFunctionBegin; 5689 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5690 PetscValidType(mat, 1); 5691 5692 inassm++; 5693 MatAssemblyEnd_InUse++; 5694 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5695 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5696 PetscTryTypeMethod(mat, assemblyend, type); 5697 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5698 } else PetscTryTypeMethod(mat, assemblyend, type); 5699 5700 /* Flush assembly is not a true assembly */ 5701 if (type != MAT_FLUSH_ASSEMBLY) { 5702 if (mat->num_ass) { 5703 if (!mat->symmetry_eternal) { 5704 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5705 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5706 } 5707 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5708 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5709 } 5710 mat->num_ass++; 5711 mat->assembled = PETSC_TRUE; 5712 mat->ass_nonzerostate = mat->nonzerostate; 5713 } 5714 5715 mat->insertmode = NOT_SET_VALUES; 5716 MatAssemblyEnd_InUse--; 5717 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5718 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5719 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5720 5721 if (mat->checksymmetryonassembly) { 5722 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5723 if (flg) { 5724 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5725 } else { 5726 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5727 } 5728 } 5729 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5730 } 5731 inassm--; 5732 PetscFunctionReturn(0); 5733 } 5734 5735 /*@ 5736 MatSetOption - Sets a parameter option for a matrix. Some options 5737 may be specific to certain storage formats. Some options 5738 determine how values will be inserted (or added). Sorted, 5739 row-oriented input will generally assemble the fastest. The default 5740 is row-oriented. 5741 5742 Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5743 5744 Input Parameters: 5745 + mat - the matrix 5746 . option - the option, one of those listed below (and possibly others), 5747 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5748 5749 Options Describing Matrix Structure: 5750 + `MAT_SPD` - symmetric positive definite 5751 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5752 . `MAT_HERMITIAN` - transpose is the complex conjugation 5753 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5754 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5755 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5756 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5757 5758 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5759 do not need to be computed (usually at a high cost) 5760 5761 Options For Use with `MatSetValues()`: 5762 Insert a logically dense subblock, which can be 5763 . `MAT_ROW_ORIENTED` - row-oriented (default) 5764 5765 Note these options reflect the data you pass in with `MatSetValues()`; it has 5766 nothing to do with how the data is stored internally in the matrix 5767 data structure. 5768 5769 When (re)assembling a matrix, we can restrict the input for 5770 efficiency/debugging purposes. These options include 5771 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5772 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5773 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5774 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5775 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5776 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5777 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5778 performance for very large process counts. 5779 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5780 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5781 functions, instead sending only neighbor messages. 5782 5783 Notes: 5784 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5785 5786 Some options are relevant only for particular matrix types and 5787 are thus ignored by others. Other options are not supported by 5788 certain matrix types and will generate an error message if set. 5789 5790 If using a Fortran 77 module to compute a matrix, one may need to 5791 use the column-oriented option (or convert to the row-oriented 5792 format). 5793 5794 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5795 that would generate a new entry in the nonzero structure is instead 5796 ignored. Thus, if memory has not alredy been allocated for this particular 5797 data, then the insertion is ignored. For dense matrices, in which 5798 the entire array is allocated, no entries are ever ignored. 5799 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5800 5801 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5802 that would generate a new entry in the nonzero structure instead produces 5803 an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats only.) If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5804 5805 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5806 that would generate a new entry that has not been preallocated will 5807 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5808 only.) This is a useful flag when debugging matrix memory preallocation. 5809 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5810 5811 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5812 other processors should be dropped, rather than stashed. 5813 This is useful if you know that the "owning" processor is also 5814 always generating the correct matrix entries, so that PETSc need 5815 not transfer duplicate entries generated on another processor. 5816 5817 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5818 searches during matrix assembly. When this flag is set, the hash table 5819 is created during the first matrix assembly. This hash table is 5820 used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()` 5821 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5822 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5823 supported by` MATMPIBAIJ` format only. 5824 5825 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5826 are kept in the nonzero structure 5827 5828 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5829 a zero location in the matrix 5830 5831 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5832 5833 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5834 zero row routines and thus improves performance for very large process counts. 5835 5836 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5837 part of the matrix (since they should match the upper triangular part). 5838 5839 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5840 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5841 with finite difference schemes with non-periodic boundary conditions. 5842 5843 Developer Note: 5844 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5845 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5846 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5847 not changed. 5848 5849 Level: intermediate 5850 5851 .seealso: `MatOption`, `Mat`, `MatGetOption()` 5852 @*/ 5853 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5854 { 5855 PetscFunctionBegin; 5856 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5857 if (op > 0) { 5858 PetscValidLogicalCollectiveEnum(mat, op, 2); 5859 PetscValidLogicalCollectiveBool(mat, flg, 3); 5860 } 5861 5862 PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op); 5863 5864 switch (op) { 5865 case MAT_FORCE_DIAGONAL_ENTRIES: 5866 mat->force_diagonals = flg; 5867 PetscFunctionReturn(0); 5868 case MAT_NO_OFF_PROC_ENTRIES: 5869 mat->nooffprocentries = flg; 5870 PetscFunctionReturn(0); 5871 case MAT_SUBSET_OFF_PROC_ENTRIES: 5872 mat->assembly_subset = flg; 5873 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5874 #if !defined(PETSC_HAVE_MPIUNI) 5875 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5876 #endif 5877 mat->stash.first_assembly_done = PETSC_FALSE; 5878 } 5879 PetscFunctionReturn(0); 5880 case MAT_NO_OFF_PROC_ZERO_ROWS: 5881 mat->nooffproczerorows = flg; 5882 PetscFunctionReturn(0); 5883 case MAT_SPD: 5884 if (flg) { 5885 mat->spd = PETSC_BOOL3_TRUE; 5886 mat->symmetric = PETSC_BOOL3_TRUE; 5887 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5888 } else { 5889 mat->spd = PETSC_BOOL3_FALSE; 5890 } 5891 break; 5892 case MAT_SYMMETRIC: 5893 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5894 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5895 #if !defined(PETSC_USE_COMPLEX) 5896 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5897 #endif 5898 break; 5899 case MAT_HERMITIAN: 5900 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5901 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5902 #if !defined(PETSC_USE_COMPLEX) 5903 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5904 #endif 5905 break; 5906 case MAT_STRUCTURALLY_SYMMETRIC: 5907 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5908 break; 5909 case MAT_SYMMETRY_ETERNAL: 5910 PetscCheck(mat->symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SYMMETRY_ETERNAL without first setting MAT_SYMMETRIC to true or false"); 5911 mat->symmetry_eternal = flg; 5912 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5913 break; 5914 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5915 PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURAL_SYMMETRIC to true or false"); 5916 mat->structural_symmetry_eternal = flg; 5917 break; 5918 case MAT_SPD_ETERNAL: 5919 PetscCheck(mat->spd != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SPD_ETERNAL without first setting MAT_SPD to true or false"); 5920 mat->spd_eternal = flg; 5921 if (flg) { 5922 mat->structural_symmetry_eternal = PETSC_TRUE; 5923 mat->symmetry_eternal = PETSC_TRUE; 5924 } 5925 break; 5926 case MAT_STRUCTURE_ONLY: 5927 mat->structure_only = flg; 5928 break; 5929 case MAT_SORTED_FULL: 5930 mat->sortedfull = flg; 5931 break; 5932 default: 5933 break; 5934 } 5935 PetscTryTypeMethod(mat, setoption, op, flg); 5936 PetscFunctionReturn(0); 5937 } 5938 5939 /*@ 5940 MatGetOption - Gets a parameter option that has been set for a matrix. 5941 5942 Logically Collective on mat 5943 5944 Input Parameters: 5945 + mat - the matrix 5946 - option - the option, this only responds to certain options, check the code for which ones 5947 5948 Output Parameter: 5949 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5950 5951 Notes: 5952 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5953 5954 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5955 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5956 5957 Level: intermediate 5958 5959 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5960 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5961 @*/ 5962 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5963 { 5964 PetscFunctionBegin; 5965 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5966 PetscValidType(mat, 1); 5967 5968 PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op); 5969 PetscCheck(((PetscObject)mat)->type_name, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_TYPENOTSET, "Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()"); 5970 5971 switch (op) { 5972 case MAT_NO_OFF_PROC_ENTRIES: 5973 *flg = mat->nooffprocentries; 5974 break; 5975 case MAT_NO_OFF_PROC_ZERO_ROWS: 5976 *flg = mat->nooffproczerorows; 5977 break; 5978 case MAT_SYMMETRIC: 5979 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 5980 break; 5981 case MAT_HERMITIAN: 5982 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 5983 break; 5984 case MAT_STRUCTURALLY_SYMMETRIC: 5985 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 5986 break; 5987 case MAT_SPD: 5988 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 5989 break; 5990 case MAT_SYMMETRY_ETERNAL: 5991 *flg = mat->symmetry_eternal; 5992 break; 5993 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5994 *flg = mat->symmetry_eternal; 5995 break; 5996 default: 5997 break; 5998 } 5999 PetscFunctionReturn(0); 6000 } 6001 6002 /*@ 6003 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6004 this routine retains the old nonzero structure. 6005 6006 Logically Collective on mat 6007 6008 Input Parameters: 6009 . mat - the matrix 6010 6011 Level: intermediate 6012 6013 Note: 6014 If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase. 6015 See the Performance chapter of the users manual for information on preallocating matrices. 6016 6017 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6018 @*/ 6019 PetscErrorCode MatZeroEntries(Mat mat) 6020 { 6021 PetscFunctionBegin; 6022 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6023 PetscValidType(mat, 1); 6024 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6025 PetscCheck(mat->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for matrices where you have set values but not yet assembled"); 6026 MatCheckPreallocated(mat, 1); 6027 6028 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6029 PetscUseTypeMethod(mat, zeroentries); 6030 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6031 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6032 PetscFunctionReturn(0); 6033 } 6034 6035 /*@ 6036 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6037 of a set of rows and columns of a matrix. 6038 6039 Collective on mat 6040 6041 Input Parameters: 6042 + mat - the matrix 6043 . numRows - the number of rows to remove 6044 . rows - the global row indices 6045 . diag - value put in the diagonal of the eliminated rows 6046 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6047 - b - optional vector of right hand side, that will be adjusted by provided solution 6048 6049 Notes: 6050 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6051 6052 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 6053 The other entries of b will be adjusted by the known values of x times the corresponding matrix entries in the columns that are being eliminated 6054 6055 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6056 Krylov method to take advantage of the known solution on the zeroed rows. 6057 6058 For the parallel case, all processes that share the matrix (i.e., 6059 those in the communicator used for matrix creation) MUST call this 6060 routine, regardless of whether any rows being zeroed are owned by 6061 them. 6062 6063 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6064 6065 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6066 list only rows local to itself). 6067 6068 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6069 6070 Level: intermediate 6071 6072 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6073 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6074 @*/ 6075 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6076 { 6077 PetscFunctionBegin; 6078 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6079 PetscValidType(mat, 1); 6080 if (numRows) PetscValidIntPointer(rows, 3); 6081 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6082 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6083 MatCheckPreallocated(mat, 1); 6084 6085 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6086 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6087 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6088 PetscFunctionReturn(0); 6089 } 6090 6091 /*@ 6092 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6093 of a set of rows and columns of a matrix. 6094 6095 Collective on mat 6096 6097 Input Parameters: 6098 + mat - the matrix 6099 . is - the rows to zero 6100 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6101 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6102 - b - optional vector of right hand side, that will be adjusted by provided solution 6103 6104 Note: 6105 See `MatZeroRowsColumns()` for details on how this routine operates. 6106 6107 Level: intermediate 6108 6109 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6110 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6111 @*/ 6112 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6113 { 6114 PetscInt numRows; 6115 const PetscInt *rows; 6116 6117 PetscFunctionBegin; 6118 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6119 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6120 PetscValidType(mat, 1); 6121 PetscValidType(is, 2); 6122 PetscCall(ISGetLocalSize(is, &numRows)); 6123 PetscCall(ISGetIndices(is, &rows)); 6124 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6125 PetscCall(ISRestoreIndices(is, &rows)); 6126 PetscFunctionReturn(0); 6127 } 6128 6129 /*@ 6130 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6131 of a set of rows of a matrix. 6132 6133 Collective on mat 6134 6135 Input Parameters: 6136 + mat - the matrix 6137 . numRows - the number of rows to remove 6138 . rows - the global row indices 6139 . diag - value put in the diagonal of the eliminated rows 6140 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6141 - b - optional vector of right hand side, that will be adjusted by provided solution 6142 6143 Notes: 6144 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6145 6146 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 6147 6148 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6149 Krylov method to take advantage of the known solution on the zeroed rows. 6150 6151 May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns) 6152 from the matrix. 6153 6154 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6155 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal 6156 formats this does not alter the nonzero structure. 6157 6158 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6159 of the matrix is not changed the values are 6160 merely zeroed. 6161 6162 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6163 formats can optionally remove the main diagonal entry from the 6164 nonzero structure as well, by passing 0.0 as the final argument). 6165 6166 For the parallel case, all processes that share the matrix (i.e., 6167 those in the communicator used for matrix creation) MUST call this 6168 routine, regardless of whether any rows being zeroed are owned by 6169 them. 6170 6171 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6172 list only rows local to itself). 6173 6174 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6175 owns that are to be zeroed. This saves a global synchronization in the implementation. 6176 6177 Level: intermediate 6178 6179 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6180 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6181 @*/ 6182 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6183 { 6184 PetscFunctionBegin; 6185 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6186 PetscValidType(mat, 1); 6187 if (numRows) PetscValidIntPointer(rows, 3); 6188 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6189 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6190 MatCheckPreallocated(mat, 1); 6191 6192 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6193 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6194 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6195 PetscFunctionReturn(0); 6196 } 6197 6198 /*@ 6199 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6200 of a set of rows of a matrix. 6201 6202 Collective on Mat 6203 6204 Input Parameters: 6205 + mat - the matrix 6206 . is - index set of rows to remove (if NULL then no row is removed) 6207 . diag - value put in all diagonals of eliminated rows 6208 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6209 - b - optional vector of right hand side, that will be adjusted by provided solution 6210 6211 Note: 6212 See `MatZeroRows()` for details on how this routine operates. 6213 6214 Level: intermediate 6215 6216 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6217 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6218 @*/ 6219 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6220 { 6221 PetscInt numRows = 0; 6222 const PetscInt *rows = NULL; 6223 6224 PetscFunctionBegin; 6225 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6226 PetscValidType(mat, 1); 6227 if (is) { 6228 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6229 PetscCall(ISGetLocalSize(is, &numRows)); 6230 PetscCall(ISGetIndices(is, &rows)); 6231 } 6232 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6233 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6234 PetscFunctionReturn(0); 6235 } 6236 6237 /*@ 6238 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6239 of a set of rows of a matrix. These rows must be local to the process. 6240 6241 Collective on mat 6242 6243 Input Parameters: 6244 + mat - the matrix 6245 . numRows - the number of rows to remove 6246 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6247 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6248 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6249 - b - optional vector of right hand side, that will be adjusted by provided solution 6250 6251 Notes: 6252 See `MatZeroRows()` for details on how this routine operates. 6253 6254 The grid coordinates are across the entire grid, not just the local portion 6255 6256 In Fortran idxm and idxn should be declared as 6257 $ MatStencil idxm(4,m) 6258 and the values inserted using 6259 $ idxm(MatStencil_i,1) = i 6260 $ idxm(MatStencil_j,1) = j 6261 $ idxm(MatStencil_k,1) = k 6262 $ idxm(MatStencil_c,1) = c 6263 etc 6264 6265 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6266 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6267 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6268 `DM_BOUNDARY_PERIODIC` boundary type. 6269 6270 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 6271 a single value per point) you can skip filling those indices. 6272 6273 Level: intermediate 6274 6275 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6276 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6277 @*/ 6278 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6279 { 6280 PetscInt dim = mat->stencil.dim; 6281 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6282 PetscInt *dims = mat->stencil.dims + 1; 6283 PetscInt *starts = mat->stencil.starts; 6284 PetscInt *dxm = (PetscInt *)rows; 6285 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6286 6287 PetscFunctionBegin; 6288 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6289 PetscValidType(mat, 1); 6290 if (numRows) PetscValidPointer(rows, 3); 6291 6292 PetscCall(PetscMalloc1(numRows, &jdxm)); 6293 for (i = 0; i < numRows; ++i) { 6294 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6295 for (j = 0; j < 3 - sdim; ++j) dxm++; 6296 /* Local index in X dir */ 6297 tmp = *dxm++ - starts[0]; 6298 /* Loop over remaining dimensions */ 6299 for (j = 0; j < dim - 1; ++j) { 6300 /* If nonlocal, set index to be negative */ 6301 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6302 /* Update local index */ 6303 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6304 } 6305 /* Skip component slot if necessary */ 6306 if (mat->stencil.noc) dxm++; 6307 /* Local row number */ 6308 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6309 } 6310 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6311 PetscCall(PetscFree(jdxm)); 6312 PetscFunctionReturn(0); 6313 } 6314 6315 /*@ 6316 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6317 of a set of rows and columns of a matrix. 6318 6319 Collective on mat 6320 6321 Input Parameters: 6322 + mat - the matrix 6323 . numRows - the number of rows/columns to remove 6324 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6325 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6326 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6327 - b - optional vector of right hand side, that will be adjusted by provided solution 6328 6329 Notes: 6330 See `MatZeroRowsColumns()` for details on how this routine operates. 6331 6332 The grid coordinates are across the entire grid, not just the local portion 6333 6334 In Fortran idxm and idxn should be declared as 6335 $ MatStencil idxm(4,m) 6336 and the values inserted using 6337 $ idxm(MatStencil_i,1) = i 6338 $ idxm(MatStencil_j,1) = j 6339 $ idxm(MatStencil_k,1) = k 6340 $ idxm(MatStencil_c,1) = c 6341 etc 6342 6343 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6344 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6345 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6346 `DM_BOUNDARY_PERIODIC` boundary type. 6347 6348 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 6349 a single value per point) you can skip filling those indices. 6350 6351 Level: intermediate 6352 6353 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6354 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6355 @*/ 6356 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6357 { 6358 PetscInt dim = mat->stencil.dim; 6359 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6360 PetscInt *dims = mat->stencil.dims + 1; 6361 PetscInt *starts = mat->stencil.starts; 6362 PetscInt *dxm = (PetscInt *)rows; 6363 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6364 6365 PetscFunctionBegin; 6366 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6367 PetscValidType(mat, 1); 6368 if (numRows) PetscValidPointer(rows, 3); 6369 6370 PetscCall(PetscMalloc1(numRows, &jdxm)); 6371 for (i = 0; i < numRows; ++i) { 6372 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6373 for (j = 0; j < 3 - sdim; ++j) dxm++; 6374 /* Local index in X dir */ 6375 tmp = *dxm++ - starts[0]; 6376 /* Loop over remaining dimensions */ 6377 for (j = 0; j < dim - 1; ++j) { 6378 /* If nonlocal, set index to be negative */ 6379 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6380 /* Update local index */ 6381 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6382 } 6383 /* Skip component slot if necessary */ 6384 if (mat->stencil.noc) dxm++; 6385 /* Local row number */ 6386 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6387 } 6388 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6389 PetscCall(PetscFree(jdxm)); 6390 PetscFunctionReturn(0); 6391 } 6392 6393 /*@C 6394 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6395 of a set of rows of a matrix; using local numbering of rows. 6396 6397 Collective on mat 6398 6399 Input Parameters: 6400 + mat - the matrix 6401 . numRows - the number of rows to remove 6402 . rows - the local row indices 6403 . diag - value put in all diagonals of eliminated rows 6404 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6405 - b - optional vector of right hand side, that will be adjusted by provided solution 6406 6407 Notes: 6408 Before calling `MatZeroRowsLocal()`, the user must first set the 6409 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6410 6411 See `MatZeroRows()` for details on how this routine operates. 6412 6413 Level: intermediate 6414 6415 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6416 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6417 @*/ 6418 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6419 { 6420 PetscFunctionBegin; 6421 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6422 PetscValidType(mat, 1); 6423 if (numRows) PetscValidIntPointer(rows, 3); 6424 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6425 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6426 MatCheckPreallocated(mat, 1); 6427 6428 if (mat->ops->zerorowslocal) { 6429 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6430 } else { 6431 IS is, newis; 6432 const PetscInt *newRows; 6433 6434 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6435 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6436 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6437 PetscCall(ISGetIndices(newis, &newRows)); 6438 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6439 PetscCall(ISRestoreIndices(newis, &newRows)); 6440 PetscCall(ISDestroy(&newis)); 6441 PetscCall(ISDestroy(&is)); 6442 } 6443 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6444 PetscFunctionReturn(0); 6445 } 6446 6447 /*@ 6448 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6449 of a set of rows of a matrix; using local numbering of rows. 6450 6451 Collective on mat 6452 6453 Input Parameters: 6454 + mat - the matrix 6455 . is - index set of rows to remove 6456 . diag - value put in all diagonals of eliminated rows 6457 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6458 - b - optional vector of right hand side, that will be adjusted by provided solution 6459 6460 Notes: 6461 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6462 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6463 6464 See `MatZeroRows()` for details on how this routine operates. 6465 6466 Level: intermediate 6467 6468 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6469 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6470 @*/ 6471 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6472 { 6473 PetscInt numRows; 6474 const PetscInt *rows; 6475 6476 PetscFunctionBegin; 6477 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6478 PetscValidType(mat, 1); 6479 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6480 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6481 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6482 MatCheckPreallocated(mat, 1); 6483 6484 PetscCall(ISGetLocalSize(is, &numRows)); 6485 PetscCall(ISGetIndices(is, &rows)); 6486 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6487 PetscCall(ISRestoreIndices(is, &rows)); 6488 PetscFunctionReturn(0); 6489 } 6490 6491 /*@ 6492 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6493 of a set of rows and columns of a matrix; using local numbering of rows. 6494 6495 Collective on mat 6496 6497 Input Parameters: 6498 + mat - the matrix 6499 . numRows - the number of rows to remove 6500 . rows - the global row indices 6501 . diag - value put in all diagonals of eliminated rows 6502 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6503 - b - optional vector of right hand side, that will be adjusted by provided solution 6504 6505 Notes: 6506 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6507 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6508 6509 See `MatZeroRowsColumns()` for details on how this routine operates. 6510 6511 Level: intermediate 6512 6513 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6514 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6515 @*/ 6516 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6517 { 6518 IS is, newis; 6519 const PetscInt *newRows; 6520 6521 PetscFunctionBegin; 6522 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6523 PetscValidType(mat, 1); 6524 if (numRows) PetscValidIntPointer(rows, 3); 6525 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6526 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6527 MatCheckPreallocated(mat, 1); 6528 6529 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6530 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6531 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6532 PetscCall(ISGetIndices(newis, &newRows)); 6533 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6534 PetscCall(ISRestoreIndices(newis, &newRows)); 6535 PetscCall(ISDestroy(&newis)); 6536 PetscCall(ISDestroy(&is)); 6537 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6538 PetscFunctionReturn(0); 6539 } 6540 6541 /*@ 6542 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6543 of a set of rows and columns of a matrix; using local numbering of rows. 6544 6545 Collective on Mat 6546 6547 Input Parameters: 6548 + mat - the matrix 6549 . is - index set of rows to remove 6550 . diag - value put in all diagonals of eliminated rows 6551 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6552 - b - optional vector of right hand side, that will be adjusted by provided solution 6553 6554 Notes: 6555 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6556 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6557 6558 See `MatZeroRowsColumns()` for details on how this routine operates. 6559 6560 Level: intermediate 6561 6562 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6563 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6564 @*/ 6565 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6566 { 6567 PetscInt numRows; 6568 const PetscInt *rows; 6569 6570 PetscFunctionBegin; 6571 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6572 PetscValidType(mat, 1); 6573 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6574 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6575 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6576 MatCheckPreallocated(mat, 1); 6577 6578 PetscCall(ISGetLocalSize(is, &numRows)); 6579 PetscCall(ISGetIndices(is, &rows)); 6580 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6581 PetscCall(ISRestoreIndices(is, &rows)); 6582 PetscFunctionReturn(0); 6583 } 6584 6585 /*@C 6586 MatGetSize - Returns the numbers of rows and columns in a matrix. 6587 6588 Not Collective 6589 6590 Input Parameter: 6591 . mat - the matrix 6592 6593 Output Parameters: 6594 + m - the number of global rows 6595 - n - the number of global columns 6596 6597 Note: both output parameters can be NULL on input. 6598 6599 Level: beginner 6600 6601 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6602 @*/ 6603 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6604 { 6605 PetscFunctionBegin; 6606 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6607 if (m) *m = mat->rmap->N; 6608 if (n) *n = mat->cmap->N; 6609 PetscFunctionReturn(0); 6610 } 6611 6612 /*@C 6613 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6614 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6615 6616 Not Collective 6617 6618 Input Parameter: 6619 . mat - the matrix 6620 6621 Output Parameters: 6622 + m - the number of local rows, use `NULL` to not obtain this value 6623 - n - the number of local columns, use `NULL` to not obtain this value 6624 6625 Level: beginner 6626 6627 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()` 6628 @*/ 6629 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6630 { 6631 PetscFunctionBegin; 6632 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6633 if (m) PetscValidIntPointer(m, 2); 6634 if (n) PetscValidIntPointer(n, 3); 6635 if (m) *m = mat->rmap->n; 6636 if (n) *n = mat->cmap->n; 6637 PetscFunctionReturn(0); 6638 } 6639 6640 /*@C 6641 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6642 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6643 6644 Not Collective, unless matrix has not been allocated, then collective on mat 6645 6646 Input Parameter: 6647 . mat - the matrix 6648 6649 Output Parameters: 6650 + m - the global index of the first local column, use `NULL` to not obtain this value 6651 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6652 6653 Level: developer 6654 6655 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6656 @*/ 6657 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6658 { 6659 PetscFunctionBegin; 6660 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6661 PetscValidType(mat, 1); 6662 if (m) PetscValidIntPointer(m, 2); 6663 if (n) PetscValidIntPointer(n, 3); 6664 MatCheckPreallocated(mat, 1); 6665 if (m) *m = mat->cmap->rstart; 6666 if (n) *n = mat->cmap->rend; 6667 PetscFunctionReturn(0); 6668 } 6669 6670 /*@C 6671 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6672 this MPI rank. For all matrices it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix 6673 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6674 6675 Not Collective 6676 6677 Input Parameter: 6678 . mat - the matrix 6679 6680 Output Parameters: 6681 + m - the global index of the first local row, use `NULL` to not obtain this value 6682 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6683 6684 Note: 6685 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6686 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6687 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6688 6689 Level: beginner 6690 6691 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6692 `PetscLayout` 6693 @*/ 6694 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6695 { 6696 PetscFunctionBegin; 6697 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6698 PetscValidType(mat, 1); 6699 if (m) PetscValidIntPointer(m, 2); 6700 if (n) PetscValidIntPointer(n, 3); 6701 MatCheckPreallocated(mat, 1); 6702 if (m) *m = mat->rmap->rstart; 6703 if (n) *n = mat->rmap->rend; 6704 PetscFunctionReturn(0); 6705 } 6706 6707 /*@C 6708 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6709 each process. For all matrices it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix 6710 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6711 6712 Not Collective, unless matrix has not been allocated, then collective on mat 6713 6714 Input Parameters: 6715 . mat - the matrix 6716 6717 Output Parameters: 6718 . ranges - start of each processors portion plus one more than the total length at the end 6719 6720 Level: beginner 6721 6722 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6723 @*/ 6724 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6725 { 6726 PetscFunctionBegin; 6727 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6728 PetscValidType(mat, 1); 6729 MatCheckPreallocated(mat, 1); 6730 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6731 PetscFunctionReturn(0); 6732 } 6733 6734 /*@C 6735 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6736 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6737 6738 Not Collective, unless matrix has not been allocated, then collective on Mat 6739 6740 Input Parameters: 6741 . mat - the matrix 6742 6743 Output Parameters: 6744 . ranges - start of each processors portion plus one more then the total length at the end 6745 6746 Level: beginner 6747 6748 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6749 @*/ 6750 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6751 { 6752 PetscFunctionBegin; 6753 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6754 PetscValidType(mat, 1); 6755 MatCheckPreallocated(mat, 1); 6756 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6757 PetscFunctionReturn(0); 6758 } 6759 6760 /*@C 6761 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6762 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6763 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6764 6765 Not Collective 6766 6767 Input Parameter: 6768 . A - matrix 6769 6770 Output Parameters: 6771 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6772 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6773 6774 Level: intermediate 6775 6776 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6777 @*/ 6778 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6779 { 6780 PetscErrorCode (*f)(Mat, IS *, IS *); 6781 6782 PetscFunctionBegin; 6783 MatCheckPreallocated(A, 1); 6784 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6785 if (f) { 6786 PetscCall((*f)(A, rows, cols)); 6787 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6788 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6789 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6790 } 6791 PetscFunctionReturn(0); 6792 } 6793 6794 /*@C 6795 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6796 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6797 to complete the factorization. 6798 6799 Collective on fact 6800 6801 Input Parameters: 6802 + fact - the factorized matrix obtained with `MatGetFactor()` 6803 . mat - the matrix 6804 . row - row permutation 6805 . column - column permutation 6806 - info - structure containing 6807 $ levels - number of levels of fill. 6808 $ expected fill - as ratio of original fill. 6809 $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6810 missing diagonal entries) 6811 6812 Output Parameters: 6813 . fact - new matrix that has been symbolically factored 6814 6815 Level: developer 6816 6817 Notes: 6818 See [Matrix Factorization](sec_matfactor) for additional information. 6819 6820 Most users should employ the `KSP` interface for linear solvers 6821 instead of working directly with matrix algebra routines such as this. 6822 See, e.g., `KSPCreate()`. 6823 6824 Uses the definition of level of fill as in Y. Saad, 2003 6825 6826 Developer Note: 6827 The Fortran interface is not autogenerated as the f90 6828 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6829 6830 References: 6831 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6832 6833 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6834 `MatGetOrdering()`, `MatFactorInfo` 6835 @*/ 6836 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6837 { 6838 PetscFunctionBegin; 6839 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6840 PetscValidType(mat, 2); 6841 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6842 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6843 PetscValidPointer(info, 5); 6844 PetscValidPointer(fact, 1); 6845 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6846 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6847 if (!fact->ops->ilufactorsymbolic) { 6848 MatSolverType stype; 6849 PetscCall(MatFactorGetSolverType(fact, &stype)); 6850 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype); 6851 } 6852 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6853 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6854 MatCheckPreallocated(mat, 2); 6855 6856 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6857 PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info)); 6858 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6859 PetscFunctionReturn(0); 6860 } 6861 6862 /*@C 6863 MatICCFactorSymbolic - Performs symbolic incomplete 6864 Cholesky factorization for a symmetric matrix. Use 6865 `MatCholeskyFactorNumeric()` to complete the factorization. 6866 6867 Collective on fact 6868 6869 Input Parameters: 6870 + fact - the factorized matrix obtained with `MatGetFactor()` 6871 . mat - the matrix to be factored 6872 . perm - row and column permutation 6873 - info - structure containing 6874 $ levels - number of levels of fill. 6875 $ expected fill - as ratio of original fill. 6876 6877 Output Parameter: 6878 . fact - the factored matrix 6879 6880 Level: developer 6881 6882 Notes: 6883 Most users should employ the `KSP` interface for linear solvers 6884 instead of working directly with matrix algebra routines such as this. 6885 See, e.g., `KSPCreate()`. 6886 6887 This uses the definition of level of fill as in Y. Saad, 2003 6888 6889 Developer Note: 6890 The Fortran interface is not autogenerated as the f90 6891 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6892 6893 References: 6894 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6895 6896 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6897 @*/ 6898 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6899 { 6900 PetscFunctionBegin; 6901 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6902 PetscValidType(mat, 2); 6903 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6904 PetscValidPointer(info, 4); 6905 PetscValidPointer(fact, 1); 6906 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6907 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6908 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6909 if (!(fact)->ops->iccfactorsymbolic) { 6910 MatSolverType stype; 6911 PetscCall(MatFactorGetSolverType(fact, &stype)); 6912 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype); 6913 } 6914 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6915 MatCheckPreallocated(mat, 2); 6916 6917 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6918 PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info)); 6919 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6920 PetscFunctionReturn(0); 6921 } 6922 6923 /*@C 6924 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6925 points to an array of valid matrices, they may be reused to store the new 6926 submatrices. 6927 6928 Collective on mat 6929 6930 Input Parameters: 6931 + mat - the matrix 6932 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6933 . irow, icol - index sets of rows and columns to extract 6934 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6935 6936 Output Parameter: 6937 . submat - the array of submatrices 6938 6939 Notes: 6940 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6941 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6942 to extract a parallel submatrix. 6943 6944 Some matrix types place restrictions on the row and column 6945 indices, such as that they be sorted or that they be equal to each other. 6946 6947 The index sets may not have duplicate entries. 6948 6949 When extracting submatrices from a parallel matrix, each processor can 6950 form a different submatrix by setting the rows and columns of its 6951 individual index sets according to the local submatrix desired. 6952 6953 When finished using the submatrices, the user should destroy 6954 them with `MatDestroySubMatrices()`. 6955 6956 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6957 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6958 6959 This routine creates the matrices in submat; you should NOT create them before 6960 calling it. It also allocates the array of matrix pointers submat. 6961 6962 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6963 request one row/column in a block, they must request all rows/columns that are in 6964 that block. For example, if the block size is 2 you cannot request just row 0 and 6965 column 0. 6966 6967 Fortran Note: 6968 The Fortran interface is slightly different from that given below; it 6969 requires one to pass in as submat a `Mat` (integer) array of size at least n+1. 6970 6971 Level: advanced 6972 6973 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6974 @*/ 6975 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 6976 { 6977 PetscInt i; 6978 PetscBool eq; 6979 6980 PetscFunctionBegin; 6981 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6982 PetscValidType(mat, 1); 6983 if (n) { 6984 PetscValidPointer(irow, 3); 6985 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 6986 PetscValidPointer(icol, 4); 6987 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 6988 } 6989 PetscValidPointer(submat, 6); 6990 if (n && scall == MAT_REUSE_MATRIX) { 6991 PetscValidPointer(*submat, 6); 6992 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 6993 } 6994 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6995 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6996 MatCheckPreallocated(mat, 1); 6997 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 6998 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 6999 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7000 for (i = 0; i < n; i++) { 7001 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7002 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7003 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7004 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7005 if (mat->boundtocpu && mat->bindingpropagates) { 7006 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7007 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7008 } 7009 #endif 7010 } 7011 PetscFunctionReturn(0); 7012 } 7013 7014 /*@C 7015 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7016 7017 Collective on mat 7018 7019 Input Parameters: 7020 + mat - the matrix 7021 . n - the number of submatrixes to be extracted 7022 . irow, icol - index sets of rows and columns to extract 7023 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7024 7025 Output Parameter: 7026 . submat - the array of submatrices 7027 7028 Level: advanced 7029 7030 Note: 7031 This is used by `PCGASM` 7032 7033 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7034 @*/ 7035 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7036 { 7037 PetscInt i; 7038 PetscBool eq; 7039 7040 PetscFunctionBegin; 7041 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7042 PetscValidType(mat, 1); 7043 if (n) { 7044 PetscValidPointer(irow, 3); 7045 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7046 PetscValidPointer(icol, 4); 7047 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7048 } 7049 PetscValidPointer(submat, 6); 7050 if (n && scall == MAT_REUSE_MATRIX) { 7051 PetscValidPointer(*submat, 6); 7052 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7053 } 7054 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7055 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7056 MatCheckPreallocated(mat, 1); 7057 7058 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7059 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7060 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7061 for (i = 0; i < n; i++) { 7062 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7063 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7064 } 7065 PetscFunctionReturn(0); 7066 } 7067 7068 /*@C 7069 MatDestroyMatrices - Destroys an array of matrices. 7070 7071 Collective on mat 7072 7073 Input Parameters: 7074 + n - the number of local matrices 7075 - mat - the matrices (note that this is a pointer to the array of matrices) 7076 7077 Level: advanced 7078 7079 Note: 7080 Frees not only the matrices, but also the array that contains the matrices 7081 In Fortran will not free the array. 7082 7083 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7084 @*/ 7085 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7086 { 7087 PetscInt i; 7088 7089 PetscFunctionBegin; 7090 if (!*mat) PetscFunctionReturn(0); 7091 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7092 PetscValidPointer(mat, 2); 7093 7094 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7095 7096 /* memory is allocated even if n = 0 */ 7097 PetscCall(PetscFree(*mat)); 7098 PetscFunctionReturn(0); 7099 } 7100 7101 /*@C 7102 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7103 7104 Collective on mat 7105 7106 Input Parameters: 7107 + n - the number of local matrices 7108 - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling 7109 sequence of MatCreateSubMatrices()) 7110 7111 Level: advanced 7112 7113 Note: 7114 Frees not only the matrices, but also the array that contains the matrices 7115 In Fortran will not free the array. 7116 7117 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7118 @*/ 7119 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7120 { 7121 Mat mat0; 7122 7123 PetscFunctionBegin; 7124 if (!*mat) PetscFunctionReturn(0); 7125 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7126 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7127 PetscValidPointer(mat, 2); 7128 7129 mat0 = (*mat)[0]; 7130 if (mat0 && mat0->ops->destroysubmatrices) { 7131 PetscCall((mat0->ops->destroysubmatrices)(n, mat)); 7132 } else { 7133 PetscCall(MatDestroyMatrices(n, mat)); 7134 } 7135 PetscFunctionReturn(0); 7136 } 7137 7138 /*@C 7139 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7140 7141 Collective on mat 7142 7143 Input Parameters: 7144 . mat - the matrix 7145 7146 Output Parameter: 7147 . matstruct - the sequential matrix with the nonzero structure of mat 7148 7149 Level: developer 7150 7151 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7152 @*/ 7153 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7154 { 7155 PetscFunctionBegin; 7156 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7157 PetscValidPointer(matstruct, 2); 7158 7159 PetscValidType(mat, 1); 7160 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7161 MatCheckPreallocated(mat, 1); 7162 7163 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7164 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7165 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7166 PetscFunctionReturn(0); 7167 } 7168 7169 /*@C 7170 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7171 7172 Collective on mat 7173 7174 Input Parameters: 7175 . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling 7176 sequence of `MatGetSequentialNonzeroStructure()`) 7177 7178 Level: advanced 7179 7180 Note: 7181 Frees not only the matrices, but also the array that contains the matrices 7182 7183 .seealso: `Mat`, `MatGetSeqNonzeroStructure()` 7184 @*/ 7185 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7186 { 7187 PetscFunctionBegin; 7188 PetscValidPointer(mat, 1); 7189 PetscCall(MatDestroy(mat)); 7190 PetscFunctionReturn(0); 7191 } 7192 7193 /*@ 7194 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7195 replaces the index sets by larger ones that represent submatrices with 7196 additional overlap. 7197 7198 Collective on mat 7199 7200 Input Parameters: 7201 + mat - the matrix 7202 . n - the number of index sets 7203 . is - the array of index sets (these index sets will changed during the call) 7204 - ov - the additional overlap requested 7205 7206 Options Database: 7207 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7208 7209 Level: developer 7210 7211 Developer Note: 7212 Any implementation must preserve block sizes. That is: if the row block size and the column block size of mat are equal to bs, then the output index sets must be compatible with bs. 7213 7214 .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7215 @*/ 7216 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7217 { 7218 PetscInt i, bs, cbs; 7219 7220 PetscFunctionBegin; 7221 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7222 PetscValidType(mat, 1); 7223 PetscValidLogicalCollectiveInt(mat, n, 2); 7224 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7225 if (n) { 7226 PetscValidPointer(is, 3); 7227 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7228 } 7229 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7230 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7231 MatCheckPreallocated(mat, 1); 7232 7233 if (!ov || !n) PetscFunctionReturn(0); 7234 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7235 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7236 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7237 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7238 if (bs == cbs) { 7239 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7240 } 7241 PetscFunctionReturn(0); 7242 } 7243 7244 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7245 7246 /*@ 7247 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7248 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7249 additional overlap. 7250 7251 Collective on mat 7252 7253 Input Parameters: 7254 + mat - the matrix 7255 . n - the number of index sets 7256 . is - the array of index sets (these index sets will changed during the call) 7257 - ov - the additional overlap requested 7258 7259 ` Options Database: 7260 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7261 7262 Level: developer 7263 7264 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7265 @*/ 7266 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7267 { 7268 PetscInt i; 7269 7270 PetscFunctionBegin; 7271 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7272 PetscValidType(mat, 1); 7273 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7274 if (n) { 7275 PetscValidPointer(is, 3); 7276 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7277 } 7278 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7279 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7280 MatCheckPreallocated(mat, 1); 7281 if (!ov) PetscFunctionReturn(0); 7282 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7283 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7284 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7285 PetscFunctionReturn(0); 7286 } 7287 7288 /*@ 7289 MatGetBlockSize - Returns the matrix block size. 7290 7291 Not Collective 7292 7293 Input Parameter: 7294 . mat - the matrix 7295 7296 Output Parameter: 7297 . bs - block size 7298 7299 Notes: 7300 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7301 7302 If the block size has not been set yet this routine returns 1. 7303 7304 Level: intermediate 7305 7306 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7307 @*/ 7308 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7309 { 7310 PetscFunctionBegin; 7311 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7312 PetscValidIntPointer(bs, 2); 7313 *bs = PetscAbs(mat->rmap->bs); 7314 PetscFunctionReturn(0); 7315 } 7316 7317 /*@ 7318 MatGetBlockSizes - Returns the matrix block row and column sizes. 7319 7320 Not Collective 7321 7322 Input Parameter: 7323 . mat - the matrix 7324 7325 Output Parameters: 7326 + rbs - row block size 7327 - cbs - column block size 7328 7329 Notes: 7330 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7331 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7332 7333 If a block size has not been set yet this routine returns 1. 7334 7335 Level: intermediate 7336 7337 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7338 @*/ 7339 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7340 { 7341 PetscFunctionBegin; 7342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7343 if (rbs) PetscValidIntPointer(rbs, 2); 7344 if (cbs) PetscValidIntPointer(cbs, 3); 7345 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7346 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7347 PetscFunctionReturn(0); 7348 } 7349 7350 /*@ 7351 MatSetBlockSize - Sets the matrix block size. 7352 7353 Logically Collective on mat 7354 7355 Input Parameters: 7356 + mat - the matrix 7357 - bs - block size 7358 7359 Notes: 7360 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7361 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7362 7363 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7364 is compatible with the matrix local sizes. 7365 7366 Level: intermediate 7367 7368 .seealso: `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7369 @*/ 7370 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7371 { 7372 PetscFunctionBegin; 7373 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7374 PetscValidLogicalCollectiveInt(mat, bs, 2); 7375 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7376 PetscFunctionReturn(0); 7377 } 7378 7379 typedef struct { 7380 PetscInt n; 7381 IS *is; 7382 Mat *mat; 7383 PetscObjectState nonzerostate; 7384 Mat C; 7385 } EnvelopeData; 7386 7387 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7388 { 7389 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7390 PetscCall(PetscFree(edata->is)); 7391 PetscCall(PetscFree(edata)); 7392 return 0; 7393 } 7394 7395 /* 7396 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7397 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7398 7399 Collective on mat 7400 7401 Input Parameter: 7402 . mat - the matrix 7403 7404 Notes: 7405 There can be zeros within the blocks 7406 7407 The blocks can overlap between processes, including laying on more than two processes 7408 7409 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7410 */ 7411 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7412 { 7413 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7414 PetscInt *diag, *odiag, sc; 7415 VecScatter scatter; 7416 PetscScalar *seqv; 7417 const PetscScalar *parv; 7418 const PetscInt *ia, *ja; 7419 PetscBool set, flag, done; 7420 Mat AA = mat, A; 7421 MPI_Comm comm; 7422 PetscMPIInt rank, size, tag; 7423 MPI_Status status; 7424 PetscContainer container; 7425 EnvelopeData *edata; 7426 Vec seq, par; 7427 IS isglobal; 7428 7429 PetscFunctionBegin; 7430 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7431 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7432 if (!set || !flag) { 7433 /* TOO: only needs nonzero structure of transpose */ 7434 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7435 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7436 } 7437 PetscCall(MatAIJGetLocalMat(AA, &A)); 7438 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7439 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7440 7441 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7442 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7443 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7444 PetscCallMPI(MPI_Comm_size(comm, &size)); 7445 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7446 7447 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7448 7449 if (rank > 0) { 7450 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7451 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7452 } 7453 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7454 for (i = 0; i < n; i++) { 7455 env = PetscMax(env, ja[ia[i + 1] - 1]); 7456 II = rstart + i; 7457 if (env == II) { 7458 starts[lblocks] = tbs; 7459 sizes[lblocks++] = 1 + II - tbs; 7460 tbs = 1 + II; 7461 } 7462 } 7463 if (rank < size - 1) { 7464 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7465 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7466 } 7467 7468 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7469 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7470 PetscCall(MatDestroy(&A)); 7471 7472 PetscCall(PetscNew(&edata)); 7473 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7474 edata->n = lblocks; 7475 /* create IS needed for extracting blocks from the original matrix */ 7476 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7477 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7478 7479 /* Create the resulting inverse matrix structure with preallocation information */ 7480 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7481 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7482 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7483 PetscCall(MatSetType(edata->C, MATAIJ)); 7484 7485 /* Communicate the start and end of each row, from each block to the correct rank */ 7486 /* TODO: Use PetscSF instead of VecScatter */ 7487 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7488 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7489 PetscCall(VecGetArrayWrite(seq, &seqv)); 7490 for (PetscInt i = 0; i < lblocks; i++) { 7491 for (PetscInt j = 0; j < sizes[i]; j++) { 7492 seqv[cnt] = starts[i]; 7493 seqv[cnt + 1] = starts[i] + sizes[i]; 7494 cnt += 2; 7495 } 7496 } 7497 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7498 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7499 sc -= cnt; 7500 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7501 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7502 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7503 PetscCall(ISDestroy(&isglobal)); 7504 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7505 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7506 PetscCall(VecScatterDestroy(&scatter)); 7507 PetscCall(VecDestroy(&seq)); 7508 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7509 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7510 PetscCall(VecGetArrayRead(par, &parv)); 7511 cnt = 0; 7512 PetscCall(MatGetSize(mat, NULL, &n)); 7513 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7514 PetscInt start, end, d = 0, od = 0; 7515 7516 start = (PetscInt)PetscRealPart(parv[cnt]); 7517 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7518 cnt += 2; 7519 7520 if (start < cstart) { 7521 od += cstart - start + n - cend; 7522 d += cend - cstart; 7523 } else if (start < cend) { 7524 od += n - cend; 7525 d += cend - start; 7526 } else od += n - start; 7527 if (end <= cstart) { 7528 od -= cstart - end + n - cend; 7529 d -= cend - cstart; 7530 } else if (end < cend) { 7531 od -= n - cend; 7532 d -= cend - end; 7533 } else od -= n - end; 7534 7535 odiag[i] = od; 7536 diag[i] = d; 7537 } 7538 PetscCall(VecRestoreArrayRead(par, &parv)); 7539 PetscCall(VecDestroy(&par)); 7540 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7541 PetscCall(PetscFree2(diag, odiag)); 7542 PetscCall(PetscFree2(sizes, starts)); 7543 7544 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7545 PetscCall(PetscContainerSetPointer(container, edata)); 7546 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7547 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7548 PetscCall(PetscObjectDereference((PetscObject)container)); 7549 PetscFunctionReturn(0); 7550 } 7551 7552 /*@ 7553 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7554 7555 Collective on A 7556 7557 Input Parameters: 7558 . A - the matrix 7559 7560 Output Parameters: 7561 . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 7562 7563 Note: 7564 For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal. 7565 7566 Level: advanced 7567 7568 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7569 @*/ 7570 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7571 { 7572 PetscContainer container; 7573 EnvelopeData *edata; 7574 PetscObjectState nonzerostate; 7575 7576 PetscFunctionBegin; 7577 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7578 if (!container) { 7579 PetscCall(MatComputeVariableBlockEnvelope(A)); 7580 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7581 } 7582 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7583 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7584 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7585 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7586 7587 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7588 *C = edata->C; 7589 7590 for (PetscInt i = 0; i < edata->n; i++) { 7591 Mat D; 7592 PetscScalar *dvalues; 7593 7594 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7595 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7596 PetscCall(MatSeqDenseInvert(D)); 7597 PetscCall(MatDenseGetArray(D, &dvalues)); 7598 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7599 PetscCall(MatDestroy(&D)); 7600 } 7601 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7602 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7603 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7604 PetscFunctionReturn(0); 7605 } 7606 7607 /*@ 7608 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7609 7610 Logically Collective on mat 7611 7612 Input Parameters: 7613 + mat - the matrix 7614 . nblocks - the number of blocks on this process, each block can only exist on a single process 7615 - bsizes - the block sizes 7616 7617 Notes: 7618 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7619 7620 Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks. 7621 7622 Level: intermediate 7623 7624 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7625 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7626 @*/ 7627 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7628 { 7629 PetscInt i, ncnt = 0, nlocal; 7630 7631 PetscFunctionBegin; 7632 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7633 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7634 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7635 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7636 PetscCheck(ncnt == nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local block sizes %" PetscInt_FMT " does not equal local size of matrix %" PetscInt_FMT, ncnt, nlocal); 7637 PetscCall(PetscFree(mat->bsizes)); 7638 mat->nblocks = nblocks; 7639 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7640 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7641 PetscFunctionReturn(0); 7642 } 7643 7644 /*@C 7645 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7646 7647 Logically Collective on mat 7648 7649 Input Parameter: 7650 . mat - the matrix 7651 7652 Output Parameters: 7653 + nblocks - the number of blocks on this process 7654 - bsizes - the block sizes 7655 7656 Fortran Note: 7657 Currently not supported from Fortran 7658 7659 Level: intermediate 7660 7661 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7662 @*/ 7663 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7664 { 7665 PetscFunctionBegin; 7666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7667 *nblocks = mat->nblocks; 7668 *bsizes = mat->bsizes; 7669 PetscFunctionReturn(0); 7670 } 7671 7672 /*@ 7673 MatSetBlockSizes - Sets the matrix block row and column sizes. 7674 7675 Logically Collective on mat 7676 7677 Input Parameters: 7678 + mat - the matrix 7679 . rbs - row block size 7680 - cbs - column block size 7681 7682 Notes: 7683 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7684 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7685 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7686 7687 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7688 are compatible with the matrix local sizes. 7689 7690 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7691 7692 Level: intermediate 7693 7694 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7695 @*/ 7696 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7697 { 7698 PetscFunctionBegin; 7699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7700 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7701 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7702 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7703 if (mat->rmap->refcnt) { 7704 ISLocalToGlobalMapping l2g = NULL; 7705 PetscLayout nmap = NULL; 7706 7707 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7708 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7709 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7710 mat->rmap = nmap; 7711 mat->rmap->mapping = l2g; 7712 } 7713 if (mat->cmap->refcnt) { 7714 ISLocalToGlobalMapping l2g = NULL; 7715 PetscLayout nmap = NULL; 7716 7717 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7718 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7719 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7720 mat->cmap = nmap; 7721 mat->cmap->mapping = l2g; 7722 } 7723 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7724 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7725 PetscFunctionReturn(0); 7726 } 7727 7728 /*@ 7729 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7730 7731 Logically Collective on mat 7732 7733 Input Parameters: 7734 + mat - the matrix 7735 . fromRow - matrix from which to copy row block size 7736 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7737 7738 Level: developer 7739 7740 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7741 @*/ 7742 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7743 { 7744 PetscFunctionBegin; 7745 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7746 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7747 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7748 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7749 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7750 PetscFunctionReturn(0); 7751 } 7752 7753 /*@ 7754 MatResidual - Default routine to calculate the residual r = b - Ax 7755 7756 Collective on mat 7757 7758 Input Parameters: 7759 + mat - the matrix 7760 . b - the right-hand-side 7761 - x - the approximate solution 7762 7763 Output Parameter: 7764 . r - location to store the residual 7765 7766 Level: developer 7767 7768 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7769 @*/ 7770 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7771 { 7772 PetscFunctionBegin; 7773 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7774 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7775 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7776 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7777 PetscValidType(mat, 1); 7778 MatCheckPreallocated(mat, 1); 7779 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7780 if (!mat->ops->residual) { 7781 PetscCall(MatMult(mat, x, r)); 7782 PetscCall(VecAYPX(r, -1.0, b)); 7783 } else { 7784 PetscUseTypeMethod(mat, residual, b, x, r); 7785 } 7786 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7787 PetscFunctionReturn(0); 7788 } 7789 7790 /*@C 7791 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7792 7793 Collective on mat 7794 7795 Input Parameters: 7796 + mat - the matrix 7797 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7798 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7799 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7800 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7801 always used. 7802 7803 Output Parameters: 7804 + n - number of local rows in the (possibly compressed) matrix, use NULL if not needed 7805 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix, use NULL if not needed 7806 . ja - the column indices, use NULL if not needed 7807 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7808 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7809 7810 Level: developer 7811 7812 Notes: 7813 You CANNOT change any of the ia[] or ja[] values. 7814 7815 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7816 7817 Fortran Notes: 7818 In Fortran use 7819 $ 7820 $ PetscInt ia(1), ja(1) 7821 $ PetscOffset iia, jja 7822 $ call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr) 7823 $ ! Access the ith and jth entries via ia(iia + i) and ja(jja + j) 7824 7825 or 7826 $ 7827 $ PetscInt, pointer :: ia(:),ja(:) 7828 $ call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7829 $ ! Access the ith and jth entries via ia(i) and ja(j) 7830 7831 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7832 @*/ 7833 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7834 { 7835 PetscFunctionBegin; 7836 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7837 PetscValidType(mat, 1); 7838 if (n) PetscValidIntPointer(n, 5); 7839 if (ia) PetscValidPointer(ia, 6); 7840 if (ja) PetscValidPointer(ja, 7); 7841 if (done) PetscValidBoolPointer(done, 8); 7842 MatCheckPreallocated(mat, 1); 7843 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7844 else { 7845 if (done) *done = PETSC_TRUE; 7846 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7847 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7848 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7849 } 7850 PetscFunctionReturn(0); 7851 } 7852 7853 /*@C 7854 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7855 7856 Collective on mat 7857 7858 Input Parameters: 7859 + mat - the matrix 7860 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7861 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7862 symmetrized 7863 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7864 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7865 always used. 7866 . n - number of columns in the (possibly compressed) matrix 7867 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7868 - ja - the row indices 7869 7870 Output Parameters: 7871 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7872 7873 Level: developer 7874 7875 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7876 @*/ 7877 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7878 { 7879 PetscFunctionBegin; 7880 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7881 PetscValidType(mat, 1); 7882 PetscValidIntPointer(n, 5); 7883 if (ia) PetscValidPointer(ia, 6); 7884 if (ja) PetscValidPointer(ja, 7); 7885 PetscValidBoolPointer(done, 8); 7886 MatCheckPreallocated(mat, 1); 7887 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7888 else { 7889 *done = PETSC_TRUE; 7890 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7891 } 7892 PetscFunctionReturn(0); 7893 } 7894 7895 /*@C 7896 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7897 7898 Collective on mat 7899 7900 Input Parameters: 7901 + mat - the matrix 7902 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7903 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7904 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7905 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7906 always used. 7907 . n - size of (possibly compressed) matrix 7908 . ia - the row pointers 7909 - ja - the column indices 7910 7911 Output Parameters: 7912 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7913 7914 Note: 7915 This routine zeros out n, ia, and ja. This is to prevent accidental 7916 us of the array after it has been restored. If you pass NULL, it will 7917 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7918 7919 Level: developer 7920 7921 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7922 @*/ 7923 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7924 { 7925 PetscFunctionBegin; 7926 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7927 PetscValidType(mat, 1); 7928 if (ia) PetscValidPointer(ia, 6); 7929 if (ja) PetscValidPointer(ja, 7); 7930 if (done) PetscValidBoolPointer(done, 8); 7931 MatCheckPreallocated(mat, 1); 7932 7933 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 7934 else { 7935 if (done) *done = PETSC_TRUE; 7936 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7937 if (n) *n = 0; 7938 if (ia) *ia = NULL; 7939 if (ja) *ja = NULL; 7940 } 7941 PetscFunctionReturn(0); 7942 } 7943 7944 /*@C 7945 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 7946 7947 Collective on Mat 7948 7949 Input Parameters: 7950 + mat - the matrix 7951 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7952 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7953 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7954 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7955 always used. 7956 7957 Output Parameters: 7958 + n - size of (possibly compressed) matrix 7959 . ia - the column pointers 7960 . ja - the row indices 7961 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7962 7963 Level: developer 7964 7965 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()` 7966 @*/ 7967 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7968 { 7969 PetscFunctionBegin; 7970 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7971 PetscValidType(mat, 1); 7972 if (ia) PetscValidPointer(ia, 6); 7973 if (ja) PetscValidPointer(ja, 7); 7974 PetscValidBoolPointer(done, 8); 7975 MatCheckPreallocated(mat, 1); 7976 7977 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 7978 else { 7979 *done = PETSC_TRUE; 7980 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7981 if (n) *n = 0; 7982 if (ia) *ia = NULL; 7983 if (ja) *ja = NULL; 7984 } 7985 PetscFunctionReturn(0); 7986 } 7987 7988 /*@C 7989 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 7990 7991 Collective on mat 7992 7993 Input Parameters: 7994 + mat - the matrix 7995 . ncolors - max color value 7996 . n - number of entries in colorarray 7997 - colorarray - array indicating color for each column 7998 7999 Output Parameters: 8000 . iscoloring - coloring generated using colorarray information 8001 8002 Level: developer 8003 8004 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()` 8005 @*/ 8006 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8007 { 8008 PetscFunctionBegin; 8009 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8010 PetscValidType(mat, 1); 8011 PetscValidIntPointer(colorarray, 4); 8012 PetscValidPointer(iscoloring, 5); 8013 MatCheckPreallocated(mat, 1); 8014 8015 if (!mat->ops->coloringpatch) { 8016 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8017 } else { 8018 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8019 } 8020 PetscFunctionReturn(0); 8021 } 8022 8023 /*@ 8024 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8025 8026 Logically Collective on mat 8027 8028 Input Parameter: 8029 . mat - the factored matrix to be reset 8030 8031 Notes: 8032 This routine should be used only with factored matrices formed by in-place 8033 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8034 format). This option can save memory, for example, when solving nonlinear 8035 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8036 ILU(0) preconditioner. 8037 8038 Note that one can specify in-place ILU(0) factorization by calling 8039 .vb 8040 PCType(pc,PCILU); 8041 PCFactorSeUseInPlace(pc); 8042 .ve 8043 or by using the options -pc_type ilu -pc_factor_in_place 8044 8045 In-place factorization ILU(0) can also be used as a local 8046 solver for the blocks within the block Jacobi or additive Schwarz 8047 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8048 for details on setting local solver options. 8049 8050 Most users should employ the `KSP` interface for linear solvers 8051 instead of working directly with matrix algebra routines such as this. 8052 See, e.g., `KSPCreate()`. 8053 8054 Level: developer 8055 8056 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8057 @*/ 8058 PetscErrorCode MatSetUnfactored(Mat mat) 8059 { 8060 PetscFunctionBegin; 8061 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8062 PetscValidType(mat, 1); 8063 MatCheckPreallocated(mat, 1); 8064 mat->factortype = MAT_FACTOR_NONE; 8065 if (!mat->ops->setunfactored) PetscFunctionReturn(0); 8066 PetscUseTypeMethod(mat, setunfactored); 8067 PetscFunctionReturn(0); 8068 } 8069 8070 /*MC 8071 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8072 8073 Synopsis: 8074 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8075 8076 Not collective 8077 8078 Input Parameter: 8079 . x - matrix 8080 8081 Output Parameters: 8082 + xx_v - the Fortran pointer to the array 8083 - ierr - error code 8084 8085 Example of Usage: 8086 .vb 8087 PetscScalar, pointer xx_v(:,:) 8088 .... 8089 call MatDenseGetArrayF90(x,xx_v,ierr) 8090 a = xx_v(3) 8091 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8092 .ve 8093 8094 Level: advanced 8095 8096 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8097 8098 M*/ 8099 8100 /*MC 8101 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8102 accessed with `MatDenseGetArrayF90()`. 8103 8104 Synopsis: 8105 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8106 8107 Not collective 8108 8109 Input Parameters: 8110 + x - matrix 8111 - xx_v - the Fortran90 pointer to the array 8112 8113 Output Parameter: 8114 . ierr - error code 8115 8116 Example of Usage: 8117 .vb 8118 PetscScalar, pointer xx_v(:,:) 8119 .... 8120 call MatDenseGetArrayF90(x,xx_v,ierr) 8121 a = xx_v(3) 8122 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8123 .ve 8124 8125 Level: advanced 8126 8127 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8128 8129 M*/ 8130 8131 /*MC 8132 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8133 8134 Synopsis: 8135 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8136 8137 Not collective 8138 8139 Input Parameter: 8140 . x - matrix 8141 8142 Output Parameters: 8143 + xx_v - the Fortran pointer to the array 8144 - ierr - error code 8145 8146 Example of Usage: 8147 .vb 8148 PetscScalar, pointer xx_v(:) 8149 .... 8150 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8151 a = xx_v(3) 8152 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8153 .ve 8154 8155 Level: advanced 8156 8157 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8158 8159 M*/ 8160 8161 /*MC 8162 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8163 accessed with `MatSeqAIJGetArrayF90()`. 8164 8165 Synopsis: 8166 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8167 8168 Not collective 8169 8170 Input Parameters: 8171 + x - matrix 8172 - xx_v - the Fortran90 pointer to the array 8173 8174 Output Parameter: 8175 . ierr - error code 8176 8177 Example of Usage: 8178 .vb 8179 PetscScalar, pointer xx_v(:) 8180 .... 8181 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8182 a = xx_v(3) 8183 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8184 .ve 8185 8186 Level: advanced 8187 8188 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8189 8190 M*/ 8191 8192 /*@ 8193 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8194 as the original matrix. 8195 8196 Collective on mat 8197 8198 Input Parameters: 8199 + mat - the original matrix 8200 . isrow - parallel IS containing the rows this processor should obtain 8201 . iscol - parallel IS containing all columns you wish to keep. Each process should list the columns that will be in IT's "diagonal part" in the new matrix. 8202 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8203 8204 Output Parameter: 8205 . newmat - the new submatrix, of the same type as the old 8206 8207 Level: advanced 8208 8209 Notes: 8210 The submatrix will be able to be multiplied with vectors using the same layout as iscol. 8211 8212 Some matrix types place restrictions on the row and column indices, such 8213 as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block; 8214 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8215 8216 The index sets may not have duplicate entries. 8217 8218 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8219 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8220 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8221 will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when 8222 you are finished using it. 8223 8224 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8225 the input matrix. 8226 8227 If iscol is NULL then all columns are obtained (not supported in Fortran). 8228 8229 Example usage: 8230 Consider the following 8x8 matrix with 34 non-zero values, that is 8231 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8232 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8233 as follows: 8234 8235 .vb 8236 1 2 0 | 0 3 0 | 0 4 8237 Proc0 0 5 6 | 7 0 0 | 8 0 8238 9 0 10 | 11 0 0 | 12 0 8239 ------------------------------------- 8240 13 0 14 | 15 16 17 | 0 0 8241 Proc1 0 18 0 | 19 20 21 | 0 0 8242 0 0 0 | 22 23 0 | 24 0 8243 ------------------------------------- 8244 Proc2 25 26 27 | 0 0 28 | 29 0 8245 30 0 0 | 31 32 33 | 0 34 8246 .ve 8247 8248 Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8249 8250 .vb 8251 2 0 | 0 3 0 | 0 8252 Proc0 5 6 | 7 0 0 | 8 8253 ------------------------------- 8254 Proc1 18 0 | 19 20 21 | 0 8255 ------------------------------- 8256 Proc2 26 27 | 0 0 28 | 29 8257 0 0 | 31 32 33 | 0 8258 .ve 8259 8260 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8261 @*/ 8262 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8263 { 8264 PetscMPIInt size; 8265 Mat *local; 8266 IS iscoltmp; 8267 PetscBool flg; 8268 8269 PetscFunctionBegin; 8270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8271 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8272 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8273 PetscValidPointer(newmat, 5); 8274 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8275 PetscValidType(mat, 1); 8276 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8277 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8278 8279 MatCheckPreallocated(mat, 1); 8280 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8281 8282 if (!iscol || isrow == iscol) { 8283 PetscBool stride; 8284 PetscMPIInt grabentirematrix = 0, grab; 8285 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8286 if (stride) { 8287 PetscInt first, step, n, rstart, rend; 8288 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8289 if (step == 1) { 8290 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8291 if (rstart == first) { 8292 PetscCall(ISGetLocalSize(isrow, &n)); 8293 if (n == rend - rstart) grabentirematrix = 1; 8294 } 8295 } 8296 } 8297 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8298 if (grab) { 8299 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8300 if (cll == MAT_INITIAL_MATRIX) { 8301 *newmat = mat; 8302 PetscCall(PetscObjectReference((PetscObject)mat)); 8303 } 8304 PetscFunctionReturn(0); 8305 } 8306 } 8307 8308 if (!iscol) { 8309 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8310 } else { 8311 iscoltmp = iscol; 8312 } 8313 8314 /* if original matrix is on just one processor then use submatrix generated */ 8315 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8316 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8317 goto setproperties; 8318 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8319 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8320 *newmat = *local; 8321 PetscCall(PetscFree(local)); 8322 goto setproperties; 8323 } else if (!mat->ops->createsubmatrix) { 8324 /* Create a new matrix type that implements the operation using the full matrix */ 8325 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8326 switch (cll) { 8327 case MAT_INITIAL_MATRIX: 8328 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8329 break; 8330 case MAT_REUSE_MATRIX: 8331 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8332 break; 8333 default: 8334 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8335 } 8336 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8337 goto setproperties; 8338 } 8339 8340 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8341 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8342 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8343 8344 setproperties: 8345 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8346 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8347 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8348 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8349 PetscFunctionReturn(0); 8350 } 8351 8352 /*@ 8353 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8354 8355 Not Collective 8356 8357 Input Parameters: 8358 + A - the matrix we wish to propagate options from 8359 - B - the matrix we wish to propagate options to 8360 8361 Level: beginner 8362 8363 Note: 8364 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8365 8366 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8367 @*/ 8368 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8369 { 8370 PetscFunctionBegin; 8371 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8372 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8373 B->symmetry_eternal = A->symmetry_eternal; 8374 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8375 B->symmetric = A->symmetric; 8376 B->structurally_symmetric = A->structurally_symmetric; 8377 B->spd = A->spd; 8378 B->hermitian = A->hermitian; 8379 PetscFunctionReturn(0); 8380 } 8381 8382 /*@ 8383 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8384 used during the assembly process to store values that belong to 8385 other processors. 8386 8387 Not Collective 8388 8389 Input Parameters: 8390 + mat - the matrix 8391 . size - the initial size of the stash. 8392 - bsize - the initial size of the block-stash(if used). 8393 8394 Options Database Keys: 8395 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8396 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8397 8398 Level: intermediate 8399 8400 Notes: 8401 The block-stash is used for values set with `MatSetValuesBlocked()` while 8402 the stash is used for values set with `MatSetValues()` 8403 8404 Run with the option -info and look for output of the form 8405 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8406 to determine the appropriate value, MM, to use for size and 8407 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8408 to determine the value, BMM to use for bsize 8409 8410 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8411 @*/ 8412 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8413 { 8414 PetscFunctionBegin; 8415 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8416 PetscValidType(mat, 1); 8417 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8418 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8419 PetscFunctionReturn(0); 8420 } 8421 8422 /*@ 8423 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8424 the matrix 8425 8426 Neighbor-wise Collective on mat 8427 8428 Input Parameters: 8429 + mat - the matrix 8430 . x,y - the vectors 8431 - w - where the result is stored 8432 8433 Level: intermediate 8434 8435 Notes: 8436 w may be the same vector as y. 8437 8438 This allows one to use either the restriction or interpolation (its transpose) 8439 matrix to do the interpolation 8440 8441 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8442 @*/ 8443 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8444 { 8445 PetscInt M, N, Ny; 8446 8447 PetscFunctionBegin; 8448 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8449 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8450 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8451 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8452 PetscCall(MatGetSize(A, &M, &N)); 8453 PetscCall(VecGetSize(y, &Ny)); 8454 if (M == Ny) { 8455 PetscCall(MatMultAdd(A, x, y, w)); 8456 } else { 8457 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8458 } 8459 PetscFunctionReturn(0); 8460 } 8461 8462 /*@ 8463 MatInterpolate - y = A*x or A'*x depending on the shape of 8464 the matrix 8465 8466 Neighbor-wise Collective on mat 8467 8468 Input Parameters: 8469 + mat - the matrix 8470 - x,y - the vectors 8471 8472 Level: intermediate 8473 8474 Note: 8475 This allows one to use either the restriction or interpolation (its transpose) 8476 matrix to do the interpolation 8477 8478 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8479 @*/ 8480 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8481 { 8482 PetscInt M, N, Ny; 8483 8484 PetscFunctionBegin; 8485 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8486 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8487 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8488 PetscCall(MatGetSize(A, &M, &N)); 8489 PetscCall(VecGetSize(y, &Ny)); 8490 if (M == Ny) { 8491 PetscCall(MatMult(A, x, y)); 8492 } else { 8493 PetscCall(MatMultTranspose(A, x, y)); 8494 } 8495 PetscFunctionReturn(0); 8496 } 8497 8498 /*@ 8499 MatRestrict - y = A*x or A'*x 8500 8501 Neighbor-wise Collective on Mat 8502 8503 Input Parameters: 8504 + mat - the matrix 8505 - x,y - the vectors 8506 8507 Level: intermediate 8508 8509 Note: 8510 This allows one to use either the restriction or interpolation (its transpose) 8511 matrix to do the restriction 8512 8513 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8514 @*/ 8515 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8516 { 8517 PetscInt M, N, Ny; 8518 8519 PetscFunctionBegin; 8520 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8521 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8522 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8523 PetscCall(MatGetSize(A, &M, &N)); 8524 PetscCall(VecGetSize(y, &Ny)); 8525 if (M == Ny) { 8526 PetscCall(MatMult(A, x, y)); 8527 } else { 8528 PetscCall(MatMultTranspose(A, x, y)); 8529 } 8530 PetscFunctionReturn(0); 8531 } 8532 8533 /*@ 8534 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8535 8536 Neighbor-wise Collective on Mat 8537 8538 Input Parameters: 8539 + mat - the matrix 8540 - w, x - the input dense matrices 8541 8542 Output Parameters: 8543 . y - the output dense matrix 8544 8545 Level: intermediate 8546 8547 Note: 8548 This allows one to use either the restriction or interpolation (its transpose) 8549 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8550 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8551 8552 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8553 @*/ 8554 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8555 { 8556 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8557 PetscBool trans = PETSC_TRUE; 8558 MatReuse reuse = MAT_INITIAL_MATRIX; 8559 8560 PetscFunctionBegin; 8561 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8562 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8563 PetscValidType(x, 2); 8564 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8565 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8566 PetscCall(MatGetSize(A, &M, &N)); 8567 PetscCall(MatGetSize(x, &Mx, &Nx)); 8568 if (N == Mx) trans = PETSC_FALSE; 8569 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); 8570 Mo = trans ? N : M; 8571 if (*y) { 8572 PetscCall(MatGetSize(*y, &My, &Ny)); 8573 if (Mo == My && Nx == Ny) { 8574 reuse = MAT_REUSE_MATRIX; 8575 } else { 8576 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); 8577 PetscCall(MatDestroy(y)); 8578 } 8579 } 8580 8581 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8582 PetscBool flg; 8583 8584 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8585 if (w) { 8586 PetscInt My, Ny, Mw, Nw; 8587 8588 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8589 PetscCall(MatGetSize(*y, &My, &Ny)); 8590 PetscCall(MatGetSize(w, &Mw, &Nw)); 8591 if (!flg || My != Mw || Ny != Nw) w = NULL; 8592 } 8593 if (!w) { 8594 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8595 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8596 PetscCall(PetscObjectDereference((PetscObject)w)); 8597 } else { 8598 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8599 } 8600 } 8601 if (!trans) { 8602 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8603 } else { 8604 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8605 } 8606 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8607 PetscFunctionReturn(0); 8608 } 8609 8610 /*@ 8611 MatMatInterpolate - Y = A*X or A'*X 8612 8613 Neighbor-wise Collective on Mat 8614 8615 Input Parameters: 8616 + mat - the matrix 8617 - x - the input dense matrix 8618 8619 Output Parameters: 8620 . y - the output dense matrix 8621 8622 Level: intermediate 8623 8624 Note: 8625 This allows one to use either the restriction or interpolation (its transpose) 8626 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8627 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8628 8629 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8630 @*/ 8631 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8632 { 8633 PetscFunctionBegin; 8634 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8635 PetscFunctionReturn(0); 8636 } 8637 8638 /*@ 8639 MatMatRestrict - Y = A*X or A'*X 8640 8641 Neighbor-wise Collective on Mat 8642 8643 Input Parameters: 8644 + mat - the matrix 8645 - x - the input dense matrix 8646 8647 Output Parameters: 8648 . y - the output dense matrix 8649 8650 Level: intermediate 8651 8652 Note: 8653 This allows one to use either the restriction or interpolation (its transpose) 8654 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8655 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8656 8657 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8658 @*/ 8659 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8660 { 8661 PetscFunctionBegin; 8662 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8663 PetscFunctionReturn(0); 8664 } 8665 8666 /*@ 8667 MatGetNullSpace - retrieves the null space of a matrix. 8668 8669 Logically Collective on mat 8670 8671 Input Parameters: 8672 + mat - the matrix 8673 - nullsp - the null space object 8674 8675 Level: developer 8676 8677 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8678 @*/ 8679 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8680 { 8681 PetscFunctionBegin; 8682 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8683 PetscValidPointer(nullsp, 2); 8684 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8685 PetscFunctionReturn(0); 8686 } 8687 8688 /*@ 8689 MatSetNullSpace - attaches a null space to a matrix. 8690 8691 Logically Collective on mat 8692 8693 Input Parameters: 8694 + mat - the matrix 8695 - nullsp - the null space object 8696 8697 Level: advanced 8698 8699 Notes: 8700 This null space is used by the `KSP` linear solvers to solve singular systems. 8701 8702 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 8703 8704 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 8705 to zero but the linear system will still be solved in a least squares sense. 8706 8707 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8708 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). 8709 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 8710 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 8711 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). 8712 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8713 8714 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8715 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8716 routine also automatically calls `MatSetTransposeNullSpace()`. 8717 8718 The user should call `MatNullSpaceDestroy()`. 8719 8720 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8721 `KSPSetPCSide()` 8722 @*/ 8723 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8724 { 8725 PetscFunctionBegin; 8726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8727 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8728 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8729 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8730 mat->nullsp = nullsp; 8731 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8732 PetscFunctionReturn(0); 8733 } 8734 8735 /*@ 8736 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8737 8738 Logically Collective on mat 8739 8740 Input Parameters: 8741 + mat - the matrix 8742 - nullsp - the null space object 8743 8744 Level: developer 8745 8746 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8747 @*/ 8748 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8749 { 8750 PetscFunctionBegin; 8751 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8752 PetscValidType(mat, 1); 8753 PetscValidPointer(nullsp, 2); 8754 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8755 PetscFunctionReturn(0); 8756 } 8757 8758 /*@ 8759 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8760 8761 Logically Collective on mat 8762 8763 Input Parameters: 8764 + mat - the matrix 8765 - nullsp - the null space object 8766 8767 Level: advanced 8768 8769 Notes: 8770 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8771 8772 See `MatSetNullSpace()` 8773 8774 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8775 @*/ 8776 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8777 { 8778 PetscFunctionBegin; 8779 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8780 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8781 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8782 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8783 mat->transnullsp = nullsp; 8784 PetscFunctionReturn(0); 8785 } 8786 8787 /*@ 8788 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8789 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8790 8791 Logically Collective on mat 8792 8793 Input Parameters: 8794 + mat - the matrix 8795 - nullsp - the null space object 8796 8797 Level: advanced 8798 8799 Notes: 8800 Overwrites any previous near null space that may have been attached 8801 8802 You can remove the null space by calling this routine with an nullsp of NULL 8803 8804 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8805 @*/ 8806 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8807 { 8808 PetscFunctionBegin; 8809 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8810 PetscValidType(mat, 1); 8811 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8812 MatCheckPreallocated(mat, 1); 8813 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8814 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8815 mat->nearnullsp = nullsp; 8816 PetscFunctionReturn(0); 8817 } 8818 8819 /*@ 8820 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8821 8822 Not Collective 8823 8824 Input Parameter: 8825 . mat - the matrix 8826 8827 Output Parameter: 8828 . nullsp - the null space object, NULL if not set 8829 8830 Level: advanced 8831 8832 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8833 @*/ 8834 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8835 { 8836 PetscFunctionBegin; 8837 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8838 PetscValidType(mat, 1); 8839 PetscValidPointer(nullsp, 2); 8840 MatCheckPreallocated(mat, 1); 8841 *nullsp = mat->nearnullsp; 8842 PetscFunctionReturn(0); 8843 } 8844 8845 /*@C 8846 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8847 8848 Collective on mat 8849 8850 Input Parameters: 8851 + mat - the matrix 8852 . row - row/column permutation 8853 . fill - expected fill factor >= 1.0 8854 - level - level of fill, for ICC(k) 8855 8856 Notes: 8857 Probably really in-place only when level of fill is zero, otherwise allocates 8858 new space to store factored matrix and deletes previous memory. 8859 8860 Most users should employ the `KSP` interface for linear solvers 8861 instead of working directly with matrix algebra routines such as this. 8862 See, e.g., `KSPCreate()`. 8863 8864 Level: developer 8865 8866 Developer Note: 8867 The Fortran interface is not autogenerated as the f90 8868 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8869 8870 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8871 @*/ 8872 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8873 { 8874 PetscFunctionBegin; 8875 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8876 PetscValidType(mat, 1); 8877 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8878 PetscValidPointer(info, 3); 8879 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8880 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8881 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8882 MatCheckPreallocated(mat, 1); 8883 PetscUseTypeMethod(mat, iccfactor, row, info); 8884 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8885 PetscFunctionReturn(0); 8886 } 8887 8888 /*@ 8889 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8890 ghosted ones. 8891 8892 Not Collective 8893 8894 Input Parameters: 8895 + mat - the matrix 8896 - diag - the diagonal values, including ghost ones 8897 8898 Level: developer 8899 8900 Notes: 8901 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8902 8903 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8904 8905 .seealso: `MatDiagonalScale()` 8906 @*/ 8907 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8908 { 8909 PetscMPIInt size; 8910 8911 PetscFunctionBegin; 8912 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8913 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8914 PetscValidType(mat, 1); 8915 8916 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8917 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8918 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8919 if (size == 1) { 8920 PetscInt n, m; 8921 PetscCall(VecGetSize(diag, &n)); 8922 PetscCall(MatGetSize(mat, NULL, &m)); 8923 if (m == n) { 8924 PetscCall(MatDiagonalScale(mat, NULL, diag)); 8925 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 8926 } else { 8927 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 8928 } 8929 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 8930 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8931 PetscFunctionReturn(0); 8932 } 8933 8934 /*@ 8935 MatGetInertia - Gets the inertia from a factored matrix 8936 8937 Collective on mat 8938 8939 Input Parameter: 8940 . mat - the matrix 8941 8942 Output Parameters: 8943 + nneg - number of negative eigenvalues 8944 . nzero - number of zero eigenvalues 8945 - npos - number of positive eigenvalues 8946 8947 Level: advanced 8948 8949 Note: 8950 Matrix must have been factored by `MatCholeskyFactor()` 8951 8952 .seealso: `MatGetFactor()`, `MatCholeskyFactor()` 8953 @*/ 8954 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 8955 { 8956 PetscFunctionBegin; 8957 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8958 PetscValidType(mat, 1); 8959 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 8960 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 8961 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 8962 PetscFunctionReturn(0); 8963 } 8964 8965 /* ----------------------------------------------------------------*/ 8966 /*@C 8967 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 8968 8969 Neighbor-wise Collective on mat 8970 8971 Input Parameters: 8972 + mat - the factored matrix obtained with `MatGetFactor()` 8973 - b - the right-hand-side vectors 8974 8975 Output Parameter: 8976 . x - the result vectors 8977 8978 Note: 8979 The vectors b and x cannot be the same. I.e., one cannot 8980 call `MatSolves`(A,x,x). 8981 8982 Level: developer 8983 8984 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 8985 @*/ 8986 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 8987 { 8988 PetscFunctionBegin; 8989 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8990 PetscValidType(mat, 1); 8991 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 8992 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 8993 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 8994 8995 MatCheckPreallocated(mat, 1); 8996 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 8997 PetscUseTypeMethod(mat, solves, b, x); 8998 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 8999 PetscFunctionReturn(0); 9000 } 9001 9002 /*@ 9003 MatIsSymmetric - Test whether a matrix is symmetric 9004 9005 Collective on mat 9006 9007 Input Parameters: 9008 + A - the matrix to test 9009 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9010 9011 Output Parameters: 9012 . flg - the result 9013 9014 Notes: 9015 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9016 9017 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9018 9019 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9020 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9021 9022 Level: intermediate 9023 9024 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9025 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9026 @*/ 9027 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9028 { 9029 PetscFunctionBegin; 9030 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9031 PetscValidBoolPointer(flg, 3); 9032 9033 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9034 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9035 else { 9036 if (!A->ops->issymmetric) { 9037 MatType mattype; 9038 PetscCall(MatGetType(A, &mattype)); 9039 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype); 9040 } 9041 PetscUseTypeMethod(A, issymmetric, tol, flg); 9042 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9043 } 9044 PetscFunctionReturn(0); 9045 } 9046 9047 /*@ 9048 MatIsHermitian - Test whether a matrix is Hermitian 9049 9050 Collective on Mat 9051 9052 Input Parameters: 9053 + A - the matrix to test 9054 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9055 9056 Output Parameters: 9057 . flg - the result 9058 9059 Level: intermediate 9060 9061 Notes: 9062 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9063 9064 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9065 9066 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9067 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9068 9069 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9070 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9071 @*/ 9072 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9073 { 9074 PetscFunctionBegin; 9075 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9076 PetscValidBoolPointer(flg, 3); 9077 9078 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9079 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9080 else { 9081 if (!A->ops->ishermitian) { 9082 MatType mattype; 9083 PetscCall(MatGetType(A, &mattype)); 9084 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype); 9085 } 9086 PetscUseTypeMethod(A, ishermitian, tol, flg); 9087 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9088 } 9089 PetscFunctionReturn(0); 9090 } 9091 9092 /*@ 9093 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9094 9095 Not Collective 9096 9097 Input Parameter: 9098 . A - the matrix to check 9099 9100 Output Parameters: 9101 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9102 - flg - the result (only valid if set is `PETSC_TRUE`) 9103 9104 Level: advanced 9105 9106 Notes: 9107 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9108 if you want it explicitly checked 9109 9110 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9111 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9112 9113 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9114 @*/ 9115 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9116 { 9117 PetscFunctionBegin; 9118 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9119 PetscValidBoolPointer(set, 2); 9120 PetscValidBoolPointer(flg, 3); 9121 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9122 *set = PETSC_TRUE; 9123 *flg = PetscBool3ToBool(A->symmetric); 9124 } else { 9125 *set = PETSC_FALSE; 9126 } 9127 PetscFunctionReturn(0); 9128 } 9129 9130 /*@ 9131 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9132 9133 Not Collective 9134 9135 Input Parameter: 9136 . A - the matrix to check 9137 9138 Output Parameters: 9139 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9140 - flg - the result (only valid if set is `PETSC_TRUE`) 9141 9142 Level: advanced 9143 9144 Notes: 9145 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9146 9147 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9148 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9149 9150 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9151 @*/ 9152 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9153 { 9154 PetscFunctionBegin; 9155 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9156 PetscValidBoolPointer(set, 2); 9157 PetscValidBoolPointer(flg, 3); 9158 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9159 *set = PETSC_TRUE; 9160 *flg = PetscBool3ToBool(A->spd); 9161 } else { 9162 *set = PETSC_FALSE; 9163 } 9164 PetscFunctionReturn(0); 9165 } 9166 9167 /*@ 9168 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9169 9170 Not Collective 9171 9172 Input Parameter: 9173 . A - the matrix to check 9174 9175 Output Parameters: 9176 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9177 - flg - the result (only valid if set is `PETSC_TRUE`) 9178 9179 Level: advanced 9180 9181 Notes: 9182 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9183 if you want it explicitly checked 9184 9185 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9186 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9187 9188 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9189 @*/ 9190 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9191 { 9192 PetscFunctionBegin; 9193 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9194 PetscValidBoolPointer(set, 2); 9195 PetscValidBoolPointer(flg, 3); 9196 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9197 *set = PETSC_TRUE; 9198 *flg = PetscBool3ToBool(A->hermitian); 9199 } else { 9200 *set = PETSC_FALSE; 9201 } 9202 PetscFunctionReturn(0); 9203 } 9204 9205 /*@ 9206 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9207 9208 Collective on Mat 9209 9210 Input Parameter: 9211 . A - the matrix to test 9212 9213 Output Parameters: 9214 . flg - the result 9215 9216 Notes: 9217 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9218 9219 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 9220 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9221 9222 Level: intermediate 9223 9224 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9225 @*/ 9226 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9227 { 9228 PetscFunctionBegin; 9229 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9230 PetscValidBoolPointer(flg, 2); 9231 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9232 *flg = PetscBool3ToBool(A->structurally_symmetric); 9233 } else { 9234 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9235 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9236 } 9237 PetscFunctionReturn(0); 9238 } 9239 9240 /*@ 9241 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9242 9243 Not Collective 9244 9245 Input Parameter: 9246 . A - the matrix to check 9247 9248 Output Parameters: 9249 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9250 - flg - the result (only valid if set is PETSC_TRUE) 9251 9252 Level: advanced 9253 9254 Notes: 9255 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 9256 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9257 9258 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9259 9260 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9261 @*/ 9262 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9263 { 9264 PetscFunctionBegin; 9265 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9266 PetscValidBoolPointer(set, 2); 9267 PetscValidBoolPointer(flg, 3); 9268 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9269 *set = PETSC_TRUE; 9270 *flg = PetscBool3ToBool(A->structurally_symmetric); 9271 } else { 9272 *set = PETSC_FALSE; 9273 } 9274 PetscFunctionReturn(0); 9275 } 9276 9277 /*@ 9278 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9279 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9280 9281 Not collective 9282 9283 Input Parameter: 9284 . mat - the matrix 9285 9286 Output Parameters: 9287 + nstash - the size of the stash 9288 . reallocs - the number of additional mallocs incurred. 9289 . bnstash - the size of the block stash 9290 - breallocs - the number of additional mallocs incurred.in the block stash 9291 9292 Level: advanced 9293 9294 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9295 @*/ 9296 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9297 { 9298 PetscFunctionBegin; 9299 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9300 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9301 PetscFunctionReturn(0); 9302 } 9303 9304 /*@C 9305 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9306 parallel layout, `PetscLayout` for rows and columns 9307 9308 Collective on mat 9309 9310 Input Parameter: 9311 . mat - the matrix 9312 9313 Output Parameters: 9314 + right - (optional) vector that the matrix can be multiplied against 9315 - left - (optional) vector that the matrix vector product can be stored in 9316 9317 Notes: 9318 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()`. 9319 9320 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9321 9322 Level: advanced 9323 9324 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9325 @*/ 9326 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9327 { 9328 PetscFunctionBegin; 9329 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9330 PetscValidType(mat, 1); 9331 if (mat->ops->getvecs) { 9332 PetscUseTypeMethod(mat, getvecs, right, left); 9333 } else { 9334 PetscInt rbs, cbs; 9335 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9336 if (right) { 9337 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9338 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9339 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9340 PetscCall(VecSetBlockSize(*right, cbs)); 9341 PetscCall(VecSetType(*right, mat->defaultvectype)); 9342 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9343 if (mat->boundtocpu && mat->bindingpropagates) { 9344 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9345 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9346 } 9347 #endif 9348 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9349 } 9350 if (left) { 9351 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9352 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9353 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9354 PetscCall(VecSetBlockSize(*left, rbs)); 9355 PetscCall(VecSetType(*left, mat->defaultvectype)); 9356 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9357 if (mat->boundtocpu && mat->bindingpropagates) { 9358 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9359 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9360 } 9361 #endif 9362 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9363 } 9364 } 9365 PetscFunctionReturn(0); 9366 } 9367 9368 /*@C 9369 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9370 with default values. 9371 9372 Not Collective 9373 9374 Input Parameters: 9375 . info - the `MatFactorInfo` data structure 9376 9377 Notes: 9378 The solvers are generally used through the `KSP` and `PC` objects, for example 9379 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9380 9381 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9382 9383 Level: developer 9384 9385 Developer Note: 9386 The Fortran interface is not autogenerated as the f90 9387 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9388 9389 .seealso: `MatGetFactor()`, `MatFactorInfo` 9390 @*/ 9391 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9392 { 9393 PetscFunctionBegin; 9394 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9395 PetscFunctionReturn(0); 9396 } 9397 9398 /*@ 9399 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9400 9401 Collective on mat 9402 9403 Input Parameters: 9404 + mat - the factored matrix 9405 - is - the index set defining the Schur indices (0-based) 9406 9407 Notes: 9408 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9409 9410 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9411 9412 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9413 9414 Level: advanced 9415 9416 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9417 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9418 9419 @*/ 9420 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9421 { 9422 PetscErrorCode (*f)(Mat, IS); 9423 9424 PetscFunctionBegin; 9425 PetscValidType(mat, 1); 9426 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9427 PetscValidType(is, 2); 9428 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9429 PetscCheckSameComm(mat, 1, is, 2); 9430 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9431 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9432 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9433 PetscCall(MatDestroy(&mat->schur)); 9434 PetscCall((*f)(mat, is)); 9435 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9436 PetscFunctionReturn(0); 9437 } 9438 9439 /*@ 9440 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9441 9442 Logically Collective on mat 9443 9444 Input Parameters: 9445 + F - the factored matrix obtained by calling `MatGetFactor()` 9446 . S - location where to return the Schur complement, can be NULL 9447 - status - the status of the Schur complement matrix, can be NULL 9448 9449 Notes: 9450 You must call `MatFactorSetSchurIS()` before calling this routine. 9451 9452 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9453 9454 The routine provides a copy of the Schur matrix stored within the solver data structures. 9455 The caller must destroy the object when it is no longer needed. 9456 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9457 9458 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) 9459 9460 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9461 9462 Developer Note: 9463 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9464 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9465 9466 Level: advanced 9467 9468 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9469 @*/ 9470 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9471 { 9472 PetscFunctionBegin; 9473 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9474 if (S) PetscValidPointer(S, 2); 9475 if (status) PetscValidPointer(status, 3); 9476 if (S) { 9477 PetscErrorCode (*f)(Mat, Mat *); 9478 9479 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9480 if (f) { 9481 PetscCall((*f)(F, S)); 9482 } else { 9483 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9484 } 9485 } 9486 if (status) *status = F->schur_status; 9487 PetscFunctionReturn(0); 9488 } 9489 9490 /*@ 9491 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9492 9493 Logically Collective on mat 9494 9495 Input Parameters: 9496 + F - the factored matrix obtained by calling `MatGetFactor()` 9497 . *S - location where to return the Schur complement, can be NULL 9498 - status - the status of the Schur complement matrix, can be NULL 9499 9500 Notes: 9501 You must call `MatFactorSetSchurIS()` before calling this routine. 9502 9503 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9504 9505 The routine returns a the Schur Complement stored within the data strutures of the solver. 9506 9507 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9508 9509 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9510 9511 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9512 9513 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9514 9515 Level: advanced 9516 9517 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9518 @*/ 9519 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9520 { 9521 PetscFunctionBegin; 9522 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9523 if (S) PetscValidPointer(S, 2); 9524 if (status) PetscValidPointer(status, 3); 9525 if (S) *S = F->schur; 9526 if (status) *status = F->schur_status; 9527 PetscFunctionReturn(0); 9528 } 9529 9530 /*@ 9531 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9532 9533 Logically Collective on mat 9534 9535 Input Parameters: 9536 + F - the factored matrix obtained by calling `MatGetFactor()` 9537 . *S - location where the Schur complement is stored 9538 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9539 9540 Level: advanced 9541 9542 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9543 @*/ 9544 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9545 { 9546 PetscFunctionBegin; 9547 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9548 if (S) { 9549 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9550 *S = NULL; 9551 } 9552 F->schur_status = status; 9553 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9554 PetscFunctionReturn(0); 9555 } 9556 9557 /*@ 9558 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9559 9560 Logically Collective on mat 9561 9562 Input Parameters: 9563 + F - the factored matrix obtained by calling `MatGetFactor()` 9564 . rhs - location where the right hand side of the Schur complement system is stored 9565 - sol - location where the solution of the Schur complement system has to be returned 9566 9567 Notes: 9568 The sizes of the vectors should match the size of the Schur complement 9569 9570 Must be called after `MatFactorSetSchurIS()` 9571 9572 Level: advanced 9573 9574 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9575 @*/ 9576 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9577 { 9578 PetscFunctionBegin; 9579 PetscValidType(F, 1); 9580 PetscValidType(rhs, 2); 9581 PetscValidType(sol, 3); 9582 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9583 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9584 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9585 PetscCheckSameComm(F, 1, rhs, 2); 9586 PetscCheckSameComm(F, 1, sol, 3); 9587 PetscCall(MatFactorFactorizeSchurComplement(F)); 9588 switch (F->schur_status) { 9589 case MAT_FACTOR_SCHUR_FACTORED: 9590 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9591 break; 9592 case MAT_FACTOR_SCHUR_INVERTED: 9593 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9594 break; 9595 default: 9596 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9597 } 9598 PetscFunctionReturn(0); 9599 } 9600 9601 /*@ 9602 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9603 9604 Logically Collective on mat 9605 9606 Input Parameters: 9607 + F - the factored matrix obtained by calling `MatGetFactor()` 9608 . rhs - location where the right hand side of the Schur complement system is stored 9609 - sol - location where the solution of the Schur complement system has to be returned 9610 9611 Notes: 9612 The sizes of the vectors should match the size of the Schur complement 9613 9614 Must be called after `MatFactorSetSchurIS()` 9615 9616 Level: advanced 9617 9618 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9619 @*/ 9620 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9621 { 9622 PetscFunctionBegin; 9623 PetscValidType(F, 1); 9624 PetscValidType(rhs, 2); 9625 PetscValidType(sol, 3); 9626 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9627 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9628 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9629 PetscCheckSameComm(F, 1, rhs, 2); 9630 PetscCheckSameComm(F, 1, sol, 3); 9631 PetscCall(MatFactorFactorizeSchurComplement(F)); 9632 switch (F->schur_status) { 9633 case MAT_FACTOR_SCHUR_FACTORED: 9634 PetscCall(MatSolve(F->schur, rhs, sol)); 9635 break; 9636 case MAT_FACTOR_SCHUR_INVERTED: 9637 PetscCall(MatMult(F->schur, rhs, sol)); 9638 break; 9639 default: 9640 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9641 } 9642 PetscFunctionReturn(0); 9643 } 9644 9645 /*@ 9646 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9647 9648 Logically Collective on F 9649 9650 Input Parameters: 9651 . F - the factored matrix obtained by calling `MatGetFactor()` 9652 9653 Notes: 9654 Must be called after `MatFactorSetSchurIS()`. 9655 9656 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9657 9658 Level: advanced 9659 9660 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9661 @*/ 9662 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9663 { 9664 PetscFunctionBegin; 9665 PetscValidType(F, 1); 9666 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9667 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0); 9668 PetscCall(MatFactorFactorizeSchurComplement(F)); 9669 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9670 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9671 PetscFunctionReturn(0); 9672 } 9673 9674 /*@ 9675 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9676 9677 Logically Collective on mat 9678 9679 Input Parameters: 9680 . F - the factored matrix obtained by calling `MatGetFactor()` 9681 9682 Note: 9683 Must be called after `MatFactorSetSchurIS()` 9684 9685 Level: advanced 9686 9687 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9688 @*/ 9689 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9690 { 9691 PetscFunctionBegin; 9692 PetscValidType(F, 1); 9693 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9694 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0); 9695 PetscCall(MatFactorFactorizeSchurComplement_Private(F)); 9696 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9697 PetscFunctionReturn(0); 9698 } 9699 9700 /*@ 9701 MatPtAP - Creates the matrix product C = P^T * A * P 9702 9703 Neighbor-wise Collective on A 9704 9705 Input Parameters: 9706 + A - the matrix 9707 . P - the projection matrix 9708 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9709 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9710 if the result is a dense matrix this is irrelevant 9711 9712 Output Parameters: 9713 . C - the product matrix 9714 9715 Notes: 9716 C will be created and must be destroyed by the user with `MatDestroy()`. 9717 9718 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9719 9720 Developer Note: 9721 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9722 9723 Level: intermediate 9724 9725 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9726 @*/ 9727 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9728 { 9729 PetscFunctionBegin; 9730 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9731 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9732 9733 if (scall == MAT_INITIAL_MATRIX) { 9734 PetscCall(MatProductCreate(A, P, NULL, C)); 9735 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9736 PetscCall(MatProductSetAlgorithm(*C, "default")); 9737 PetscCall(MatProductSetFill(*C, fill)); 9738 9739 (*C)->product->api_user = PETSC_TRUE; 9740 PetscCall(MatProductSetFromOptions(*C)); 9741 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); 9742 PetscCall(MatProductSymbolic(*C)); 9743 } else { /* scall == MAT_REUSE_MATRIX */ 9744 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9745 } 9746 9747 PetscCall(MatProductNumeric(*C)); 9748 (*C)->symmetric = A->symmetric; 9749 (*C)->spd = A->spd; 9750 PetscFunctionReturn(0); 9751 } 9752 9753 /*@ 9754 MatRARt - Creates the matrix product C = R * A * R^T 9755 9756 Neighbor-wise Collective on A 9757 9758 Input Parameters: 9759 + A - the matrix 9760 . R - the projection matrix 9761 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9762 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9763 if the result is a dense matrix this is irrelevant 9764 9765 Output Parameters: 9766 . C - the product matrix 9767 9768 Notes: 9769 C will be created and must be destroyed by the user with `MatDestroy()`. 9770 9771 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9772 9773 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9774 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9775 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9776 We recommend using MatPtAP(). 9777 9778 Level: intermediate 9779 9780 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9781 @*/ 9782 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9783 { 9784 PetscFunctionBegin; 9785 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9786 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9787 9788 if (scall == MAT_INITIAL_MATRIX) { 9789 PetscCall(MatProductCreate(A, R, NULL, C)); 9790 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9791 PetscCall(MatProductSetAlgorithm(*C, "default")); 9792 PetscCall(MatProductSetFill(*C, fill)); 9793 9794 (*C)->product->api_user = PETSC_TRUE; 9795 PetscCall(MatProductSetFromOptions(*C)); 9796 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); 9797 PetscCall(MatProductSymbolic(*C)); 9798 } else { /* scall == MAT_REUSE_MATRIX */ 9799 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9800 } 9801 9802 PetscCall(MatProductNumeric(*C)); 9803 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9804 PetscFunctionReturn(0); 9805 } 9806 9807 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9808 { 9809 PetscFunctionBegin; 9810 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9811 9812 if (scall == MAT_INITIAL_MATRIX) { 9813 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9814 PetscCall(MatProductCreate(A, B, NULL, C)); 9815 PetscCall(MatProductSetType(*C, ptype)); 9816 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9817 PetscCall(MatProductSetFill(*C, fill)); 9818 9819 (*C)->product->api_user = PETSC_TRUE; 9820 PetscCall(MatProductSetFromOptions(*C)); 9821 PetscCall(MatProductSymbolic(*C)); 9822 } else { /* scall == MAT_REUSE_MATRIX */ 9823 Mat_Product *product = (*C)->product; 9824 PetscBool isdense; 9825 9826 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9827 if (isdense && product && product->type != ptype) { 9828 PetscCall(MatProductClear(*C)); 9829 product = NULL; 9830 } 9831 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9832 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9833 if (isdense) { 9834 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9835 product = (*C)->product; 9836 product->fill = fill; 9837 product->api_user = PETSC_TRUE; 9838 product->clear = PETSC_TRUE; 9839 9840 PetscCall(MatProductSetType(*C, ptype)); 9841 PetscCall(MatProductSetFromOptions(*C)); 9842 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); 9843 PetscCall(MatProductSymbolic(*C)); 9844 } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9845 } else { /* user may change input matrices A or B when REUSE */ 9846 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9847 } 9848 } 9849 PetscCall(MatProductNumeric(*C)); 9850 PetscFunctionReturn(0); 9851 } 9852 9853 /*@ 9854 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9855 9856 Neighbor-wise Collective on A 9857 9858 Input Parameters: 9859 + A - the left matrix 9860 . B - the right matrix 9861 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9862 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9863 if the result is a dense matrix this is irrelevant 9864 9865 Output Parameters: 9866 . C - the product matrix 9867 9868 Notes: 9869 Unless scall is `MAT_REUSE_MATRIX` C will be created. 9870 9871 `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 9872 call to this function with `MAT_INITIAL_MATRIX`. 9873 9874 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 9875 9876 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`, 9877 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 9878 9879 Example of Usage: 9880 .vb 9881 MatProductCreate(A,B,NULL,&C); 9882 MatProductSetType(C,MATPRODUCT_AB); 9883 MatProductSymbolic(C); 9884 MatProductNumeric(C); // compute C=A * B 9885 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 9886 MatProductNumeric(C); 9887 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 9888 MatProductNumeric(C); 9889 .ve 9890 9891 Level: intermediate 9892 9893 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 9894 @*/ 9895 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9896 { 9897 PetscFunctionBegin; 9898 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 9899 PetscFunctionReturn(0); 9900 } 9901 9902 /*@ 9903 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 9904 9905 Neighbor-wise Collective on A 9906 9907 Input Parameters: 9908 + A - the left matrix 9909 . B - the right matrix 9910 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9911 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9912 9913 Output Parameters: 9914 . C - the product matrix 9915 9916 Notes: 9917 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 9918 9919 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 9920 9921 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9922 actually needed. 9923 9924 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 9925 and for pairs of `MATMPIDENSE` matrices. 9926 9927 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 9928 9929 Options Database Keys: 9930 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 9931 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 9932 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 9933 9934 Level: intermediate 9935 9936 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 9937 @*/ 9938 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9939 { 9940 PetscFunctionBegin; 9941 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 9942 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9943 PetscFunctionReturn(0); 9944 } 9945 9946 /*@ 9947 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 9948 9949 Neighbor-wise Collective on A 9950 9951 Input Parameters: 9952 + A - the left matrix 9953 . B - the right matrix 9954 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9955 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9956 9957 Output Parameters: 9958 . C - the product matrix 9959 9960 Notes: 9961 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 9962 9963 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 9964 9965 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 9966 9967 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9968 actually needed. 9969 9970 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 9971 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 9972 9973 Level: intermediate 9974 9975 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 9976 @*/ 9977 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9978 { 9979 PetscFunctionBegin; 9980 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 9981 PetscFunctionReturn(0); 9982 } 9983 9984 /*@ 9985 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 9986 9987 Neighbor-wise Collective on A 9988 9989 Input Parameters: 9990 + A - the left matrix 9991 . B - the middle matrix 9992 . C - the right matrix 9993 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9994 - 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 9995 if the result is a dense matrix this is irrelevant 9996 9997 Output Parameters: 9998 . D - the product matrix 9999 10000 Notes: 10001 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10002 10003 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10004 10005 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10006 10007 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10008 actually needed. 10009 10010 If you have many matrices with the same non-zero structure to multiply, you 10011 should use `MAT_REUSE_MATRIX` in all calls but the first 10012 10013 Level: intermediate 10014 10015 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10016 @*/ 10017 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10018 { 10019 PetscFunctionBegin; 10020 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10021 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10022 10023 if (scall == MAT_INITIAL_MATRIX) { 10024 PetscCall(MatProductCreate(A, B, C, D)); 10025 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10026 PetscCall(MatProductSetAlgorithm(*D, "default")); 10027 PetscCall(MatProductSetFill(*D, fill)); 10028 10029 (*D)->product->api_user = PETSC_TRUE; 10030 PetscCall(MatProductSetFromOptions(*D)); 10031 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, 10032 ((PetscObject)C)->type_name); 10033 PetscCall(MatProductSymbolic(*D)); 10034 } else { /* user may change input matrices when REUSE */ 10035 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10036 } 10037 PetscCall(MatProductNumeric(*D)); 10038 PetscFunctionReturn(0); 10039 } 10040 10041 /*@ 10042 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10043 10044 Collective on mat 10045 10046 Input Parameters: 10047 + mat - the matrix 10048 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10049 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10050 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10051 10052 Output Parameter: 10053 . matredundant - redundant matrix 10054 10055 Notes: 10056 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10057 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10058 10059 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10060 calling it. 10061 10062 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10063 10064 Level: advanced 10065 10066 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10067 @*/ 10068 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10069 { 10070 MPI_Comm comm; 10071 PetscMPIInt size; 10072 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10073 Mat_Redundant *redund = NULL; 10074 PetscSubcomm psubcomm = NULL; 10075 MPI_Comm subcomm_in = subcomm; 10076 Mat *matseq; 10077 IS isrow, iscol; 10078 PetscBool newsubcomm = PETSC_FALSE; 10079 10080 PetscFunctionBegin; 10081 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10082 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10083 PetscValidPointer(*matredundant, 5); 10084 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10085 } 10086 10087 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10088 if (size == 1 || nsubcomm == 1) { 10089 if (reuse == MAT_INITIAL_MATRIX) { 10090 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10091 } else { 10092 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"); 10093 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10094 } 10095 PetscFunctionReturn(0); 10096 } 10097 10098 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10099 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10100 MatCheckPreallocated(mat, 1); 10101 10102 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10103 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10104 /* create psubcomm, then get subcomm */ 10105 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10106 PetscCallMPI(MPI_Comm_size(comm, &size)); 10107 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10108 10109 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10110 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10111 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10112 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10113 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10114 newsubcomm = PETSC_TRUE; 10115 PetscCall(PetscSubcommDestroy(&psubcomm)); 10116 } 10117 10118 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10119 if (reuse == MAT_INITIAL_MATRIX) { 10120 mloc_sub = PETSC_DECIDE; 10121 nloc_sub = PETSC_DECIDE; 10122 if (bs < 1) { 10123 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10124 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10125 } else { 10126 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10127 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10128 } 10129 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10130 rstart = rend - mloc_sub; 10131 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10132 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10133 } else { /* reuse == MAT_REUSE_MATRIX */ 10134 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"); 10135 /* retrieve subcomm */ 10136 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10137 redund = (*matredundant)->redundant; 10138 isrow = redund->isrow; 10139 iscol = redund->iscol; 10140 matseq = redund->matseq; 10141 } 10142 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10143 10144 /* get matredundant over subcomm */ 10145 if (reuse == MAT_INITIAL_MATRIX) { 10146 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10147 10148 /* create a supporting struct and attach it to C for reuse */ 10149 PetscCall(PetscNew(&redund)); 10150 (*matredundant)->redundant = redund; 10151 redund->isrow = isrow; 10152 redund->iscol = iscol; 10153 redund->matseq = matseq; 10154 if (newsubcomm) { 10155 redund->subcomm = subcomm; 10156 } else { 10157 redund->subcomm = MPI_COMM_NULL; 10158 } 10159 } else { 10160 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10161 } 10162 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10163 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10164 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10165 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10166 } 10167 #endif 10168 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10169 PetscFunctionReturn(0); 10170 } 10171 10172 /*@C 10173 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10174 a given `Mat`. Each submatrix can span multiple procs. 10175 10176 Collective on mat 10177 10178 Input Parameters: 10179 + mat - the matrix 10180 . subcomm - the subcommunicator obtained by MPI_Com_split(comm) 10181 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10182 10183 Output Parameter: 10184 . subMat - 'parallel submatrices each spans a given subcomm 10185 10186 Notes: 10187 The submatrix partition across processors is dictated by 'subComm' a 10188 communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm 10189 is not restriced to be grouped with consecutive original ranks. 10190 10191 Due the MPI_Comm_split() usage, the parallel layout of the submatrices 10192 map directly to the layout of the original matrix [wrt the local 10193 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10194 into the 'DiagonalMat' of the subMat, hence it is used directly from 10195 the subMat. However the offDiagMat looses some columns - and this is 10196 reconstructed with `MatSetValues()` 10197 10198 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10199 10200 Level: advanced 10201 10202 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10203 @*/ 10204 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10205 { 10206 PetscMPIInt commsize, subCommSize; 10207 10208 PetscFunctionBegin; 10209 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10210 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10211 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10212 10213 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"); 10214 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10215 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10216 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10217 PetscFunctionReturn(0); 10218 } 10219 10220 /*@ 10221 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10222 10223 Not Collective 10224 10225 Input Parameters: 10226 + mat - matrix to extract local submatrix from 10227 . isrow - local row indices for submatrix 10228 - iscol - local column indices for submatrix 10229 10230 Output Parameter: 10231 . submat - the submatrix 10232 10233 Level: intermediate 10234 10235 Notes: 10236 The submat should be returned with `MatRestoreLocalSubMatrix()`. 10237 10238 Depending on the format of mat, the returned submat may not implement `MatMult()`. Its communicator may be 10239 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's. 10240 10241 The submat always implements `MatSetValuesLocal()`. If isrow and iscol have the same block size, then 10242 `MatSetValuesBlockedLocal()` will also be implemented. 10243 10244 The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10245 Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided. 10246 10247 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10248 @*/ 10249 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10250 { 10251 PetscFunctionBegin; 10252 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10253 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10254 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10255 PetscCheckSameComm(isrow, 2, iscol, 3); 10256 PetscValidPointer(submat, 4); 10257 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10258 10259 if (mat->ops->getlocalsubmatrix) { 10260 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10261 } else { 10262 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10263 } 10264 PetscFunctionReturn(0); 10265 } 10266 10267 /*@ 10268 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10269 10270 Not Collective 10271 10272 Input Parameters: 10273 + mat - matrix to extract local submatrix from 10274 . isrow - local row indices for submatrix 10275 . iscol - local column indices for submatrix 10276 - submat - the submatrix 10277 10278 Level: intermediate 10279 10280 .seealso: `MatGetLocalSubMatrix()` 10281 @*/ 10282 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10283 { 10284 PetscFunctionBegin; 10285 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10286 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10287 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10288 PetscCheckSameComm(isrow, 2, iscol, 3); 10289 PetscValidPointer(submat, 4); 10290 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10291 10292 if (mat->ops->restorelocalsubmatrix) { 10293 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10294 } else { 10295 PetscCall(MatDestroy(submat)); 10296 } 10297 *submat = NULL; 10298 PetscFunctionReturn(0); 10299 } 10300 10301 /* --------------------------------------------------------*/ 10302 /*@ 10303 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10304 10305 Collective on mat 10306 10307 Input Parameter: 10308 . mat - the matrix 10309 10310 Output Parameter: 10311 . is - if any rows have zero diagonals this contains the list of them 10312 10313 Level: developer 10314 10315 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10316 @*/ 10317 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10318 { 10319 PetscFunctionBegin; 10320 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10321 PetscValidType(mat, 1); 10322 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10323 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10324 10325 if (!mat->ops->findzerodiagonals) { 10326 Vec diag; 10327 const PetscScalar *a; 10328 PetscInt *rows; 10329 PetscInt rStart, rEnd, r, nrow = 0; 10330 10331 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10332 PetscCall(MatGetDiagonal(mat, diag)); 10333 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10334 PetscCall(VecGetArrayRead(diag, &a)); 10335 for (r = 0; r < rEnd - rStart; ++r) 10336 if (a[r] == 0.0) ++nrow; 10337 PetscCall(PetscMalloc1(nrow, &rows)); 10338 nrow = 0; 10339 for (r = 0; r < rEnd - rStart; ++r) 10340 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10341 PetscCall(VecRestoreArrayRead(diag, &a)); 10342 PetscCall(VecDestroy(&diag)); 10343 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10344 } else { 10345 PetscUseTypeMethod(mat, findzerodiagonals, is); 10346 } 10347 PetscFunctionReturn(0); 10348 } 10349 10350 /*@ 10351 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10352 10353 Collective on mat 10354 10355 Input Parameter: 10356 . mat - the matrix 10357 10358 Output Parameter: 10359 . is - contains the list of rows with off block diagonal entries 10360 10361 Level: developer 10362 10363 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10364 @*/ 10365 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10366 { 10367 PetscFunctionBegin; 10368 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10369 PetscValidType(mat, 1); 10370 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10371 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10372 10373 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10374 PetscFunctionReturn(0); 10375 } 10376 10377 /*@C 10378 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10379 10380 Collective on mat 10381 10382 Input Parameters: 10383 . mat - the matrix 10384 10385 Output Parameters: 10386 . values - the block inverses in column major order (FORTRAN-like) 10387 10388 Notes: 10389 The size of the blocks is determined by the block size of the matrix. 10390 10391 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10392 10393 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10394 10395 Fortran Note: 10396 This routine is not available from Fortran. 10397 10398 Level: advanced 10399 10400 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10401 @*/ 10402 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10403 { 10404 PetscFunctionBegin; 10405 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10406 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10407 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10408 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10409 PetscFunctionReturn(0); 10410 } 10411 10412 /*@C 10413 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10414 10415 Collective on mat 10416 10417 Input Parameters: 10418 + mat - the matrix 10419 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10420 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10421 10422 Output Parameters: 10423 . values - the block inverses in column major order (FORTRAN-like) 10424 10425 Notes: 10426 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10427 10428 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10429 10430 Fortran Note: 10431 This routine is not available from Fortran. 10432 10433 Level: advanced 10434 10435 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10436 @*/ 10437 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10438 { 10439 PetscFunctionBegin; 10440 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10441 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10442 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10443 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10444 PetscFunctionReturn(0); 10445 } 10446 10447 /*@ 10448 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10449 10450 Collective on Mat 10451 10452 Input Parameters: 10453 + A - the matrix 10454 - C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 10455 10456 Note: 10457 The blocksize of the matrix is used to determine the blocks on the diagonal of C 10458 10459 Level: advanced 10460 10461 .seealso: `MatInvertBlockDiagonal()` 10462 @*/ 10463 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10464 { 10465 const PetscScalar *vals; 10466 PetscInt *dnnz; 10467 PetscInt m, rstart, rend, bs, i, j; 10468 10469 PetscFunctionBegin; 10470 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10471 PetscCall(MatGetBlockSize(A, &bs)); 10472 PetscCall(MatGetLocalSize(A, &m, NULL)); 10473 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10474 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10475 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10476 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10477 PetscCall(PetscFree(dnnz)); 10478 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10479 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10480 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10481 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10482 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10483 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10484 PetscFunctionReturn(0); 10485 } 10486 10487 /*@C 10488 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10489 via `MatTransposeColoringCreate()`. 10490 10491 Collective on c 10492 10493 Input Parameter: 10494 . c - coloring context 10495 10496 Level: intermediate 10497 10498 .seealso: `MatTransposeColoringCreate()` 10499 @*/ 10500 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10501 { 10502 MatTransposeColoring matcolor = *c; 10503 10504 PetscFunctionBegin; 10505 if (!matcolor) PetscFunctionReturn(0); 10506 if (--((PetscObject)matcolor)->refct > 0) { 10507 matcolor = NULL; 10508 PetscFunctionReturn(0); 10509 } 10510 10511 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10512 PetscCall(PetscFree(matcolor->rows)); 10513 PetscCall(PetscFree(matcolor->den2sp)); 10514 PetscCall(PetscFree(matcolor->colorforcol)); 10515 PetscCall(PetscFree(matcolor->columns)); 10516 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10517 PetscCall(PetscHeaderDestroy(c)); 10518 PetscFunctionReturn(0); 10519 } 10520 10521 /*@C 10522 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10523 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10524 `MatTransposeColoring` to sparse B. 10525 10526 Collective on coloring 10527 10528 Input Parameters: 10529 + B - sparse matrix B 10530 . Btdense - symbolic dense matrix B^T 10531 - coloring - coloring context created with `MatTransposeColoringCreate()` 10532 10533 Output Parameter: 10534 . Btdense - dense matrix B^T 10535 10536 Level: developer 10537 10538 Note: 10539 These are used internally for some implementations of `MatRARt()` 10540 10541 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10542 10543 @*/ 10544 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10545 { 10546 PetscFunctionBegin; 10547 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10548 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10549 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10550 10551 PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10552 PetscFunctionReturn(0); 10553 } 10554 10555 /*@C 10556 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10557 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10558 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10559 Csp from Cden. 10560 10561 Collective on matcoloring 10562 10563 Input Parameters: 10564 + coloring - coloring context created with `MatTransposeColoringCreate()` 10565 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10566 10567 Output Parameter: 10568 . Csp - sparse matrix 10569 10570 Level: developer 10571 10572 Note: 10573 These are used internally for some implementations of `MatRARt()` 10574 10575 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10576 10577 @*/ 10578 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10579 { 10580 PetscFunctionBegin; 10581 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10582 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10583 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10584 10585 PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10586 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10587 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10588 PetscFunctionReturn(0); 10589 } 10590 10591 /*@C 10592 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10593 10594 Collective on mat 10595 10596 Input Parameters: 10597 + mat - the matrix product C 10598 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10599 10600 Output Parameter: 10601 . color - the new coloring context 10602 10603 Level: intermediate 10604 10605 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10606 `MatTransColoringApplyDenToSp()` 10607 @*/ 10608 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10609 { 10610 MatTransposeColoring c; 10611 MPI_Comm comm; 10612 10613 PetscFunctionBegin; 10614 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10615 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10616 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10617 10618 c->ctype = iscoloring->ctype; 10619 if (mat->ops->transposecoloringcreate) { 10620 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10621 } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name); 10622 10623 *color = c; 10624 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10625 PetscFunctionReturn(0); 10626 } 10627 10628 /*@ 10629 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10630 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10631 same, otherwise it will be larger 10632 10633 Not Collective 10634 10635 Input Parameter: 10636 . A - the matrix 10637 10638 Output Parameter: 10639 . state - the current state 10640 10641 Notes: 10642 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10643 different matrices 10644 10645 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10646 10647 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10648 10649 Level: intermediate 10650 10651 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()` 10652 @*/ 10653 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10654 { 10655 PetscFunctionBegin; 10656 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10657 *state = mat->nonzerostate; 10658 PetscFunctionReturn(0); 10659 } 10660 10661 /*@ 10662 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10663 matrices from each processor 10664 10665 Collective 10666 10667 Input Parameters: 10668 + comm - the communicators the parallel matrix will live on 10669 . seqmat - the input sequential matrices 10670 . n - number of local columns (or `PETSC_DECIDE`) 10671 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10672 10673 Output Parameter: 10674 . mpimat - the parallel matrix generated 10675 10676 Level: developer 10677 10678 Note: 10679 The number of columns of the matrix in EACH processor MUST be the same. 10680 10681 .seealso: `Mat` 10682 @*/ 10683 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10684 { 10685 PetscMPIInt size; 10686 10687 PetscFunctionBegin; 10688 PetscCallMPI(MPI_Comm_size(comm, &size)); 10689 if (size == 1) { 10690 if (reuse == MAT_INITIAL_MATRIX) { 10691 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10692 } else { 10693 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10694 } 10695 PetscFunctionReturn(0); 10696 } 10697 10698 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"); 10699 10700 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10701 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10702 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10703 PetscFunctionReturn(0); 10704 } 10705 10706 /*@ 10707 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10708 10709 Collective on A 10710 10711 Input Parameters: 10712 + A - the matrix to create subdomains from 10713 - N - requested number of subdomains 10714 10715 Output Parameters: 10716 + n - number of subdomains resulting on this rank 10717 - iss - `IS` list with indices of subdomains on this rank 10718 10719 Level: advanced 10720 10721 Note: 10722 The number of subdomains must be smaller than the communicator size 10723 10724 .seealso: `Mat`, `IS` 10725 @*/ 10726 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10727 { 10728 MPI_Comm comm, subcomm; 10729 PetscMPIInt size, rank, color; 10730 PetscInt rstart, rend, k; 10731 10732 PetscFunctionBegin; 10733 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10734 PetscCallMPI(MPI_Comm_size(comm, &size)); 10735 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10736 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); 10737 *n = 1; 10738 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10739 color = rank / k; 10740 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10741 PetscCall(PetscMalloc1(1, iss)); 10742 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10743 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10744 PetscCallMPI(MPI_Comm_free(&subcomm)); 10745 PetscFunctionReturn(0); 10746 } 10747 10748 /*@ 10749 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10750 10751 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10752 If they are not the same, uses `MatMatMatMult()`. 10753 10754 Once the coarse grid problem is constructed, correct for interpolation operators 10755 that are not of full rank, which can legitimately happen in the case of non-nested 10756 geometric multigrid. 10757 10758 Input Parameters: 10759 + restrct - restriction operator 10760 . dA - fine grid matrix 10761 . interpolate - interpolation operator 10762 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10763 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10764 10765 Output Parameters: 10766 . A - the Galerkin coarse matrix 10767 10768 Options Database Key: 10769 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10770 10771 Level: developer 10772 10773 .seealso: `MatPtAP()`, `MatMatMatMult()` 10774 @*/ 10775 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10776 { 10777 IS zerorows; 10778 Vec diag; 10779 10780 PetscFunctionBegin; 10781 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10782 /* Construct the coarse grid matrix */ 10783 if (interpolate == restrct) { 10784 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10785 } else { 10786 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10787 } 10788 10789 /* If the interpolation matrix is not of full rank, A will have zero rows. 10790 This can legitimately happen in the case of non-nested geometric multigrid. 10791 In that event, we set the rows of the matrix to the rows of the identity, 10792 ignoring the equations (as the RHS will also be zero). */ 10793 10794 PetscCall(MatFindZeroRows(*A, &zerorows)); 10795 10796 if (zerorows != NULL) { /* if there are any zero rows */ 10797 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10798 PetscCall(MatGetDiagonal(*A, diag)); 10799 PetscCall(VecISSet(diag, zerorows, 1.0)); 10800 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10801 PetscCall(VecDestroy(&diag)); 10802 PetscCall(ISDestroy(&zerorows)); 10803 } 10804 PetscFunctionReturn(0); 10805 } 10806 10807 /*@C 10808 MatSetOperation - Allows user to set a matrix operation for any matrix type 10809 10810 Logically Collective on mat 10811 10812 Input Parameters: 10813 + mat - the matrix 10814 . op - the name of the operation 10815 - f - the function that provides the operation 10816 10817 Level: developer 10818 10819 Usage: 10820 $ extern PetscErrorCode usermult(Mat,Vec,Vec); 10821 $ PetscCall(MatCreateXXX(comm,...&A); 10822 $ PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult); 10823 10824 Notes: 10825 See the file include/petscmat.h for a complete list of matrix 10826 operations, which all have the form MATOP_<OPERATION>, where 10827 <OPERATION> is the name (in all capital letters) of the 10828 user interface routine (e.g., MatMult() -> MATOP_MULT). 10829 10830 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10831 sequence as the usual matrix interface routines, since they 10832 are intended to be accessed via the usual matrix interface 10833 routines, e.g., 10834 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 10835 10836 In particular each function MUST return an error code of 0 on success and 10837 nonzero on failure. 10838 10839 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10840 10841 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10842 @*/ 10843 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10844 { 10845 PetscFunctionBegin; 10846 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10847 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10848 (((void (**)(void))mat->ops)[op]) = f; 10849 PetscFunctionReturn(0); 10850 } 10851 10852 /*@C 10853 MatGetOperation - Gets a matrix operation for any matrix type. 10854 10855 Not Collective 10856 10857 Input Parameters: 10858 + mat - the matrix 10859 - op - the name of the operation 10860 10861 Output Parameter: 10862 . f - the function that provides the operation 10863 10864 Level: developer 10865 10866 Usage: 10867 $ PetscErrorCode (*usermult)(Mat,Vec,Vec); 10868 $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult); 10869 10870 Notes: 10871 See the file include/petscmat.h for a complete list of matrix 10872 operations, which all have the form MATOP_<OPERATION>, where 10873 <OPERATION> is the name (in all capital letters) of the 10874 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10875 10876 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 10877 10878 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 10879 @*/ 10880 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 10881 { 10882 PetscFunctionBegin; 10883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10884 *f = (((void (**)(void))mat->ops)[op]); 10885 PetscFunctionReturn(0); 10886 } 10887 10888 /*@ 10889 MatHasOperation - Determines whether the given matrix supports the particular operation. 10890 10891 Not Collective 10892 10893 Input Parameters: 10894 + mat - the matrix 10895 - op - the operation, for example, `MATOP_GET_DIAGONAL` 10896 10897 Output Parameter: 10898 . has - either `PETSC_TRUE` or `PETSC_FALSE` 10899 10900 Level: advanced 10901 10902 Note: 10903 See the file include/petscmat.h for a complete list of matrix 10904 operations, which all have the form MATOP_<OPERATION>, where 10905 <OPERATION> is the name (in all capital letters) of the 10906 user-level routine. E.g., `MatNorm()` -> `MATOP_NORM`. 10907 10908 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 10909 @*/ 10910 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 10911 { 10912 PetscFunctionBegin; 10913 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10914 PetscValidBoolPointer(has, 3); 10915 if (mat->ops->hasoperation) { 10916 PetscUseTypeMethod(mat, hasoperation, op, has); 10917 } else { 10918 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 10919 else { 10920 *has = PETSC_FALSE; 10921 if (op == MATOP_CREATE_SUBMATRIX) { 10922 PetscMPIInt size; 10923 10924 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10925 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 10926 } 10927 } 10928 } 10929 PetscFunctionReturn(0); 10930 } 10931 10932 /*@ 10933 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 10934 10935 Collective on mat 10936 10937 Input Parameters: 10938 . mat - the matrix 10939 10940 Output Parameter: 10941 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 10942 10943 Level: beginner 10944 10945 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout` 10946 @*/ 10947 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 10948 { 10949 PetscFunctionBegin; 10950 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10951 PetscValidType(mat, 1); 10952 PetscValidBoolPointer(cong, 2); 10953 if (!mat->rmap || !mat->cmap) { 10954 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 10955 PetscFunctionReturn(0); 10956 } 10957 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 10958 PetscCall(PetscLayoutSetUp(mat->rmap)); 10959 PetscCall(PetscLayoutSetUp(mat->cmap)); 10960 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 10961 if (*cong) mat->congruentlayouts = 1; 10962 else mat->congruentlayouts = 0; 10963 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 10964 PetscFunctionReturn(0); 10965 } 10966 10967 PetscErrorCode MatSetInf(Mat A) 10968 { 10969 PetscFunctionBegin; 10970 PetscUseTypeMethod(A, setinf); 10971 PetscFunctionReturn(0); 10972 } 10973 10974 /*C 10975 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 10976 and possibly removes small values from the graph structure. 10977 10978 Collective on mat 10979 10980 Input Parameters: 10981 + A - the matrix 10982 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 10983 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 10984 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 10985 10986 Output Parameter: 10987 . graph - the resulting graph 10988 10989 Level: advanced 10990 10991 .seealso: `MatCreate()`, `PCGAMG` 10992 */ 10993 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 10994 { 10995 PetscFunctionBegin; 10996 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 10997 PetscValidType(A, 1); 10998 PetscValidPointer(graph, 3); 10999 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11000 PetscFunctionReturn(0); 11001 } 11002