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. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Output Parameter: 61 . x - the matrix 62 63 Example of Usage: 64 .vb 65 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 66 MatSetRandom(x,rctx); 67 PetscRandomDestroy(rctx); 68 .ve 69 70 Level: intermediate 71 72 Note: 73 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 74 for sparse matrices that already have locations it fills the locations with random numbers. It generates an error if used on sparse matrices that have 75 not been preallocated. 76 77 .seealso: `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 78 @*/ 79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 80 { 81 PetscRandom randObj = NULL; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 86 PetscValidType(x, 1); 87 MatCheckPreallocated(x, 1); 88 89 if (!rctx) { 90 MPI_Comm comm; 91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 92 PetscCall(PetscRandomCreate(comm, &randObj)); 93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 94 PetscCall(PetscRandomSetFromOptions(randObj)); 95 rctx = randObj; 96 } 97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 98 PetscUseTypeMethod(x, setrandom, rctx); 99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 100 101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 103 PetscCall(PetscRandomDestroy(&randObj)); 104 PetscFunctionReturn(0); 105 } 106 107 /*@ 108 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 109 110 Logically Collective 111 112 Input Parameter: 113 . mat - the factored matrix 114 115 Output Parameters: 116 + pivot - the pivot value computed 117 - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes 118 the share the matrix 119 120 Level: advanced 121 122 Notes: 123 This routine does not work for factorizations done with external packages. 124 125 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 126 127 This can be called on non-factored matrices that come from, for example, matrices used in SOR. 128 129 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 130 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 131 @*/ 132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 136 PetscValidRealPointer(pivot, 2); 137 PetscValidIntPointer(row, 3); 138 *pivot = mat->factorerror_zeropivot_value; 139 *row = mat->factorerror_zeropivot_row; 140 PetscFunctionReturn(0); 141 } 142 143 /*@ 144 MatFactorGetError - gets the error code from a factorization 145 146 Logically Collective 147 148 Input Parameters: 149 . mat - the factored matrix 150 151 Output Parameter: 152 . err - the error code 153 154 Level: advanced 155 156 Note: 157 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 158 159 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 160 `MatFactorError` 161 @*/ 162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 163 { 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 166 PetscValidPointer(err, 2); 167 *err = mat->factorerrortype; 168 PetscFunctionReturn(0); 169 } 170 171 /*@ 172 MatFactorClearError - clears the error code in a factorization 173 174 Logically Collective 175 176 Input Parameter: 177 . mat - the factored matrix 178 179 Level: developer 180 181 Note: 182 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 183 184 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 185 `MatGetErrorCode()`, `MatFactorError` 186 @*/ 187 PetscErrorCode MatFactorClearError(Mat mat) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 191 mat->factorerrortype = MAT_FACTOR_NOERROR; 192 mat->factorerror_zeropivot_value = 0.0; 193 mat->factorerror_zeropivot_row = 0; 194 PetscFunctionReturn(0); 195 } 196 197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 198 { 199 Vec r, l; 200 const PetscScalar *al; 201 PetscInt i, nz, gnz, N, n; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetSize(mat, &N, NULL)); 207 PetscCall(MatGetLocalSize(mat, &n, NULL)); 208 PetscCall(VecSet(l, 0.0)); 209 PetscCall(VecSetRandom(r, NULL)); 210 PetscCall(MatMult(mat, r, l)); 211 PetscCall(VecGetArrayRead(l, &al)); 212 } else { /* nonzero columns */ 213 PetscCall(MatGetSize(mat, NULL, &N)); 214 PetscCall(MatGetLocalSize(mat, NULL, &n)); 215 PetscCall(VecSet(r, 0.0)); 216 PetscCall(VecSetRandom(l, NULL)); 217 PetscCall(MatMultTranspose(mat, l, r)); 218 PetscCall(VecGetArrayRead(r, &al)); 219 } 220 if (tol <= 0.0) { 221 for (i = 0, nz = 0; i < n; i++) 222 if (al[i] != 0.0) nz++; 223 } else { 224 for (i = 0, nz = 0; i < n; i++) 225 if (PetscAbsScalar(al[i]) > tol) nz++; 226 } 227 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 228 if (gnz != N) { 229 PetscInt *nzr; 230 PetscCall(PetscMalloc1(nz, &nzr)); 231 if (nz) { 232 if (tol < 0) { 233 for (i = 0, nz = 0; i < n; i++) 234 if (al[i] != 0.0) nzr[nz++] = i; 235 } else { 236 for (i = 0, nz = 0; i < n; i++) 237 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 238 } 239 } 240 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 241 } else *nonzero = NULL; 242 if (!cols) { /* nonzero rows */ 243 PetscCall(VecRestoreArrayRead(l, &al)); 244 } else { 245 PetscCall(VecRestoreArrayRead(r, &al)); 246 } 247 PetscCall(VecDestroy(&l)); 248 PetscCall(VecDestroy(&r)); 249 PetscFunctionReturn(0); 250 } 251 252 /*@ 253 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 254 255 Input Parameter: 256 . A - the matrix 257 258 Output Parameter: 259 . keptrows - the rows that are not completely zero 260 261 Level: intermediate 262 263 Note: 264 `keptrows` is set to `NULL` if all rows are nonzero. 265 266 .seealso: `Mat`, `MatFindZeroRows()` 267 @*/ 268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 269 { 270 PetscFunctionBegin; 271 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 272 PetscValidType(mat, 1); 273 PetscValidPointer(keptrows, 2); 274 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 275 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 276 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 277 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 278 PetscFunctionReturn(0); 279 } 280 281 /*@ 282 MatFindZeroRows - Locate all rows that are completely zero in the matrix 283 284 Input Parameter: 285 . A - the matrix 286 287 Output Parameter: 288 . zerorows - the rows that are completely zero 289 290 Level: intermediate 291 292 Note: 293 `zerorows` is set to `NULL` if no rows are zero. 294 295 .seealso: `Mat`, `MatFindNonzeroRows()` 296 @*/ 297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 298 { 299 IS keptrows; 300 PetscInt m, n; 301 302 PetscFunctionBegin; 303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 304 PetscValidType(mat, 1); 305 PetscValidPointer(zerorows, 2); 306 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 307 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 308 In keeping with this convention, we set zerorows to NULL if there are no zero 309 rows. */ 310 if (keptrows == NULL) { 311 *zerorows = NULL; 312 } else { 313 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 314 PetscCall(ISComplement(keptrows, m, n, zerorows)); 315 PetscCall(ISDestroy(&keptrows)); 316 } 317 PetscFunctionReturn(0); 318 } 319 320 /*@ 321 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 322 323 Not Collective 324 325 Input Parameters: 326 . A - the matrix 327 328 Output Parameters: 329 . a - the diagonal part (which is a SEQUENTIAL matrix) 330 331 Level: advanced 332 333 Notes: 334 See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 335 336 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 337 338 .seealso: `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 339 @*/ 340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 341 { 342 PetscFunctionBegin; 343 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 344 PetscValidType(A, 1); 345 PetscValidPointer(a, 2); 346 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 347 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 348 else { 349 PetscMPIInt size; 350 351 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 352 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 353 *a = A; 354 } 355 PetscFunctionReturn(0); 356 } 357 358 /*@ 359 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 360 361 Collective 362 363 Input Parameters: 364 . mat - the matrix 365 366 Output Parameter: 367 . trace - the sum of the diagonal entries 368 369 Level: advanced 370 371 .seealso: `Mat` 372 @*/ 373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 374 { 375 Vec diag; 376 377 PetscFunctionBegin; 378 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 379 PetscValidScalarPointer(trace, 2); 380 PetscCall(MatCreateVecs(mat, &diag, NULL)); 381 PetscCall(MatGetDiagonal(mat, diag)); 382 PetscCall(VecSum(diag, trace)); 383 PetscCall(VecDestroy(&diag)); 384 PetscFunctionReturn(0); 385 } 386 387 /*@ 388 MatRealPart - Zeros out the imaginary part of the matrix 389 390 Logically Collective 391 392 Input Parameters: 393 . mat - the matrix 394 395 Level: advanced 396 397 .seealso: `Mat`, `MatImaginaryPart()` 398 @*/ 399 PetscErrorCode MatRealPart(Mat mat) 400 { 401 PetscFunctionBegin; 402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 403 PetscValidType(mat, 1); 404 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 405 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 406 MatCheckPreallocated(mat, 1); 407 PetscUseTypeMethod(mat, realpart); 408 PetscFunctionReturn(0); 409 } 410 411 /*@C 412 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 413 414 Collective 415 416 Input Parameter: 417 . mat - the matrix 418 419 Output Parameters: 420 + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 421 - ghosts - the global indices of the ghost points 422 423 Level: advanced 424 425 Note: 426 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 427 428 .seealso: `Mat`, `VecCreateGhost()` 429 @*/ 430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 431 { 432 PetscFunctionBegin; 433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 434 PetscValidType(mat, 1); 435 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 436 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 437 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 438 else { 439 if (nghosts) *nghosts = 0; 440 if (ghosts) *ghosts = NULL; 441 } 442 PetscFunctionReturn(0); 443 } 444 445 /*@ 446 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 447 448 Logically Collective 449 450 Input Parameters: 451 . mat - the matrix 452 453 Level: advanced 454 455 .seealso: `Mat`, `MatRealPart()` 456 @*/ 457 PetscErrorCode MatImaginaryPart(Mat mat) 458 { 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 461 PetscValidType(mat, 1); 462 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 463 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 464 MatCheckPreallocated(mat, 1); 465 PetscUseTypeMethod(mat, imaginarypart); 466 PetscFunctionReturn(0); 467 } 468 469 /*@ 470 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 471 472 Not Collective 473 474 Input Parameter: 475 . mat - the matrix 476 477 Output Parameters: 478 + missing - is any diagonal missing 479 - dd - first diagonal entry that is missing (optional) on this process 480 481 Level: advanced 482 483 .seealso: `Mat` 484 @*/ 485 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 486 { 487 PetscFunctionBegin; 488 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 489 PetscValidType(mat, 1); 490 PetscValidBoolPointer(missing, 2); 491 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 492 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 493 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 494 PetscFunctionReturn(0); 495 } 496 497 /*@C 498 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 499 for each row that you get to ensure that your application does 500 not bleed memory. 501 502 Not Collective 503 504 Input Parameters: 505 + mat - the matrix 506 - row - the row to get 507 508 Output Parameters: 509 + ncols - if not `NULL`, the number of nonzeros in the row 510 . cols - if not `NULL`, the column numbers 511 - vals - if not `NULL`, the values 512 513 Level: advanced 514 515 Notes: 516 This routine is provided for people who need to have direct access 517 to the structure of a matrix. We hope that we provide enough 518 high-level matrix routines that few users will need it. 519 520 `MatGetRow()` always returns 0-based column indices, regardless of 521 whether the internal representation is 0-based (default) or 1-based. 522 523 For better efficiency, set cols and/or vals to `NULL` if you do 524 not wish to extract these quantities. 525 526 The user can only examine the values extracted with `MatGetRow()`; 527 the values cannot be altered. To change the matrix entries, one 528 must use `MatSetValues()`. 529 530 You can only have one call to `MatGetRow()` outstanding for a particular 531 matrix at a time, per processor. `MatGetRow()` can only obtain rows 532 associated with the given processor, it cannot get rows from the 533 other processors; for that we suggest using `MatCreateSubMatrices()`, then 534 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 535 is in the global number of rows. 536 537 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 538 539 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 540 541 Fortran Note: 542 The calling sequence is 543 .vb 544 MatGetRow(matrix,row,ncols,cols,values,ierr) 545 Mat matrix (input) 546 integer row (input) 547 integer ncols (output) 548 integer cols(maxcols) (output) 549 double precision (or double complex) values(maxcols) output 550 .ve 551 where maxcols >= maximum nonzeros in any row of the matrix. 552 553 Caution: 554 Do not try to change the contents of the output arrays (cols and vals). 555 In some cases, this may corrupt the matrix. 556 557 .seealso: `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 558 @*/ 559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 560 { 561 PetscInt incols; 562 563 PetscFunctionBegin; 564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 565 PetscValidType(mat, 1); 566 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 567 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 568 MatCheckPreallocated(mat, 1); 569 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); 570 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 571 PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals)); 572 if (ncols) *ncols = incols; 573 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 574 PetscFunctionReturn(0); 575 } 576 577 /*@ 578 MatConjugate - replaces the matrix values with their complex conjugates 579 580 Logically Collective 581 582 Input Parameters: 583 . mat - the matrix 584 585 Level: advanced 586 587 .seealso: `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 588 @*/ 589 PetscErrorCode MatConjugate(Mat mat) 590 { 591 PetscFunctionBegin; 592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 593 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 594 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 595 PetscUseTypeMethod(mat, conjugate); 596 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 597 } 598 PetscFunctionReturn(0); 599 } 600 601 /*@C 602 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 603 604 Not Collective 605 606 Input Parameters: 607 + mat - the matrix 608 . row - the row to get 609 . ncols, cols - the number of nonzeros and their columns 610 - vals - if nonzero the column values 611 612 Level: advanced 613 614 Notes: 615 This routine should be called after you have finished examining the entries. 616 617 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 618 us of the array after it has been restored. If you pass `NULL`, it will 619 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 620 621 Fortran Notes: 622 The calling sequence is 623 .vb 624 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 625 Mat matrix (input) 626 integer row (input) 627 integer ncols (output) 628 integer cols(maxcols) (output) 629 double precision (or double complex) values(maxcols) output 630 .ve 631 Where maxcols >= maximum nonzeros in any row of the matrix. 632 633 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 634 before another call to `MatGetRow()` can be made. 635 636 .seealso: `Mat`, `MatGetRow()` 637 @*/ 638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 639 { 640 PetscFunctionBegin; 641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 642 if (ncols) PetscValidIntPointer(ncols, 3); 643 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 644 if (!mat->ops->restorerow) PetscFunctionReturn(0); 645 PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals)); 646 if (ncols) *ncols = 0; 647 if (cols) *cols = NULL; 648 if (vals) *vals = NULL; 649 PetscFunctionReturn(0); 650 } 651 652 /*@ 653 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 654 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 655 656 Not Collective 657 658 Input Parameters: 659 . mat - the matrix 660 661 Level: advanced 662 663 Note: 664 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. 665 666 .seealso: `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 667 @*/ 668 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 669 { 670 PetscFunctionBegin; 671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 672 PetscValidType(mat, 1); 673 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 674 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 675 MatCheckPreallocated(mat, 1); 676 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0); 677 PetscUseTypeMethod(mat, getrowuppertriangular); 678 PetscFunctionReturn(0); 679 } 680 681 /*@ 682 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 683 684 Not Collective 685 686 Input Parameters: 687 . mat - the matrix 688 689 Level: advanced 690 691 Note: 692 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 693 694 .seealso: `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 695 @*/ 696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 697 { 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 700 PetscValidType(mat, 1); 701 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 702 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 703 MatCheckPreallocated(mat, 1); 704 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0); 705 PetscUseTypeMethod(mat, restorerowuppertriangular); 706 PetscFunctionReturn(0); 707 } 708 709 /*@C 710 MatSetOptionsPrefix - Sets the prefix used for searching for all 711 `Mat` options in the database. 712 713 Logically Collective 714 715 Input Parameters: 716 + A - the matrix 717 - prefix - the prefix to prepend to all option names 718 719 Level: advanced 720 721 Notes: 722 A hyphen (-) must NOT be given at the beginning of the prefix name. 723 The first character of all runtime options is AUTOMATICALLY the hyphen. 724 725 This is NOT used for options for the factorization of the matrix. Normally the 726 prefix is automatically passed in from the PC calling the factorization. To set 727 it directly use `MatSetOptionsPrefixFactor()` 728 729 .seealso: `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 730 @*/ 731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 732 { 733 PetscFunctionBegin; 734 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 735 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 736 PetscFunctionReturn(0); 737 } 738 739 /*@C 740 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 741 for matrices created with `MatGetFactor()` 742 743 Logically Collective 744 745 Input Parameters: 746 + A - the matrix 747 - prefix - the prefix to prepend to all option names for the factored matrix 748 749 Level: developer 750 751 Notes: 752 A hyphen (-) must NOT be given at the beginning of the prefix name. 753 The first character of all runtime options is AUTOMATICALLY the hyphen. 754 755 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 756 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 757 758 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 759 @*/ 760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 761 { 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 764 if (prefix) { 765 PetscValidCharPointer(prefix, 2); 766 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 767 if (prefix != A->factorprefix) { 768 PetscCall(PetscFree(A->factorprefix)); 769 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 770 } 771 } else PetscCall(PetscFree(A->factorprefix)); 772 PetscFunctionReturn(0); 773 } 774 775 /*@C 776 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 777 for matrices created with `MatGetFactor()` 778 779 Logically Collective 780 781 Input Parameters: 782 + A - the matrix 783 - prefix - the prefix to prepend to all option names for the factored matrix 784 785 Level: developer 786 787 Notes: 788 A hyphen (-) must NOT be given at the beginning of the prefix name. 789 The first character of all runtime options is AUTOMATICALLY the hyphen. 790 791 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 792 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 793 794 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 795 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 796 `MatSetOptionsPrefix()` 797 @*/ 798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 799 { 800 char *buf = A->factorprefix; 801 size_t len1, len2; 802 803 PetscFunctionBegin; 804 PetscValidHeader(A, 1); 805 if (!prefix) PetscFunctionReturn(0); 806 if (!buf) { 807 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 808 PetscFunctionReturn(0); 809 } 810 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 811 812 PetscCall(PetscStrlen(prefix, &len1)); 813 PetscCall(PetscStrlen(buf, &len2)); 814 PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix)); 815 PetscCall(PetscStrcpy(A->factorprefix, buf)); 816 PetscCall(PetscStrcat(A->factorprefix, prefix)); 817 PetscCall(PetscFree(buf)); 818 PetscFunctionReturn(0); 819 } 820 821 /*@C 822 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 823 matrix options in the database. 824 825 Logically Collective 826 827 Input Parameters: 828 + A - the matrix 829 - prefix - the prefix to prepend to all option names 830 831 Level: advanced 832 833 Note: 834 A hyphen (-) must NOT be given at the beginning of the prefix name. 835 The first character of all runtime options is AUTOMATICALLY the hyphen. 836 837 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 838 @*/ 839 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 840 { 841 PetscFunctionBegin; 842 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 843 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 844 PetscFunctionReturn(0); 845 } 846 847 /*@C 848 MatGetOptionsPrefix - Gets the prefix used for searching for all 849 matrix options in the database. 850 851 Not Collective 852 853 Input Parameter: 854 . A - the matrix 855 856 Output Parameter: 857 . prefix - pointer to the prefix string used 858 859 Level: advanced 860 861 Fortran Note: 862 On the fortran side, the user should pass in a string `prefix` of 863 sufficient length to hold the prefix. 864 865 .seealso: `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 866 @*/ 867 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 868 { 869 PetscFunctionBegin; 870 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 871 PetscValidPointer(prefix, 2); 872 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 873 PetscFunctionReturn(0); 874 } 875 876 /*@ 877 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 878 879 Collective 880 881 Input Parameters: 882 . A - the matrix 883 884 Level: beginner 885 886 Notes: 887 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 888 889 Users can reset the preallocation to access the original memory. 890 891 Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices. 892 893 .seealso: `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 894 @*/ 895 PetscErrorCode MatResetPreallocation(Mat A) 896 { 897 PetscFunctionBegin; 898 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 899 PetscValidType(A, 1); 900 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 901 PetscFunctionReturn(0); 902 } 903 904 /*@ 905 MatSetUp - Sets up the internal matrix data structures for later use. 906 907 Collective 908 909 Input Parameters: 910 . A - the matrix 911 912 Level: intermediate 913 914 Notes: 915 If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used. 916 917 If a suitable preallocation routine is used, this function does not need to be called. 918 919 See the Performance chapter of the PETSc users manual for how to preallocate matrices 920 921 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 922 923 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()` 924 @*/ 925 PetscErrorCode MatSetUp(Mat A) 926 { 927 PetscFunctionBegin; 928 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 929 if (!((PetscObject)A)->type_name) { 930 PetscMPIInt size; 931 932 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 933 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 934 } 935 if (!A->preallocated && A->ops->setup) { 936 PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n")); 937 PetscUseTypeMethod(A, setup); 938 } 939 PetscCall(PetscLayoutSetUp(A->rmap)); 940 PetscCall(PetscLayoutSetUp(A->cmap)); 941 A->preallocated = PETSC_TRUE; 942 PetscFunctionReturn(0); 943 } 944 945 #if defined(PETSC_HAVE_SAWS) 946 #include <petscviewersaws.h> 947 #endif 948 949 /*@C 950 MatViewFromOptions - View properties of the matrix from the options database 951 952 Collective 953 954 Input Parameters: 955 + A - the matrix 956 . obj - optional additional object that provides the options prefix to use 957 - name - command line option 958 959 Options Database Key: 960 . -mat_view [viewertype]:... - the viewer and its options 961 962 Level: intermediate 963 964 Notes: 965 .vb 966 If no value is provided ascii:stdout is used 967 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 968 for example ascii::ascii_info prints just the information about the object not all details 969 unless :append is given filename opens in write mode, overwriting what was already there 970 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 971 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 972 socket[:port] defaults to the standard output port 973 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 974 .ve 975 976 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 977 @*/ 978 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 979 { 980 PetscFunctionBegin; 981 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 982 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 983 PetscFunctionReturn(0); 984 } 985 986 /*@C 987 MatView - display information about a matrix in a variety ways 988 989 Collective 990 991 Input Parameters: 992 + mat - the matrix 993 - viewer - visualization context 994 995 Notes: 996 The available visualization contexts include 997 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 998 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 999 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1000 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1001 1002 The user can open alternative visualization contexts with 1003 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1004 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1005 specified file; corresponding input uses MatLoad() 1006 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1007 an X window display 1008 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1009 Currently only the sequential dense and AIJ 1010 matrix types support the Socket viewer. 1011 1012 The user can call `PetscViewerPushFormat()` to specify the output 1013 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1014 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1015 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1016 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1017 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1018 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1019 format common among all matrix types 1020 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1021 format (which is in many cases the same as the default) 1022 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1023 size and structure (not the matrix entries) 1024 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1025 the matrix structure 1026 1027 Options Database Keys: 1028 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1029 . -mat_view ::ascii_info_detail - Prints more detailed info 1030 . -mat_view - Prints matrix in ASCII format 1031 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1032 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1033 . -display <name> - Sets display name (default is host) 1034 . -draw_pause <sec> - Sets number of seconds to pause after display 1035 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1036 . -viewer_socket_machine <machine> - 1037 . -viewer_socket_port <port> - 1038 . -mat_view binary - save matrix to file in binary format 1039 - -viewer_binary_filename <name> - 1040 1041 Level: beginner 1042 1043 Notes: 1044 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1045 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1046 1047 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1048 1049 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1050 viewer is used. 1051 1052 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1053 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1054 1055 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1056 and then use the following mouse functions. 1057 .vb 1058 left mouse: zoom in 1059 middle mouse: zoom out 1060 right mouse: continue with the simulation 1061 .ve 1062 1063 .seealso: `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1064 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1065 @*/ 1066 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1067 { 1068 PetscInt rows, cols, rbs, cbs; 1069 PetscBool isascii, isstring, issaws; 1070 PetscViewerFormat format; 1071 PetscMPIInt size; 1072 1073 PetscFunctionBegin; 1074 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1075 PetscValidType(mat, 1); 1076 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1077 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1078 PetscCheckSameComm(mat, 1, viewer, 2); 1079 1080 PetscCall(PetscViewerGetFormat(viewer, &format)); 1081 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1082 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0); 1083 1084 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1085 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1086 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1087 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"); 1088 1089 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1090 if (isascii) { 1091 if (!mat->preallocated) { 1092 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1093 PetscFunctionReturn(0); 1094 } 1095 if (!mat->assembled) { 1096 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1097 PetscFunctionReturn(0); 1098 } 1099 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1100 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1101 MatNullSpace nullsp, transnullsp; 1102 1103 PetscCall(PetscViewerASCIIPushTab(viewer)); 1104 PetscCall(MatGetSize(mat, &rows, &cols)); 1105 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1106 if (rbs != 1 || cbs != 1) { 1107 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1108 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1109 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1110 if (mat->factortype) { 1111 MatSolverType solver; 1112 PetscCall(MatFactorGetSolverType(mat, &solver)); 1113 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1114 } 1115 if (mat->ops->getinfo) { 1116 MatInfo info; 1117 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1118 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1119 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1120 } 1121 PetscCall(MatGetNullSpace(mat, &nullsp)); 1122 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1123 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1124 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1125 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1126 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1127 PetscCall(PetscViewerASCIIPushTab(viewer)); 1128 PetscCall(MatProductView(mat, viewer)); 1129 PetscCall(PetscViewerASCIIPopTab(viewer)); 1130 } 1131 } else if (issaws) { 1132 #if defined(PETSC_HAVE_SAWS) 1133 PetscMPIInt rank; 1134 1135 PetscCall(PetscObjectName((PetscObject)mat)); 1136 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1137 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1138 #endif 1139 } else if (isstring) { 1140 const char *type; 1141 PetscCall(MatGetType(mat, &type)); 1142 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1143 PetscTryTypeMethod(mat, view, viewer); 1144 } 1145 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1146 PetscCall(PetscViewerASCIIPushTab(viewer)); 1147 PetscUseTypeMethod(mat, viewnative, viewer); 1148 PetscCall(PetscViewerASCIIPopTab(viewer)); 1149 } else if (mat->ops->view) { 1150 PetscCall(PetscViewerASCIIPushTab(viewer)); 1151 PetscUseTypeMethod(mat, view, viewer); 1152 PetscCall(PetscViewerASCIIPopTab(viewer)); 1153 } 1154 if (isascii) { 1155 PetscCall(PetscViewerGetFormat(viewer, &format)); 1156 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1157 } 1158 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1159 PetscFunctionReturn(0); 1160 } 1161 1162 #if defined(PETSC_USE_DEBUG) 1163 #include <../src/sys/totalview/tv_data_display.h> 1164 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1165 { 1166 TV_add_row("Local rows", "int", &mat->rmap->n); 1167 TV_add_row("Local columns", "int", &mat->cmap->n); 1168 TV_add_row("Global rows", "int", &mat->rmap->N); 1169 TV_add_row("Global columns", "int", &mat->cmap->N); 1170 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1171 return TV_format_OK; 1172 } 1173 #endif 1174 1175 /*@C 1176 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1177 with `MatView()`. The matrix format is determined from the options database. 1178 Generates a parallel MPI matrix if the communicator has more than one 1179 processor. The default matrix type is `MATAIJ`. 1180 1181 Collective 1182 1183 Input Parameters: 1184 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1185 or some related function before a call to `MatLoad()` 1186 - viewer - binary/HDF5 file viewer 1187 1188 Options Database Keys: 1189 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1190 block size 1191 . -matload_block_size <bs> - set block size 1192 1193 Level: beginner 1194 1195 Notes: 1196 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1197 `Mat` before calling this routine if you wish to set it from the options database. 1198 1199 `MatLoad()` automatically loads into the options database any options 1200 given in the file filename.info where filename is the name of the file 1201 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1202 file will be ignored if you use the -viewer_binary_skip_info option. 1203 1204 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1205 sets the default matrix type AIJ and sets the local and global sizes. 1206 If type and/or size is already set, then the same are used. 1207 1208 In parallel, each processor can load a subset of rows (or the 1209 entire matrix). This routine is especially useful when a large 1210 matrix is stored on disk and only part of it is desired on each 1211 processor. For example, a parallel solver may access only some of 1212 the rows from each processor. The algorithm used here reads 1213 relatively small blocks of data rather than reading the entire 1214 matrix and then subsetting it. 1215 1216 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1217 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1218 or the sequence like 1219 .vb 1220 `PetscViewer` v; 1221 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1222 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1223 `PetscViewerSetFromOptions`(v); 1224 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1225 `PetscViewerFileSetName`(v,"datafile"); 1226 .ve 1227 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1228 $ -viewer_type {binary,hdf5} 1229 1230 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1231 and src/mat/tutorials/ex10.c with the second approach. 1232 1233 Notes about the PETSc binary format: 1234 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1235 is read onto rank 0 and then shipped to its destination rank, one after another. 1236 Multiple objects, both matrices and vectors, can be stored within the same file. 1237 Their PetscObject name is ignored; they are loaded in the order of their storage. 1238 1239 Most users should not need to know the details of the binary storage 1240 format, since `MatLoad()` and `MatView()` completely hide these details. 1241 But for anyone who's interested, the standard binary matrix storage 1242 format is 1243 1244 $ PetscInt MAT_FILE_CLASSID 1245 $ PetscInt number of rows 1246 $ PetscInt number of columns 1247 $ PetscInt total number of nonzeros 1248 $ PetscInt *number nonzeros in each row 1249 $ PetscInt *column indices of all nonzeros (starting index is zero) 1250 $ PetscScalar *values of all nonzeros 1251 1252 PETSc automatically does the byte swapping for 1253 machines that store the bytes reversed, e.g. DEC alpha, freebsd, 1254 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary 1255 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1256 and `PetscBinaryWrite()` to see how this may be done. 1257 1258 Notes about the HDF5 (MATLAB MAT-File Version 7.3) format: 1259 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1260 Each processor's chunk is loaded independently by its owning rank. 1261 Multiple objects, both matrices and vectors, can be stored within the same file. 1262 They are looked up by their PetscObject name. 1263 1264 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1265 by default the same structure and naming of the AIJ arrays and column count 1266 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1267 $ save example.mat A b -v7.3 1268 can be directly read by this routine (see Reference 1 for details). 1269 Note that depending on your MATLAB version, this format might be a default, 1270 otherwise you can set it as default in Preferences. 1271 1272 Unless -nocompression flag is used to save the file in MATLAB, 1273 PETSc must be configured with ZLIB package. 1274 1275 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1276 1277 Current HDF5 (MAT-File) limitations: 1278 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices. 1279 1280 Corresponding `MatView()` is not yet implemented. 1281 1282 The loaded matrix is actually a transpose of the original one in MATLAB, 1283 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1284 With this format, matrix is automatically transposed by PETSc, 1285 unless the matrix is marked as SPD or symmetric 1286 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1287 1288 References: 1289 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1290 1291 .seealso: `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1292 @*/ 1293 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1294 { 1295 PetscBool flg; 1296 1297 PetscFunctionBegin; 1298 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1299 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1300 1301 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1302 1303 flg = PETSC_FALSE; 1304 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1305 if (flg) { 1306 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1307 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1308 } 1309 flg = PETSC_FALSE; 1310 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1311 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1312 1313 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1314 PetscUseTypeMethod(mat, load, viewer); 1315 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1316 PetscFunctionReturn(0); 1317 } 1318 1319 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1320 { 1321 Mat_Redundant *redund = *redundant; 1322 1323 PetscFunctionBegin; 1324 if (redund) { 1325 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1326 PetscCall(ISDestroy(&redund->isrow)); 1327 PetscCall(ISDestroy(&redund->iscol)); 1328 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1329 } else { 1330 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1331 PetscCall(PetscFree(redund->sbuf_j)); 1332 PetscCall(PetscFree(redund->sbuf_a)); 1333 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1334 PetscCall(PetscFree(redund->rbuf_j[i])); 1335 PetscCall(PetscFree(redund->rbuf_a[i])); 1336 } 1337 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1338 } 1339 1340 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1341 PetscCall(PetscFree(redund)); 1342 } 1343 PetscFunctionReturn(0); 1344 } 1345 1346 /*@C 1347 MatDestroy - Frees space taken by a matrix. 1348 1349 Collective 1350 1351 Input Parameter: 1352 . A - the matrix 1353 1354 Level: beginner 1355 1356 Developer Note: 1357 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1358 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1359 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1360 if changes are needed here. 1361 1362 .seealso: `Mat`, `MatCreate()` 1363 @*/ 1364 PetscErrorCode MatDestroy(Mat *A) 1365 { 1366 PetscFunctionBegin; 1367 if (!*A) PetscFunctionReturn(0); 1368 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1369 if (--((PetscObject)(*A))->refct > 0) { 1370 *A = NULL; 1371 PetscFunctionReturn(0); 1372 } 1373 1374 /* if memory was published with SAWs then destroy it */ 1375 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1376 PetscTryTypeMethod((*A), destroy); 1377 1378 PetscCall(PetscFree((*A)->factorprefix)); 1379 PetscCall(PetscFree((*A)->defaultvectype)); 1380 PetscCall(PetscFree((*A)->defaultrandtype)); 1381 PetscCall(PetscFree((*A)->bsizes)); 1382 PetscCall(PetscFree((*A)->solvertype)); 1383 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1384 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1385 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1386 PetscCall(MatProductClear(*A)); 1387 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1388 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1389 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1390 PetscCall(MatDestroy(&(*A)->schur)); 1391 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1392 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1393 PetscCall(PetscHeaderDestroy(A)); 1394 PetscFunctionReturn(0); 1395 } 1396 1397 /*@C 1398 MatSetValues - Inserts or adds a block of values into a matrix. 1399 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1400 MUST be called after all calls to `MatSetValues()` have been completed. 1401 1402 Not Collective 1403 1404 Input Parameters: 1405 + mat - the matrix 1406 . v - a logically two-dimensional array of values 1407 . m, idxm - the number of rows and their global indices 1408 . n, idxn - the number of columns and their global indices 1409 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1410 1411 Level: beginner 1412 1413 Notes: 1414 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1415 `MatSetUp()` before using this routine 1416 1417 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1418 1419 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1420 options cannot be mixed without intervening calls to the assembly 1421 routines. 1422 1423 `MatSetValues()` uses 0-based row and column numbers in Fortran 1424 as well as in C. 1425 1426 Negative indices may be passed in idxm and idxn, these rows and columns are 1427 simply ignored. This allows easily inserting element stiffness matrices 1428 with homogeneous Dirchlet boundary conditions that you don't want represented 1429 in the matrix. 1430 1431 Efficiency Alert: 1432 The routine `MatSetValuesBlocked()` may offer much better efficiency 1433 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1434 1435 Developer Note: 1436 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1437 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1438 1439 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1440 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1441 @*/ 1442 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1443 { 1444 PetscFunctionBeginHot; 1445 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1446 PetscValidType(mat, 1); 1447 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1448 PetscValidIntPointer(idxm, 3); 1449 PetscValidIntPointer(idxn, 5); 1450 MatCheckPreallocated(mat, 1); 1451 1452 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1453 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1454 1455 if (PetscDefined(USE_DEBUG)) { 1456 PetscInt i, j; 1457 1458 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1459 for (i = 0; i < m; i++) { 1460 for (j = 0; j < n; j++) { 1461 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1462 #if defined(PETSC_USE_COMPLEX) 1463 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]); 1464 #else 1465 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]); 1466 #endif 1467 } 1468 } 1469 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); 1470 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); 1471 } 1472 1473 if (mat->assembled) { 1474 mat->was_assembled = PETSC_TRUE; 1475 mat->assembled = PETSC_FALSE; 1476 } 1477 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1478 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1479 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1480 PetscFunctionReturn(0); 1481 } 1482 1483 /*@C 1484 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1485 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1486 MUST be called after all calls to `MatSetValues()` have been completed. 1487 1488 Not Collective 1489 1490 Input Parameters: 1491 + mat - the matrix 1492 . v - a logically two-dimensional array of values 1493 . ism - the rows to provide 1494 . isn - the columns to provide 1495 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1496 1497 Level: beginner 1498 1499 Notes: 1500 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1501 `MatSetUp()` before using this routine 1502 1503 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1504 1505 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1506 options cannot be mixed without intervening calls to the assembly 1507 routines. 1508 1509 `MatSetValues()` uses 0-based row and column numbers in Fortran 1510 as well as in C. 1511 1512 Negative indices may be passed in ism and isn, these rows and columns are 1513 simply ignored. This allows easily inserting element stiffness matrices 1514 with homogeneous Dirchlet boundary conditions that you don't want represented 1515 in the matrix. 1516 1517 Efficiency Alert: 1518 The routine `MatSetValuesBlocked()` may offer much better efficiency 1519 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1520 1521 This is currently not optimized for any particular `ISType` 1522 1523 Developer Notes: 1524 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1525 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1526 1527 .seealso: `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1528 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1529 @*/ 1530 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1531 { 1532 PetscInt m, n; 1533 const PetscInt *rows, *cols; 1534 1535 PetscFunctionBeginHot; 1536 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1537 PetscCall(ISGetIndices(ism, &rows)); 1538 PetscCall(ISGetIndices(isn, &cols)); 1539 PetscCall(ISGetLocalSize(ism, &m)); 1540 PetscCall(ISGetLocalSize(isn, &n)); 1541 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1542 PetscCall(ISRestoreIndices(ism, &rows)); 1543 PetscCall(ISRestoreIndices(isn, &cols)); 1544 PetscFunctionReturn(0); 1545 } 1546 1547 /*@ 1548 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1549 values into a matrix 1550 1551 Not Collective 1552 1553 Input Parameters: 1554 + mat - the matrix 1555 . row - the (block) row to set 1556 - v - a logically two-dimensional array of values 1557 1558 Level: intermediate 1559 1560 Notes: 1561 The values, `v`, are column-oriented (for the block version) and sorted 1562 1563 All the nonzeros in the row must be provided 1564 1565 The matrix must have previously had its column indices set 1566 1567 The row must belong to this process 1568 1569 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1570 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1571 @*/ 1572 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1573 { 1574 PetscInt globalrow; 1575 1576 PetscFunctionBegin; 1577 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1578 PetscValidType(mat, 1); 1579 PetscValidScalarPointer(v, 3); 1580 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1581 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1582 PetscFunctionReturn(0); 1583 } 1584 1585 /*@ 1586 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1587 values into a matrix 1588 1589 Not Collective 1590 1591 Input Parameters: 1592 + mat - the matrix 1593 . row - the (block) row to set 1594 - 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 1595 1596 Level: advanced 1597 1598 Notes: 1599 The values, `v`, are column-oriented for the block version. 1600 1601 All the nonzeros in the row must be provided 1602 1603 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1604 1605 The row must belong to this process 1606 1607 .seealso: `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1608 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1609 @*/ 1610 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1611 { 1612 PetscFunctionBeginHot; 1613 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1614 PetscValidType(mat, 1); 1615 MatCheckPreallocated(mat, 1); 1616 PetscValidScalarPointer(v, 3); 1617 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1618 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1619 mat->insertmode = INSERT_VALUES; 1620 1621 if (mat->assembled) { 1622 mat->was_assembled = PETSC_TRUE; 1623 mat->assembled = PETSC_FALSE; 1624 } 1625 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1626 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1627 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1628 PetscFunctionReturn(0); 1629 } 1630 1631 /*@ 1632 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1633 Using structured grid indexing 1634 1635 Not Collective 1636 1637 Input Parameters: 1638 + mat - the matrix 1639 . m - number of rows being entered 1640 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1641 . n - number of columns being entered 1642 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1643 . v - a logically two-dimensional array of values 1644 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1645 1646 Level: beginner 1647 1648 Notes: 1649 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1650 1651 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1652 options cannot be mixed without intervening calls to the assembly 1653 routines. 1654 1655 The grid coordinates are across the entire grid, not just the local portion 1656 1657 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1658 as well as in C. 1659 1660 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1661 1662 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1663 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1664 1665 The columns and rows in the stencil passed in MUST be contained within the 1666 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1667 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1668 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1669 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1670 1671 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1672 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1673 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1674 `DM_BOUNDARY_PERIODIC` boundary type. 1675 1676 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 1677 a single value per point) you can skip filling those indices. 1678 1679 Inspired by the structured grid interface to the HYPRE package 1680 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1681 1682 Efficiency Alert: 1683 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1684 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1685 1686 Fortran Note: 1687 In Fortran idxm and idxn should be declared as 1688 $ MatStencil idxm(4,m),idxn(4,n) 1689 and the values inserted using 1690 .vb 1691 idxm(MatStencil_i,1) = i 1692 idxm(MatStencil_j,1) = j 1693 idxm(MatStencil_k,1) = k 1694 idxm(MatStencil_c,1) = c 1695 etc 1696 .ve 1697 1698 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1699 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1700 @*/ 1701 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1702 { 1703 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1704 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1705 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1706 1707 PetscFunctionBegin; 1708 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1709 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1710 PetscValidType(mat, 1); 1711 PetscValidPointer(idxm, 3); 1712 PetscValidPointer(idxn, 5); 1713 1714 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1715 jdxm = buf; 1716 jdxn = buf + m; 1717 } else { 1718 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1719 jdxm = bufm; 1720 jdxn = bufn; 1721 } 1722 for (i = 0; i < m; i++) { 1723 for (j = 0; j < 3 - sdim; j++) dxm++; 1724 tmp = *dxm++ - starts[0]; 1725 for (j = 0; j < dim - 1; j++) { 1726 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1727 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1728 } 1729 if (mat->stencil.noc) dxm++; 1730 jdxm[i] = tmp; 1731 } 1732 for (i = 0; i < n; i++) { 1733 for (j = 0; j < 3 - sdim; j++) dxn++; 1734 tmp = *dxn++ - starts[0]; 1735 for (j = 0; j < dim - 1; j++) { 1736 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1737 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1738 } 1739 if (mat->stencil.noc) dxn++; 1740 jdxn[i] = tmp; 1741 } 1742 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1743 PetscCall(PetscFree2(bufm, bufn)); 1744 PetscFunctionReturn(0); 1745 } 1746 1747 /*@ 1748 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1749 Using structured grid indexing 1750 1751 Not Collective 1752 1753 Input Parameters: 1754 + mat - the matrix 1755 . m - number of rows being entered 1756 . idxm - grid coordinates for matrix rows being entered 1757 . n - number of columns being entered 1758 . idxn - grid coordinates for matrix columns being entered 1759 . v - a logically two-dimensional array of values 1760 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1761 1762 Level: beginner 1763 1764 Notes: 1765 By default the values, `v`, are row-oriented and unsorted. 1766 See `MatSetOption()` for other options. 1767 1768 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1769 options cannot be mixed without intervening calls to the assembly 1770 routines. 1771 1772 The grid coordinates are across the entire grid, not just the local portion 1773 1774 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1775 as well as in C. 1776 1777 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1778 1779 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1780 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1781 1782 The columns and rows in the stencil passed in MUST be contained within the 1783 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1784 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1785 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1786 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1787 1788 Negative indices may be passed in idxm and idxn, these rows and columns are 1789 simply ignored. This allows easily inserting element stiffness matrices 1790 with homogeneous Dirchlet boundary conditions that you don't want represented 1791 in the matrix. 1792 1793 Inspired by the structured grid interface to the HYPRE package 1794 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1795 1796 Fortran Note: 1797 In Fortran idxm and idxn should be declared as 1798 $ MatStencil idxm(4,m),idxn(4,n) 1799 and the values inserted using 1800 .vb 1801 idxm(MatStencil_i,1) = i 1802 idxm(MatStencil_j,1) = j 1803 idxm(MatStencil_k,1) = k 1804 etc 1805 .ve 1806 1807 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1808 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1809 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1810 @*/ 1811 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1812 { 1813 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1814 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1815 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1816 1817 PetscFunctionBegin; 1818 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1819 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1820 PetscValidType(mat, 1); 1821 PetscValidPointer(idxm, 3); 1822 PetscValidPointer(idxn, 5); 1823 PetscValidScalarPointer(v, 6); 1824 1825 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1826 jdxm = buf; 1827 jdxn = buf + m; 1828 } else { 1829 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1830 jdxm = bufm; 1831 jdxn = bufn; 1832 } 1833 for (i = 0; i < m; i++) { 1834 for (j = 0; j < 3 - sdim; j++) dxm++; 1835 tmp = *dxm++ - starts[0]; 1836 for (j = 0; j < sdim - 1; j++) { 1837 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1838 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1839 } 1840 dxm++; 1841 jdxm[i] = tmp; 1842 } 1843 for (i = 0; i < n; i++) { 1844 for (j = 0; j < 3 - sdim; j++) dxn++; 1845 tmp = *dxn++ - starts[0]; 1846 for (j = 0; j < sdim - 1; j++) { 1847 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1848 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1849 } 1850 dxn++; 1851 jdxn[i] = tmp; 1852 } 1853 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1854 PetscCall(PetscFree2(bufm, bufn)); 1855 PetscFunctionReturn(0); 1856 } 1857 1858 /*@ 1859 MatSetStencil - Sets the grid information for setting values into a matrix via 1860 `MatSetValuesStencil()` 1861 1862 Not Collective 1863 1864 Input Parameters: 1865 + mat - the matrix 1866 . dim - dimension of the grid 1, 2, or 3 1867 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1868 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1869 - dof - number of degrees of freedom per node 1870 1871 Level: beginner 1872 1873 Notes: 1874 Inspired by the structured grid interface to the HYPRE package 1875 (www.llnl.gov/CASC/hyper) 1876 1877 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1878 user. 1879 1880 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1881 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1882 @*/ 1883 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1884 { 1885 PetscFunctionBegin; 1886 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1887 PetscValidIntPointer(dims, 3); 1888 PetscValidIntPointer(starts, 4); 1889 1890 mat->stencil.dim = dim + (dof > 1); 1891 for (PetscInt i = 0; i < dim; i++) { 1892 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1893 mat->stencil.starts[i] = starts[dim - i - 1]; 1894 } 1895 mat->stencil.dims[dim] = dof; 1896 mat->stencil.starts[dim] = 0; 1897 mat->stencil.noc = (PetscBool)(dof == 1); 1898 PetscFunctionReturn(0); 1899 } 1900 1901 /*@C 1902 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1903 1904 Not Collective 1905 1906 Input Parameters: 1907 + mat - the matrix 1908 . v - a logically two-dimensional array of values 1909 . m - the number of block rows 1910 . idxm - the global block indices 1911 . n - the number of block columns 1912 . idxn - the global block indices 1913 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1914 1915 Level: intermediate 1916 1917 Notes: 1918 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1919 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1920 1921 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1922 NOT the total number of rows/columns; for example, if the block size is 2 and 1923 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1924 The values in idxm would be 1 2; that is the first index for each block divided by 1925 the block size. 1926 1927 Note that you must call `MatSetBlockSize()` when constructing this matrix (before 1928 preallocating it). 1929 1930 By default the values, `v`, are row-oriented, so the layout of 1931 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1932 1933 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1934 options cannot be mixed without intervening calls to the assembly 1935 routines. 1936 1937 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1938 as well as in C. 1939 1940 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1941 simply ignored. This allows easily inserting element stiffness matrices 1942 with homogeneous Dirchlet boundary conditions that you don't want represented 1943 in the matrix. 1944 1945 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1946 internal searching must be done to determine where to place the 1947 data in the matrix storage space. By instead inserting blocks of 1948 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1949 reduced. 1950 1951 Example: 1952 .vb 1953 Suppose m=n=2 and block size(bs) = 2 The array is 1954 1955 1 2 | 3 4 1956 5 6 | 7 8 1957 - - - | - - - 1958 9 10 | 11 12 1959 13 14 | 15 16 1960 1961 v[] should be passed in like 1962 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1963 1964 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1965 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1966 .ve 1967 1968 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1969 @*/ 1970 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1971 { 1972 PetscFunctionBeginHot; 1973 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1974 PetscValidType(mat, 1); 1975 if (!m || !n) PetscFunctionReturn(0); /* no values to insert */ 1976 PetscValidIntPointer(idxm, 3); 1977 PetscValidIntPointer(idxn, 5); 1978 MatCheckPreallocated(mat, 1); 1979 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1980 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1981 if (PetscDefined(USE_DEBUG)) { 1982 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1983 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1984 } 1985 if (PetscDefined(USE_DEBUG)) { 1986 PetscInt rbs, cbs, M, N, i; 1987 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1988 PetscCall(MatGetSize(mat, &M, &N)); 1989 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); 1990 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); 1991 } 1992 if (mat->assembled) { 1993 mat->was_assembled = PETSC_TRUE; 1994 mat->assembled = PETSC_FALSE; 1995 } 1996 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1997 if (mat->ops->setvaluesblocked) { 1998 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1999 } else { 2000 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2001 PetscInt i, j, bs, cbs; 2002 2003 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2004 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2005 iidxm = buf; 2006 iidxn = buf + m * bs; 2007 } else { 2008 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2009 iidxm = bufr; 2010 iidxn = bufc; 2011 } 2012 for (i = 0; i < m; i++) { 2013 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2014 } 2015 if (m != n || bs != cbs || idxm != idxn) { 2016 for (i = 0; i < n; i++) { 2017 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2018 } 2019 } else iidxn = iidxm; 2020 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2021 PetscCall(PetscFree2(bufr, bufc)); 2022 } 2023 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2024 PetscFunctionReturn(0); 2025 } 2026 2027 /*@C 2028 MatGetValues - Gets a block of local values from a matrix. 2029 2030 Not Collective; can only return values that are owned by the give process 2031 2032 Input Parameters: 2033 + mat - the matrix 2034 . v - a logically two-dimensional array for storing the values 2035 . m - the number of rows 2036 . idxm - the global indices of the rows 2037 . n - the number of columns 2038 - idxn - the global indices of the columns 2039 2040 Level: advanced 2041 2042 Notes: 2043 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2044 The values, `v`, are then returned in a row-oriented format, 2045 analogous to that used by default in `MatSetValues()`. 2046 2047 `MatGetValues()` uses 0-based row and column numbers in 2048 Fortran as well as in C. 2049 2050 `MatGetValues()` requires that the matrix has been assembled 2051 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2052 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2053 without intermediate matrix assembly. 2054 2055 Negative row or column indices will be ignored and those locations in `v` will be 2056 left unchanged. 2057 2058 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank. 2059 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2060 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2061 2062 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2063 @*/ 2064 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2065 { 2066 PetscFunctionBegin; 2067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2068 PetscValidType(mat, 1); 2069 if (!m || !n) PetscFunctionReturn(0); 2070 PetscValidIntPointer(idxm, 3); 2071 PetscValidIntPointer(idxn, 5); 2072 PetscValidScalarPointer(v, 6); 2073 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2074 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2075 MatCheckPreallocated(mat, 1); 2076 2077 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2078 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2079 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2080 PetscFunctionReturn(0); 2081 } 2082 2083 /*@C 2084 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2085 defined previously by `MatSetLocalToGlobalMapping()` 2086 2087 Not Collective 2088 2089 Input Parameters: 2090 + mat - the matrix 2091 . nrow - number of rows 2092 . irow - the row local indices 2093 . ncol - number of columns 2094 - icol - the column local indices 2095 2096 Output Parameter: 2097 . y - a logically two-dimensional array of values 2098 2099 Level: advanced 2100 2101 Notes: 2102 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2103 2104 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, 2105 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2106 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2107 with `MatSetLocalToGlobalMapping()`. 2108 2109 Developer Note: 2110 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2111 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2112 2113 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2114 `MatSetValuesLocal()`, `MatGetValues()` 2115 @*/ 2116 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2117 { 2118 PetscFunctionBeginHot; 2119 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2120 PetscValidType(mat, 1); 2121 MatCheckPreallocated(mat, 1); 2122 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */ 2123 PetscValidIntPointer(irow, 3); 2124 PetscValidIntPointer(icol, 5); 2125 if (PetscDefined(USE_DEBUG)) { 2126 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2127 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2128 } 2129 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2130 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2131 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2132 else { 2133 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2134 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2135 irowm = buf; 2136 icolm = buf + nrow; 2137 } else { 2138 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2139 irowm = bufr; 2140 icolm = bufc; 2141 } 2142 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2143 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2144 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2145 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2146 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2147 PetscCall(PetscFree2(bufr, bufc)); 2148 } 2149 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2150 PetscFunctionReturn(0); 2151 } 2152 2153 /*@ 2154 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2155 the same size. Currently, this can only be called once and creates the given matrix. 2156 2157 Not Collective 2158 2159 Input Parameters: 2160 + mat - the matrix 2161 . nb - the number of blocks 2162 . bs - the number of rows (and columns) in each block 2163 . rows - a concatenation of the rows for each block 2164 - v - a concatenation of logically two-dimensional arrays of values 2165 2166 Level: advanced 2167 2168 Note: 2169 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2170 2171 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2172 2173 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2174 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2175 @*/ 2176 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2177 { 2178 PetscFunctionBegin; 2179 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2180 PetscValidType(mat, 1); 2181 PetscValidIntPointer(rows, 4); 2182 PetscValidScalarPointer(v, 5); 2183 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2184 2185 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2186 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2187 else { 2188 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2189 } 2190 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2191 PetscFunctionReturn(0); 2192 } 2193 2194 /*@ 2195 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2196 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2197 using a local (per-processor) numbering. 2198 2199 Not Collective 2200 2201 Input Parameters: 2202 + x - the matrix 2203 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2204 - cmapping - column mapping 2205 2206 Level: intermediate 2207 2208 Note: 2209 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2210 2211 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2212 @*/ 2213 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2214 { 2215 PetscFunctionBegin; 2216 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2217 PetscValidType(x, 1); 2218 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2219 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2220 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2221 else { 2222 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2223 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2224 } 2225 PetscFunctionReturn(0); 2226 } 2227 2228 /*@ 2229 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2230 2231 Not Collective 2232 2233 Input Parameter: 2234 . A - the matrix 2235 2236 Output Parameters: 2237 + rmapping - row mapping 2238 - cmapping - column mapping 2239 2240 Level: advanced 2241 2242 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2243 @*/ 2244 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2245 { 2246 PetscFunctionBegin; 2247 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2248 PetscValidType(A, 1); 2249 if (rmapping) { 2250 PetscValidPointer(rmapping, 2); 2251 *rmapping = A->rmap->mapping; 2252 } 2253 if (cmapping) { 2254 PetscValidPointer(cmapping, 3); 2255 *cmapping = A->cmap->mapping; 2256 } 2257 PetscFunctionReturn(0); 2258 } 2259 2260 /*@ 2261 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2262 2263 Logically Collective 2264 2265 Input Parameters: 2266 + A - the matrix 2267 . rmap - row layout 2268 - cmap - column layout 2269 2270 Level: advanced 2271 2272 Note: 2273 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2274 2275 .seealso: `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2276 @*/ 2277 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2278 { 2279 PetscFunctionBegin; 2280 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2281 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2282 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2283 PetscFunctionReturn(0); 2284 } 2285 2286 /*@ 2287 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2288 2289 Not Collective 2290 2291 Input Parameter: 2292 . A - the matrix 2293 2294 Output Parameters: 2295 + rmap - row layout 2296 - cmap - column layout 2297 2298 Level: advanced 2299 2300 .seealso: `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2301 @*/ 2302 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2303 { 2304 PetscFunctionBegin; 2305 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2306 PetscValidType(A, 1); 2307 if (rmap) { 2308 PetscValidPointer(rmap, 2); 2309 *rmap = A->rmap; 2310 } 2311 if (cmap) { 2312 PetscValidPointer(cmap, 3); 2313 *cmap = A->cmap; 2314 } 2315 PetscFunctionReturn(0); 2316 } 2317 2318 /*@C 2319 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2320 using a local numbering of the nodes. 2321 2322 Not Collective 2323 2324 Input Parameters: 2325 + mat - the matrix 2326 . nrow - number of rows 2327 . irow - the row local indices 2328 . ncol - number of columns 2329 . icol - the column local indices 2330 . y - a logically two-dimensional array of values 2331 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2332 2333 Level: intermediate 2334 2335 Notes: 2336 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2337 `MatSetUp()` before using this routine 2338 2339 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2340 2341 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2342 options cannot be mixed without intervening calls to the assembly 2343 routines. 2344 2345 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2346 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2347 2348 Developer Note: 2349 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2350 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2351 2352 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2353 `MatGetValuesLocal()` 2354 @*/ 2355 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2356 { 2357 PetscFunctionBeginHot; 2358 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2359 PetscValidType(mat, 1); 2360 MatCheckPreallocated(mat, 1); 2361 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2362 PetscValidIntPointer(irow, 3); 2363 PetscValidIntPointer(icol, 5); 2364 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2365 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2366 if (PetscDefined(USE_DEBUG)) { 2367 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2368 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2369 } 2370 2371 if (mat->assembled) { 2372 mat->was_assembled = PETSC_TRUE; 2373 mat->assembled = PETSC_FALSE; 2374 } 2375 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2376 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2377 else { 2378 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2379 const PetscInt *irowm, *icolm; 2380 2381 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2382 bufr = buf; 2383 bufc = buf + nrow; 2384 irowm = bufr; 2385 icolm = bufc; 2386 } else { 2387 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2388 irowm = bufr; 2389 icolm = bufc; 2390 } 2391 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2392 else irowm = irow; 2393 if (mat->cmap->mapping) { 2394 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2395 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2396 } else icolm = irowm; 2397 } else icolm = icol; 2398 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2399 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2400 } 2401 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2402 PetscFunctionReturn(0); 2403 } 2404 2405 /*@C 2406 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2407 using a local ordering of the nodes a block at a time. 2408 2409 Not Collective 2410 2411 Input Parameters: 2412 + x - the matrix 2413 . nrow - number of rows 2414 . irow - the row local indices 2415 . ncol - number of columns 2416 . icol - the column local indices 2417 . y - a logically two-dimensional array of values 2418 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2419 2420 Level: intermediate 2421 2422 Notes: 2423 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2424 `MatSetUp()` before using this routine 2425 2426 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2427 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2428 2429 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2430 options cannot be mixed without intervening calls to the assembly 2431 routines. 2432 2433 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2434 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2435 2436 Developer Note: 2437 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2438 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2439 2440 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2441 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2442 @*/ 2443 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2444 { 2445 PetscFunctionBeginHot; 2446 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2447 PetscValidType(mat, 1); 2448 MatCheckPreallocated(mat, 1); 2449 if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */ 2450 PetscValidIntPointer(irow, 3); 2451 PetscValidIntPointer(icol, 5); 2452 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2453 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2454 if (PetscDefined(USE_DEBUG)) { 2455 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2456 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); 2457 } 2458 2459 if (mat->assembled) { 2460 mat->was_assembled = PETSC_TRUE; 2461 mat->assembled = PETSC_FALSE; 2462 } 2463 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2464 PetscInt irbs, rbs; 2465 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2466 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2467 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2468 } 2469 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2470 PetscInt icbs, cbs; 2471 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2472 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2473 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2474 } 2475 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2476 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2477 else { 2478 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2479 const PetscInt *irowm, *icolm; 2480 2481 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2482 bufr = buf; 2483 bufc = buf + nrow; 2484 irowm = bufr; 2485 icolm = bufc; 2486 } else { 2487 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2488 irowm = bufr; 2489 icolm = bufc; 2490 } 2491 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2492 else irowm = irow; 2493 if (mat->cmap->mapping) { 2494 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2495 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2496 } else icolm = irowm; 2497 } else icolm = icol; 2498 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2499 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2500 } 2501 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2502 PetscFunctionReturn(0); 2503 } 2504 2505 /*@ 2506 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2507 2508 Collective 2509 2510 Input Parameters: 2511 + mat - the matrix 2512 - x - the vector to be multiplied 2513 2514 Output Parameters: 2515 . y - the result 2516 2517 Level: developer 2518 2519 Note: 2520 The vectors `x` and `y` cannot be the same. I.e., one cannot 2521 call `MatMultDiagonalBlock`(A,y,y). 2522 2523 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2524 @*/ 2525 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2526 { 2527 PetscFunctionBegin; 2528 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2529 PetscValidType(mat, 1); 2530 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2531 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2532 2533 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2534 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2535 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2536 MatCheckPreallocated(mat, 1); 2537 2538 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2539 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2540 PetscFunctionReturn(0); 2541 } 2542 2543 /*@ 2544 MatMult - Computes the matrix-vector product, y = Ax. 2545 2546 Neighbor-wise Collective 2547 2548 Input Parameters: 2549 + mat - the matrix 2550 - x - the vector to be multiplied 2551 2552 Output Parameters: 2553 . y - the result 2554 2555 Level: beginner 2556 2557 Note: 2558 The vectors `x` and `y` cannot be the same. I.e., one cannot 2559 call `MatMult`(A,y,y). 2560 2561 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2562 @*/ 2563 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2564 { 2565 PetscFunctionBegin; 2566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2567 PetscValidType(mat, 1); 2568 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2569 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2570 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2571 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2572 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2573 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); 2574 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); 2575 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); 2576 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); 2577 PetscCall(VecSetErrorIfLocked(y, 3)); 2578 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2579 MatCheckPreallocated(mat, 1); 2580 2581 PetscCall(VecLockReadPush(x)); 2582 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2583 PetscUseTypeMethod(mat, mult, x, y); 2584 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2585 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2586 PetscCall(VecLockReadPop(x)); 2587 PetscFunctionReturn(0); 2588 } 2589 2590 /*@ 2591 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2592 2593 Neighbor-wise Collective 2594 2595 Input Parameters: 2596 + mat - the matrix 2597 - x - the vector to be multiplied 2598 2599 Output Parameters: 2600 . y - the result 2601 2602 Level: beginner 2603 2604 Notes: 2605 The vectors `x` and `y` cannot be the same. I.e., one cannot 2606 call `MatMultTranspose`(A,y,y). 2607 2608 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2609 use `MatMultHermitianTranspose()` 2610 2611 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2612 @*/ 2613 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2614 { 2615 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2616 2617 PetscFunctionBegin; 2618 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2619 PetscValidType(mat, 1); 2620 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2621 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2622 2623 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2624 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2625 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2626 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); 2627 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); 2628 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); 2629 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); 2630 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2631 MatCheckPreallocated(mat, 1); 2632 2633 if (!mat->ops->multtranspose) { 2634 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2635 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); 2636 } else op = mat->ops->multtranspose; 2637 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2638 PetscCall(VecLockReadPush(x)); 2639 PetscCall((*op)(mat, x, y)); 2640 PetscCall(VecLockReadPop(x)); 2641 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2642 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2643 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2644 PetscFunctionReturn(0); 2645 } 2646 2647 /*@ 2648 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2649 2650 Neighbor-wise Collective 2651 2652 Input Parameters: 2653 + mat - the matrix 2654 - x - the vector to be multilplied 2655 2656 Output Parameters: 2657 . y - the result 2658 2659 Level: beginner 2660 2661 Notes: 2662 The vectors `x` and `y` cannot be the same. I.e., one cannot 2663 call `MatMultHermitianTranspose`(A,y,y). 2664 2665 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2666 2667 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2668 2669 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2670 @*/ 2671 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2672 { 2673 PetscFunctionBegin; 2674 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2675 PetscValidType(mat, 1); 2676 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2677 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2678 2679 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2680 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2681 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2682 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); 2683 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); 2684 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); 2685 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); 2686 MatCheckPreallocated(mat, 1); 2687 2688 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2689 #if defined(PETSC_USE_COMPLEX) 2690 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2691 PetscCall(VecLockReadPush(x)); 2692 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2693 else PetscUseTypeMethod(mat, mult, x, y); 2694 PetscCall(VecLockReadPop(x)); 2695 } else { 2696 Vec w; 2697 PetscCall(VecDuplicate(x, &w)); 2698 PetscCall(VecCopy(x, w)); 2699 PetscCall(VecConjugate(w)); 2700 PetscCall(MatMultTranspose(mat, w, y)); 2701 PetscCall(VecDestroy(&w)); 2702 PetscCall(VecConjugate(y)); 2703 } 2704 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2705 #else 2706 PetscCall(MatMultTranspose(mat, x, y)); 2707 #endif 2708 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2709 PetscFunctionReturn(0); 2710 } 2711 2712 /*@ 2713 MatMultAdd - Computes v3 = v2 + A * v1. 2714 2715 Neighbor-wise Collective 2716 2717 Input Parameters: 2718 + mat - the matrix 2719 - v1, v2 - the vectors 2720 2721 Output Parameters: 2722 . v3 - the result 2723 2724 Level: beginner 2725 2726 Note: 2727 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2728 call `MatMultAdd`(A,v1,v2,v1). 2729 2730 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2731 @*/ 2732 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2733 { 2734 PetscFunctionBegin; 2735 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2736 PetscValidType(mat, 1); 2737 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2738 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2739 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2740 2741 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2742 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2743 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); 2744 /* 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); 2745 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); */ 2746 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); 2747 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); 2748 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2749 MatCheckPreallocated(mat, 1); 2750 2751 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2752 PetscCall(VecLockReadPush(v1)); 2753 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2754 PetscCall(VecLockReadPop(v1)); 2755 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2756 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2757 PetscFunctionReturn(0); 2758 } 2759 2760 /*@ 2761 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2762 2763 Neighbor-wise Collective 2764 2765 Input Parameters: 2766 + mat - the matrix 2767 - v1, v2 - the vectors 2768 2769 Output Parameters: 2770 . v3 - the result 2771 2772 Level: beginner 2773 2774 Note: 2775 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2776 call `MatMultTransposeAdd`(A,v1,v2,v1). 2777 2778 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2779 @*/ 2780 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2781 { 2782 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2783 2784 PetscFunctionBegin; 2785 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2786 PetscValidType(mat, 1); 2787 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2788 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2789 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2790 2791 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2792 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2793 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); 2794 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); 2795 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); 2796 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2797 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2798 MatCheckPreallocated(mat, 1); 2799 2800 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2801 PetscCall(VecLockReadPush(v1)); 2802 PetscCall((*op)(mat, v1, v2, v3)); 2803 PetscCall(VecLockReadPop(v1)); 2804 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2805 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2806 PetscFunctionReturn(0); 2807 } 2808 2809 /*@ 2810 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2811 2812 Neighbor-wise Collective 2813 2814 Input Parameters: 2815 + mat - the matrix 2816 - v1, v2 - the vectors 2817 2818 Output Parameters: 2819 . v3 - the result 2820 2821 Level: beginner 2822 2823 Note: 2824 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2825 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2826 2827 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2828 @*/ 2829 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2830 { 2831 PetscFunctionBegin; 2832 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2833 PetscValidType(mat, 1); 2834 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2835 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2836 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2837 2838 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2839 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2840 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2841 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); 2842 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); 2843 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); 2844 MatCheckPreallocated(mat, 1); 2845 2846 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2847 PetscCall(VecLockReadPush(v1)); 2848 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2849 else { 2850 Vec w, z; 2851 PetscCall(VecDuplicate(v1, &w)); 2852 PetscCall(VecCopy(v1, w)); 2853 PetscCall(VecConjugate(w)); 2854 PetscCall(VecDuplicate(v3, &z)); 2855 PetscCall(MatMultTranspose(mat, w, z)); 2856 PetscCall(VecDestroy(&w)); 2857 PetscCall(VecConjugate(z)); 2858 if (v2 != v3) { 2859 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2860 } else { 2861 PetscCall(VecAXPY(v3, 1.0, z)); 2862 } 2863 PetscCall(VecDestroy(&z)); 2864 } 2865 PetscCall(VecLockReadPop(v1)); 2866 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2867 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2868 PetscFunctionReturn(0); 2869 } 2870 2871 /*@C 2872 MatGetFactorType - gets the type of factorization it is 2873 2874 Not Collective 2875 2876 Input Parameters: 2877 . mat - the matrix 2878 2879 Output Parameters: 2880 . 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` 2881 2882 Level: intermediate 2883 2884 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2885 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2886 @*/ 2887 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2888 { 2889 PetscFunctionBegin; 2890 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2891 PetscValidType(mat, 1); 2892 PetscValidPointer(t, 2); 2893 *t = mat->factortype; 2894 PetscFunctionReturn(0); 2895 } 2896 2897 /*@C 2898 MatSetFactorType - sets the type of factorization it is 2899 2900 Logically Collective 2901 2902 Input Parameters: 2903 + mat - the matrix 2904 - 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` 2905 2906 Level: intermediate 2907 2908 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2909 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2910 @*/ 2911 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2912 { 2913 PetscFunctionBegin; 2914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2915 PetscValidType(mat, 1); 2916 mat->factortype = t; 2917 PetscFunctionReturn(0); 2918 } 2919 2920 /*@C 2921 MatGetInfo - Returns information about matrix storage (number of 2922 nonzeros, memory, etc.). 2923 2924 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2925 2926 Input Parameters: 2927 + mat - the matrix 2928 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 2929 2930 Output Parameters: 2931 . info - matrix information context 2932 2933 Notes: 2934 The `MatInfo` context contains a variety of matrix data, including 2935 number of nonzeros allocated and used, number of mallocs during 2936 matrix assembly, etc. Additional information for factored matrices 2937 is provided (such as the fill ratio, number of mallocs during 2938 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2939 when using the runtime options 2940 $ -info -mat_view ::ascii_info 2941 2942 Example for C/C++ Users: 2943 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2944 data within the MatInfo context. For example, 2945 .vb 2946 MatInfo info; 2947 Mat A; 2948 double mal, nz_a, nz_u; 2949 2950 MatGetInfo(A,MAT_LOCAL,&info); 2951 mal = info.mallocs; 2952 nz_a = info.nz_allocated; 2953 .ve 2954 2955 Example for Fortran Users: 2956 Fortran users should declare info as a double precision 2957 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2958 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2959 a complete list of parameter names. 2960 .vb 2961 double precision info(MAT_INFO_SIZE) 2962 double precision mal, nz_a 2963 Mat A 2964 integer ierr 2965 2966 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2967 mal = info(MAT_INFO_MALLOCS) 2968 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2969 .ve 2970 2971 Level: intermediate 2972 2973 Developer Note: 2974 Fortran interface is not autogenerated as the 2975 interface definition cannot be generated correctly [due to MatInfo] 2976 2977 .seealso: `Mat`, `MatInfo`, `MatStashGetInfo()` 2978 @*/ 2979 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2980 { 2981 PetscFunctionBegin; 2982 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2983 PetscValidType(mat, 1); 2984 PetscValidPointer(info, 3); 2985 MatCheckPreallocated(mat, 1); 2986 PetscUseTypeMethod(mat, getinfo, flag, info); 2987 PetscFunctionReturn(0); 2988 } 2989 2990 /* 2991 This is used by external packages where it is not easy to get the info from the actual 2992 matrix factorization. 2993 */ 2994 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2995 { 2996 PetscFunctionBegin; 2997 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2998 PetscFunctionReturn(0); 2999 } 3000 3001 /*@C 3002 MatLUFactor - Performs in-place LU factorization of matrix. 3003 3004 Collective 3005 3006 Input Parameters: 3007 + mat - the matrix 3008 . row - row permutation 3009 . col - column permutation 3010 - info - options for factorization, includes 3011 .vb 3012 fill - expected fill as ratio of original fill. 3013 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3014 Run with the option -info to determine an optimal value to use 3015 .ve 3016 Level: developer 3017 3018 Notes: 3019 Most users should employ the `KSP` interface for linear solvers 3020 instead of working directly with matrix algebra routines such as this. 3021 See, e.g., `KSPCreate()`. 3022 3023 This changes the state of the matrix to a factored matrix; it cannot be used 3024 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3025 3026 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3027 when not using `KSP`. 3028 3029 Developer Note: 3030 The Fortran interface is not autogenerated as the 3031 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3032 3033 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3034 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3035 @*/ 3036 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3037 { 3038 MatFactorInfo tinfo; 3039 3040 PetscFunctionBegin; 3041 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3042 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3043 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3044 if (info) PetscValidPointer(info, 4); 3045 PetscValidType(mat, 1); 3046 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3047 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3048 MatCheckPreallocated(mat, 1); 3049 if (!info) { 3050 PetscCall(MatFactorInfoInitialize(&tinfo)); 3051 info = &tinfo; 3052 } 3053 3054 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3055 PetscUseTypeMethod(mat, lufactor, row, col, info); 3056 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3057 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3058 PetscFunctionReturn(0); 3059 } 3060 3061 /*@C 3062 MatILUFactor - Performs in-place ILU factorization of matrix. 3063 3064 Collective 3065 3066 Input Parameters: 3067 + mat - the matrix 3068 . row - row permutation 3069 . col - column permutation 3070 - info - structure containing 3071 .vb 3072 levels - number of levels of fill. 3073 expected fill - as ratio of original fill. 3074 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3075 missing diagonal entries) 3076 .ve 3077 3078 Level: developer 3079 3080 Notes: 3081 Most users should employ the `KSP` interface for linear solvers 3082 instead of working directly with matrix algebra routines such as this. 3083 See, e.g., `KSPCreate()`. 3084 3085 Probably really in-place only when level of fill is zero, otherwise allocates 3086 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3087 when not using `KSP`. 3088 3089 Developer Note: 3090 The Fortran interface is not autogenerated as the 3091 interface definition cannot be generated correctly [due to MatFactorInfo] 3092 3093 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3094 @*/ 3095 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3096 { 3097 PetscFunctionBegin; 3098 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3099 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3100 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3101 PetscValidPointer(info, 4); 3102 PetscValidType(mat, 1); 3103 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3104 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3105 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3106 MatCheckPreallocated(mat, 1); 3107 3108 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3109 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3110 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3111 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3112 PetscFunctionReturn(0); 3113 } 3114 3115 /*@C 3116 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3117 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3118 3119 Collective on fact 3120 3121 Input Parameters: 3122 + fact - the factor matrix obtained with `MatGetFactor()` 3123 . mat - the matrix 3124 . row, col - row and column permutations 3125 - info - options for factorization, includes 3126 .vb 3127 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3128 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3129 .ve 3130 3131 Level: developer 3132 3133 Notes: 3134 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3135 3136 Most users should employ the simplified `KSP` interface for linear solvers 3137 instead of working directly with matrix algebra routines such as this. 3138 See, e.g., `KSPCreate()`. 3139 3140 Developer Note: 3141 The Fortran interface is not autogenerated as the 3142 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3143 3144 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3145 @*/ 3146 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3147 { 3148 MatFactorInfo tinfo; 3149 3150 PetscFunctionBegin; 3151 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3152 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3153 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3154 if (info) PetscValidPointer(info, 5); 3155 PetscValidType(mat, 2); 3156 PetscValidPointer(fact, 1); 3157 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3158 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3159 if (!(fact)->ops->lufactorsymbolic) { 3160 MatSolverType stype; 3161 PetscCall(MatFactorGetSolverType(fact, &stype)); 3162 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype); 3163 } 3164 MatCheckPreallocated(mat, 2); 3165 if (!info) { 3166 PetscCall(MatFactorInfoInitialize(&tinfo)); 3167 info = &tinfo; 3168 } 3169 3170 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3171 PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info)); 3172 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3173 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3174 PetscFunctionReturn(0); 3175 } 3176 3177 /*@C 3178 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3179 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3180 3181 Collective on fact 3182 3183 Input Parameters: 3184 + fact - the factor matrix obtained with `MatGetFactor()` 3185 . mat - the matrix 3186 - info - options for factorization 3187 3188 Level: developer 3189 3190 Notes: 3191 See `MatLUFactor()` for in-place factorization. See 3192 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3193 3194 Most users should employ the `KSP` interface for linear solvers 3195 instead of working directly with matrix algebra routines such as this. 3196 See, e.g., `KSPCreate()`. 3197 3198 Developer Note: 3199 The Fortran interface is not autogenerated as the 3200 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3201 3202 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3203 @*/ 3204 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3205 { 3206 MatFactorInfo tinfo; 3207 3208 PetscFunctionBegin; 3209 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3210 PetscValidType(mat, 2); 3211 PetscValidPointer(fact, 1); 3212 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3213 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3214 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, 3215 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3216 3217 PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name); 3218 MatCheckPreallocated(mat, 2); 3219 if (!info) { 3220 PetscCall(MatFactorInfoInitialize(&tinfo)); 3221 info = &tinfo; 3222 } 3223 3224 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3225 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3226 PetscCall((fact->ops->lufactornumeric)(fact, mat, info)); 3227 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3228 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3229 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3230 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3231 PetscFunctionReturn(0); 3232 } 3233 3234 /*@C 3235 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3236 symmetric matrix. 3237 3238 Collective 3239 3240 Input Parameters: 3241 + mat - the matrix 3242 . perm - row and column permutations 3243 - f - expected fill as ratio of original fill 3244 3245 Level: developer 3246 3247 Notes: 3248 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3249 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3250 3251 Most users should employ the `KSP` interface for linear solvers 3252 instead of working directly with matrix algebra routines such as this. 3253 See, e.g., `KSPCreate()`. 3254 3255 Developer Note: 3256 The Fortran interface is not autogenerated as the 3257 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3258 3259 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3260 `MatGetOrdering()` 3261 @*/ 3262 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3263 { 3264 MatFactorInfo tinfo; 3265 3266 PetscFunctionBegin; 3267 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3268 PetscValidType(mat, 1); 3269 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3270 if (info) PetscValidPointer(info, 3); 3271 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3272 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3273 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3274 MatCheckPreallocated(mat, 1); 3275 if (!info) { 3276 PetscCall(MatFactorInfoInitialize(&tinfo)); 3277 info = &tinfo; 3278 } 3279 3280 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3281 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3282 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3283 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3284 PetscFunctionReturn(0); 3285 } 3286 3287 /*@C 3288 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3289 of a symmetric matrix. 3290 3291 Collective on fact 3292 3293 Input Parameters: 3294 + fact - the factor matrix obtained with `MatGetFactor()` 3295 . mat - the matrix 3296 . perm - row and column permutations 3297 - info - options for factorization, includes 3298 .vb 3299 fill - expected fill as ratio of original fill. 3300 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3301 Run with the option -info to determine an optimal value to use 3302 .ve 3303 3304 Level: developer 3305 3306 Notes: 3307 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3308 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3309 3310 Most users should employ the `KSP` interface for linear solvers 3311 instead of working directly with matrix algebra routines such as this. 3312 See, e.g., `KSPCreate()`. 3313 3314 Developer Note: 3315 The Fortran interface is not autogenerated as the 3316 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3317 3318 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3319 `MatGetOrdering()` 3320 @*/ 3321 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3322 { 3323 MatFactorInfo tinfo; 3324 3325 PetscFunctionBegin; 3326 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3327 PetscValidType(mat, 2); 3328 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3329 if (info) PetscValidPointer(info, 4); 3330 PetscValidPointer(fact, 1); 3331 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3332 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3333 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3334 if (!(fact)->ops->choleskyfactorsymbolic) { 3335 MatSolverType stype; 3336 PetscCall(MatFactorGetSolverType(fact, &stype)); 3337 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype); 3338 } 3339 MatCheckPreallocated(mat, 2); 3340 if (!info) { 3341 PetscCall(MatFactorInfoInitialize(&tinfo)); 3342 info = &tinfo; 3343 } 3344 3345 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3346 PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info)); 3347 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3348 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3349 PetscFunctionReturn(0); 3350 } 3351 3352 /*@C 3353 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3354 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3355 `MatCholeskyFactorSymbolic()`. 3356 3357 Collective on fact 3358 3359 Input Parameters: 3360 + fact - the factor matrix obtained with `MatGetFactor()` 3361 . mat - the initial matrix 3362 . info - options for factorization 3363 - fact - the symbolic factor of mat 3364 3365 Level: developer 3366 3367 Note: 3368 Most users should employ the `KSP` interface for linear solvers 3369 instead of working directly with matrix algebra routines such as this. 3370 See, e.g., `KSPCreate()`. 3371 3372 Developer Note: 3373 The Fortran interface is not autogenerated as the 3374 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3375 3376 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3377 @*/ 3378 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3379 { 3380 MatFactorInfo tinfo; 3381 3382 PetscFunctionBegin; 3383 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3384 PetscValidType(mat, 2); 3385 PetscValidPointer(fact, 1); 3386 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3387 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3388 PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name); 3389 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, 3390 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3391 MatCheckPreallocated(mat, 2); 3392 if (!info) { 3393 PetscCall(MatFactorInfoInitialize(&tinfo)); 3394 info = &tinfo; 3395 } 3396 3397 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3398 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3399 PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info)); 3400 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3401 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3402 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3403 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3404 PetscFunctionReturn(0); 3405 } 3406 3407 /*@ 3408 MatQRFactor - Performs in-place QR factorization of matrix. 3409 3410 Collective 3411 3412 Input Parameters: 3413 + mat - the matrix 3414 . col - column permutation 3415 - info - options for factorization, includes 3416 .vb 3417 fill - expected fill as ratio of original fill. 3418 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3419 Run with the option -info to determine an optimal value to use 3420 .ve 3421 3422 Level: developer 3423 3424 Notes: 3425 Most users should employ the `KSP` interface for linear solvers 3426 instead of working directly with matrix algebra routines such as this. 3427 See, e.g., `KSPCreate()`. 3428 3429 This changes the state of the matrix to a factored matrix; it cannot be used 3430 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3431 3432 Developer Note: 3433 The Fortran interface is not autogenerated as the 3434 interface definition cannot be generated correctly [due to MatFactorInfo] 3435 3436 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3437 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3438 @*/ 3439 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3440 { 3441 PetscFunctionBegin; 3442 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3443 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3444 if (info) PetscValidPointer(info, 3); 3445 PetscValidType(mat, 1); 3446 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3447 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3448 MatCheckPreallocated(mat, 1); 3449 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3450 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3451 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3452 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3453 PetscFunctionReturn(0); 3454 } 3455 3456 /*@ 3457 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3458 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3459 3460 Collective on fact 3461 3462 Input Parameters: 3463 + fact - the factor matrix obtained with `MatGetFactor()` 3464 . mat - the matrix 3465 . col - column permutation 3466 - info - options for factorization, includes 3467 .vb 3468 fill - expected fill as ratio of original fill. 3469 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3470 Run with the option -info to determine an optimal value to use 3471 .ve 3472 3473 Level: developer 3474 3475 Note: 3476 Most users should employ the `KSP` interface for linear solvers 3477 instead of working directly with matrix algebra routines such as this. 3478 See, e.g., `KSPCreate()`. 3479 3480 Developer Note: 3481 The Fortran interface is not autogenerated as the 3482 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3483 3484 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3485 @*/ 3486 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3487 { 3488 MatFactorInfo tinfo; 3489 3490 PetscFunctionBegin; 3491 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3492 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3493 if (info) PetscValidPointer(info, 4); 3494 PetscValidType(mat, 2); 3495 PetscValidPointer(fact, 1); 3496 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3497 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3498 MatCheckPreallocated(mat, 2); 3499 if (!info) { 3500 PetscCall(MatFactorInfoInitialize(&tinfo)); 3501 info = &tinfo; 3502 } 3503 3504 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3505 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3506 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3507 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3508 PetscFunctionReturn(0); 3509 } 3510 3511 /*@ 3512 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3513 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3514 3515 Collective on fact 3516 3517 Input Parameters: 3518 + fact - the factor matrix obtained with `MatGetFactor()` 3519 . mat - the matrix 3520 - info - options for factorization 3521 3522 Level: developer 3523 3524 Notes: 3525 See `MatQRFactor()` for in-place factorization. 3526 3527 Most users should employ the `KSP` interface for linear solvers 3528 instead of working directly with matrix algebra routines such as this. 3529 See, e.g., `KSPCreate()`. 3530 3531 Developer Note: 3532 The Fortran interface is not autogenerated as the 3533 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3534 3535 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3536 @*/ 3537 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3538 { 3539 MatFactorInfo tinfo; 3540 3541 PetscFunctionBegin; 3542 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3543 PetscValidType(mat, 2); 3544 PetscValidPointer(fact, 1); 3545 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3546 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3547 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, 3548 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3549 3550 MatCheckPreallocated(mat, 2); 3551 if (!info) { 3552 PetscCall(MatFactorInfoInitialize(&tinfo)); 3553 info = &tinfo; 3554 } 3555 3556 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3557 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3558 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3559 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3560 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3561 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3562 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3563 PetscFunctionReturn(0); 3564 } 3565 3566 /*@ 3567 MatSolve - Solves A x = b, given a factored matrix. 3568 3569 Neighbor-wise Collective 3570 3571 Input Parameters: 3572 + mat - the factored matrix 3573 - b - the right-hand-side vector 3574 3575 Output Parameter: 3576 . x - the result vector 3577 3578 Level: developer 3579 3580 Notes: 3581 The vectors `b` and `x` cannot be the same. I.e., one cannot 3582 call `MatSolve`(A,x,x). 3583 3584 Most users should employ the `KSP` interface for linear solvers 3585 instead of working directly with matrix algebra routines such as this. 3586 See, e.g., `KSPCreate()`. 3587 3588 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3589 @*/ 3590 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3591 { 3592 PetscFunctionBegin; 3593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3594 PetscValidType(mat, 1); 3595 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3596 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3597 PetscCheckSameComm(mat, 1, b, 2); 3598 PetscCheckSameComm(mat, 1, x, 3); 3599 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3600 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); 3601 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); 3602 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); 3603 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3604 MatCheckPreallocated(mat, 1); 3605 3606 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3607 if (mat->factorerrortype) { 3608 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3609 PetscCall(VecSetInf(x)); 3610 } else PetscUseTypeMethod(mat, solve, b, x); 3611 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3612 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3613 PetscFunctionReturn(0); 3614 } 3615 3616 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3617 { 3618 Vec b, x; 3619 PetscInt N, i; 3620 PetscErrorCode (*f)(Mat, Vec, Vec); 3621 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3622 3623 PetscFunctionBegin; 3624 if (A->factorerrortype) { 3625 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3626 PetscCall(MatSetInf(X)); 3627 PetscFunctionReturn(0); 3628 } 3629 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3630 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3631 PetscCall(MatBoundToCPU(A, &Abound)); 3632 if (!Abound) { 3633 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3634 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3635 } 3636 #if defined(PETSC_HAVE_CUDA) 3637 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3638 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3639 #elif (PETSC_HAVE_HIP) 3640 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3641 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3642 #endif 3643 PetscCall(MatGetSize(B, NULL, &N)); 3644 for (i = 0; i < N; i++) { 3645 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3646 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3647 PetscCall((*f)(A, b, x)); 3648 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3649 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3650 } 3651 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3652 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3653 PetscFunctionReturn(0); 3654 } 3655 3656 /*@ 3657 MatMatSolve - Solves A X = B, given a factored matrix. 3658 3659 Neighbor-wise Collective 3660 3661 Input Parameters: 3662 + A - the factored matrix 3663 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3664 3665 Output Parameter: 3666 . X - the result matrix (dense matrix) 3667 3668 Level: developer 3669 3670 Note: 3671 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3672 otherwise, `B` and `X` cannot be the same. 3673 3674 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3675 @*/ 3676 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3677 { 3678 PetscFunctionBegin; 3679 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3680 PetscValidType(A, 1); 3681 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3682 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3683 PetscCheckSameComm(A, 1, B, 2); 3684 PetscCheckSameComm(A, 1, X, 3); 3685 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); 3686 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); 3687 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"); 3688 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3689 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3690 MatCheckPreallocated(A, 1); 3691 3692 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3693 if (!A->ops->matsolve) { 3694 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3695 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3696 } else PetscUseTypeMethod(A, matsolve, B, X); 3697 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3698 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3699 PetscFunctionReturn(0); 3700 } 3701 3702 /*@ 3703 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3704 3705 Neighbor-wise Collective 3706 3707 Input Parameters: 3708 + A - the factored matrix 3709 - B - the right-hand-side matrix (`MATDENSE` matrix) 3710 3711 Output Parameter: 3712 . X - the result matrix (dense matrix) 3713 3714 Level: developer 3715 3716 Note: 3717 The matrices `B` and `X` cannot be the same. I.e., one cannot 3718 call `MatMatSolveTranspose`(A,X,X). 3719 3720 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3721 @*/ 3722 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3723 { 3724 PetscFunctionBegin; 3725 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3726 PetscValidType(A, 1); 3727 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3728 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3729 PetscCheckSameComm(A, 1, B, 2); 3730 PetscCheckSameComm(A, 1, X, 3); 3731 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3732 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); 3733 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); 3734 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); 3735 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"); 3736 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3737 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3738 MatCheckPreallocated(A, 1); 3739 3740 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3741 if (!A->ops->matsolvetranspose) { 3742 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3743 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3744 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3745 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3746 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3747 PetscFunctionReturn(0); 3748 } 3749 3750 /*@ 3751 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3752 3753 Neighbor-wise Collective 3754 3755 Input Parameters: 3756 + A - the factored matrix 3757 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3758 3759 Output Parameter: 3760 . X - the result matrix (dense matrix) 3761 3762 Level: developer 3763 3764 Note: 3765 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 3766 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3767 3768 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3769 @*/ 3770 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3771 { 3772 PetscFunctionBegin; 3773 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3774 PetscValidType(A, 1); 3775 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3776 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3777 PetscCheckSameComm(A, 1, Bt, 2); 3778 PetscCheckSameComm(A, 1, X, 3); 3779 3780 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3781 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); 3782 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); 3783 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"); 3784 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0); 3785 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3786 MatCheckPreallocated(A, 1); 3787 3788 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3789 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3790 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3791 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3792 PetscFunctionReturn(0); 3793 } 3794 3795 /*@ 3796 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3797 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3798 3799 Neighbor-wise Collective 3800 3801 Input Parameters: 3802 + mat - the factored matrix 3803 - b - the right-hand-side vector 3804 3805 Output Parameter: 3806 . x - the result vector 3807 3808 Level: developer 3809 3810 Notes: 3811 `MatSolve()` should be used for most applications, as it performs 3812 a forward solve followed by a backward solve. 3813 3814 The vectors `b` and `x` cannot be the same, i.e., one cannot 3815 call `MatForwardSolve`(A,x,x). 3816 3817 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3818 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3819 `MatForwardSolve()` solves U^T*D y = b, and 3820 `MatBackwardSolve()` solves U x = y. 3821 Thus they do not provide a symmetric preconditioner. 3822 3823 .seealso: `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3824 @*/ 3825 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3826 { 3827 PetscFunctionBegin; 3828 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3829 PetscValidType(mat, 1); 3830 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3831 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3832 PetscCheckSameComm(mat, 1, b, 2); 3833 PetscCheckSameComm(mat, 1, x, 3); 3834 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3835 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); 3836 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); 3837 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); 3838 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3839 MatCheckPreallocated(mat, 1); 3840 3841 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3842 PetscUseTypeMethod(mat, forwardsolve, b, x); 3843 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3844 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3845 PetscFunctionReturn(0); 3846 } 3847 3848 /*@ 3849 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3850 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3851 3852 Neighbor-wise Collective 3853 3854 Input Parameters: 3855 + mat - the factored matrix 3856 - b - the right-hand-side vector 3857 3858 Output Parameter: 3859 . x - the result vector 3860 3861 Level: developer 3862 3863 Notes: 3864 `MatSolve()` should be used for most applications, as it performs 3865 a forward solve followed by a backward solve. 3866 3867 The vectors `b` and `x` cannot be the same. I.e., one cannot 3868 call `MatBackwardSolve`(A,x,x). 3869 3870 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3871 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3872 `MatForwardSolve()` solves U^T*D y = b, and 3873 `MatBackwardSolve()` solves U x = y. 3874 Thus they do not provide a symmetric preconditioner. 3875 3876 .seealso: `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3877 @*/ 3878 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3879 { 3880 PetscFunctionBegin; 3881 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3882 PetscValidType(mat, 1); 3883 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3884 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3885 PetscCheckSameComm(mat, 1, b, 2); 3886 PetscCheckSameComm(mat, 1, x, 3); 3887 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3888 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); 3889 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); 3890 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); 3891 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3892 MatCheckPreallocated(mat, 1); 3893 3894 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3895 PetscUseTypeMethod(mat, backwardsolve, b, x); 3896 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3897 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3898 PetscFunctionReturn(0); 3899 } 3900 3901 /*@ 3902 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3903 3904 Neighbor-wise Collective 3905 3906 Input Parameters: 3907 + mat - the factored matrix 3908 . b - the right-hand-side vector 3909 - y - the vector to be added to 3910 3911 Output Parameter: 3912 . x - the result vector 3913 3914 Level: developer 3915 3916 Note: 3917 The vectors `b` and `x` cannot be the same. I.e., one cannot 3918 call `MatSolveAdd`(A,x,y,x). 3919 3920 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3921 @*/ 3922 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3923 { 3924 PetscScalar one = 1.0; 3925 Vec tmp; 3926 3927 PetscFunctionBegin; 3928 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3929 PetscValidType(mat, 1); 3930 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3931 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3932 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3933 PetscCheckSameComm(mat, 1, b, 2); 3934 PetscCheckSameComm(mat, 1, y, 3); 3935 PetscCheckSameComm(mat, 1, x, 4); 3936 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3937 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); 3938 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); 3939 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); 3940 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); 3941 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); 3942 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 3943 MatCheckPreallocated(mat, 1); 3944 3945 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3946 if (mat->factorerrortype) { 3947 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3948 PetscCall(VecSetInf(x)); 3949 } else if (mat->ops->solveadd) { 3950 PetscUseTypeMethod(mat, solveadd, b, y, x); 3951 } else { 3952 /* do the solve then the add manually */ 3953 if (x != y) { 3954 PetscCall(MatSolve(mat, b, x)); 3955 PetscCall(VecAXPY(x, one, y)); 3956 } else { 3957 PetscCall(VecDuplicate(x, &tmp)); 3958 PetscCall(VecCopy(x, tmp)); 3959 PetscCall(MatSolve(mat, b, x)); 3960 PetscCall(VecAXPY(x, one, tmp)); 3961 PetscCall(VecDestroy(&tmp)); 3962 } 3963 } 3964 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3965 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3966 PetscFunctionReturn(0); 3967 } 3968 3969 /*@ 3970 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3971 3972 Neighbor-wise Collective 3973 3974 Input Parameters: 3975 + mat - the factored matrix 3976 - b - the right-hand-side vector 3977 3978 Output Parameter: 3979 . x - the result vector 3980 3981 Level: developer 3982 3983 Notes: 3984 The vectors `b` and `x` cannot be the same. I.e., one cannot 3985 call `MatSolveTranspose`(A,x,x). 3986 3987 Most users should employ the `KSP` interface for linear solvers 3988 instead of working directly with matrix algebra routines such as this. 3989 See, e.g., `KSPCreate()`. 3990 3991 .seealso: `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3992 @*/ 3993 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3994 { 3995 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3996 3997 PetscFunctionBegin; 3998 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3999 PetscValidType(mat, 1); 4000 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4001 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4002 PetscCheckSameComm(mat, 1, b, 2); 4003 PetscCheckSameComm(mat, 1, x, 3); 4004 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4005 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); 4006 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); 4007 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 4008 MatCheckPreallocated(mat, 1); 4009 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4010 if (mat->factorerrortype) { 4011 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4012 PetscCall(VecSetInf(x)); 4013 } else { 4014 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4015 PetscCall((*f)(mat, b, x)); 4016 } 4017 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4018 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4019 PetscFunctionReturn(0); 4020 } 4021 4022 /*@ 4023 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4024 factored matrix. 4025 4026 Neighbor-wise Collective 4027 4028 Input Parameters: 4029 + mat - the factored matrix 4030 . b - the right-hand-side vector 4031 - y - the vector to be added to 4032 4033 Output Parameter: 4034 . x - the result vector 4035 4036 Level: developer 4037 4038 Note: 4039 The vectors `b` and `x` cannot be the same. I.e., one cannot 4040 call `MatSolveTransposeAdd`(A,x,y,x). 4041 4042 .seealso: `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4043 @*/ 4044 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4045 { 4046 PetscScalar one = 1.0; 4047 Vec tmp; 4048 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4049 4050 PetscFunctionBegin; 4051 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4052 PetscValidType(mat, 1); 4053 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4054 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4055 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4056 PetscCheckSameComm(mat, 1, b, 2); 4057 PetscCheckSameComm(mat, 1, y, 3); 4058 PetscCheckSameComm(mat, 1, x, 4); 4059 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4060 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); 4061 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); 4062 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); 4063 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); 4064 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 4065 MatCheckPreallocated(mat, 1); 4066 4067 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4068 if (mat->factorerrortype) { 4069 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4070 PetscCall(VecSetInf(x)); 4071 } else if (f) { 4072 PetscCall((*f)(mat, b, y, x)); 4073 } else { 4074 /* do the solve then the add manually */ 4075 if (x != y) { 4076 PetscCall(MatSolveTranspose(mat, b, x)); 4077 PetscCall(VecAXPY(x, one, y)); 4078 } else { 4079 PetscCall(VecDuplicate(x, &tmp)); 4080 PetscCall(VecCopy(x, tmp)); 4081 PetscCall(MatSolveTranspose(mat, b, x)); 4082 PetscCall(VecAXPY(x, one, tmp)); 4083 PetscCall(VecDestroy(&tmp)); 4084 } 4085 } 4086 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4087 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4088 PetscFunctionReturn(0); 4089 } 4090 4091 /*@ 4092 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4093 4094 Neighbor-wise Collective 4095 4096 Input Parameters: 4097 + mat - the matrix 4098 . b - the right hand side 4099 . omega - the relaxation factor 4100 . flag - flag indicating the type of SOR (see below) 4101 . shift - diagonal shift 4102 . its - the number of iterations 4103 - lits - the number of local iterations 4104 4105 Output Parameter: 4106 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4107 4108 SOR Flags: 4109 + `SOR_FORWARD_SWEEP` - forward SOR 4110 . `SOR_BACKWARD_SWEEP` - backward SOR 4111 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4112 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4113 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4114 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4115 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4116 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4117 upper/lower triangular part of matrix to 4118 vector (with omega) 4119 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4120 4121 Level: developer 4122 4123 Notes: 4124 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4125 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4126 on each processor. 4127 4128 Application programmers will not generally use `MatSOR()` directly, 4129 but instead will employ the `KSP`/`PC` interface. 4130 4131 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4132 4133 Most users should employ the `KSP` interface for linear solvers 4134 instead of working directly with matrix algebra routines such as this. 4135 See, e.g., `KSPCreate()`. 4136 4137 Vectors `x` and `b` CANNOT be the same 4138 4139 Notes for Advanced Users: 4140 The flags are implemented as bitwise inclusive or operations. 4141 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4142 to specify a zero initial guess for SSOR. 4143 4144 Developer Note: 4145 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4146 4147 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4148 @*/ 4149 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4150 { 4151 PetscFunctionBegin; 4152 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4153 PetscValidType(mat, 1); 4154 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4155 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4156 PetscCheckSameComm(mat, 1, b, 2); 4157 PetscCheckSameComm(mat, 1, x, 8); 4158 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4159 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4160 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); 4161 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); 4162 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); 4163 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4164 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4165 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4166 4167 MatCheckPreallocated(mat, 1); 4168 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4169 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4170 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4171 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4172 PetscFunctionReturn(0); 4173 } 4174 4175 /* 4176 Default matrix copy routine. 4177 */ 4178 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4179 { 4180 PetscInt i, rstart = 0, rend = 0, nz; 4181 const PetscInt *cwork; 4182 const PetscScalar *vwork; 4183 4184 PetscFunctionBegin; 4185 if (B->assembled) PetscCall(MatZeroEntries(B)); 4186 if (str == SAME_NONZERO_PATTERN) { 4187 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4188 for (i = rstart; i < rend; i++) { 4189 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4190 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4191 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4192 } 4193 } else { 4194 PetscCall(MatAYPX(B, 0.0, A, str)); 4195 } 4196 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4197 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4198 PetscFunctionReturn(0); 4199 } 4200 4201 /*@ 4202 MatCopy - Copies a matrix to another matrix. 4203 4204 Collective 4205 4206 Input Parameters: 4207 + A - the matrix 4208 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4209 4210 Output Parameter: 4211 . B - where the copy is put 4212 4213 Level: intermediate 4214 4215 Notes: 4216 If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash. 4217 4218 `MatCopy()` copies the matrix entries of a matrix to another existing 4219 matrix (after first zeroing the second matrix). A related routine is 4220 `MatConvert()`, which first creates a new matrix and then copies the data. 4221 4222 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()` 4223 @*/ 4224 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4225 { 4226 PetscInt i; 4227 4228 PetscFunctionBegin; 4229 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4230 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4231 PetscValidType(A, 1); 4232 PetscValidType(B, 2); 4233 PetscCheckSameComm(A, 1, B, 2); 4234 MatCheckPreallocated(B, 2); 4235 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4236 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4237 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, 4238 A->cmap->N, B->cmap->N); 4239 MatCheckPreallocated(A, 1); 4240 if (A == B) PetscFunctionReturn(0); 4241 4242 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4243 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4244 else PetscCall(MatCopy_Basic(A, B, str)); 4245 4246 B->stencil.dim = A->stencil.dim; 4247 B->stencil.noc = A->stencil.noc; 4248 for (i = 0; i <= A->stencil.dim; i++) { 4249 B->stencil.dims[i] = A->stencil.dims[i]; 4250 B->stencil.starts[i] = A->stencil.starts[i]; 4251 } 4252 4253 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4254 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4255 PetscFunctionReturn(0); 4256 } 4257 4258 /*@C 4259 MatConvert - Converts a matrix to another matrix, either of the same 4260 or different type. 4261 4262 Collective 4263 4264 Input Parameters: 4265 + mat - the matrix 4266 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4267 same type as the original matrix. 4268 - reuse - denotes if the destination matrix is to be created or reused. 4269 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 4270 `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). 4271 4272 Output Parameter: 4273 . M - pointer to place new matrix 4274 4275 Level: intermediate 4276 4277 Notes: 4278 `MatConvert()` first creates a new matrix and then copies the data from 4279 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4280 entries of one matrix to another already existing matrix context. 4281 4282 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4283 the MPI communicator of the generated matrix is always the same as the communicator 4284 of the input matrix. 4285 4286 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4287 @*/ 4288 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4289 { 4290 PetscBool sametype, issame, flg; 4291 PetscBool3 issymmetric, ishermitian; 4292 char convname[256], mtype[256]; 4293 Mat B; 4294 4295 PetscFunctionBegin; 4296 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4297 PetscValidType(mat, 1); 4298 PetscValidPointer(M, 4); 4299 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4300 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4301 MatCheckPreallocated(mat, 1); 4302 4303 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4304 if (flg) newtype = mtype; 4305 4306 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4307 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4308 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4309 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"); 4310 4311 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4312 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4313 PetscFunctionReturn(0); 4314 } 4315 4316 /* Cache Mat options because some converters use MatHeaderReplace */ 4317 issymmetric = mat->symmetric; 4318 ishermitian = mat->hermitian; 4319 4320 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4321 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4322 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4323 } else { 4324 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4325 const char *prefix[3] = {"seq", "mpi", ""}; 4326 PetscInt i; 4327 /* 4328 Order of precedence: 4329 0) See if newtype is a superclass of the current matrix. 4330 1) See if a specialized converter is known to the current matrix. 4331 2) See if a specialized converter is known to the desired matrix class. 4332 3) See if a good general converter is registered for the desired class 4333 (as of 6/27/03 only MATMPIADJ falls into this category). 4334 4) See if a good general converter is known for the current matrix. 4335 5) Use a really basic converter. 4336 */ 4337 4338 /* 0) See if newtype is a superclass of the current matrix. 4339 i.e mat is mpiaij and newtype is aij */ 4340 for (i = 0; i < 2; i++) { 4341 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4342 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4343 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4344 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4345 if (flg) { 4346 if (reuse == MAT_INPLACE_MATRIX) { 4347 PetscCall(PetscInfo(mat, "Early return\n")); 4348 PetscFunctionReturn(0); 4349 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4350 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4351 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4352 PetscFunctionReturn(0); 4353 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4354 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4355 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4356 PetscFunctionReturn(0); 4357 } 4358 } 4359 } 4360 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4361 for (i = 0; i < 3; i++) { 4362 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4363 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4364 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4365 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4366 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4367 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4368 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4369 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4370 if (conv) goto foundconv; 4371 } 4372 4373 /* 2) See if a specialized converter is known to the desired matrix class. */ 4374 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4375 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4376 PetscCall(MatSetType(B, newtype)); 4377 for (i = 0; i < 3; i++) { 4378 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4379 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4380 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4381 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4382 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4383 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4384 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4385 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4386 if (conv) { 4387 PetscCall(MatDestroy(&B)); 4388 goto foundconv; 4389 } 4390 } 4391 4392 /* 3) See if a good general converter is registered for the desired class */ 4393 conv = B->ops->convertfrom; 4394 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4395 PetscCall(MatDestroy(&B)); 4396 if (conv) goto foundconv; 4397 4398 /* 4) See if a good general converter is known for the current matrix */ 4399 if (mat->ops->convert) conv = mat->ops->convert; 4400 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4401 if (conv) goto foundconv; 4402 4403 /* 5) Use a really basic converter. */ 4404 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4405 conv = MatConvert_Basic; 4406 4407 foundconv: 4408 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4409 PetscCall((*conv)(mat, newtype, reuse, M)); 4410 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4411 /* the block sizes must be same if the mappings are copied over */ 4412 (*M)->rmap->bs = mat->rmap->bs; 4413 (*M)->cmap->bs = mat->cmap->bs; 4414 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4415 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4416 (*M)->rmap->mapping = mat->rmap->mapping; 4417 (*M)->cmap->mapping = mat->cmap->mapping; 4418 } 4419 (*M)->stencil.dim = mat->stencil.dim; 4420 (*M)->stencil.noc = mat->stencil.noc; 4421 for (i = 0; i <= mat->stencil.dim; i++) { 4422 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4423 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4424 } 4425 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4426 } 4427 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4428 4429 /* Copy Mat options */ 4430 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4431 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4432 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4433 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4434 PetscFunctionReturn(0); 4435 } 4436 4437 /*@C 4438 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4439 4440 Not Collective 4441 4442 Input Parameter: 4443 . mat - the matrix, must be a factored matrix 4444 4445 Output Parameter: 4446 . type - the string name of the package (do not free this string) 4447 4448 Level: intermediate 4449 4450 Fortran Note: 4451 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4452 4453 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4454 @*/ 4455 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4456 { 4457 PetscErrorCode (*conv)(Mat, MatSolverType *); 4458 4459 PetscFunctionBegin; 4460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4461 PetscValidType(mat, 1); 4462 PetscValidPointer(type, 2); 4463 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4464 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4465 if (conv) PetscCall((*conv)(mat, type)); 4466 else *type = MATSOLVERPETSC; 4467 PetscFunctionReturn(0); 4468 } 4469 4470 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4471 struct _MatSolverTypeForSpecifcType { 4472 MatType mtype; 4473 /* no entry for MAT_FACTOR_NONE */ 4474 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4475 MatSolverTypeForSpecifcType next; 4476 }; 4477 4478 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4479 struct _MatSolverTypeHolder { 4480 char *name; 4481 MatSolverTypeForSpecifcType handlers; 4482 MatSolverTypeHolder next; 4483 }; 4484 4485 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4486 4487 /*@C 4488 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4489 4490 Input Parameters: 4491 + package - name of the package, for example petsc or superlu 4492 . mtype - the matrix type that works with this package 4493 . ftype - the type of factorization supported by the package 4494 - createfactor - routine that will create the factored matrix ready to be used 4495 4496 Level: developer 4497 4498 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4499 @*/ 4500 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4501 { 4502 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4503 PetscBool flg; 4504 MatSolverTypeForSpecifcType inext, iprev = NULL; 4505 4506 PetscFunctionBegin; 4507 PetscCall(MatInitializePackage()); 4508 if (!next) { 4509 PetscCall(PetscNew(&MatSolverTypeHolders)); 4510 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4511 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4512 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4513 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4514 PetscFunctionReturn(0); 4515 } 4516 while (next) { 4517 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4518 if (flg) { 4519 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4520 inext = next->handlers; 4521 while (inext) { 4522 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4523 if (flg) { 4524 inext->createfactor[(int)ftype - 1] = createfactor; 4525 PetscFunctionReturn(0); 4526 } 4527 iprev = inext; 4528 inext = inext->next; 4529 } 4530 PetscCall(PetscNew(&iprev->next)); 4531 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4532 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4533 PetscFunctionReturn(0); 4534 } 4535 prev = next; 4536 next = next->next; 4537 } 4538 PetscCall(PetscNew(&prev->next)); 4539 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4540 PetscCall(PetscNew(&prev->next->handlers)); 4541 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4542 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4543 PetscFunctionReturn(0); 4544 } 4545 4546 /*@C 4547 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4548 4549 Input Parameters: 4550 + type - name of the package, for example petsc or superlu 4551 . ftype - the type of factorization supported by the type 4552 - mtype - the matrix type that works with this type 4553 4554 Output Parameters: 4555 + foundtype - `PETSC_TRUE` if the type was registered 4556 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4557 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4558 4559 Level: developer 4560 4561 .seealso: `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4562 @*/ 4563 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4564 { 4565 MatSolverTypeHolder next = MatSolverTypeHolders; 4566 PetscBool flg; 4567 MatSolverTypeForSpecifcType inext; 4568 4569 PetscFunctionBegin; 4570 if (foundtype) *foundtype = PETSC_FALSE; 4571 if (foundmtype) *foundmtype = PETSC_FALSE; 4572 if (createfactor) *createfactor = NULL; 4573 4574 if (type) { 4575 while (next) { 4576 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4577 if (flg) { 4578 if (foundtype) *foundtype = PETSC_TRUE; 4579 inext = next->handlers; 4580 while (inext) { 4581 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4582 if (flg) { 4583 if (foundmtype) *foundmtype = PETSC_TRUE; 4584 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4585 PetscFunctionReturn(0); 4586 } 4587 inext = inext->next; 4588 } 4589 } 4590 next = next->next; 4591 } 4592 } else { 4593 while (next) { 4594 inext = next->handlers; 4595 while (inext) { 4596 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4597 if (flg && inext->createfactor[(int)ftype - 1]) { 4598 if (foundtype) *foundtype = PETSC_TRUE; 4599 if (foundmtype) *foundmtype = PETSC_TRUE; 4600 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4601 PetscFunctionReturn(0); 4602 } 4603 inext = inext->next; 4604 } 4605 next = next->next; 4606 } 4607 /* try with base classes inext->mtype */ 4608 next = MatSolverTypeHolders; 4609 while (next) { 4610 inext = next->handlers; 4611 while (inext) { 4612 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4613 if (flg && inext->createfactor[(int)ftype - 1]) { 4614 if (foundtype) *foundtype = PETSC_TRUE; 4615 if (foundmtype) *foundmtype = PETSC_TRUE; 4616 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4617 PetscFunctionReturn(0); 4618 } 4619 inext = inext->next; 4620 } 4621 next = next->next; 4622 } 4623 } 4624 PetscFunctionReturn(0); 4625 } 4626 4627 PetscErrorCode MatSolverTypeDestroy(void) 4628 { 4629 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4630 MatSolverTypeForSpecifcType inext, iprev; 4631 4632 PetscFunctionBegin; 4633 while (next) { 4634 PetscCall(PetscFree(next->name)); 4635 inext = next->handlers; 4636 while (inext) { 4637 PetscCall(PetscFree(inext->mtype)); 4638 iprev = inext; 4639 inext = inext->next; 4640 PetscCall(PetscFree(iprev)); 4641 } 4642 prev = next; 4643 next = next->next; 4644 PetscCall(PetscFree(prev)); 4645 } 4646 MatSolverTypeHolders = NULL; 4647 PetscFunctionReturn(0); 4648 } 4649 4650 /*@C 4651 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4652 4653 Logically Collective 4654 4655 Input Parameters: 4656 . mat - the matrix 4657 4658 Output Parameters: 4659 . flg - `PETSC_TRUE` if uses the ordering 4660 4661 Level: developer 4662 4663 Note: 4664 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4665 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4666 4667 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4668 @*/ 4669 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4670 { 4671 PetscFunctionBegin; 4672 *flg = mat->canuseordering; 4673 PetscFunctionReturn(0); 4674 } 4675 4676 /*@C 4677 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4678 4679 Logically Collective 4680 4681 Input Parameters: 4682 . mat - the matrix obtained with `MatGetFactor()` 4683 4684 Output Parameters: 4685 . otype - the preferred type 4686 4687 Level: developer 4688 4689 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4690 @*/ 4691 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4692 { 4693 PetscFunctionBegin; 4694 *otype = mat->preferredordering[ftype]; 4695 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4696 PetscFunctionReturn(0); 4697 } 4698 4699 /*@C 4700 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4701 4702 Collective 4703 4704 Input Parameters: 4705 + mat - the matrix 4706 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4707 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4708 4709 Output Parameters: 4710 . f - the factor matrix used with MatXXFactorSymbolic() calls 4711 4712 Options Database Key: 4713 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4714 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4715 4716 Level: intermediate 4717 4718 Notes: 4719 Users usually access the factorization solvers via `KSP` 4720 4721 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4722 such as pastix, superlu, mumps etc. 4723 4724 PETSc must have been ./configure to use the external solver, using the option --download-package 4725 4726 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4727 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4728 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4729 4730 Developer Note: 4731 This should actually be called `MatCreateFactor()` since it creates a new factor object 4732 4733 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4734 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4735 @*/ 4736 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4737 { 4738 PetscBool foundtype, foundmtype; 4739 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4740 4741 PetscFunctionBegin; 4742 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4743 PetscValidType(mat, 1); 4744 4745 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4746 MatCheckPreallocated(mat, 1); 4747 4748 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4749 if (!foundtype) { 4750 if (type) { 4751 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], 4752 ((PetscObject)mat)->type_name, type); 4753 } else { 4754 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); 4755 } 4756 } 4757 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4758 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); 4759 4760 PetscCall((*conv)(mat, ftype, f)); 4761 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4762 PetscFunctionReturn(0); 4763 } 4764 4765 /*@C 4766 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4767 4768 Not Collective 4769 4770 Input Parameters: 4771 + mat - the matrix 4772 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4773 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4774 4775 Output Parameter: 4776 . flg - PETSC_TRUE if the factorization is available 4777 4778 Level: intermediate 4779 4780 Notes: 4781 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4782 such as pastix, superlu, mumps etc. 4783 4784 PETSc must have been ./configure to use the external solver, using the option --download-package 4785 4786 Developer Note: 4787 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4788 4789 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4790 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4791 @*/ 4792 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4793 { 4794 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4795 4796 PetscFunctionBegin; 4797 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4798 PetscValidType(mat, 1); 4799 PetscValidBoolPointer(flg, 4); 4800 4801 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4802 MatCheckPreallocated(mat, 1); 4803 4804 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4805 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4806 PetscFunctionReturn(0); 4807 } 4808 4809 /*@ 4810 MatDuplicate - Duplicates a matrix including the non-zero structure. 4811 4812 Collective 4813 4814 Input Parameters: 4815 + mat - the matrix 4816 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4817 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4818 4819 Output Parameter: 4820 . M - pointer to place new matrix 4821 4822 Level: intermediate 4823 4824 Notes: 4825 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4826 4827 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. 4828 4829 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 4830 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4831 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4832 4833 .seealso: `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4834 @*/ 4835 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4836 { 4837 Mat B; 4838 VecType vtype; 4839 PetscInt i; 4840 PetscObject dm; 4841 void (*viewf)(void); 4842 4843 PetscFunctionBegin; 4844 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4845 PetscValidType(mat, 1); 4846 PetscValidPointer(M, 3); 4847 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4848 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4849 MatCheckPreallocated(mat, 1); 4850 4851 *M = NULL; 4852 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4853 PetscUseTypeMethod(mat, duplicate, op, M); 4854 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4855 B = *M; 4856 4857 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4858 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4859 PetscCall(MatGetVecType(mat, &vtype)); 4860 PetscCall(MatSetVecType(B, vtype)); 4861 4862 B->stencil.dim = mat->stencil.dim; 4863 B->stencil.noc = mat->stencil.noc; 4864 for (i = 0; i <= mat->stencil.dim; i++) { 4865 B->stencil.dims[i] = mat->stencil.dims[i]; 4866 B->stencil.starts[i] = mat->stencil.starts[i]; 4867 } 4868 4869 B->nooffproczerorows = mat->nooffproczerorows; 4870 B->nooffprocentries = mat->nooffprocentries; 4871 4872 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4873 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4874 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4875 PetscFunctionReturn(0); 4876 } 4877 4878 /*@ 4879 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4880 4881 Logically Collective 4882 4883 Input Parameters: 4884 + mat - the matrix 4885 - v - the vector for storing the diagonal 4886 4887 Output Parameter: 4888 . v - the diagonal of the matrix 4889 4890 Level: intermediate 4891 4892 Note: 4893 Currently only correct in parallel for square matrices. 4894 4895 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4896 @*/ 4897 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4898 { 4899 PetscFunctionBegin; 4900 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4901 PetscValidType(mat, 1); 4902 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4903 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4904 MatCheckPreallocated(mat, 1); 4905 4906 PetscUseTypeMethod(mat, getdiagonal, v); 4907 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4908 PetscFunctionReturn(0); 4909 } 4910 4911 /*@C 4912 MatGetRowMin - Gets the minimum value (of the real part) of each 4913 row of the matrix 4914 4915 Logically Collective 4916 4917 Input Parameter: 4918 . mat - the matrix 4919 4920 Output Parameters: 4921 + v - the vector for storing the maximums 4922 - idx - the indices of the column found for each row (optional) 4923 4924 Level: intermediate 4925 4926 Note: 4927 The result of this call are the same as if one converted the matrix to dense format 4928 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4929 4930 This code is only implemented for a couple of matrix formats. 4931 4932 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4933 `MatGetRowMax()` 4934 @*/ 4935 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4936 { 4937 PetscFunctionBegin; 4938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4939 PetscValidType(mat, 1); 4940 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4941 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4942 4943 if (!mat->cmap->N) { 4944 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4945 if (idx) { 4946 PetscInt i, m = mat->rmap->n; 4947 for (i = 0; i < m; i++) idx[i] = -1; 4948 } 4949 } else { 4950 MatCheckPreallocated(mat, 1); 4951 } 4952 PetscUseTypeMethod(mat, getrowmin, v, idx); 4953 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4954 PetscFunctionReturn(0); 4955 } 4956 4957 /*@C 4958 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4959 row of the matrix 4960 4961 Logically Collective 4962 4963 Input Parameter: 4964 . mat - the matrix 4965 4966 Output Parameters: 4967 + v - the vector for storing the minimums 4968 - idx - the indices of the column found for each row (or `NULL` if not needed) 4969 4970 Level: intermediate 4971 4972 Notes: 4973 if a row is completely empty or has only 0.0 values then the idx[] value for that 4974 row is 0 (the first column). 4975 4976 This code is only implemented for a couple of matrix formats. 4977 4978 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4979 @*/ 4980 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4981 { 4982 PetscFunctionBegin; 4983 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4984 PetscValidType(mat, 1); 4985 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4986 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4987 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4988 4989 if (!mat->cmap->N) { 4990 PetscCall(VecSet(v, 0.0)); 4991 if (idx) { 4992 PetscInt i, m = mat->rmap->n; 4993 for (i = 0; i < m; i++) idx[i] = -1; 4994 } 4995 } else { 4996 MatCheckPreallocated(mat, 1); 4997 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4998 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4999 } 5000 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5001 PetscFunctionReturn(0); 5002 } 5003 5004 /*@C 5005 MatGetRowMax - Gets the maximum value (of the real part) of each 5006 row of the matrix 5007 5008 Logically Collective 5009 5010 Input Parameter: 5011 . mat - the matrix 5012 5013 Output Parameters: 5014 + v - the vector for storing the maximums 5015 - idx - the indices of the column found for each row (optional) 5016 5017 Level: intermediate 5018 5019 Notes: 5020 The result of this call are the same as if one converted the matrix to dense format 5021 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5022 5023 This code is only implemented for a couple of matrix formats. 5024 5025 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5026 @*/ 5027 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5028 { 5029 PetscFunctionBegin; 5030 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5031 PetscValidType(mat, 1); 5032 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5033 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5034 5035 if (!mat->cmap->N) { 5036 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5037 if (idx) { 5038 PetscInt i, m = mat->rmap->n; 5039 for (i = 0; i < m; i++) idx[i] = -1; 5040 } 5041 } else { 5042 MatCheckPreallocated(mat, 1); 5043 PetscUseTypeMethod(mat, getrowmax, v, idx); 5044 } 5045 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5046 PetscFunctionReturn(0); 5047 } 5048 5049 /*@C 5050 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5051 row of the matrix 5052 5053 Logically Collective 5054 5055 Input Parameter: 5056 . mat - the matrix 5057 5058 Output Parameters: 5059 + v - the vector for storing the maximums 5060 - idx - the indices of the column found for each row (or `NULL` if not needed) 5061 5062 Level: intermediate 5063 5064 Notes: 5065 if a row is completely empty or has only 0.0 values then the idx[] value for that 5066 row is 0 (the first column). 5067 5068 This code is only implemented for a couple of matrix formats. 5069 5070 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5071 @*/ 5072 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5073 { 5074 PetscFunctionBegin; 5075 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5076 PetscValidType(mat, 1); 5077 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5078 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5079 5080 if (!mat->cmap->N) { 5081 PetscCall(VecSet(v, 0.0)); 5082 if (idx) { 5083 PetscInt i, m = mat->rmap->n; 5084 for (i = 0; i < m; i++) idx[i] = -1; 5085 } 5086 } else { 5087 MatCheckPreallocated(mat, 1); 5088 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5089 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5090 } 5091 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5092 PetscFunctionReturn(0); 5093 } 5094 5095 /*@ 5096 MatGetRowSum - Gets the sum of each row of the matrix 5097 5098 Logically or Neighborhood Collective 5099 5100 Input Parameters: 5101 . mat - the matrix 5102 5103 Output Parameter: 5104 . v - the vector for storing the sum of rows 5105 5106 Level: intermediate 5107 5108 Notes: 5109 This code is slow since it is not currently specialized for different formats 5110 5111 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5112 @*/ 5113 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5114 { 5115 Vec ones; 5116 5117 PetscFunctionBegin; 5118 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5119 PetscValidType(mat, 1); 5120 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5121 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5122 MatCheckPreallocated(mat, 1); 5123 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5124 PetscCall(VecSet(ones, 1.)); 5125 PetscCall(MatMult(mat, ones, v)); 5126 PetscCall(VecDestroy(&ones)); 5127 PetscFunctionReturn(0); 5128 } 5129 5130 /*@ 5131 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5132 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5133 5134 Collective 5135 5136 Input Parameter: 5137 . mat - the matrix to provide the transpose 5138 5139 Output Parameter: 5140 . 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 5141 5142 Level: advanced 5143 5144 Note: 5145 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 5146 routine allows bypassing that call. 5147 5148 .seealso: `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5149 @*/ 5150 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5151 { 5152 PetscContainer rB = NULL; 5153 MatParentState *rb = NULL; 5154 5155 PetscFunctionBegin; 5156 PetscCall(PetscNew(&rb)); 5157 rb->id = ((PetscObject)mat)->id; 5158 rb->state = 0; 5159 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5160 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5161 PetscCall(PetscContainerSetPointer(rB, rb)); 5162 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5163 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5164 PetscCall(PetscObjectDereference((PetscObject)rB)); 5165 PetscFunctionReturn(0); 5166 } 5167 5168 /*@ 5169 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5170 5171 Collective 5172 5173 Input Parameters: 5174 + mat - the matrix to transpose 5175 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5176 5177 Output Parameter: 5178 . B - the transpose 5179 5180 Level: intermediate 5181 5182 Notes: 5183 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5184 5185 `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 5186 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5187 5188 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. 5189 5190 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5191 5192 If mat is unchanged from the last call this function returns immediately without recomputing the result 5193 5194 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5195 5196 .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5197 `MatTransposeSymbolic()` 5198 @*/ 5199 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5200 { 5201 PetscContainer rB = NULL; 5202 MatParentState *rb = NULL; 5203 5204 PetscFunctionBegin; 5205 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5206 PetscValidType(mat, 1); 5207 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5208 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5209 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5210 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5211 MatCheckPreallocated(mat, 1); 5212 if (reuse == MAT_REUSE_MATRIX) { 5213 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5214 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5215 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5216 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5217 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0); 5218 } 5219 5220 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5221 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5222 PetscUseTypeMethod(mat, transpose, reuse, B); 5223 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5224 } 5225 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5226 5227 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5228 if (reuse != MAT_INPLACE_MATRIX) { 5229 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5230 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5231 rb->state = ((PetscObject)mat)->state; 5232 rb->nonzerostate = mat->nonzerostate; 5233 } 5234 PetscFunctionReturn(0); 5235 } 5236 5237 /*@ 5238 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5239 5240 Collective 5241 5242 Input Parameters: 5243 . A - the matrix to transpose 5244 5245 Output Parameter: 5246 . 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 5247 numerical portion. 5248 5249 Level: intermediate 5250 5251 Note: 5252 This is not supported for many matrix types, use `MatTranspose()` in those cases 5253 5254 .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5255 @*/ 5256 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5257 { 5258 PetscFunctionBegin; 5259 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5260 PetscValidType(A, 1); 5261 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5262 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5263 PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 5264 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5265 PetscCall((*A->ops->transposesymbolic)(A, B)); 5266 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5267 5268 PetscCall(MatTransposeSetPrecursor(A, *B)); 5269 PetscFunctionReturn(0); 5270 } 5271 5272 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5273 { 5274 PetscContainer rB; 5275 MatParentState *rb; 5276 5277 PetscFunctionBegin; 5278 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5279 PetscValidType(A, 1); 5280 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5281 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5282 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5283 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5284 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5285 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5286 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5287 PetscFunctionReturn(0); 5288 } 5289 5290 /*@ 5291 MatIsTranspose - Test whether a matrix is another one's transpose, 5292 or its own, in which case it tests symmetry. 5293 5294 Collective 5295 5296 Input Parameters: 5297 + A - the matrix to test 5298 - B - the matrix to test against, this can equal the first parameter 5299 5300 Output Parameters: 5301 . flg - the result 5302 5303 Level: intermediate 5304 5305 Notes: 5306 Only available for `MATAIJ` matrices. 5307 5308 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5309 test involves parallel copies of the block-offdiagonal parts of the matrix. 5310 5311 .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5312 @*/ 5313 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5314 { 5315 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5316 5317 PetscFunctionBegin; 5318 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5319 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5320 PetscValidBoolPointer(flg, 4); 5321 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5322 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5323 *flg = PETSC_FALSE; 5324 if (f && g) { 5325 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5326 PetscCall((*f)(A, B, tol, flg)); 5327 } else { 5328 MatType mattype; 5329 5330 PetscCall(MatGetType(f ? B : A, &mattype)); 5331 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5332 } 5333 PetscFunctionReturn(0); 5334 } 5335 5336 /*@ 5337 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5338 5339 Collective 5340 5341 Input Parameters: 5342 + mat - the matrix to transpose and complex conjugate 5343 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5344 5345 Output Parameter: 5346 . B - the Hermitian transpose 5347 5348 Level: intermediate 5349 5350 .seealso: `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5351 @*/ 5352 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5353 { 5354 PetscFunctionBegin; 5355 PetscCall(MatTranspose(mat, reuse, B)); 5356 #if defined(PETSC_USE_COMPLEX) 5357 PetscCall(MatConjugate(*B)); 5358 #endif 5359 PetscFunctionReturn(0); 5360 } 5361 5362 /*@ 5363 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5364 5365 Collective 5366 5367 Input Parameters: 5368 + A - the matrix to test 5369 - B - the matrix to test against, this can equal the first parameter 5370 5371 Output Parameters: 5372 . flg - the result 5373 5374 Level: intermediate 5375 5376 Notes: 5377 Only available for `MATAIJ` matrices. 5378 5379 The sequential algorithm 5380 has a running time of the order of the number of nonzeros; the parallel 5381 test involves parallel copies of the block-offdiagonal parts of the matrix. 5382 5383 .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5384 @*/ 5385 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5386 { 5387 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5388 5389 PetscFunctionBegin; 5390 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5391 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5392 PetscValidBoolPointer(flg, 4); 5393 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5394 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5395 if (f && g) { 5396 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5397 PetscCall((*f)(A, B, tol, flg)); 5398 } 5399 PetscFunctionReturn(0); 5400 } 5401 5402 /*@ 5403 MatPermute - Creates a new matrix with rows and columns permuted from the 5404 original. 5405 5406 Collective 5407 5408 Input Parameters: 5409 + mat - the matrix to permute 5410 . row - row permutation, each processor supplies only the permutation for its rows 5411 - col - column permutation, each processor supplies only the permutation for its columns 5412 5413 Output Parameters: 5414 . B - the permuted matrix 5415 5416 Level: advanced 5417 5418 Note: 5419 The index sets map from row/col of permuted matrix to row/col of original matrix. 5420 The index sets should be on the same communicator as mat and have the same local sizes. 5421 5422 Developer Note: 5423 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5424 exploit the fact that row and col are permutations, consider implementing the 5425 more general `MatCreateSubMatrix()` instead. 5426 5427 .seealso: `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5428 @*/ 5429 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5430 { 5431 PetscFunctionBegin; 5432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5433 PetscValidType(mat, 1); 5434 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5435 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5436 PetscValidPointer(B, 4); 5437 PetscCheckSameComm(mat, 1, row, 2); 5438 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5439 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5440 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5441 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5442 MatCheckPreallocated(mat, 1); 5443 5444 if (mat->ops->permute) { 5445 PetscUseTypeMethod(mat, permute, row, col, B); 5446 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5447 } else { 5448 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5449 } 5450 PetscFunctionReturn(0); 5451 } 5452 5453 /*@ 5454 MatEqual - Compares two matrices. 5455 5456 Collective 5457 5458 Input Parameters: 5459 + A - the first matrix 5460 - B - the second matrix 5461 5462 Output Parameter: 5463 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5464 5465 Level: intermediate 5466 5467 .seealso: `Mat` 5468 @*/ 5469 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5470 { 5471 PetscFunctionBegin; 5472 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5473 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5474 PetscValidType(A, 1); 5475 PetscValidType(B, 2); 5476 PetscValidBoolPointer(flg, 3); 5477 PetscCheckSameComm(A, 1, B, 2); 5478 MatCheckPreallocated(A, 1); 5479 MatCheckPreallocated(B, 2); 5480 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5481 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5482 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, 5483 B->cmap->N); 5484 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5485 PetscUseTypeMethod(A, equal, B, flg); 5486 } else { 5487 PetscCall(MatMultEqual(A, B, 10, flg)); 5488 } 5489 PetscFunctionReturn(0); 5490 } 5491 5492 /*@ 5493 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5494 matrices that are stored as vectors. Either of the two scaling 5495 matrices can be `NULL`. 5496 5497 Collective 5498 5499 Input Parameters: 5500 + mat - the matrix to be scaled 5501 . l - the left scaling vector (or `NULL`) 5502 - r - the right scaling vector (or `NULL`) 5503 5504 Level: intermediate 5505 5506 Note: 5507 `MatDiagonalScale()` computes A = LAR, where 5508 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5509 The L scales the rows of the matrix, the R scales the columns of the matrix. 5510 5511 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5512 @*/ 5513 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5514 { 5515 PetscFunctionBegin; 5516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5517 PetscValidType(mat, 1); 5518 if (l) { 5519 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5520 PetscCheckSameComm(mat, 1, l, 2); 5521 } 5522 if (r) { 5523 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5524 PetscCheckSameComm(mat, 1, r, 3); 5525 } 5526 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5527 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5528 MatCheckPreallocated(mat, 1); 5529 if (!l && !r) PetscFunctionReturn(0); 5530 5531 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5532 PetscUseTypeMethod(mat, diagonalscale, l, r); 5533 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5534 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5535 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5536 PetscFunctionReturn(0); 5537 } 5538 5539 /*@ 5540 MatScale - Scales all elements of a matrix by a given number. 5541 5542 Logically Collective 5543 5544 Input Parameters: 5545 + mat - the matrix to be scaled 5546 - a - the scaling value 5547 5548 Output Parameter: 5549 . mat - the scaled matrix 5550 5551 Level: intermediate 5552 5553 .seealso: `Mat`, `MatDiagonalScale()` 5554 @*/ 5555 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5556 { 5557 PetscFunctionBegin; 5558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5559 PetscValidType(mat, 1); 5560 PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 5561 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5562 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5563 PetscValidLogicalCollectiveScalar(mat, a, 2); 5564 MatCheckPreallocated(mat, 1); 5565 5566 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5567 if (a != (PetscScalar)1.0) { 5568 PetscUseTypeMethod(mat, scale, a); 5569 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5570 } 5571 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5572 PetscFunctionReturn(0); 5573 } 5574 5575 /*@ 5576 MatNorm - Calculates various norms of a matrix. 5577 5578 Collective 5579 5580 Input Parameters: 5581 + mat - the matrix 5582 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5583 5584 Output Parameter: 5585 . nrm - the resulting norm 5586 5587 Level: intermediate 5588 5589 .seealso: `Mat` 5590 @*/ 5591 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5592 { 5593 PetscFunctionBegin; 5594 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5595 PetscValidType(mat, 1); 5596 PetscValidRealPointer(nrm, 3); 5597 5598 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5599 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5600 MatCheckPreallocated(mat, 1); 5601 5602 PetscUseTypeMethod(mat, norm, type, nrm); 5603 PetscFunctionReturn(0); 5604 } 5605 5606 /* 5607 This variable is used to prevent counting of MatAssemblyBegin() that 5608 are called from within a MatAssemblyEnd(). 5609 */ 5610 static PetscInt MatAssemblyEnd_InUse = 0; 5611 /*@ 5612 MatAssemblyBegin - Begins assembling the matrix. This routine should 5613 be called after completing all calls to `MatSetValues()`. 5614 5615 Collective 5616 5617 Input Parameters: 5618 + mat - the matrix 5619 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5620 5621 Level: beginner 5622 5623 Notes: 5624 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5625 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5626 5627 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5628 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5629 using the matrix. 5630 5631 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5632 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 5633 a global collective operation requiring all processes that share the matrix. 5634 5635 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5636 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5637 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5638 5639 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5640 @*/ 5641 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5642 { 5643 PetscFunctionBegin; 5644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5645 PetscValidType(mat, 1); 5646 MatCheckPreallocated(mat, 1); 5647 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5648 if (mat->assembled) { 5649 mat->was_assembled = PETSC_TRUE; 5650 mat->assembled = PETSC_FALSE; 5651 } 5652 5653 if (!MatAssemblyEnd_InUse) { 5654 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5655 PetscTryTypeMethod(mat, assemblybegin, type); 5656 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5657 } else PetscTryTypeMethod(mat, assemblybegin, type); 5658 PetscFunctionReturn(0); 5659 } 5660 5661 /*@ 5662 MatAssembled - Indicates if a matrix has been assembled and is ready for 5663 use; for example, in matrix-vector product. 5664 5665 Not Collective 5666 5667 Input Parameter: 5668 . mat - the matrix 5669 5670 Output Parameter: 5671 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5672 5673 Level: advanced 5674 5675 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5676 @*/ 5677 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5678 { 5679 PetscFunctionBegin; 5680 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5681 PetscValidBoolPointer(assembled, 2); 5682 *assembled = mat->assembled; 5683 PetscFunctionReturn(0); 5684 } 5685 5686 /*@ 5687 MatAssemblyEnd - Completes assembling the matrix. This routine should 5688 be called after `MatAssemblyBegin()`. 5689 5690 Collective on Mat 5691 5692 Input Parameters: 5693 + mat - the matrix 5694 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5695 5696 Options Database Keys: 5697 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5698 . -mat_view ::ascii_info_detail - Prints more detailed info 5699 . -mat_view - Prints matrix in ASCII format 5700 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5701 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5702 . -display <name> - Sets display name (default is host) 5703 . -draw_pause <sec> - Sets number of seconds to pause after display 5704 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5705 . -viewer_socket_machine <machine> - Machine to use for socket 5706 . -viewer_socket_port <port> - Port number to use for socket 5707 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5708 5709 Level: beginner 5710 5711 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5712 @*/ 5713 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5714 { 5715 static PetscInt inassm = 0; 5716 PetscBool flg = PETSC_FALSE; 5717 5718 PetscFunctionBegin; 5719 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5720 PetscValidType(mat, 1); 5721 5722 inassm++; 5723 MatAssemblyEnd_InUse++; 5724 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5725 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5726 PetscTryTypeMethod(mat, assemblyend, type); 5727 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5728 } else PetscTryTypeMethod(mat, assemblyend, type); 5729 5730 /* Flush assembly is not a true assembly */ 5731 if (type != MAT_FLUSH_ASSEMBLY) { 5732 if (mat->num_ass) { 5733 if (!mat->symmetry_eternal) { 5734 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5735 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5736 } 5737 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5738 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5739 } 5740 mat->num_ass++; 5741 mat->assembled = PETSC_TRUE; 5742 mat->ass_nonzerostate = mat->nonzerostate; 5743 } 5744 5745 mat->insertmode = NOT_SET_VALUES; 5746 MatAssemblyEnd_InUse--; 5747 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5748 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5749 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5750 5751 if (mat->checksymmetryonassembly) { 5752 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5753 if (flg) { 5754 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5755 } else { 5756 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5757 } 5758 } 5759 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5760 } 5761 inassm--; 5762 PetscFunctionReturn(0); 5763 } 5764 5765 /*@ 5766 MatSetOption - Sets a parameter option for a matrix. Some options 5767 may be specific to certain storage formats. Some options 5768 determine how values will be inserted (or added). Sorted, 5769 row-oriented input will generally assemble the fastest. The default 5770 is row-oriented. 5771 5772 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5773 5774 Input Parameters: 5775 + mat - the matrix 5776 . option - the option, one of those listed below (and possibly others), 5777 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5778 5779 Options Describing Matrix Structure: 5780 + `MAT_SPD` - symmetric positive definite 5781 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5782 . `MAT_HERMITIAN` - transpose is the complex conjugation 5783 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5784 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5785 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5786 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5787 5788 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5789 do not need to be computed (usually at a high cost) 5790 5791 Options For Use with `MatSetValues()`: 5792 Insert a logically dense subblock, which can be 5793 . `MAT_ROW_ORIENTED` - row-oriented (default) 5794 5795 Note these options reflect the data you pass in with `MatSetValues()`; it has 5796 nothing to do with how the data is stored internally in the matrix 5797 data structure. 5798 5799 When (re)assembling a matrix, we can restrict the input for 5800 efficiency/debugging purposes. These options include 5801 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5802 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5803 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5804 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5805 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5806 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5807 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5808 performance for very large process counts. 5809 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5810 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5811 functions, instead sending only neighbor messages. 5812 5813 Level: intermediate 5814 5815 Notes: 5816 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5817 5818 Some options are relevant only for particular matrix types and 5819 are thus ignored by others. Other options are not supported by 5820 certain matrix types and will generate an error message if set. 5821 5822 If using Fortran to compute a matrix, one may need to 5823 use the column-oriented option (or convert to the row-oriented 5824 format). 5825 5826 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5827 that would generate a new entry in the nonzero structure is instead 5828 ignored. Thus, if memory has not already been allocated for this particular 5829 data, then the insertion is ignored. For dense matrices, in which 5830 the entire array is allocated, no entries are ever ignored. 5831 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5832 5833 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5834 that would generate a new entry in the nonzero structure instead produces 5835 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 5836 5837 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5838 that would generate a new entry that has not been preallocated will 5839 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5840 only.) This is a useful flag when debugging matrix memory preallocation. 5841 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5842 5843 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5844 other processors should be dropped, rather than stashed. 5845 This is useful if you know that the "owning" processor is also 5846 always generating the correct matrix entries, so that PETSc need 5847 not transfer duplicate entries generated on another processor. 5848 5849 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5850 searches during matrix assembly. When this flag is set, the hash table 5851 is created during the first matrix assembly. This hash table is 5852 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5853 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5854 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5855 supported by `MATMPIBAIJ` format only. 5856 5857 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5858 are kept in the nonzero structure 5859 5860 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5861 a zero location in the matrix 5862 5863 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5864 5865 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5866 zero row routines and thus improves performance for very large process counts. 5867 5868 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5869 part of the matrix (since they should match the upper triangular part). 5870 5871 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5872 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5873 with finite difference schemes with non-periodic boundary conditions. 5874 5875 Developer Note: 5876 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5877 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5878 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5879 not changed. 5880 5881 .seealso: `MatOption`, `Mat`, `MatGetOption()` 5882 @*/ 5883 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5884 { 5885 PetscFunctionBegin; 5886 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5887 if (op > 0) { 5888 PetscValidLogicalCollectiveEnum(mat, op, 2); 5889 PetscValidLogicalCollectiveBool(mat, flg, 3); 5890 } 5891 5892 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); 5893 5894 switch (op) { 5895 case MAT_FORCE_DIAGONAL_ENTRIES: 5896 mat->force_diagonals = flg; 5897 PetscFunctionReturn(0); 5898 case MAT_NO_OFF_PROC_ENTRIES: 5899 mat->nooffprocentries = flg; 5900 PetscFunctionReturn(0); 5901 case MAT_SUBSET_OFF_PROC_ENTRIES: 5902 mat->assembly_subset = flg; 5903 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5904 #if !defined(PETSC_HAVE_MPIUNI) 5905 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5906 #endif 5907 mat->stash.first_assembly_done = PETSC_FALSE; 5908 } 5909 PetscFunctionReturn(0); 5910 case MAT_NO_OFF_PROC_ZERO_ROWS: 5911 mat->nooffproczerorows = flg; 5912 PetscFunctionReturn(0); 5913 case MAT_SPD: 5914 if (flg) { 5915 mat->spd = PETSC_BOOL3_TRUE; 5916 mat->symmetric = PETSC_BOOL3_TRUE; 5917 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5918 } else { 5919 mat->spd = PETSC_BOOL3_FALSE; 5920 } 5921 break; 5922 case MAT_SYMMETRIC: 5923 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5924 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5925 #if !defined(PETSC_USE_COMPLEX) 5926 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5927 #endif 5928 break; 5929 case MAT_HERMITIAN: 5930 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5931 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5932 #if !defined(PETSC_USE_COMPLEX) 5933 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5934 #endif 5935 break; 5936 case MAT_STRUCTURALLY_SYMMETRIC: 5937 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5938 break; 5939 case MAT_SYMMETRY_ETERNAL: 5940 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"); 5941 mat->symmetry_eternal = flg; 5942 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5943 break; 5944 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5945 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"); 5946 mat->structural_symmetry_eternal = flg; 5947 break; 5948 case MAT_SPD_ETERNAL: 5949 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"); 5950 mat->spd_eternal = flg; 5951 if (flg) { 5952 mat->structural_symmetry_eternal = PETSC_TRUE; 5953 mat->symmetry_eternal = PETSC_TRUE; 5954 } 5955 break; 5956 case MAT_STRUCTURE_ONLY: 5957 mat->structure_only = flg; 5958 break; 5959 case MAT_SORTED_FULL: 5960 mat->sortedfull = flg; 5961 break; 5962 default: 5963 break; 5964 } 5965 PetscTryTypeMethod(mat, setoption, op, flg); 5966 PetscFunctionReturn(0); 5967 } 5968 5969 /*@ 5970 MatGetOption - Gets a parameter option that has been set for a matrix. 5971 5972 Logically Collective 5973 5974 Input Parameters: 5975 + mat - the matrix 5976 - option - the option, this only responds to certain options, check the code for which ones 5977 5978 Output Parameter: 5979 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5980 5981 Level: intermediate 5982 5983 Notes: 5984 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5985 5986 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5987 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5988 5989 .seealso: `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5990 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5991 @*/ 5992 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5993 { 5994 PetscFunctionBegin; 5995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5996 PetscValidType(mat, 1); 5997 5998 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); 5999 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()"); 6000 6001 switch (op) { 6002 case MAT_NO_OFF_PROC_ENTRIES: 6003 *flg = mat->nooffprocentries; 6004 break; 6005 case MAT_NO_OFF_PROC_ZERO_ROWS: 6006 *flg = mat->nooffproczerorows; 6007 break; 6008 case MAT_SYMMETRIC: 6009 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6010 break; 6011 case MAT_HERMITIAN: 6012 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6013 break; 6014 case MAT_STRUCTURALLY_SYMMETRIC: 6015 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6016 break; 6017 case MAT_SPD: 6018 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6019 break; 6020 case MAT_SYMMETRY_ETERNAL: 6021 *flg = mat->symmetry_eternal; 6022 break; 6023 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6024 *flg = mat->symmetry_eternal; 6025 break; 6026 default: 6027 break; 6028 } 6029 PetscFunctionReturn(0); 6030 } 6031 6032 /*@ 6033 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6034 this routine retains the old nonzero structure. 6035 6036 Logically Collective 6037 6038 Input Parameters: 6039 . mat - the matrix 6040 6041 Level: intermediate 6042 6043 Note: 6044 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. 6045 See the Performance chapter of the users manual for information on preallocating matrices. 6046 6047 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6048 @*/ 6049 PetscErrorCode MatZeroEntries(Mat mat) 6050 { 6051 PetscFunctionBegin; 6052 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6053 PetscValidType(mat, 1); 6054 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6055 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"); 6056 MatCheckPreallocated(mat, 1); 6057 6058 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6059 PetscUseTypeMethod(mat, zeroentries); 6060 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6061 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6062 PetscFunctionReturn(0); 6063 } 6064 6065 /*@ 6066 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6067 of a set of rows and columns of a matrix. 6068 6069 Collective 6070 6071 Input Parameters: 6072 + mat - the matrix 6073 . numRows - the number of rows/columns to zero 6074 . rows - the global row indices 6075 . diag - value put in the diagonal of the eliminated rows 6076 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6077 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6078 6079 Level: intermediate 6080 6081 Notes: 6082 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6083 6084 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6085 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 6086 6087 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6088 Krylov method to take advantage of the known solution on the zeroed rows. 6089 6090 For the parallel case, all processes that share the matrix (i.e., 6091 those in the communicator used for matrix creation) MUST call this 6092 routine, regardless of whether any rows being zeroed are owned by 6093 them. 6094 6095 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6096 6097 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6098 list only rows local to itself). 6099 6100 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6101 6102 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6103 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6104 @*/ 6105 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6106 { 6107 PetscFunctionBegin; 6108 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6109 PetscValidType(mat, 1); 6110 if (numRows) PetscValidIntPointer(rows, 3); 6111 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6112 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6113 MatCheckPreallocated(mat, 1); 6114 6115 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6116 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6117 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6118 PetscFunctionReturn(0); 6119 } 6120 6121 /*@ 6122 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6123 of a set of rows and columns of a matrix. 6124 6125 Collective 6126 6127 Input Parameters: 6128 + mat - the matrix 6129 . is - the rows to zero 6130 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6131 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6132 - b - optional vector of right hand side, that will be adjusted by provided solution 6133 6134 Level: intermediate 6135 6136 Note: 6137 See `MatZeroRowsColumns()` for details on how this routine operates. 6138 6139 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6140 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6141 @*/ 6142 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6143 { 6144 PetscInt numRows; 6145 const PetscInt *rows; 6146 6147 PetscFunctionBegin; 6148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6149 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6150 PetscValidType(mat, 1); 6151 PetscValidType(is, 2); 6152 PetscCall(ISGetLocalSize(is, &numRows)); 6153 PetscCall(ISGetIndices(is, &rows)); 6154 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6155 PetscCall(ISRestoreIndices(is, &rows)); 6156 PetscFunctionReturn(0); 6157 } 6158 6159 /*@ 6160 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6161 of a set of rows of a matrix. 6162 6163 Collective 6164 6165 Input Parameters: 6166 + mat - the matrix 6167 . numRows - the number of rows to zero 6168 . rows - the global row indices 6169 . diag - value put in the diagonal of the zeroed rows 6170 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6171 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6172 6173 Level: intermediate 6174 6175 Notes: 6176 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6177 6178 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6179 6180 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6181 Krylov method to take advantage of the known solution on the zeroed rows. 6182 6183 May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns) 6184 from the matrix. 6185 6186 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6187 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 6188 formats this does not alter the nonzero structure. 6189 6190 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6191 of the matrix is not changed the values are 6192 merely zeroed. 6193 6194 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6195 formats can optionally remove the main diagonal entry from the 6196 nonzero structure as well, by passing 0.0 as the final argument). 6197 6198 For the parallel case, all processes that share the matrix (i.e., 6199 those in the communicator used for matrix creation) MUST call this 6200 routine, regardless of whether any rows being zeroed are owned by 6201 them. 6202 6203 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6204 list only rows local to itself). 6205 6206 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6207 owns that are to be zeroed. This saves a global synchronization in the implementation. 6208 6209 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6210 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6211 @*/ 6212 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6213 { 6214 PetscFunctionBegin; 6215 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6216 PetscValidType(mat, 1); 6217 if (numRows) PetscValidIntPointer(rows, 3); 6218 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6219 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6220 MatCheckPreallocated(mat, 1); 6221 6222 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6223 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6224 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6225 PetscFunctionReturn(0); 6226 } 6227 6228 /*@ 6229 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6230 of a set of rows of a matrix. 6231 6232 Collective on Mat 6233 6234 Input Parameters: 6235 + mat - the matrix 6236 . is - index set of rows to remove (if `NULL` then no row is removed) 6237 . diag - value put in all diagonals of eliminated rows 6238 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6239 - b - optional vector of right hand side, that will be adjusted by provided solution 6240 6241 Level: intermediate 6242 6243 Note: 6244 See `MatZeroRows()` for details on how this routine operates. 6245 6246 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6247 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6248 @*/ 6249 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6250 { 6251 PetscInt numRows = 0; 6252 const PetscInt *rows = NULL; 6253 6254 PetscFunctionBegin; 6255 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6256 PetscValidType(mat, 1); 6257 if (is) { 6258 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6259 PetscCall(ISGetLocalSize(is, &numRows)); 6260 PetscCall(ISGetIndices(is, &rows)); 6261 } 6262 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6263 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6264 PetscFunctionReturn(0); 6265 } 6266 6267 /*@ 6268 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6269 of a set of rows of a matrix. These rows must be local to the process. 6270 6271 Collective 6272 6273 Input Parameters: 6274 + mat - the matrix 6275 . numRows - the number of rows to remove 6276 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6277 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6278 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6279 - b - optional vector of right hand side, that will be adjusted by provided solution 6280 6281 Level: intermediate 6282 6283 Notes: 6284 See `MatZeroRows()` for details on how this routine operates. 6285 6286 The grid coordinates are across the entire grid, not just the local portion 6287 6288 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6289 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6290 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6291 `DM_BOUNDARY_PERIODIC` boundary type. 6292 6293 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 6294 a single value per point) you can skip filling those indices. 6295 6296 Fortran Note: 6297 idxm and idxn should be declared as 6298 $ MatStencil idxm(4,m) 6299 and the values inserted using 6300 .vb 6301 idxm(MatStencil_i,1) = i 6302 idxm(MatStencil_j,1) = j 6303 idxm(MatStencil_k,1) = k 6304 idxm(MatStencil_c,1) = c 6305 etc 6306 .ve 6307 6308 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6309 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6310 @*/ 6311 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6312 { 6313 PetscInt dim = mat->stencil.dim; 6314 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6315 PetscInt *dims = mat->stencil.dims + 1; 6316 PetscInt *starts = mat->stencil.starts; 6317 PetscInt *dxm = (PetscInt *)rows; 6318 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6319 6320 PetscFunctionBegin; 6321 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6322 PetscValidType(mat, 1); 6323 if (numRows) PetscValidPointer(rows, 3); 6324 6325 PetscCall(PetscMalloc1(numRows, &jdxm)); 6326 for (i = 0; i < numRows; ++i) { 6327 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6328 for (j = 0; j < 3 - sdim; ++j) dxm++; 6329 /* Local index in X dir */ 6330 tmp = *dxm++ - starts[0]; 6331 /* Loop over remaining dimensions */ 6332 for (j = 0; j < dim - 1; ++j) { 6333 /* If nonlocal, set index to be negative */ 6334 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6335 /* Update local index */ 6336 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6337 } 6338 /* Skip component slot if necessary */ 6339 if (mat->stencil.noc) dxm++; 6340 /* Local row number */ 6341 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6342 } 6343 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6344 PetscCall(PetscFree(jdxm)); 6345 PetscFunctionReturn(0); 6346 } 6347 6348 /*@ 6349 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6350 of a set of rows and columns of a matrix. 6351 6352 Collective 6353 6354 Input Parameters: 6355 + mat - the matrix 6356 . numRows - the number of rows/columns to remove 6357 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6358 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6359 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6360 - b - optional vector of right hand side, that will be adjusted by provided solution 6361 6362 Level: intermediate 6363 6364 Notes: 6365 See `MatZeroRowsColumns()` for details on how this routine operates. 6366 6367 The grid coordinates are across the entire grid, not just the local portion 6368 6369 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6370 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6371 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6372 `DM_BOUNDARY_PERIODIC` boundary type. 6373 6374 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 6375 a single value per point) you can skip filling those indices. 6376 6377 Fortran Note: 6378 In Fortran idxm and idxn should be declared as 6379 $ MatStencil idxm(4,m) 6380 and the values inserted using 6381 .vb 6382 idxm(MatStencil_i,1) = i 6383 idxm(MatStencil_j,1) = j 6384 idxm(MatStencil_k,1) = k 6385 idxm(MatStencil_c,1) = c 6386 etc 6387 .ve 6388 6389 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6390 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6391 @*/ 6392 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6393 { 6394 PetscInt dim = mat->stencil.dim; 6395 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6396 PetscInt *dims = mat->stencil.dims + 1; 6397 PetscInt *starts = mat->stencil.starts; 6398 PetscInt *dxm = (PetscInt *)rows; 6399 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6400 6401 PetscFunctionBegin; 6402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6403 PetscValidType(mat, 1); 6404 if (numRows) PetscValidPointer(rows, 3); 6405 6406 PetscCall(PetscMalloc1(numRows, &jdxm)); 6407 for (i = 0; i < numRows; ++i) { 6408 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6409 for (j = 0; j < 3 - sdim; ++j) dxm++; 6410 /* Local index in X dir */ 6411 tmp = *dxm++ - starts[0]; 6412 /* Loop over remaining dimensions */ 6413 for (j = 0; j < dim - 1; ++j) { 6414 /* If nonlocal, set index to be negative */ 6415 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6416 /* Update local index */ 6417 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6418 } 6419 /* Skip component slot if necessary */ 6420 if (mat->stencil.noc) dxm++; 6421 /* Local row number */ 6422 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6423 } 6424 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6425 PetscCall(PetscFree(jdxm)); 6426 PetscFunctionReturn(0); 6427 } 6428 6429 /*@C 6430 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6431 of a set of rows of a matrix; using local numbering of rows. 6432 6433 Collective 6434 6435 Input Parameters: 6436 + mat - the matrix 6437 . numRows - the number of rows to remove 6438 . rows - the local row indices 6439 . diag - value put in all diagonals of eliminated rows 6440 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6441 - b - optional vector of right hand side, that will be adjusted by provided solution 6442 6443 Level: intermediate 6444 6445 Notes: 6446 Before calling `MatZeroRowsLocal()`, the user must first set the 6447 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6448 6449 See `MatZeroRows()` for details on how this routine operates. 6450 6451 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6452 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6453 @*/ 6454 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6455 { 6456 PetscFunctionBegin; 6457 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6458 PetscValidType(mat, 1); 6459 if (numRows) PetscValidIntPointer(rows, 3); 6460 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6461 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6462 MatCheckPreallocated(mat, 1); 6463 6464 if (mat->ops->zerorowslocal) { 6465 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6466 } else { 6467 IS is, newis; 6468 const PetscInt *newRows; 6469 6470 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6471 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6472 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6473 PetscCall(ISGetIndices(newis, &newRows)); 6474 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6475 PetscCall(ISRestoreIndices(newis, &newRows)); 6476 PetscCall(ISDestroy(&newis)); 6477 PetscCall(ISDestroy(&is)); 6478 } 6479 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6480 PetscFunctionReturn(0); 6481 } 6482 6483 /*@ 6484 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6485 of a set of rows of a matrix; using local numbering of rows. 6486 6487 Collective 6488 6489 Input Parameters: 6490 + mat - the matrix 6491 . is - index set of rows to remove 6492 . diag - value put in all diagonals of eliminated rows 6493 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6494 - b - optional vector of right hand side, that will be adjusted by provided solution 6495 6496 Level: intermediate 6497 6498 Notes: 6499 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6500 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6501 6502 See `MatZeroRows()` for details on how this routine operates. 6503 6504 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6505 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6506 @*/ 6507 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6508 { 6509 PetscInt numRows; 6510 const PetscInt *rows; 6511 6512 PetscFunctionBegin; 6513 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6514 PetscValidType(mat, 1); 6515 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6516 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6517 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6518 MatCheckPreallocated(mat, 1); 6519 6520 PetscCall(ISGetLocalSize(is, &numRows)); 6521 PetscCall(ISGetIndices(is, &rows)); 6522 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6523 PetscCall(ISRestoreIndices(is, &rows)); 6524 PetscFunctionReturn(0); 6525 } 6526 6527 /*@ 6528 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6529 of a set of rows and columns of a matrix; using local numbering of rows. 6530 6531 Collective 6532 6533 Input Parameters: 6534 + mat - the matrix 6535 . numRows - the number of rows to remove 6536 . rows - the global row indices 6537 . diag - value put in all diagonals of eliminated rows 6538 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6539 - b - optional vector of right hand side, that will be adjusted by provided solution 6540 6541 Level: intermediate 6542 6543 Notes: 6544 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6545 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6546 6547 See `MatZeroRowsColumns()` for details on how this routine operates. 6548 6549 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6550 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6551 @*/ 6552 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6553 { 6554 IS is, newis; 6555 const PetscInt *newRows; 6556 6557 PetscFunctionBegin; 6558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6559 PetscValidType(mat, 1); 6560 if (numRows) PetscValidIntPointer(rows, 3); 6561 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6562 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6563 MatCheckPreallocated(mat, 1); 6564 6565 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6566 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6567 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6568 PetscCall(ISGetIndices(newis, &newRows)); 6569 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6570 PetscCall(ISRestoreIndices(newis, &newRows)); 6571 PetscCall(ISDestroy(&newis)); 6572 PetscCall(ISDestroy(&is)); 6573 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6574 PetscFunctionReturn(0); 6575 } 6576 6577 /*@ 6578 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6579 of a set of rows and columns of a matrix; using local numbering of rows. 6580 6581 Collective on Mat 6582 6583 Input Parameters: 6584 + mat - the matrix 6585 . is - index set of rows to remove 6586 . diag - value put in all diagonals of eliminated rows 6587 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6588 - b - optional vector of right hand side, that will be adjusted by provided solution 6589 6590 Level: intermediate 6591 6592 Notes: 6593 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6594 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6595 6596 See `MatZeroRowsColumns()` for details on how this routine operates. 6597 6598 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6599 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6600 @*/ 6601 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6602 { 6603 PetscInt numRows; 6604 const PetscInt *rows; 6605 6606 PetscFunctionBegin; 6607 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6608 PetscValidType(mat, 1); 6609 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6610 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6611 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6612 MatCheckPreallocated(mat, 1); 6613 6614 PetscCall(ISGetLocalSize(is, &numRows)); 6615 PetscCall(ISGetIndices(is, &rows)); 6616 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6617 PetscCall(ISRestoreIndices(is, &rows)); 6618 PetscFunctionReturn(0); 6619 } 6620 6621 /*@C 6622 MatGetSize - Returns the numbers of rows and columns in a matrix. 6623 6624 Not Collective 6625 6626 Input Parameter: 6627 . mat - the matrix 6628 6629 Level: beginner 6630 6631 Output Parameters: 6632 + m - the number of global rows 6633 - n - the number of global columns 6634 6635 Note: 6636 Both output parameters can be `NULL` on input. 6637 6638 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6639 @*/ 6640 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6641 { 6642 PetscFunctionBegin; 6643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6644 if (m) *m = mat->rmap->N; 6645 if (n) *n = mat->cmap->N; 6646 PetscFunctionReturn(0); 6647 } 6648 6649 /*@C 6650 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6651 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6652 6653 Not Collective 6654 6655 Input Parameter: 6656 . mat - the matrix 6657 6658 Output Parameters: 6659 + m - the number of local rows, use `NULL` to not obtain this value 6660 - n - the number of local columns, use `NULL` to not obtain this value 6661 6662 Level: beginner 6663 6664 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()` 6665 @*/ 6666 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6667 { 6668 PetscFunctionBegin; 6669 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6670 if (m) PetscValidIntPointer(m, 2); 6671 if (n) PetscValidIntPointer(n, 3); 6672 if (m) *m = mat->rmap->n; 6673 if (n) *n = mat->cmap->n; 6674 PetscFunctionReturn(0); 6675 } 6676 6677 /*@C 6678 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6679 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6680 6681 Not Collective, unless matrix has not been allocated, then collective 6682 6683 Input Parameter: 6684 . mat - the matrix 6685 6686 Output Parameters: 6687 + m - the global index of the first local column, use `NULL` to not obtain this value 6688 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6689 6690 Level: developer 6691 6692 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6693 @*/ 6694 PetscErrorCode MatGetOwnershipRangeColumn(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->cmap->rstart; 6703 if (n) *n = mat->cmap->rend; 6704 PetscFunctionReturn(0); 6705 } 6706 6707 /*@C 6708 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6709 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 6710 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6711 6712 Not Collective 6713 6714 Input Parameter: 6715 . mat - the matrix 6716 6717 Output Parameters: 6718 + m - the global index of the first local row, use `NULL` to not obtain this value 6719 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6720 6721 Level: beginner 6722 6723 Note: 6724 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6725 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6726 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6727 6728 .seealso: `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6729 `PetscLayout` 6730 @*/ 6731 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6732 { 6733 PetscFunctionBegin; 6734 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6735 PetscValidType(mat, 1); 6736 if (m) PetscValidIntPointer(m, 2); 6737 if (n) PetscValidIntPointer(n, 3); 6738 MatCheckPreallocated(mat, 1); 6739 if (m) *m = mat->rmap->rstart; 6740 if (n) *n = mat->rmap->rend; 6741 PetscFunctionReturn(0); 6742 } 6743 6744 /*@C 6745 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6746 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 6747 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6748 6749 Not Collective, unless matrix has not been allocated, then collective 6750 6751 Input Parameters: 6752 . mat - the matrix 6753 6754 Output Parameters: 6755 . ranges - start of each processors portion plus one more than the total length at the end 6756 6757 Level: beginner 6758 6759 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6760 @*/ 6761 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6762 { 6763 PetscFunctionBegin; 6764 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6765 PetscValidType(mat, 1); 6766 MatCheckPreallocated(mat, 1); 6767 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6768 PetscFunctionReturn(0); 6769 } 6770 6771 /*@C 6772 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6773 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6774 6775 Not Collective, unless matrix has not been allocated, then collective on Mat 6776 6777 Input Parameters: 6778 . mat - the matrix 6779 6780 Output Parameters: 6781 . ranges - start of each processors portion plus one more then the total length at the end 6782 6783 Level: beginner 6784 6785 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6786 @*/ 6787 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6788 { 6789 PetscFunctionBegin; 6790 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6791 PetscValidType(mat, 1); 6792 MatCheckPreallocated(mat, 1); 6793 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6794 PetscFunctionReturn(0); 6795 } 6796 6797 /*@C 6798 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6799 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6800 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6801 6802 Not Collective 6803 6804 Input Parameter: 6805 . A - matrix 6806 6807 Output Parameters: 6808 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6809 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6810 6811 Level: intermediate 6812 6813 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6814 @*/ 6815 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6816 { 6817 PetscErrorCode (*f)(Mat, IS *, IS *); 6818 6819 PetscFunctionBegin; 6820 MatCheckPreallocated(A, 1); 6821 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6822 if (f) { 6823 PetscCall((*f)(A, rows, cols)); 6824 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6825 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6826 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6827 } 6828 PetscFunctionReturn(0); 6829 } 6830 6831 /*@C 6832 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6833 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6834 to complete the factorization. 6835 6836 Collective on fact 6837 6838 Input Parameters: 6839 + fact - the factorized matrix obtained with `MatGetFactor()` 6840 . mat - the matrix 6841 . row - row permutation 6842 . column - column permutation 6843 - info - structure containing 6844 .vb 6845 levels - number of levels of fill. 6846 expected fill - as ratio of original fill. 6847 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6848 missing diagonal entries) 6849 .ve 6850 6851 Output Parameters: 6852 . fact - new matrix that has been symbolically factored 6853 6854 Level: developer 6855 6856 Notes: 6857 See [Matrix Factorization](sec_matfactor) for additional information. 6858 6859 Most users should employ the `KSP` interface for linear solvers 6860 instead of working directly with matrix algebra routines such as this. 6861 See, e.g., `KSPCreate()`. 6862 6863 Uses the definition of level of fill as in Y. Saad, 2003 6864 6865 Developer Note: 6866 The Fortran interface is not autogenerated as the 6867 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6868 6869 References: 6870 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6871 6872 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6873 `MatGetOrdering()`, `MatFactorInfo` 6874 @*/ 6875 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6876 { 6877 PetscFunctionBegin; 6878 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6879 PetscValidType(mat, 2); 6880 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6881 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6882 PetscValidPointer(info, 5); 6883 PetscValidPointer(fact, 1); 6884 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6885 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6886 if (!fact->ops->ilufactorsymbolic) { 6887 MatSolverType stype; 6888 PetscCall(MatFactorGetSolverType(fact, &stype)); 6889 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype); 6890 } 6891 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6892 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6893 MatCheckPreallocated(mat, 2); 6894 6895 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6896 PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info)); 6897 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6898 PetscFunctionReturn(0); 6899 } 6900 6901 /*@C 6902 MatICCFactorSymbolic - Performs symbolic incomplete 6903 Cholesky factorization for a symmetric matrix. Use 6904 `MatCholeskyFactorNumeric()` to complete the factorization. 6905 6906 Collective on fact 6907 6908 Input Parameters: 6909 + fact - the factorized matrix obtained with `MatGetFactor()` 6910 . mat - the matrix to be factored 6911 . perm - row and column permutation 6912 - info - structure containing 6913 .vb 6914 levels - number of levels of fill. 6915 expected fill - as ratio of original fill. 6916 .ve 6917 6918 Output Parameter: 6919 . fact - the factored matrix 6920 6921 Level: developer 6922 6923 Notes: 6924 Most users should employ the `KSP` interface for linear solvers 6925 instead of working directly with matrix algebra routines such as this. 6926 See, e.g., `KSPCreate()`. 6927 6928 This uses the definition of level of fill as in Y. Saad, 2003 6929 6930 Developer Note: 6931 The Fortran interface is not autogenerated as the 6932 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6933 6934 References: 6935 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6936 6937 .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6938 @*/ 6939 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6940 { 6941 PetscFunctionBegin; 6942 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6943 PetscValidType(mat, 2); 6944 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6945 PetscValidPointer(info, 4); 6946 PetscValidPointer(fact, 1); 6947 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6948 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6949 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6950 if (!(fact)->ops->iccfactorsymbolic) { 6951 MatSolverType stype; 6952 PetscCall(MatFactorGetSolverType(fact, &stype)); 6953 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype); 6954 } 6955 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6956 MatCheckPreallocated(mat, 2); 6957 6958 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6959 PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info)); 6960 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6961 PetscFunctionReturn(0); 6962 } 6963 6964 /*@C 6965 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6966 points to an array of valid matrices, they may be reused to store the new 6967 submatrices. 6968 6969 Collective 6970 6971 Input Parameters: 6972 + mat - the matrix 6973 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6974 . irow, icol - index sets of rows and columns to extract 6975 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6976 6977 Output Parameter: 6978 . submat - the array of submatrices 6979 6980 Level: advanced 6981 6982 Notes: 6983 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6984 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6985 to extract a parallel submatrix. 6986 6987 Some matrix types place restrictions on the row and column 6988 indices, such as that they be sorted or that they be equal to each other. 6989 6990 The index sets may not have duplicate entries. 6991 6992 When extracting submatrices from a parallel matrix, each processor can 6993 form a different submatrix by setting the rows and columns of its 6994 individual index sets according to the local submatrix desired. 6995 6996 When finished using the submatrices, the user should destroy 6997 them with `MatDestroySubMatrices()`. 6998 6999 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7000 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7001 7002 This routine creates the matrices in submat; you should NOT create them before 7003 calling it. It also allocates the array of matrix pointers submat. 7004 7005 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7006 request one row/column in a block, they must request all rows/columns that are in 7007 that block. For example, if the block size is 2 you cannot request just row 0 and 7008 column 0. 7009 7010 Fortran Note: 7011 The Fortran interface is slightly different from that given below; it 7012 requires one to pass in as submat a `Mat` (integer) array of size at least n+1. 7013 7014 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7015 @*/ 7016 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7017 { 7018 PetscInt i; 7019 PetscBool eq; 7020 7021 PetscFunctionBegin; 7022 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7023 PetscValidType(mat, 1); 7024 if (n) { 7025 PetscValidPointer(irow, 3); 7026 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7027 PetscValidPointer(icol, 4); 7028 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7029 } 7030 PetscValidPointer(submat, 6); 7031 if (n && scall == MAT_REUSE_MATRIX) { 7032 PetscValidPointer(*submat, 6); 7033 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7034 } 7035 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7036 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7037 MatCheckPreallocated(mat, 1); 7038 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7039 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7040 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7041 for (i = 0; i < n; i++) { 7042 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7043 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7044 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7045 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7046 if (mat->boundtocpu && mat->bindingpropagates) { 7047 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7048 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7049 } 7050 #endif 7051 } 7052 PetscFunctionReturn(0); 7053 } 7054 7055 /*@C 7056 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7057 7058 Collective 7059 7060 Input Parameters: 7061 + mat - the matrix 7062 . n - the number of submatrixes to be extracted 7063 . irow, icol - index sets of rows and columns to extract 7064 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7065 7066 Output Parameter: 7067 . submat - the array of submatrices 7068 7069 Level: advanced 7070 7071 Note: 7072 This is used by `PCGASM` 7073 7074 .seealso: `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7075 @*/ 7076 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7077 { 7078 PetscInt i; 7079 PetscBool eq; 7080 7081 PetscFunctionBegin; 7082 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7083 PetscValidType(mat, 1); 7084 if (n) { 7085 PetscValidPointer(irow, 3); 7086 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7087 PetscValidPointer(icol, 4); 7088 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7089 } 7090 PetscValidPointer(submat, 6); 7091 if (n && scall == MAT_REUSE_MATRIX) { 7092 PetscValidPointer(*submat, 6); 7093 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7094 } 7095 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7096 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7097 MatCheckPreallocated(mat, 1); 7098 7099 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7100 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7101 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7102 for (i = 0; i < n; i++) { 7103 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7104 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7105 } 7106 PetscFunctionReturn(0); 7107 } 7108 7109 /*@C 7110 MatDestroyMatrices - Destroys an array of matrices. 7111 7112 Collective 7113 7114 Input Parameters: 7115 + n - the number of local matrices 7116 - mat - the matrices (note that this is a pointer to the array of matrices) 7117 7118 Level: advanced 7119 7120 Note: 7121 Frees not only the matrices, but also the array that contains the matrices 7122 7123 Fortran Note: 7124 Will not free the array. 7125 7126 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7127 @*/ 7128 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7129 { 7130 PetscInt i; 7131 7132 PetscFunctionBegin; 7133 if (!*mat) PetscFunctionReturn(0); 7134 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7135 PetscValidPointer(mat, 2); 7136 7137 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7138 7139 /* memory is allocated even if n = 0 */ 7140 PetscCall(PetscFree(*mat)); 7141 PetscFunctionReturn(0); 7142 } 7143 7144 /*@C 7145 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7146 7147 Collective 7148 7149 Input Parameters: 7150 + n - the number of local matrices 7151 - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling 7152 sequence of MatCreateSubMatrices()) 7153 7154 Level: advanced 7155 7156 Note: 7157 Frees not only the matrices, but also the array that contains the matrices 7158 7159 Fortran Note: 7160 Will not free the array. 7161 7162 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7163 @*/ 7164 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7165 { 7166 Mat mat0; 7167 7168 PetscFunctionBegin; 7169 if (!*mat) PetscFunctionReturn(0); 7170 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7171 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7172 PetscValidPointer(mat, 2); 7173 7174 mat0 = (*mat)[0]; 7175 if (mat0 && mat0->ops->destroysubmatrices) { 7176 PetscCall((mat0->ops->destroysubmatrices)(n, mat)); 7177 } else { 7178 PetscCall(MatDestroyMatrices(n, mat)); 7179 } 7180 PetscFunctionReturn(0); 7181 } 7182 7183 /*@C 7184 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7185 7186 Collective 7187 7188 Input Parameters: 7189 . mat - the matrix 7190 7191 Output Parameter: 7192 . matstruct - the sequential matrix with the nonzero structure of mat 7193 7194 Level: developer 7195 7196 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7197 @*/ 7198 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7199 { 7200 PetscFunctionBegin; 7201 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7202 PetscValidPointer(matstruct, 2); 7203 7204 PetscValidType(mat, 1); 7205 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7206 MatCheckPreallocated(mat, 1); 7207 7208 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7209 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7210 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7211 PetscFunctionReturn(0); 7212 } 7213 7214 /*@C 7215 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7216 7217 Collective 7218 7219 Input Parameters: 7220 . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling 7221 sequence of `MatGetSequentialNonzeroStructure()`) 7222 7223 Level: advanced 7224 7225 Note: 7226 Frees not only the matrices, but also the array that contains the matrices 7227 7228 .seealso: `Mat`, `MatGetSeqNonzeroStructure()` 7229 @*/ 7230 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7231 { 7232 PetscFunctionBegin; 7233 PetscValidPointer(mat, 1); 7234 PetscCall(MatDestroy(mat)); 7235 PetscFunctionReturn(0); 7236 } 7237 7238 /*@ 7239 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7240 replaces the index sets by larger ones that represent submatrices with 7241 additional overlap. 7242 7243 Collective 7244 7245 Input Parameters: 7246 + mat - the matrix 7247 . n - the number of index sets 7248 . is - the array of index sets (these index sets will changed during the call) 7249 - ov - the additional overlap requested 7250 7251 Options Database Key: 7252 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7253 7254 Level: developer 7255 7256 Note: 7257 The computed overlap preserves the matrix block sizes when the blocks are square. 7258 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7259 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7260 7261 .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7262 @*/ 7263 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7264 { 7265 PetscInt i, bs, cbs; 7266 7267 PetscFunctionBegin; 7268 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7269 PetscValidType(mat, 1); 7270 PetscValidLogicalCollectiveInt(mat, n, 2); 7271 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7272 if (n) { 7273 PetscValidPointer(is, 3); 7274 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7275 } 7276 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7277 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7278 MatCheckPreallocated(mat, 1); 7279 7280 if (!ov || !n) PetscFunctionReturn(0); 7281 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7282 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7283 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7284 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7285 if (bs == cbs) { 7286 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7287 } 7288 PetscFunctionReturn(0); 7289 } 7290 7291 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7292 7293 /*@ 7294 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7295 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7296 additional overlap. 7297 7298 Collective 7299 7300 Input Parameters: 7301 + mat - the matrix 7302 . n - the number of index sets 7303 . is - the array of index sets (these index sets will changed during the call) 7304 - ov - the additional overlap requested 7305 7306 ` Options Database Key: 7307 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7308 7309 Level: developer 7310 7311 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7312 @*/ 7313 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7314 { 7315 PetscInt i; 7316 7317 PetscFunctionBegin; 7318 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7319 PetscValidType(mat, 1); 7320 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7321 if (n) { 7322 PetscValidPointer(is, 3); 7323 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7324 } 7325 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7326 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7327 MatCheckPreallocated(mat, 1); 7328 if (!ov) PetscFunctionReturn(0); 7329 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7330 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7331 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7332 PetscFunctionReturn(0); 7333 } 7334 7335 /*@ 7336 MatGetBlockSize - Returns the matrix block size. 7337 7338 Not Collective 7339 7340 Input Parameter: 7341 . mat - the matrix 7342 7343 Output Parameter: 7344 . bs - block size 7345 7346 Level: intermediate 7347 7348 Notes: 7349 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7350 7351 If the block size has not been set yet this routine returns 1. 7352 7353 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7354 @*/ 7355 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7356 { 7357 PetscFunctionBegin; 7358 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7359 PetscValidIntPointer(bs, 2); 7360 *bs = PetscAbs(mat->rmap->bs); 7361 PetscFunctionReturn(0); 7362 } 7363 7364 /*@ 7365 MatGetBlockSizes - Returns the matrix block row and column sizes. 7366 7367 Not Collective 7368 7369 Input Parameter: 7370 . mat - the matrix 7371 7372 Output Parameters: 7373 + rbs - row block size 7374 - cbs - column block size 7375 7376 Level: intermediate 7377 7378 Notes: 7379 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7380 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7381 7382 If a block size has not been set yet this routine returns 1. 7383 7384 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7385 @*/ 7386 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7387 { 7388 PetscFunctionBegin; 7389 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7390 if (rbs) PetscValidIntPointer(rbs, 2); 7391 if (cbs) PetscValidIntPointer(cbs, 3); 7392 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7393 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7394 PetscFunctionReturn(0); 7395 } 7396 7397 /*@ 7398 MatSetBlockSize - Sets the matrix block size. 7399 7400 Logically Collective 7401 7402 Input Parameters: 7403 + mat - the matrix 7404 - bs - block size 7405 7406 Level: intermediate 7407 7408 Notes: 7409 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7410 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7411 7412 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7413 is compatible with the matrix local sizes. 7414 7415 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7416 @*/ 7417 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7418 { 7419 PetscFunctionBegin; 7420 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7421 PetscValidLogicalCollectiveInt(mat, bs, 2); 7422 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7423 PetscFunctionReturn(0); 7424 } 7425 7426 typedef struct { 7427 PetscInt n; 7428 IS *is; 7429 Mat *mat; 7430 PetscObjectState nonzerostate; 7431 Mat C; 7432 } EnvelopeData; 7433 7434 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7435 { 7436 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7437 PetscCall(PetscFree(edata->is)); 7438 PetscCall(PetscFree(edata)); 7439 return 0; 7440 } 7441 7442 /* 7443 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7444 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7445 7446 Collective 7447 7448 Input Parameter: 7449 . mat - the matrix 7450 7451 Notes: 7452 There can be zeros within the blocks 7453 7454 The blocks can overlap between processes, including laying on more than two processes 7455 7456 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7457 */ 7458 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7459 { 7460 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7461 PetscInt *diag, *odiag, sc; 7462 VecScatter scatter; 7463 PetscScalar *seqv; 7464 const PetscScalar *parv; 7465 const PetscInt *ia, *ja; 7466 PetscBool set, flag, done; 7467 Mat AA = mat, A; 7468 MPI_Comm comm; 7469 PetscMPIInt rank, size, tag; 7470 MPI_Status status; 7471 PetscContainer container; 7472 EnvelopeData *edata; 7473 Vec seq, par; 7474 IS isglobal; 7475 7476 PetscFunctionBegin; 7477 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7478 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7479 if (!set || !flag) { 7480 /* TOO: only needs nonzero structure of transpose */ 7481 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7482 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7483 } 7484 PetscCall(MatAIJGetLocalMat(AA, &A)); 7485 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7486 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7487 7488 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7489 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7490 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7491 PetscCallMPI(MPI_Comm_size(comm, &size)); 7492 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7493 7494 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7495 7496 if (rank > 0) { 7497 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7498 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7499 } 7500 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7501 for (i = 0; i < n; i++) { 7502 env = PetscMax(env, ja[ia[i + 1] - 1]); 7503 II = rstart + i; 7504 if (env == II) { 7505 starts[lblocks] = tbs; 7506 sizes[lblocks++] = 1 + II - tbs; 7507 tbs = 1 + II; 7508 } 7509 } 7510 if (rank < size - 1) { 7511 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7512 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7513 } 7514 7515 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7516 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7517 PetscCall(MatDestroy(&A)); 7518 7519 PetscCall(PetscNew(&edata)); 7520 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7521 edata->n = lblocks; 7522 /* create IS needed for extracting blocks from the original matrix */ 7523 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7524 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7525 7526 /* Create the resulting inverse matrix structure with preallocation information */ 7527 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7528 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7529 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7530 PetscCall(MatSetType(edata->C, MATAIJ)); 7531 7532 /* Communicate the start and end of each row, from each block to the correct rank */ 7533 /* TODO: Use PetscSF instead of VecScatter */ 7534 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7535 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7536 PetscCall(VecGetArrayWrite(seq, &seqv)); 7537 for (PetscInt i = 0; i < lblocks; i++) { 7538 for (PetscInt j = 0; j < sizes[i]; j++) { 7539 seqv[cnt] = starts[i]; 7540 seqv[cnt + 1] = starts[i] + sizes[i]; 7541 cnt += 2; 7542 } 7543 } 7544 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7545 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7546 sc -= cnt; 7547 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7548 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7549 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7550 PetscCall(ISDestroy(&isglobal)); 7551 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7552 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7553 PetscCall(VecScatterDestroy(&scatter)); 7554 PetscCall(VecDestroy(&seq)); 7555 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7556 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7557 PetscCall(VecGetArrayRead(par, &parv)); 7558 cnt = 0; 7559 PetscCall(MatGetSize(mat, NULL, &n)); 7560 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7561 PetscInt start, end, d = 0, od = 0; 7562 7563 start = (PetscInt)PetscRealPart(parv[cnt]); 7564 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7565 cnt += 2; 7566 7567 if (start < cstart) { 7568 od += cstart - start + n - cend; 7569 d += cend - cstart; 7570 } else if (start < cend) { 7571 od += n - cend; 7572 d += cend - start; 7573 } else od += n - start; 7574 if (end <= cstart) { 7575 od -= cstart - end + n - cend; 7576 d -= cend - cstart; 7577 } else if (end < cend) { 7578 od -= n - cend; 7579 d -= cend - end; 7580 } else od -= n - end; 7581 7582 odiag[i] = od; 7583 diag[i] = d; 7584 } 7585 PetscCall(VecRestoreArrayRead(par, &parv)); 7586 PetscCall(VecDestroy(&par)); 7587 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7588 PetscCall(PetscFree2(diag, odiag)); 7589 PetscCall(PetscFree2(sizes, starts)); 7590 7591 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7592 PetscCall(PetscContainerSetPointer(container, edata)); 7593 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7594 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7595 PetscCall(PetscObjectDereference((PetscObject)container)); 7596 PetscFunctionReturn(0); 7597 } 7598 7599 /*@ 7600 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7601 7602 Collective 7603 7604 Input Parameters: 7605 . A - the matrix 7606 7607 Output Parameters: 7608 . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 7609 7610 Level: advanced 7611 7612 Note: 7613 For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal. 7614 7615 .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7616 @*/ 7617 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7618 { 7619 PetscContainer container; 7620 EnvelopeData *edata; 7621 PetscObjectState nonzerostate; 7622 7623 PetscFunctionBegin; 7624 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7625 if (!container) { 7626 PetscCall(MatComputeVariableBlockEnvelope(A)); 7627 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7628 } 7629 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7630 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7631 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7632 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7633 7634 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7635 *C = edata->C; 7636 7637 for (PetscInt i = 0; i < edata->n; i++) { 7638 Mat D; 7639 PetscScalar *dvalues; 7640 7641 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7642 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7643 PetscCall(MatSeqDenseInvert(D)); 7644 PetscCall(MatDenseGetArray(D, &dvalues)); 7645 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7646 PetscCall(MatDestroy(&D)); 7647 } 7648 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7649 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7650 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7651 PetscFunctionReturn(0); 7652 } 7653 7654 /*@ 7655 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7656 7657 Logically Collective 7658 7659 Input Parameters: 7660 + mat - the matrix 7661 . nblocks - the number of blocks on this process, each block can only exist on a single process 7662 - bsizes - the block sizes 7663 7664 Level: intermediate 7665 7666 Notes: 7667 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7668 7669 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. 7670 7671 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7672 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7673 @*/ 7674 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7675 { 7676 PetscInt i, ncnt = 0, nlocal; 7677 7678 PetscFunctionBegin; 7679 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7680 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7681 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7682 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7683 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); 7684 PetscCall(PetscFree(mat->bsizes)); 7685 mat->nblocks = nblocks; 7686 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7687 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7688 PetscFunctionReturn(0); 7689 } 7690 7691 /*@C 7692 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7693 7694 Logically Collective; No Fortran Support 7695 7696 Input Parameter: 7697 . mat - the matrix 7698 7699 Output Parameters: 7700 + nblocks - the number of blocks on this process 7701 - bsizes - the block sizes 7702 7703 Level: intermediate 7704 7705 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7706 @*/ 7707 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7708 { 7709 PetscFunctionBegin; 7710 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7711 *nblocks = mat->nblocks; 7712 *bsizes = mat->bsizes; 7713 PetscFunctionReturn(0); 7714 } 7715 7716 /*@ 7717 MatSetBlockSizes - Sets the matrix block row and column sizes. 7718 7719 Logically Collective 7720 7721 Input Parameters: 7722 + mat - the matrix 7723 . rbs - row block size 7724 - cbs - column block size 7725 7726 Level: intermediate 7727 7728 Notes: 7729 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7730 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7731 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7732 7733 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7734 are compatible with the matrix local sizes. 7735 7736 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7737 7738 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7739 @*/ 7740 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7741 { 7742 PetscFunctionBegin; 7743 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7744 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7745 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7746 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7747 if (mat->rmap->refcnt) { 7748 ISLocalToGlobalMapping l2g = NULL; 7749 PetscLayout nmap = NULL; 7750 7751 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7752 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7753 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7754 mat->rmap = nmap; 7755 mat->rmap->mapping = l2g; 7756 } 7757 if (mat->cmap->refcnt) { 7758 ISLocalToGlobalMapping l2g = NULL; 7759 PetscLayout nmap = NULL; 7760 7761 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7762 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7763 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7764 mat->cmap = nmap; 7765 mat->cmap->mapping = l2g; 7766 } 7767 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7768 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7769 PetscFunctionReturn(0); 7770 } 7771 7772 /*@ 7773 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7774 7775 Logically Collective 7776 7777 Input Parameters: 7778 + mat - the matrix 7779 . fromRow - matrix from which to copy row block size 7780 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7781 7782 Level: developer 7783 7784 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7785 @*/ 7786 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7787 { 7788 PetscFunctionBegin; 7789 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7790 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7791 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7792 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7793 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7794 PetscFunctionReturn(0); 7795 } 7796 7797 /*@ 7798 MatResidual - Default routine to calculate the residual r = b - Ax 7799 7800 Collective 7801 7802 Input Parameters: 7803 + mat - the matrix 7804 . b - the right-hand-side 7805 - x - the approximate solution 7806 7807 Output Parameter: 7808 . r - location to store the residual 7809 7810 Level: developer 7811 7812 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7813 @*/ 7814 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7815 { 7816 PetscFunctionBegin; 7817 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7818 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7819 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7820 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7821 PetscValidType(mat, 1); 7822 MatCheckPreallocated(mat, 1); 7823 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7824 if (!mat->ops->residual) { 7825 PetscCall(MatMult(mat, x, r)); 7826 PetscCall(VecAYPX(r, -1.0, b)); 7827 } else { 7828 PetscUseTypeMethod(mat, residual, b, x, r); 7829 } 7830 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7831 PetscFunctionReturn(0); 7832 } 7833 7834 /*@C 7835 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7836 7837 Collective 7838 7839 Input Parameters: 7840 + mat - the matrix 7841 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7842 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7843 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7844 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7845 always used. 7846 7847 Output Parameters: 7848 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7849 . 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 7850 . ja - the column indices, use `NULL` if not needed 7851 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7852 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7853 7854 Level: developer 7855 7856 Notes: 7857 You CANNOT change any of the ia[] or ja[] values. 7858 7859 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7860 7861 Fortran Notes: 7862 In Fortran use 7863 .vb 7864 PetscInt ia(1), ja(1) 7865 PetscOffset iia, jja 7866 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr) 7867 ! Access the ith and jth entries via ia(iia + i) and ja(jja + j) 7868 .ve 7869 or 7870 .vb 7871 PetscInt, pointer :: ia(:),ja(:) 7872 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7873 ! Access the ith and jth entries via ia(i) and ja(j) 7874 .ve 7875 7876 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7877 @*/ 7878 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7879 { 7880 PetscFunctionBegin; 7881 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7882 PetscValidType(mat, 1); 7883 if (n) PetscValidIntPointer(n, 5); 7884 if (ia) PetscValidPointer(ia, 6); 7885 if (ja) PetscValidPointer(ja, 7); 7886 if (done) PetscValidBoolPointer(done, 8); 7887 MatCheckPreallocated(mat, 1); 7888 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7889 else { 7890 if (done) *done = PETSC_TRUE; 7891 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7892 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7893 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7894 } 7895 PetscFunctionReturn(0); 7896 } 7897 7898 /*@C 7899 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7900 7901 Collective 7902 7903 Input Parameters: 7904 + mat - the matrix 7905 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7906 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7907 symmetrized 7908 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7909 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7910 always used. 7911 . n - number of columns in the (possibly compressed) matrix 7912 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7913 - ja - the row indices 7914 7915 Output Parameters: 7916 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7917 7918 Level: developer 7919 7920 .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7921 @*/ 7922 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7923 { 7924 PetscFunctionBegin; 7925 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7926 PetscValidType(mat, 1); 7927 PetscValidIntPointer(n, 5); 7928 if (ia) PetscValidPointer(ia, 6); 7929 if (ja) PetscValidPointer(ja, 7); 7930 PetscValidBoolPointer(done, 8); 7931 MatCheckPreallocated(mat, 1); 7932 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7933 else { 7934 *done = PETSC_TRUE; 7935 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7936 } 7937 PetscFunctionReturn(0); 7938 } 7939 7940 /*@C 7941 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7942 7943 Collective 7944 7945 Input Parameters: 7946 + mat - the matrix 7947 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7948 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7949 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7950 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7951 always used. 7952 . n - size of (possibly compressed) matrix 7953 . ia - the row pointers 7954 - ja - the column indices 7955 7956 Output Parameters: 7957 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7958 7959 Level: developer 7960 7961 Note: 7962 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 7963 us of the array after it has been restored. If you pass `NULL`, it will 7964 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7965 7966 .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7967 @*/ 7968 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7969 { 7970 PetscFunctionBegin; 7971 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7972 PetscValidType(mat, 1); 7973 if (ia) PetscValidPointer(ia, 6); 7974 if (ja) PetscValidPointer(ja, 7); 7975 if (done) PetscValidBoolPointer(done, 8); 7976 MatCheckPreallocated(mat, 1); 7977 7978 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 7979 else { 7980 if (done) *done = PETSC_TRUE; 7981 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7982 if (n) *n = 0; 7983 if (ia) *ia = NULL; 7984 if (ja) *ja = NULL; 7985 } 7986 PetscFunctionReturn(0); 7987 } 7988 7989 /*@C 7990 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 7991 7992 Collective on Mat 7993 7994 Input Parameters: 7995 + mat - the matrix 7996 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7997 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7998 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7999 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8000 always used. 8001 8002 Output Parameters: 8003 + n - size of (possibly compressed) matrix 8004 . ia - the column pointers 8005 . ja - the row indices 8006 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8007 8008 Level: developer 8009 8010 .seealso: `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8011 @*/ 8012 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8013 { 8014 PetscFunctionBegin; 8015 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8016 PetscValidType(mat, 1); 8017 if (ia) PetscValidPointer(ia, 6); 8018 if (ja) PetscValidPointer(ja, 7); 8019 PetscValidBoolPointer(done, 8); 8020 MatCheckPreallocated(mat, 1); 8021 8022 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8023 else { 8024 *done = PETSC_TRUE; 8025 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8026 if (n) *n = 0; 8027 if (ia) *ia = NULL; 8028 if (ja) *ja = NULL; 8029 } 8030 PetscFunctionReturn(0); 8031 } 8032 8033 /*@C 8034 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8035 8036 Collective 8037 8038 Input Parameters: 8039 + mat - the matrix 8040 . ncolors - max color value 8041 . n - number of entries in colorarray 8042 - colorarray - array indicating color for each column 8043 8044 Output Parameters: 8045 . iscoloring - coloring generated using colorarray information 8046 8047 Level: developer 8048 8049 .seealso: `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8050 @*/ 8051 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8052 { 8053 PetscFunctionBegin; 8054 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8055 PetscValidType(mat, 1); 8056 PetscValidIntPointer(colorarray, 4); 8057 PetscValidPointer(iscoloring, 5); 8058 MatCheckPreallocated(mat, 1); 8059 8060 if (!mat->ops->coloringpatch) { 8061 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8062 } else { 8063 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8064 } 8065 PetscFunctionReturn(0); 8066 } 8067 8068 /*@ 8069 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8070 8071 Logically Collective 8072 8073 Input Parameter: 8074 . mat - the factored matrix to be reset 8075 8076 Level: developer 8077 8078 Notes: 8079 This routine should be used only with factored matrices formed by in-place 8080 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8081 format). This option can save memory, for example, when solving nonlinear 8082 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8083 ILU(0) preconditioner. 8084 8085 Note that one can specify in-place ILU(0) factorization by calling 8086 .vb 8087 PCType(pc,PCILU); 8088 PCFactorSeUseInPlace(pc); 8089 .ve 8090 or by using the options -pc_type ilu -pc_factor_in_place 8091 8092 In-place factorization ILU(0) can also be used as a local 8093 solver for the blocks within the block Jacobi or additive Schwarz 8094 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8095 for details on setting local solver options. 8096 8097 Most users should employ the `KSP` interface for linear solvers 8098 instead of working directly with matrix algebra routines such as this. 8099 See, e.g., `KSPCreate()`. 8100 8101 .seealso: `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8102 @*/ 8103 PetscErrorCode MatSetUnfactored(Mat mat) 8104 { 8105 PetscFunctionBegin; 8106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8107 PetscValidType(mat, 1); 8108 MatCheckPreallocated(mat, 1); 8109 mat->factortype = MAT_FACTOR_NONE; 8110 if (!mat->ops->setunfactored) PetscFunctionReturn(0); 8111 PetscUseTypeMethod(mat, setunfactored); 8112 PetscFunctionReturn(0); 8113 } 8114 8115 /*MC 8116 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8117 8118 Synopsis: 8119 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8120 8121 Not collective 8122 8123 Input Parameter: 8124 . x - matrix 8125 8126 Output Parameters: 8127 + xx_v - the Fortran pointer to the array 8128 - ierr - error code 8129 8130 Example of Usage: 8131 .vb 8132 PetscScalar, pointer xx_v(:,:) 8133 .... 8134 call MatDenseGetArrayF90(x,xx_v,ierr) 8135 a = xx_v(3) 8136 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8137 .ve 8138 8139 Level: advanced 8140 8141 .seealso: `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8142 M*/ 8143 8144 /*MC 8145 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8146 accessed with `MatDenseGetArrayF90()`. 8147 8148 Synopsis: 8149 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8150 8151 Not collective 8152 8153 Input Parameters: 8154 + x - matrix 8155 - xx_v - the Fortran90 pointer to the array 8156 8157 Output Parameter: 8158 . ierr - error code 8159 8160 Example of Usage: 8161 .vb 8162 PetscScalar, pointer xx_v(:,:) 8163 .... 8164 call MatDenseGetArrayF90(x,xx_v,ierr) 8165 a = xx_v(3) 8166 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8167 .ve 8168 8169 Level: advanced 8170 8171 .seealso: `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8172 M*/ 8173 8174 /*MC 8175 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8176 8177 Synopsis: 8178 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8179 8180 Not collective 8181 8182 Input Parameter: 8183 . x - matrix 8184 8185 Output Parameters: 8186 + xx_v - the Fortran pointer to the array 8187 - ierr - error code 8188 8189 Example of Usage: 8190 .vb 8191 PetscScalar, pointer xx_v(:) 8192 .... 8193 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8194 a = xx_v(3) 8195 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8196 .ve 8197 8198 Level: advanced 8199 8200 .seealso: `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8201 M*/ 8202 8203 /*MC 8204 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8205 accessed with `MatSeqAIJGetArrayF90()`. 8206 8207 Synopsis: 8208 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8209 8210 Not collective 8211 8212 Input Parameters: 8213 + x - matrix 8214 - xx_v - the Fortran90 pointer to the array 8215 8216 Output Parameter: 8217 . ierr - error code 8218 8219 Example of Usage: 8220 .vb 8221 PetscScalar, pointer xx_v(:) 8222 .... 8223 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8224 a = xx_v(3) 8225 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8226 .ve 8227 8228 Level: advanced 8229 8230 .seealso: `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8231 M*/ 8232 8233 /*@ 8234 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8235 as the original matrix. 8236 8237 Collective 8238 8239 Input Parameters: 8240 + mat - the original matrix 8241 . isrow - parallel IS containing the rows this processor should obtain 8242 . 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. 8243 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8244 8245 Output Parameter: 8246 . newmat - the new submatrix, of the same type as the old 8247 8248 Level: advanced 8249 8250 Notes: 8251 The submatrix will be able to be multiplied with vectors using the same layout as iscol. 8252 8253 Some matrix types place restrictions on the row and column indices, such 8254 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; 8255 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8256 8257 The index sets may not have duplicate entries. 8258 8259 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8260 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8261 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8262 will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when 8263 you are finished using it. 8264 8265 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8266 the input matrix. 8267 8268 If iscol is `NULL` then all columns are obtained (not supported in Fortran). 8269 8270 Example usage: 8271 Consider the following 8x8 matrix with 34 non-zero values, that is 8272 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8273 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8274 as follows: 8275 8276 .vb 8277 1 2 0 | 0 3 0 | 0 4 8278 Proc0 0 5 6 | 7 0 0 | 8 0 8279 9 0 10 | 11 0 0 | 12 0 8280 ------------------------------------- 8281 13 0 14 | 15 16 17 | 0 0 8282 Proc1 0 18 0 | 19 20 21 | 0 0 8283 0 0 0 | 22 23 0 | 24 0 8284 ------------------------------------- 8285 Proc2 25 26 27 | 0 0 28 | 29 0 8286 30 0 0 | 31 32 33 | 0 34 8287 .ve 8288 8289 Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8290 8291 .vb 8292 2 0 | 0 3 0 | 0 8293 Proc0 5 6 | 7 0 0 | 8 8294 ------------------------------- 8295 Proc1 18 0 | 19 20 21 | 0 8296 ------------------------------- 8297 Proc2 26 27 | 0 0 28 | 29 8298 0 0 | 31 32 33 | 0 8299 .ve 8300 8301 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8302 @*/ 8303 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8304 { 8305 PetscMPIInt size; 8306 Mat *local; 8307 IS iscoltmp; 8308 PetscBool flg; 8309 8310 PetscFunctionBegin; 8311 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8312 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8313 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8314 PetscValidPointer(newmat, 5); 8315 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8316 PetscValidType(mat, 1); 8317 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8318 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8319 8320 MatCheckPreallocated(mat, 1); 8321 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8322 8323 if (!iscol || isrow == iscol) { 8324 PetscBool stride; 8325 PetscMPIInt grabentirematrix = 0, grab; 8326 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8327 if (stride) { 8328 PetscInt first, step, n, rstart, rend; 8329 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8330 if (step == 1) { 8331 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8332 if (rstart == first) { 8333 PetscCall(ISGetLocalSize(isrow, &n)); 8334 if (n == rend - rstart) grabentirematrix = 1; 8335 } 8336 } 8337 } 8338 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8339 if (grab) { 8340 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8341 if (cll == MAT_INITIAL_MATRIX) { 8342 *newmat = mat; 8343 PetscCall(PetscObjectReference((PetscObject)mat)); 8344 } 8345 PetscFunctionReturn(0); 8346 } 8347 } 8348 8349 if (!iscol) { 8350 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8351 } else { 8352 iscoltmp = iscol; 8353 } 8354 8355 /* if original matrix is on just one processor then use submatrix generated */ 8356 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8357 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8358 goto setproperties; 8359 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8360 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8361 *newmat = *local; 8362 PetscCall(PetscFree(local)); 8363 goto setproperties; 8364 } else if (!mat->ops->createsubmatrix) { 8365 /* Create a new matrix type that implements the operation using the full matrix */ 8366 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8367 switch (cll) { 8368 case MAT_INITIAL_MATRIX: 8369 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8370 break; 8371 case MAT_REUSE_MATRIX: 8372 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8373 break; 8374 default: 8375 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8376 } 8377 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8378 goto setproperties; 8379 } 8380 8381 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8382 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8383 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8384 8385 setproperties: 8386 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8387 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8388 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8389 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8390 PetscFunctionReturn(0); 8391 } 8392 8393 /*@ 8394 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8395 8396 Not Collective 8397 8398 Input Parameters: 8399 + A - the matrix we wish to propagate options from 8400 - B - the matrix we wish to propagate options to 8401 8402 Level: beginner 8403 8404 Note: 8405 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8406 8407 .seealso: `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8408 @*/ 8409 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8410 { 8411 PetscFunctionBegin; 8412 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8413 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8414 B->symmetry_eternal = A->symmetry_eternal; 8415 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8416 B->symmetric = A->symmetric; 8417 B->structurally_symmetric = A->structurally_symmetric; 8418 B->spd = A->spd; 8419 B->hermitian = A->hermitian; 8420 PetscFunctionReturn(0); 8421 } 8422 8423 /*@ 8424 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8425 used during the assembly process to store values that belong to 8426 other processors. 8427 8428 Not Collective 8429 8430 Input Parameters: 8431 + mat - the matrix 8432 . size - the initial size of the stash. 8433 - bsize - the initial size of the block-stash(if used). 8434 8435 Options Database Keys: 8436 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8437 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8438 8439 Level: intermediate 8440 8441 Notes: 8442 The block-stash is used for values set with `MatSetValuesBlocked()` while 8443 the stash is used for values set with `MatSetValues()` 8444 8445 Run with the option -info and look for output of the form 8446 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8447 to determine the appropriate value, MM, to use for size and 8448 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8449 to determine the value, BMM to use for bsize 8450 8451 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8452 @*/ 8453 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8454 { 8455 PetscFunctionBegin; 8456 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8457 PetscValidType(mat, 1); 8458 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8459 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8460 PetscFunctionReturn(0); 8461 } 8462 8463 /*@ 8464 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8465 the matrix 8466 8467 Neighbor-wise Collective 8468 8469 Input Parameters: 8470 + mat - the matrix 8471 . x,y - the vectors 8472 - w - where the result is stored 8473 8474 Level: intermediate 8475 8476 Notes: 8477 `w` may be the same vector as `y`. 8478 8479 This allows one to use either the restriction or interpolation (its transpose) 8480 matrix to do the interpolation 8481 8482 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8483 @*/ 8484 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8485 { 8486 PetscInt M, N, Ny; 8487 8488 PetscFunctionBegin; 8489 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8490 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8491 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8492 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8493 PetscCall(MatGetSize(A, &M, &N)); 8494 PetscCall(VecGetSize(y, &Ny)); 8495 if (M == Ny) { 8496 PetscCall(MatMultAdd(A, x, y, w)); 8497 } else { 8498 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8499 } 8500 PetscFunctionReturn(0); 8501 } 8502 8503 /*@ 8504 MatInterpolate - y = A*x or A'*x depending on the shape of 8505 the matrix 8506 8507 Neighbor-wise Collective 8508 8509 Input Parameters: 8510 + mat - the matrix 8511 - x,y - the vectors 8512 8513 Level: intermediate 8514 8515 Note: 8516 This allows one to use either the restriction or interpolation (its transpose) 8517 matrix to do the interpolation 8518 8519 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8520 @*/ 8521 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8522 { 8523 PetscInt M, N, Ny; 8524 8525 PetscFunctionBegin; 8526 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8527 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8528 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8529 PetscCall(MatGetSize(A, &M, &N)); 8530 PetscCall(VecGetSize(y, &Ny)); 8531 if (M == Ny) { 8532 PetscCall(MatMult(A, x, y)); 8533 } else { 8534 PetscCall(MatMultTranspose(A, x, y)); 8535 } 8536 PetscFunctionReturn(0); 8537 } 8538 8539 /*@ 8540 MatRestrict - y = A*x or A'*x 8541 8542 Neighbor-wise Collective on Mat 8543 8544 Input Parameters: 8545 + mat - the matrix 8546 - x,y - the vectors 8547 8548 Level: intermediate 8549 8550 Note: 8551 This allows one to use either the restriction or interpolation (its transpose) 8552 matrix to do the restriction 8553 8554 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8555 @*/ 8556 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8557 { 8558 PetscInt M, N, Ny; 8559 8560 PetscFunctionBegin; 8561 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8562 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8563 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8564 PetscCall(MatGetSize(A, &M, &N)); 8565 PetscCall(VecGetSize(y, &Ny)); 8566 if (M == Ny) { 8567 PetscCall(MatMult(A, x, y)); 8568 } else { 8569 PetscCall(MatMultTranspose(A, x, y)); 8570 } 8571 PetscFunctionReturn(0); 8572 } 8573 8574 /*@ 8575 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8576 8577 Neighbor-wise Collective on Mat 8578 8579 Input Parameters: 8580 + mat - the matrix 8581 - w, x - the input dense matrices 8582 8583 Output Parameters: 8584 . y - the output dense matrix 8585 8586 Level: intermediate 8587 8588 Note: 8589 This allows one to use either the restriction or interpolation (its transpose) 8590 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8591 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8592 8593 .seealso: `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8594 @*/ 8595 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8596 { 8597 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8598 PetscBool trans = PETSC_TRUE; 8599 MatReuse reuse = MAT_INITIAL_MATRIX; 8600 8601 PetscFunctionBegin; 8602 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8603 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8604 PetscValidType(x, 2); 8605 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8606 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8607 PetscCall(MatGetSize(A, &M, &N)); 8608 PetscCall(MatGetSize(x, &Mx, &Nx)); 8609 if (N == Mx) trans = PETSC_FALSE; 8610 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); 8611 Mo = trans ? N : M; 8612 if (*y) { 8613 PetscCall(MatGetSize(*y, &My, &Ny)); 8614 if (Mo == My && Nx == Ny) { 8615 reuse = MAT_REUSE_MATRIX; 8616 } else { 8617 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); 8618 PetscCall(MatDestroy(y)); 8619 } 8620 } 8621 8622 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8623 PetscBool flg; 8624 8625 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8626 if (w) { 8627 PetscInt My, Ny, Mw, Nw; 8628 8629 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8630 PetscCall(MatGetSize(*y, &My, &Ny)); 8631 PetscCall(MatGetSize(w, &Mw, &Nw)); 8632 if (!flg || My != Mw || Ny != Nw) w = NULL; 8633 } 8634 if (!w) { 8635 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8636 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8637 PetscCall(PetscObjectDereference((PetscObject)w)); 8638 } else { 8639 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8640 } 8641 } 8642 if (!trans) { 8643 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8644 } else { 8645 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8646 } 8647 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8648 PetscFunctionReturn(0); 8649 } 8650 8651 /*@ 8652 MatMatInterpolate - Y = A*X or A'*X 8653 8654 Neighbor-wise Collective on Mat 8655 8656 Input Parameters: 8657 + mat - the matrix 8658 - x - the input dense matrix 8659 8660 Output Parameters: 8661 . y - the output dense matrix 8662 8663 Level: intermediate 8664 8665 Note: 8666 This allows one to use either the restriction or interpolation (its transpose) 8667 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8668 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8669 8670 .seealso: `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8671 @*/ 8672 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8673 { 8674 PetscFunctionBegin; 8675 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8676 PetscFunctionReturn(0); 8677 } 8678 8679 /*@ 8680 MatMatRestrict - Y = A*X or A'*X 8681 8682 Neighbor-wise Collective on Mat 8683 8684 Input Parameters: 8685 + mat - the matrix 8686 - x - the input dense matrix 8687 8688 Output Parameters: 8689 . y - the output dense matrix 8690 8691 Level: intermediate 8692 8693 Note: 8694 This allows one to use either the restriction or interpolation (its transpose) 8695 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8696 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8697 8698 .seealso: `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8699 @*/ 8700 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8701 { 8702 PetscFunctionBegin; 8703 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8704 PetscFunctionReturn(0); 8705 } 8706 8707 /*@ 8708 MatGetNullSpace - retrieves the null space of a matrix. 8709 8710 Logically Collective 8711 8712 Input Parameters: 8713 + mat - the matrix 8714 - nullsp - the null space object 8715 8716 Level: developer 8717 8718 .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8719 @*/ 8720 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8721 { 8722 PetscFunctionBegin; 8723 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8724 PetscValidPointer(nullsp, 2); 8725 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8726 PetscFunctionReturn(0); 8727 } 8728 8729 /*@ 8730 MatSetNullSpace - attaches a null space to a matrix. 8731 8732 Logically Collective 8733 8734 Input Parameters: 8735 + mat - the matrix 8736 - nullsp - the null space object 8737 8738 Level: advanced 8739 8740 Notes: 8741 This null space is used by the `KSP` linear solvers to solve singular systems. 8742 8743 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` 8744 8745 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 8746 to zero but the linear system will still be solved in a least squares sense. 8747 8748 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8749 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). 8750 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 8751 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 8752 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). 8753 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8754 8755 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8756 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8757 routine also automatically calls `MatSetTransposeNullSpace()`. 8758 8759 The user should call `MatNullSpaceDestroy()`. 8760 8761 .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8762 `KSPSetPCSide()` 8763 @*/ 8764 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8765 { 8766 PetscFunctionBegin; 8767 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8768 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8769 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8770 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8771 mat->nullsp = nullsp; 8772 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8773 PetscFunctionReturn(0); 8774 } 8775 8776 /*@ 8777 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8778 8779 Logically Collective 8780 8781 Input Parameters: 8782 + mat - the matrix 8783 - nullsp - the null space object 8784 8785 Level: developer 8786 8787 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8788 @*/ 8789 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8790 { 8791 PetscFunctionBegin; 8792 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8793 PetscValidType(mat, 1); 8794 PetscValidPointer(nullsp, 2); 8795 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8796 PetscFunctionReturn(0); 8797 } 8798 8799 /*@ 8800 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8801 8802 Logically Collective 8803 8804 Input Parameters: 8805 + mat - the matrix 8806 - nullsp - the null space object 8807 8808 Level: advanced 8809 8810 Notes: 8811 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8812 8813 See `MatSetNullSpace()` 8814 8815 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8816 @*/ 8817 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8818 { 8819 PetscFunctionBegin; 8820 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8821 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8822 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8823 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8824 mat->transnullsp = nullsp; 8825 PetscFunctionReturn(0); 8826 } 8827 8828 /*@ 8829 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8830 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8831 8832 Logically Collective 8833 8834 Input Parameters: 8835 + mat - the matrix 8836 - nullsp - the null space object 8837 8838 Level: advanced 8839 8840 Notes: 8841 Overwrites any previous near null space that may have been attached 8842 8843 You can remove the null space by calling this routine with an nullsp of `NULL` 8844 8845 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8846 @*/ 8847 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8848 { 8849 PetscFunctionBegin; 8850 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8851 PetscValidType(mat, 1); 8852 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8853 MatCheckPreallocated(mat, 1); 8854 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8855 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8856 mat->nearnullsp = nullsp; 8857 PetscFunctionReturn(0); 8858 } 8859 8860 /*@ 8861 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8862 8863 Not Collective 8864 8865 Input Parameter: 8866 . mat - the matrix 8867 8868 Output Parameter: 8869 . nullsp - the null space object, `NULL` if not set 8870 8871 Level: advanced 8872 8873 .seealso: `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8874 @*/ 8875 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8876 { 8877 PetscFunctionBegin; 8878 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8879 PetscValidType(mat, 1); 8880 PetscValidPointer(nullsp, 2); 8881 MatCheckPreallocated(mat, 1); 8882 *nullsp = mat->nearnullsp; 8883 PetscFunctionReturn(0); 8884 } 8885 8886 /*@C 8887 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8888 8889 Collective 8890 8891 Input Parameters: 8892 + mat - the matrix 8893 . row - row/column permutation 8894 . fill - expected fill factor >= 1.0 8895 - level - level of fill, for ICC(k) 8896 8897 Notes: 8898 Probably really in-place only when level of fill is zero, otherwise allocates 8899 new space to store factored matrix and deletes previous memory. 8900 8901 Most users should employ the `KSP` interface for linear solvers 8902 instead of working directly with matrix algebra routines such as this. 8903 See, e.g., `KSPCreate()`. 8904 8905 Level: developer 8906 8907 Developer Note: 8908 The Fortran interface is not autogenerated as the 8909 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8910 8911 .seealso: `Mat`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8912 @*/ 8913 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8914 { 8915 PetscFunctionBegin; 8916 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8917 PetscValidType(mat, 1); 8918 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8919 PetscValidPointer(info, 3); 8920 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8921 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8922 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8923 MatCheckPreallocated(mat, 1); 8924 PetscUseTypeMethod(mat, iccfactor, row, info); 8925 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8926 PetscFunctionReturn(0); 8927 } 8928 8929 /*@ 8930 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8931 ghosted ones. 8932 8933 Not Collective 8934 8935 Input Parameters: 8936 + mat - the matrix 8937 - diag - the diagonal values, including ghost ones 8938 8939 Level: developer 8940 8941 Notes: 8942 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8943 8944 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8945 8946 .seealso: `Mat`, `MatDiagonalScale()` 8947 @*/ 8948 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8949 { 8950 PetscMPIInt size; 8951 8952 PetscFunctionBegin; 8953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8954 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8955 PetscValidType(mat, 1); 8956 8957 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8958 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8959 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8960 if (size == 1) { 8961 PetscInt n, m; 8962 PetscCall(VecGetSize(diag, &n)); 8963 PetscCall(MatGetSize(mat, NULL, &m)); 8964 if (m == n) { 8965 PetscCall(MatDiagonalScale(mat, NULL, diag)); 8966 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 8967 } else { 8968 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 8969 } 8970 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 8971 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8972 PetscFunctionReturn(0); 8973 } 8974 8975 /*@ 8976 MatGetInertia - Gets the inertia from a factored matrix 8977 8978 Collective 8979 8980 Input Parameter: 8981 . mat - the matrix 8982 8983 Output Parameters: 8984 + nneg - number of negative eigenvalues 8985 . nzero - number of zero eigenvalues 8986 - npos - number of positive eigenvalues 8987 8988 Level: advanced 8989 8990 Note: 8991 Matrix must have been factored by `MatCholeskyFactor()` 8992 8993 .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 8994 @*/ 8995 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 8996 { 8997 PetscFunctionBegin; 8998 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8999 PetscValidType(mat, 1); 9000 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9001 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9002 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9003 PetscFunctionReturn(0); 9004 } 9005 9006 /*@C 9007 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9008 9009 Neighbor-wise Collective 9010 9011 Input Parameters: 9012 + mat - the factored matrix obtained with `MatGetFactor()` 9013 - b - the right-hand-side vectors 9014 9015 Output Parameter: 9016 . x - the result vectors 9017 9018 Level: developer 9019 9020 Note: 9021 The vectors `b` and `x` cannot be the same. I.e., one cannot 9022 call `MatSolves`(A,x,x). 9023 9024 .seealso: `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9025 @*/ 9026 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9027 { 9028 PetscFunctionBegin; 9029 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9030 PetscValidType(mat, 1); 9031 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9032 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9033 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0); 9034 9035 MatCheckPreallocated(mat, 1); 9036 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9037 PetscUseTypeMethod(mat, solves, b, x); 9038 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9039 PetscFunctionReturn(0); 9040 } 9041 9042 /*@ 9043 MatIsSymmetric - Test whether a matrix is symmetric 9044 9045 Collective 9046 9047 Input Parameters: 9048 + A - the matrix to test 9049 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9050 9051 Output Parameters: 9052 . flg - the result 9053 9054 Level: intermediate 9055 9056 Notes: 9057 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9058 9059 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9060 9061 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9062 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9063 9064 .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9065 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9066 @*/ 9067 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9068 { 9069 PetscFunctionBegin; 9070 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9071 PetscValidBoolPointer(flg, 3); 9072 9073 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9074 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9075 else { 9076 if (!A->ops->issymmetric) { 9077 MatType mattype; 9078 PetscCall(MatGetType(A, &mattype)); 9079 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype); 9080 } 9081 PetscUseTypeMethod(A, issymmetric, tol, flg); 9082 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9083 } 9084 PetscFunctionReturn(0); 9085 } 9086 9087 /*@ 9088 MatIsHermitian - Test whether a matrix is Hermitian 9089 9090 Collective on Mat 9091 9092 Input Parameters: 9093 + A - the matrix to test 9094 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9095 9096 Output Parameters: 9097 . flg - the result 9098 9099 Level: intermediate 9100 9101 Notes: 9102 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9103 9104 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9105 9106 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9107 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9108 9109 .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9110 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9111 @*/ 9112 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9113 { 9114 PetscFunctionBegin; 9115 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9116 PetscValidBoolPointer(flg, 3); 9117 9118 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9119 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9120 else { 9121 if (!A->ops->ishermitian) { 9122 MatType mattype; 9123 PetscCall(MatGetType(A, &mattype)); 9124 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype); 9125 } 9126 PetscUseTypeMethod(A, ishermitian, tol, flg); 9127 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9128 } 9129 PetscFunctionReturn(0); 9130 } 9131 9132 /*@ 9133 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9134 9135 Not Collective 9136 9137 Input Parameter: 9138 . A - the matrix to check 9139 9140 Output Parameters: 9141 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9142 - flg - the result (only valid if set is `PETSC_TRUE`) 9143 9144 Level: advanced 9145 9146 Notes: 9147 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9148 if you want it explicitly checked 9149 9150 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9151 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9152 9153 .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9154 @*/ 9155 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9156 { 9157 PetscFunctionBegin; 9158 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9159 PetscValidBoolPointer(set, 2); 9160 PetscValidBoolPointer(flg, 3); 9161 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9162 *set = PETSC_TRUE; 9163 *flg = PetscBool3ToBool(A->symmetric); 9164 } else { 9165 *set = PETSC_FALSE; 9166 } 9167 PetscFunctionReturn(0); 9168 } 9169 9170 /*@ 9171 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9172 9173 Not Collective 9174 9175 Input Parameter: 9176 . A - the matrix to check 9177 9178 Output Parameters: 9179 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9180 - flg - the result (only valid if set is `PETSC_TRUE`) 9181 9182 Level: advanced 9183 9184 Notes: 9185 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9186 9187 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9188 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9189 9190 .seealso: `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9191 @*/ 9192 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9193 { 9194 PetscFunctionBegin; 9195 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9196 PetscValidBoolPointer(set, 2); 9197 PetscValidBoolPointer(flg, 3); 9198 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9199 *set = PETSC_TRUE; 9200 *flg = PetscBool3ToBool(A->spd); 9201 } else { 9202 *set = PETSC_FALSE; 9203 } 9204 PetscFunctionReturn(0); 9205 } 9206 9207 /*@ 9208 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9209 9210 Not Collective 9211 9212 Input Parameter: 9213 . A - the matrix to check 9214 9215 Output Parameters: 9216 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9217 - flg - the result (only valid if set is `PETSC_TRUE`) 9218 9219 Level: advanced 9220 9221 Notes: 9222 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9223 if you want it explicitly checked 9224 9225 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9226 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9227 9228 .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9229 @*/ 9230 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9231 { 9232 PetscFunctionBegin; 9233 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9234 PetscValidBoolPointer(set, 2); 9235 PetscValidBoolPointer(flg, 3); 9236 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9237 *set = PETSC_TRUE; 9238 *flg = PetscBool3ToBool(A->hermitian); 9239 } else { 9240 *set = PETSC_FALSE; 9241 } 9242 PetscFunctionReturn(0); 9243 } 9244 9245 /*@ 9246 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9247 9248 Collective on Mat 9249 9250 Input Parameter: 9251 . A - the matrix to test 9252 9253 Output Parameters: 9254 . flg - the result 9255 9256 Level: intermediate 9257 9258 Notes: 9259 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9260 9261 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 9262 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9263 9264 .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9265 @*/ 9266 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9267 { 9268 PetscFunctionBegin; 9269 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9270 PetscValidBoolPointer(flg, 2); 9271 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9272 *flg = PetscBool3ToBool(A->structurally_symmetric); 9273 } else { 9274 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9275 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9276 } 9277 PetscFunctionReturn(0); 9278 } 9279 9280 /*@ 9281 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9282 9283 Not Collective 9284 9285 Input Parameter: 9286 . A - the matrix to check 9287 9288 Output Parameters: 9289 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9290 - flg - the result (only valid if set is PETSC_TRUE) 9291 9292 Level: advanced 9293 9294 Notes: 9295 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 9296 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9297 9298 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9299 9300 .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9301 @*/ 9302 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9303 { 9304 PetscFunctionBegin; 9305 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9306 PetscValidBoolPointer(set, 2); 9307 PetscValidBoolPointer(flg, 3); 9308 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9309 *set = PETSC_TRUE; 9310 *flg = PetscBool3ToBool(A->structurally_symmetric); 9311 } else { 9312 *set = PETSC_FALSE; 9313 } 9314 PetscFunctionReturn(0); 9315 } 9316 9317 /*@ 9318 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9319 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9320 9321 Not collective 9322 9323 Input Parameter: 9324 . mat - the matrix 9325 9326 Output Parameters: 9327 + nstash - the size of the stash 9328 . reallocs - the number of additional mallocs incurred. 9329 . bnstash - the size of the block stash 9330 - breallocs - the number of additional mallocs incurred.in the block stash 9331 9332 Level: advanced 9333 9334 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9335 @*/ 9336 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9337 { 9338 PetscFunctionBegin; 9339 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9340 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9341 PetscFunctionReturn(0); 9342 } 9343 9344 /*@C 9345 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9346 parallel layout, `PetscLayout` for rows and columns 9347 9348 Collective 9349 9350 Input Parameter: 9351 . mat - the matrix 9352 9353 Output Parameters: 9354 + right - (optional) vector that the matrix can be multiplied against 9355 - left - (optional) vector that the matrix vector product can be stored in 9356 9357 Level: advanced 9358 9359 Notes: 9360 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()`. 9361 9362 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9363 9364 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9365 @*/ 9366 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9367 { 9368 PetscFunctionBegin; 9369 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9370 PetscValidType(mat, 1); 9371 if (mat->ops->getvecs) { 9372 PetscUseTypeMethod(mat, getvecs, right, left); 9373 } else { 9374 PetscInt rbs, cbs; 9375 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9376 if (right) { 9377 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9378 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9379 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9380 PetscCall(VecSetBlockSize(*right, cbs)); 9381 PetscCall(VecSetType(*right, mat->defaultvectype)); 9382 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9383 if (mat->boundtocpu && mat->bindingpropagates) { 9384 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9385 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9386 } 9387 #endif 9388 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9389 } 9390 if (left) { 9391 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9392 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9393 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9394 PetscCall(VecSetBlockSize(*left, rbs)); 9395 PetscCall(VecSetType(*left, mat->defaultvectype)); 9396 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9397 if (mat->boundtocpu && mat->bindingpropagates) { 9398 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9399 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9400 } 9401 #endif 9402 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9403 } 9404 } 9405 PetscFunctionReturn(0); 9406 } 9407 9408 /*@C 9409 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9410 with default values. 9411 9412 Not Collective 9413 9414 Input Parameters: 9415 . info - the `MatFactorInfo` data structure 9416 9417 Level: developer 9418 9419 Notes: 9420 The solvers are generally used through the `KSP` and `PC` objects, for example 9421 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9422 9423 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9424 9425 Developer Note: 9426 The Fortran interface is not autogenerated as the 9427 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9428 9429 .seealso: `Mat`, `MatGetFactor()`, `MatFactorInfo` 9430 @*/ 9431 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9432 { 9433 PetscFunctionBegin; 9434 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9435 PetscFunctionReturn(0); 9436 } 9437 9438 /*@ 9439 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9440 9441 Collective 9442 9443 Input Parameters: 9444 + mat - the factored matrix 9445 - is - the index set defining the Schur indices (0-based) 9446 9447 Level: advanced 9448 9449 Notes: 9450 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9451 9452 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9453 9454 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9455 9456 .seealso: `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9457 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9458 @*/ 9459 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9460 { 9461 PetscErrorCode (*f)(Mat, IS); 9462 9463 PetscFunctionBegin; 9464 PetscValidType(mat, 1); 9465 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9466 PetscValidType(is, 2); 9467 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9468 PetscCheckSameComm(mat, 1, is, 2); 9469 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9470 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9471 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9472 PetscCall(MatDestroy(&mat->schur)); 9473 PetscCall((*f)(mat, is)); 9474 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9475 PetscFunctionReturn(0); 9476 } 9477 9478 /*@ 9479 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9480 9481 Logically Collective 9482 9483 Input Parameters: 9484 + F - the factored matrix obtained by calling `MatGetFactor()` 9485 . S - location where to return the Schur complement, can be `NULL` 9486 - status - the status of the Schur complement matrix, can be `NULL` 9487 9488 Level: advanced 9489 9490 Notes: 9491 You must call `MatFactorSetSchurIS()` before calling this routine. 9492 9493 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9494 9495 The routine provides a copy of the Schur matrix stored within the solver data structures. 9496 The caller must destroy the object when it is no longer needed. 9497 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9498 9499 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) 9500 9501 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9502 9503 Developer Note: 9504 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9505 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9506 9507 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9508 @*/ 9509 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9510 { 9511 PetscFunctionBegin; 9512 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9513 if (S) PetscValidPointer(S, 2); 9514 if (status) PetscValidPointer(status, 3); 9515 if (S) { 9516 PetscErrorCode (*f)(Mat, Mat *); 9517 9518 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9519 if (f) { 9520 PetscCall((*f)(F, S)); 9521 } else { 9522 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9523 } 9524 } 9525 if (status) *status = F->schur_status; 9526 PetscFunctionReturn(0); 9527 } 9528 9529 /*@ 9530 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9531 9532 Logically Collective 9533 9534 Input Parameters: 9535 + F - the factored matrix obtained by calling `MatGetFactor()` 9536 . *S - location where to return the Schur complement, can be `NULL` 9537 - status - the status of the Schur complement matrix, can be `NULL` 9538 9539 Level: advanced 9540 9541 Notes: 9542 You must call `MatFactorSetSchurIS()` before calling this routine. 9543 9544 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9545 9546 The routine returns a the Schur Complement stored within the data structures of the solver. 9547 9548 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9549 9550 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9551 9552 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9553 9554 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9555 9556 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9557 @*/ 9558 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9559 { 9560 PetscFunctionBegin; 9561 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9562 if (S) PetscValidPointer(S, 2); 9563 if (status) PetscValidPointer(status, 3); 9564 if (S) *S = F->schur; 9565 if (status) *status = F->schur_status; 9566 PetscFunctionReturn(0); 9567 } 9568 9569 /*@ 9570 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9571 9572 Logically Collective 9573 9574 Input Parameters: 9575 + F - the factored matrix obtained by calling `MatGetFactor()` 9576 . *S - location where the Schur complement is stored 9577 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9578 9579 Level: advanced 9580 9581 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9582 @*/ 9583 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9584 { 9585 PetscFunctionBegin; 9586 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9587 if (S) { 9588 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9589 *S = NULL; 9590 } 9591 F->schur_status = status; 9592 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9593 PetscFunctionReturn(0); 9594 } 9595 9596 /*@ 9597 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9598 9599 Logically Collective 9600 9601 Input Parameters: 9602 + F - the factored matrix obtained by calling `MatGetFactor()` 9603 . rhs - location where the right hand side of the Schur complement system is stored 9604 - sol - location where the solution of the Schur complement system has to be returned 9605 9606 Level: advanced 9607 9608 Notes: 9609 The sizes of the vectors should match the size of the Schur complement 9610 9611 Must be called after `MatFactorSetSchurIS()` 9612 9613 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9614 @*/ 9615 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9616 { 9617 PetscFunctionBegin; 9618 PetscValidType(F, 1); 9619 PetscValidType(rhs, 2); 9620 PetscValidType(sol, 3); 9621 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9622 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9623 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9624 PetscCheckSameComm(F, 1, rhs, 2); 9625 PetscCheckSameComm(F, 1, sol, 3); 9626 PetscCall(MatFactorFactorizeSchurComplement(F)); 9627 switch (F->schur_status) { 9628 case MAT_FACTOR_SCHUR_FACTORED: 9629 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9630 break; 9631 case MAT_FACTOR_SCHUR_INVERTED: 9632 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9633 break; 9634 default: 9635 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9636 } 9637 PetscFunctionReturn(0); 9638 } 9639 9640 /*@ 9641 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9642 9643 Logically Collective 9644 9645 Input Parameters: 9646 + F - the factored matrix obtained by calling `MatGetFactor()` 9647 . rhs - location where the right hand side of the Schur complement system is stored 9648 - sol - location where the solution of the Schur complement system has to be returned 9649 9650 Level: advanced 9651 9652 Notes: 9653 The sizes of the vectors should match the size of the Schur complement 9654 9655 Must be called after `MatFactorSetSchurIS()` 9656 9657 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9658 @*/ 9659 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9660 { 9661 PetscFunctionBegin; 9662 PetscValidType(F, 1); 9663 PetscValidType(rhs, 2); 9664 PetscValidType(sol, 3); 9665 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9666 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9667 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9668 PetscCheckSameComm(F, 1, rhs, 2); 9669 PetscCheckSameComm(F, 1, sol, 3); 9670 PetscCall(MatFactorFactorizeSchurComplement(F)); 9671 switch (F->schur_status) { 9672 case MAT_FACTOR_SCHUR_FACTORED: 9673 PetscCall(MatSolve(F->schur, rhs, sol)); 9674 break; 9675 case MAT_FACTOR_SCHUR_INVERTED: 9676 PetscCall(MatMult(F->schur, rhs, sol)); 9677 break; 9678 default: 9679 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9680 } 9681 PetscFunctionReturn(0); 9682 } 9683 9684 /*@ 9685 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9686 9687 Logically Collective on F 9688 9689 Input Parameters: 9690 . F - the factored matrix obtained by calling `MatGetFactor()` 9691 9692 Level: advanced 9693 9694 Notes: 9695 Must be called after `MatFactorSetSchurIS()`. 9696 9697 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9698 9699 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9700 @*/ 9701 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9702 { 9703 PetscFunctionBegin; 9704 PetscValidType(F, 1); 9705 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9706 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0); 9707 PetscCall(MatFactorFactorizeSchurComplement(F)); 9708 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9709 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9710 PetscFunctionReturn(0); 9711 } 9712 9713 /*@ 9714 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9715 9716 Logically Collective 9717 9718 Input Parameters: 9719 . F - the factored matrix obtained by calling `MatGetFactor()` 9720 9721 Level: advanced 9722 9723 Note: 9724 Must be called after `MatFactorSetSchurIS()` 9725 9726 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9727 @*/ 9728 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9729 { 9730 PetscFunctionBegin; 9731 PetscValidType(F, 1); 9732 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9733 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0); 9734 PetscCall(MatFactorFactorizeSchurComplement_Private(F)); 9735 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9736 PetscFunctionReturn(0); 9737 } 9738 9739 /*@ 9740 MatPtAP - Creates the matrix product C = P^T * A * P 9741 9742 Neighbor-wise Collective 9743 9744 Input Parameters: 9745 + A - the matrix 9746 . P - the projection matrix 9747 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9748 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9749 if the result is a dense matrix this is irrelevant 9750 9751 Output Parameters: 9752 . C - the product matrix 9753 9754 Level: intermediate 9755 9756 Notes: 9757 C will be created and must be destroyed by the user with `MatDestroy()`. 9758 9759 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9760 9761 Developer Note: 9762 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9763 9764 .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9765 @*/ 9766 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9767 { 9768 PetscFunctionBegin; 9769 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9770 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9771 9772 if (scall == MAT_INITIAL_MATRIX) { 9773 PetscCall(MatProductCreate(A, P, NULL, C)); 9774 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9775 PetscCall(MatProductSetAlgorithm(*C, "default")); 9776 PetscCall(MatProductSetFill(*C, fill)); 9777 9778 (*C)->product->api_user = PETSC_TRUE; 9779 PetscCall(MatProductSetFromOptions(*C)); 9780 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); 9781 PetscCall(MatProductSymbolic(*C)); 9782 } else { /* scall == MAT_REUSE_MATRIX */ 9783 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9784 } 9785 9786 PetscCall(MatProductNumeric(*C)); 9787 (*C)->symmetric = A->symmetric; 9788 (*C)->spd = A->spd; 9789 PetscFunctionReturn(0); 9790 } 9791 9792 /*@ 9793 MatRARt - Creates the matrix product C = R * A * R^T 9794 9795 Neighbor-wise Collective 9796 9797 Input Parameters: 9798 + A - the matrix 9799 . R - the projection matrix 9800 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9801 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9802 if the result is a dense matrix this is irrelevant 9803 9804 Output Parameters: 9805 . C - the product matrix 9806 9807 Level: intermediate 9808 9809 Notes: 9810 C will be created and must be destroyed by the user with `MatDestroy()`. 9811 9812 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9813 9814 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9815 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9816 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9817 We recommend using MatPtAP(). 9818 9819 .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9820 @*/ 9821 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9822 { 9823 PetscFunctionBegin; 9824 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9825 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9826 9827 if (scall == MAT_INITIAL_MATRIX) { 9828 PetscCall(MatProductCreate(A, R, NULL, C)); 9829 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9830 PetscCall(MatProductSetAlgorithm(*C, "default")); 9831 PetscCall(MatProductSetFill(*C, fill)); 9832 9833 (*C)->product->api_user = PETSC_TRUE; 9834 PetscCall(MatProductSetFromOptions(*C)); 9835 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); 9836 PetscCall(MatProductSymbolic(*C)); 9837 } else { /* scall == MAT_REUSE_MATRIX */ 9838 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9839 } 9840 9841 PetscCall(MatProductNumeric(*C)); 9842 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9843 PetscFunctionReturn(0); 9844 } 9845 9846 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9847 { 9848 PetscFunctionBegin; 9849 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9850 9851 if (scall == MAT_INITIAL_MATRIX) { 9852 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9853 PetscCall(MatProductCreate(A, B, NULL, C)); 9854 PetscCall(MatProductSetType(*C, ptype)); 9855 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9856 PetscCall(MatProductSetFill(*C, fill)); 9857 9858 (*C)->product->api_user = PETSC_TRUE; 9859 PetscCall(MatProductSetFromOptions(*C)); 9860 PetscCall(MatProductSymbolic(*C)); 9861 } else { /* scall == MAT_REUSE_MATRIX */ 9862 Mat_Product *product = (*C)->product; 9863 PetscBool isdense; 9864 9865 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9866 if (isdense && product && product->type != ptype) { 9867 PetscCall(MatProductClear(*C)); 9868 product = NULL; 9869 } 9870 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9871 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9872 if (isdense) { 9873 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9874 product = (*C)->product; 9875 product->fill = fill; 9876 product->api_user = PETSC_TRUE; 9877 product->clear = PETSC_TRUE; 9878 9879 PetscCall(MatProductSetType(*C, ptype)); 9880 PetscCall(MatProductSetFromOptions(*C)); 9881 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); 9882 PetscCall(MatProductSymbolic(*C)); 9883 } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9884 } else { /* user may change input matrices A or B when REUSE */ 9885 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9886 } 9887 } 9888 PetscCall(MatProductNumeric(*C)); 9889 PetscFunctionReturn(0); 9890 } 9891 9892 /*@ 9893 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9894 9895 Neighbor-wise Collective 9896 9897 Input Parameters: 9898 + A - the left matrix 9899 . B - the right matrix 9900 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9901 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9902 if the result is a dense matrix this is irrelevant 9903 9904 Output Parameters: 9905 . C - the product matrix 9906 9907 Notes: 9908 Unless scall is `MAT_REUSE_MATRIX` C will be created. 9909 9910 `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 9911 call to this function with `MAT_INITIAL_MATRIX`. 9912 9913 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 9914 9915 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`, 9916 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 9917 9918 Example of Usage: 9919 .vb 9920 MatProductCreate(A,B,NULL,&C); 9921 MatProductSetType(C,MATPRODUCT_AB); 9922 MatProductSymbolic(C); 9923 MatProductNumeric(C); // compute C=A * B 9924 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 9925 MatProductNumeric(C); 9926 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 9927 MatProductNumeric(C); 9928 .ve 9929 9930 Level: intermediate 9931 9932 .seealso: `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 9933 @*/ 9934 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9935 { 9936 PetscFunctionBegin; 9937 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 9938 PetscFunctionReturn(0); 9939 } 9940 9941 /*@ 9942 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 9943 9944 Neighbor-wise Collective 9945 9946 Input Parameters: 9947 + A - the left matrix 9948 . B - the right matrix 9949 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9950 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9951 9952 Output Parameters: 9953 . C - the product matrix 9954 9955 Level: intermediate 9956 9957 Notes: 9958 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 9959 9960 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 9961 9962 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 9963 actually needed. 9964 9965 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 9966 and for pairs of `MATMPIDENSE` matrices. 9967 9968 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 9969 9970 Options Database Keys: 9971 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 9972 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 9973 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 9974 9975 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 9976 @*/ 9977 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9978 { 9979 PetscFunctionBegin; 9980 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 9981 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9982 PetscFunctionReturn(0); 9983 } 9984 9985 /*@ 9986 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 9987 9988 Neighbor-wise Collective 9989 9990 Input Parameters: 9991 + A - the left matrix 9992 . B - the right matrix 9993 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9994 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9995 9996 Output Parameters: 9997 . C - the product matrix 9998 9999 Level: intermediate 10000 10001 Notes: 10002 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10003 10004 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10005 10006 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10007 10008 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10009 actually needed. 10010 10011 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10012 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10013 10014 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10015 @*/ 10016 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10017 { 10018 PetscFunctionBegin; 10019 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10020 PetscFunctionReturn(0); 10021 } 10022 10023 /*@ 10024 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10025 10026 Neighbor-wise Collective 10027 10028 Input Parameters: 10029 + A - the left matrix 10030 . B - the middle matrix 10031 . C - the right matrix 10032 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10033 - 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 10034 if the result is a dense matrix this is irrelevant 10035 10036 Output Parameters: 10037 . D - the product matrix 10038 10039 Level: intermediate 10040 10041 Notes: 10042 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10043 10044 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10045 10046 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10047 10048 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10049 actually needed. 10050 10051 If you have many matrices with the same non-zero structure to multiply, you 10052 should use `MAT_REUSE_MATRIX` in all calls but the first 10053 10054 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10055 @*/ 10056 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10057 { 10058 PetscFunctionBegin; 10059 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10060 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10061 10062 if (scall == MAT_INITIAL_MATRIX) { 10063 PetscCall(MatProductCreate(A, B, C, D)); 10064 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10065 PetscCall(MatProductSetAlgorithm(*D, "default")); 10066 PetscCall(MatProductSetFill(*D, fill)); 10067 10068 (*D)->product->api_user = PETSC_TRUE; 10069 PetscCall(MatProductSetFromOptions(*D)); 10070 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, 10071 ((PetscObject)C)->type_name); 10072 PetscCall(MatProductSymbolic(*D)); 10073 } else { /* user may change input matrices when REUSE */ 10074 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10075 } 10076 PetscCall(MatProductNumeric(*D)); 10077 PetscFunctionReturn(0); 10078 } 10079 10080 /*@ 10081 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10082 10083 Collective 10084 10085 Input Parameters: 10086 + mat - the matrix 10087 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10088 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10089 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10090 10091 Output Parameter: 10092 . matredundant - redundant matrix 10093 10094 Level: advanced 10095 10096 Notes: 10097 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10098 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10099 10100 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10101 calling it. 10102 10103 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10104 10105 .seealso: `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10106 @*/ 10107 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10108 { 10109 MPI_Comm comm; 10110 PetscMPIInt size; 10111 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10112 Mat_Redundant *redund = NULL; 10113 PetscSubcomm psubcomm = NULL; 10114 MPI_Comm subcomm_in = subcomm; 10115 Mat *matseq; 10116 IS isrow, iscol; 10117 PetscBool newsubcomm = PETSC_FALSE; 10118 10119 PetscFunctionBegin; 10120 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10121 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10122 PetscValidPointer(*matredundant, 5); 10123 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10124 } 10125 10126 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10127 if (size == 1 || nsubcomm == 1) { 10128 if (reuse == MAT_INITIAL_MATRIX) { 10129 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10130 } else { 10131 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"); 10132 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10133 } 10134 PetscFunctionReturn(0); 10135 } 10136 10137 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10138 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10139 MatCheckPreallocated(mat, 1); 10140 10141 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10142 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10143 /* create psubcomm, then get subcomm */ 10144 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10145 PetscCallMPI(MPI_Comm_size(comm, &size)); 10146 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10147 10148 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10149 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10150 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10151 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10152 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10153 newsubcomm = PETSC_TRUE; 10154 PetscCall(PetscSubcommDestroy(&psubcomm)); 10155 } 10156 10157 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10158 if (reuse == MAT_INITIAL_MATRIX) { 10159 mloc_sub = PETSC_DECIDE; 10160 nloc_sub = PETSC_DECIDE; 10161 if (bs < 1) { 10162 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10163 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10164 } else { 10165 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10166 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10167 } 10168 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10169 rstart = rend - mloc_sub; 10170 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10171 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10172 } else { /* reuse == MAT_REUSE_MATRIX */ 10173 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"); 10174 /* retrieve subcomm */ 10175 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10176 redund = (*matredundant)->redundant; 10177 isrow = redund->isrow; 10178 iscol = redund->iscol; 10179 matseq = redund->matseq; 10180 } 10181 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10182 10183 /* get matredundant over subcomm */ 10184 if (reuse == MAT_INITIAL_MATRIX) { 10185 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10186 10187 /* create a supporting struct and attach it to C for reuse */ 10188 PetscCall(PetscNew(&redund)); 10189 (*matredundant)->redundant = redund; 10190 redund->isrow = isrow; 10191 redund->iscol = iscol; 10192 redund->matseq = matseq; 10193 if (newsubcomm) { 10194 redund->subcomm = subcomm; 10195 } else { 10196 redund->subcomm = MPI_COMM_NULL; 10197 } 10198 } else { 10199 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10200 } 10201 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10202 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10203 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10204 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10205 } 10206 #endif 10207 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10208 PetscFunctionReturn(0); 10209 } 10210 10211 /*@C 10212 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10213 a given `Mat`. Each submatrix can span multiple procs. 10214 10215 Collective 10216 10217 Input Parameters: 10218 + mat - the matrix 10219 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10220 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10221 10222 Output Parameter: 10223 . subMat - parallel sub-matrices each spanning a given `subcomm` 10224 10225 Level: advanced 10226 10227 Notes: 10228 The submatrix partition across processors is dictated by `subComm` a 10229 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10230 is not restricted to be grouped with consecutive original ranks. 10231 10232 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10233 map directly to the layout of the original matrix [wrt the local 10234 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10235 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10236 the `subMat`. However the offDiagMat looses some columns - and this is 10237 reconstructed with `MatSetValues()` 10238 10239 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10240 10241 .seealso: `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10242 @*/ 10243 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10244 { 10245 PetscMPIInt commsize, subCommSize; 10246 10247 PetscFunctionBegin; 10248 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10249 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10250 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10251 10252 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"); 10253 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10254 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10255 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10256 PetscFunctionReturn(0); 10257 } 10258 10259 /*@ 10260 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10261 10262 Not Collective 10263 10264 Input Parameters: 10265 + mat - matrix to extract local submatrix from 10266 . isrow - local row indices for submatrix 10267 - iscol - local column indices for submatrix 10268 10269 Output Parameter: 10270 . submat - the submatrix 10271 10272 Level: intermediate 10273 10274 Notes: 10275 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10276 10277 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10278 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10279 10280 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10281 `MatSetValuesBlockedLocal()` will also be implemented. 10282 10283 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10284 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10285 10286 .seealso: `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10287 @*/ 10288 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10289 { 10290 PetscFunctionBegin; 10291 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10292 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10293 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10294 PetscCheckSameComm(isrow, 2, iscol, 3); 10295 PetscValidPointer(submat, 4); 10296 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10297 10298 if (mat->ops->getlocalsubmatrix) { 10299 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10300 } else { 10301 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10302 } 10303 PetscFunctionReturn(0); 10304 } 10305 10306 /*@ 10307 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10308 10309 Not Collective 10310 10311 Input Parameters: 10312 + mat - matrix to extract local submatrix from 10313 . isrow - local row indices for submatrix 10314 . iscol - local column indices for submatrix 10315 - submat - the submatrix 10316 10317 Level: intermediate 10318 10319 .seealso: `Mat`, `MatGetLocalSubMatrix()` 10320 @*/ 10321 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10322 { 10323 PetscFunctionBegin; 10324 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10325 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10326 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10327 PetscCheckSameComm(isrow, 2, iscol, 3); 10328 PetscValidPointer(submat, 4); 10329 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10330 10331 if (mat->ops->restorelocalsubmatrix) { 10332 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10333 } else { 10334 PetscCall(MatDestroy(submat)); 10335 } 10336 *submat = NULL; 10337 PetscFunctionReturn(0); 10338 } 10339 10340 /*@ 10341 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10342 10343 Collective 10344 10345 Input Parameter: 10346 . mat - the matrix 10347 10348 Output Parameter: 10349 . is - if any rows have zero diagonals this contains the list of them 10350 10351 Level: developer 10352 10353 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10354 @*/ 10355 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10356 { 10357 PetscFunctionBegin; 10358 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10359 PetscValidType(mat, 1); 10360 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10361 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10362 10363 if (!mat->ops->findzerodiagonals) { 10364 Vec diag; 10365 const PetscScalar *a; 10366 PetscInt *rows; 10367 PetscInt rStart, rEnd, r, nrow = 0; 10368 10369 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10370 PetscCall(MatGetDiagonal(mat, diag)); 10371 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10372 PetscCall(VecGetArrayRead(diag, &a)); 10373 for (r = 0; r < rEnd - rStart; ++r) 10374 if (a[r] == 0.0) ++nrow; 10375 PetscCall(PetscMalloc1(nrow, &rows)); 10376 nrow = 0; 10377 for (r = 0; r < rEnd - rStart; ++r) 10378 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10379 PetscCall(VecRestoreArrayRead(diag, &a)); 10380 PetscCall(VecDestroy(&diag)); 10381 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10382 } else { 10383 PetscUseTypeMethod(mat, findzerodiagonals, is); 10384 } 10385 PetscFunctionReturn(0); 10386 } 10387 10388 /*@ 10389 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10390 10391 Collective 10392 10393 Input Parameter: 10394 . mat - the matrix 10395 10396 Output Parameter: 10397 . is - contains the list of rows with off block diagonal entries 10398 10399 Level: developer 10400 10401 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10402 @*/ 10403 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10404 { 10405 PetscFunctionBegin; 10406 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10407 PetscValidType(mat, 1); 10408 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10409 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10410 10411 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10412 PetscFunctionReturn(0); 10413 } 10414 10415 /*@C 10416 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10417 10418 Collective; No Fortran Support 10419 10420 Input Parameters: 10421 . mat - the matrix 10422 10423 Output Parameters: 10424 . values - the block inverses in column major order (FORTRAN-like) 10425 10426 Level: advanced 10427 10428 Notes: 10429 The size of the blocks is determined by the block size of the matrix. 10430 10431 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10432 10433 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10434 10435 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10436 @*/ 10437 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const 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, invertblockdiagonal, values); 10444 PetscFunctionReturn(0); 10445 } 10446 10447 /*@C 10448 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10449 10450 Collective; No Fortran Support 10451 10452 Input Parameters: 10453 + mat - the matrix 10454 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10455 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10456 10457 Output Parameters: 10458 . values - the block inverses in column major order (FORTRAN-like) 10459 10460 Level: advanced 10461 10462 Notes: 10463 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10464 10465 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10466 10467 .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10468 @*/ 10469 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10470 { 10471 PetscFunctionBegin; 10472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10473 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10474 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10475 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10476 PetscFunctionReturn(0); 10477 } 10478 10479 /*@ 10480 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10481 10482 Collective on Mat 10483 10484 Input Parameters: 10485 + A - the matrix 10486 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10487 10488 Level: advanced 10489 10490 Note: 10491 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10492 10493 .seealso: `Mat`, `MatInvertBlockDiagonal()` 10494 @*/ 10495 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10496 { 10497 const PetscScalar *vals; 10498 PetscInt *dnnz; 10499 PetscInt m, rstart, rend, bs, i, j; 10500 10501 PetscFunctionBegin; 10502 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10503 PetscCall(MatGetBlockSize(A, &bs)); 10504 PetscCall(MatGetLocalSize(A, &m, NULL)); 10505 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10506 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10507 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10508 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10509 PetscCall(PetscFree(dnnz)); 10510 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10511 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10512 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10513 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10514 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10515 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10516 PetscFunctionReturn(0); 10517 } 10518 10519 /*@C 10520 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10521 via `MatTransposeColoringCreate()`. 10522 10523 Collective on c 10524 10525 Input Parameter: 10526 . c - coloring context 10527 10528 Level: intermediate 10529 10530 .seealso: `Mat`, `MatTransposeColoringCreate()` 10531 @*/ 10532 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10533 { 10534 MatTransposeColoring matcolor = *c; 10535 10536 PetscFunctionBegin; 10537 if (!matcolor) PetscFunctionReturn(0); 10538 if (--((PetscObject)matcolor)->refct > 0) { 10539 matcolor = NULL; 10540 PetscFunctionReturn(0); 10541 } 10542 10543 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10544 PetscCall(PetscFree(matcolor->rows)); 10545 PetscCall(PetscFree(matcolor->den2sp)); 10546 PetscCall(PetscFree(matcolor->colorforcol)); 10547 PetscCall(PetscFree(matcolor->columns)); 10548 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10549 PetscCall(PetscHeaderDestroy(c)); 10550 PetscFunctionReturn(0); 10551 } 10552 10553 /*@C 10554 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10555 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10556 `MatTransposeColoring` to sparse B. 10557 10558 Collective on coloring 10559 10560 Input Parameters: 10561 + B - sparse matrix B 10562 . Btdense - symbolic dense matrix B^T 10563 - coloring - coloring context created with `MatTransposeColoringCreate()` 10564 10565 Output Parameter: 10566 . Btdense - dense matrix B^T 10567 10568 Level: developer 10569 10570 Note: 10571 These are used internally for some implementations of `MatRARt()` 10572 10573 .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10574 @*/ 10575 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10576 { 10577 PetscFunctionBegin; 10578 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10579 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10580 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10581 10582 PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10583 PetscFunctionReturn(0); 10584 } 10585 10586 /*@C 10587 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10588 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10589 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10590 Csp from Cden. 10591 10592 Collective 10593 10594 Input Parameters: 10595 + coloring - coloring context created with `MatTransposeColoringCreate()` 10596 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10597 10598 Output Parameter: 10599 . Csp - sparse matrix 10600 10601 Level: developer 10602 10603 Note: 10604 These are used internally for some implementations of `MatRARt()` 10605 10606 .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10607 @*/ 10608 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10609 { 10610 PetscFunctionBegin; 10611 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10612 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10613 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10614 10615 PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10616 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10617 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10618 PetscFunctionReturn(0); 10619 } 10620 10621 /*@C 10622 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10623 10624 Collective 10625 10626 Input Parameters: 10627 + mat - the matrix product C 10628 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10629 10630 Output Parameter: 10631 . color - the new coloring context 10632 10633 Level: intermediate 10634 10635 .seealso: `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10636 `MatTransColoringApplyDenToSp()` 10637 @*/ 10638 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10639 { 10640 MatTransposeColoring c; 10641 MPI_Comm comm; 10642 10643 PetscFunctionBegin; 10644 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10645 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10646 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10647 10648 c->ctype = iscoloring->ctype; 10649 if (mat->ops->transposecoloringcreate) { 10650 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10651 } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name); 10652 10653 *color = c; 10654 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10655 PetscFunctionReturn(0); 10656 } 10657 10658 /*@ 10659 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10660 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10661 same, otherwise it will be larger 10662 10663 Not Collective 10664 10665 Input Parameter: 10666 . A - the matrix 10667 10668 Output Parameter: 10669 . state - the current state 10670 10671 Level: intermediate 10672 10673 Notes: 10674 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10675 different matrices 10676 10677 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10678 10679 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10680 10681 .seealso: `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10682 @*/ 10683 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10684 { 10685 PetscFunctionBegin; 10686 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10687 *state = mat->nonzerostate; 10688 PetscFunctionReturn(0); 10689 } 10690 10691 /*@ 10692 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10693 matrices from each processor 10694 10695 Collective 10696 10697 Input Parameters: 10698 + comm - the communicators the parallel matrix will live on 10699 . seqmat - the input sequential matrices 10700 . n - number of local columns (or `PETSC_DECIDE`) 10701 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10702 10703 Output Parameter: 10704 . mpimat - the parallel matrix generated 10705 10706 Level: developer 10707 10708 Note: 10709 The number of columns of the matrix in EACH processor MUST be the same. 10710 10711 .seealso: `Mat` 10712 @*/ 10713 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10714 { 10715 PetscMPIInt size; 10716 10717 PetscFunctionBegin; 10718 PetscCallMPI(MPI_Comm_size(comm, &size)); 10719 if (size == 1) { 10720 if (reuse == MAT_INITIAL_MATRIX) { 10721 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10722 } else { 10723 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10724 } 10725 PetscFunctionReturn(0); 10726 } 10727 10728 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"); 10729 10730 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10731 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10732 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10733 PetscFunctionReturn(0); 10734 } 10735 10736 /*@ 10737 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10738 10739 Collective 10740 10741 Input Parameters: 10742 + A - the matrix to create subdomains from 10743 - N - requested number of subdomains 10744 10745 Output Parameters: 10746 + n - number of subdomains resulting on this rank 10747 - iss - `IS` list with indices of subdomains on this rank 10748 10749 Level: advanced 10750 10751 Note: 10752 The number of subdomains must be smaller than the communicator size 10753 10754 .seealso: `Mat`, `IS` 10755 @*/ 10756 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10757 { 10758 MPI_Comm comm, subcomm; 10759 PetscMPIInt size, rank, color; 10760 PetscInt rstart, rend, k; 10761 10762 PetscFunctionBegin; 10763 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10764 PetscCallMPI(MPI_Comm_size(comm, &size)); 10765 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10766 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); 10767 *n = 1; 10768 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10769 color = rank / k; 10770 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10771 PetscCall(PetscMalloc1(1, iss)); 10772 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10773 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10774 PetscCallMPI(MPI_Comm_free(&subcomm)); 10775 PetscFunctionReturn(0); 10776 } 10777 10778 /*@ 10779 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10780 10781 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10782 If they are not the same, uses `MatMatMatMult()`. 10783 10784 Once the coarse grid problem is constructed, correct for interpolation operators 10785 that are not of full rank, which can legitimately happen in the case of non-nested 10786 geometric multigrid. 10787 10788 Input Parameters: 10789 + restrct - restriction operator 10790 . dA - fine grid matrix 10791 . interpolate - interpolation operator 10792 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10793 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10794 10795 Output Parameters: 10796 . A - the Galerkin coarse matrix 10797 10798 Options Database Key: 10799 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10800 10801 Level: developer 10802 10803 .seealso: `Mat`, `MatPtAP()`, `MatMatMatMult()` 10804 @*/ 10805 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10806 { 10807 IS zerorows; 10808 Vec diag; 10809 10810 PetscFunctionBegin; 10811 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10812 /* Construct the coarse grid matrix */ 10813 if (interpolate == restrct) { 10814 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10815 } else { 10816 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10817 } 10818 10819 /* If the interpolation matrix is not of full rank, A will have zero rows. 10820 This can legitimately happen in the case of non-nested geometric multigrid. 10821 In that event, we set the rows of the matrix to the rows of the identity, 10822 ignoring the equations (as the RHS will also be zero). */ 10823 10824 PetscCall(MatFindZeroRows(*A, &zerorows)); 10825 10826 if (zerorows != NULL) { /* if there are any zero rows */ 10827 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10828 PetscCall(MatGetDiagonal(*A, diag)); 10829 PetscCall(VecISSet(diag, zerorows, 1.0)); 10830 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10831 PetscCall(VecDestroy(&diag)); 10832 PetscCall(ISDestroy(&zerorows)); 10833 } 10834 PetscFunctionReturn(0); 10835 } 10836 10837 /*@C 10838 MatSetOperation - Allows user to set a matrix operation for any matrix type 10839 10840 Logically Collective 10841 10842 Input Parameters: 10843 + mat - the matrix 10844 . op - the name of the operation 10845 - f - the function that provides the operation 10846 10847 Level: developer 10848 10849 Usage: 10850 .vb 10851 extern PetscErrorCode usermult(Mat, Vec, Vec); 10852 10853 PetscCall(MatCreateXXX(comm, ..., &A)); 10854 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10855 .ve 10856 10857 Notes: 10858 See the file `include/petscmat.h` for a complete list of matrix 10859 operations, which all have the form MATOP_<OPERATION>, where 10860 <OPERATION> is the name (in all capital letters) of the 10861 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10862 10863 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10864 sequence as the usual matrix interface routines, since they 10865 are intended to be accessed via the usual matrix interface 10866 routines, e.g., 10867 .vb 10868 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10869 .ve 10870 10871 In particular each function MUST return `PETSC_SUCCESS` on success and 10872 nonzero on failure. 10873 10874 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10875 10876 .seealso: `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10877 @*/ 10878 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10879 { 10880 PetscFunctionBegin; 10881 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10882 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10883 (((void (**)(void))mat->ops)[op]) = f; 10884 PetscFunctionReturn(0); 10885 } 10886 10887 /*@C 10888 MatGetOperation - Gets a matrix operation for any matrix type. 10889 10890 Not Collective 10891 10892 Input Parameters: 10893 + mat - the matrix 10894 - op - the name of the operation 10895 10896 Output Parameter: 10897 . f - the function that provides the operation 10898 10899 Level: developer 10900 10901 Usage: 10902 $ PetscErrorCode (*usermult)(Mat,Vec,Vec); 10903 $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult); 10904 10905 Notes: 10906 See the file include/petscmat.h for a complete list of matrix 10907 operations, which all have the form MATOP_<OPERATION>, where 10908 <OPERATION> is the name (in all capital letters) of the 10909 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10910 10911 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 10912 10913 .seealso: `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 10914 @*/ 10915 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 10916 { 10917 PetscFunctionBegin; 10918 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10919 *f = (((void (**)(void))mat->ops)[op]); 10920 PetscFunctionReturn(0); 10921 } 10922 10923 /*@ 10924 MatHasOperation - Determines whether the given matrix supports the particular operation. 10925 10926 Not Collective 10927 10928 Input Parameters: 10929 + mat - the matrix 10930 - op - the operation, for example, `MATOP_GET_DIAGONAL` 10931 10932 Output Parameter: 10933 . has - either `PETSC_TRUE` or `PETSC_FALSE` 10934 10935 Level: advanced 10936 10937 Note: 10938 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 10939 10940 .seealso: `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 10941 @*/ 10942 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 10943 { 10944 PetscFunctionBegin; 10945 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10946 PetscValidBoolPointer(has, 3); 10947 if (mat->ops->hasoperation) { 10948 PetscUseTypeMethod(mat, hasoperation, op, has); 10949 } else { 10950 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 10951 else { 10952 *has = PETSC_FALSE; 10953 if (op == MATOP_CREATE_SUBMATRIX) { 10954 PetscMPIInt size; 10955 10956 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10957 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 10958 } 10959 } 10960 } 10961 PetscFunctionReturn(0); 10962 } 10963 10964 /*@ 10965 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 10966 10967 Collective 10968 10969 Input Parameters: 10970 . mat - the matrix 10971 10972 Output Parameter: 10973 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 10974 10975 Level: beginner 10976 10977 .seealso: `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 10978 @*/ 10979 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 10980 { 10981 PetscFunctionBegin; 10982 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10983 PetscValidType(mat, 1); 10984 PetscValidBoolPointer(cong, 2); 10985 if (!mat->rmap || !mat->cmap) { 10986 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 10987 PetscFunctionReturn(0); 10988 } 10989 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 10990 PetscCall(PetscLayoutSetUp(mat->rmap)); 10991 PetscCall(PetscLayoutSetUp(mat->cmap)); 10992 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 10993 if (*cong) mat->congruentlayouts = 1; 10994 else mat->congruentlayouts = 0; 10995 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 10996 PetscFunctionReturn(0); 10997 } 10998 10999 PetscErrorCode MatSetInf(Mat A) 11000 { 11001 PetscFunctionBegin; 11002 PetscUseTypeMethod(A, setinf); 11003 PetscFunctionReturn(0); 11004 } 11005 11006 /*C 11007 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 11008 and possibly removes small values from the graph structure. 11009 11010 Collective 11011 11012 Input Parameters: 11013 + A - the matrix 11014 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11015 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11016 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11017 11018 Output Parameter: 11019 . graph - the resulting graph 11020 11021 Level: advanced 11022 11023 .seealso: `Mat`, `MatCreate()`, `PCGAMG` 11024 */ 11025 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11026 { 11027 PetscFunctionBegin; 11028 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11029 PetscValidType(A, 1); 11030 PetscValidPointer(graph, 3); 11031 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11032 PetscFunctionReturn(0); 11033 } 11034