-
Notifications
You must be signed in to change notification settings - Fork 104
Snes with constrains #3251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Snes with constrains #3251
Conversation
…on of algebraic equations. For now it is only supported by backward_euler option. We will modify the rest of the options later.
…ork with petsc vectors instead of bout++ variables. I added an option to split the preconditioner so that the user can use a different PC_type for the algebraic equation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang-tidy made some suggestions
| if (have_constraints) { | ||
| // CreatePETSc-native index sets representing the two parts of your DAE. | ||
| PetscInt istart, iend; | ||
| PetscCall(VecGetOwnershipRange(snes_x, &istart, &iend)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: multiple declarations in a single statement reduces readability [readability-isolate-declaration]
| PetscCall(VecGetOwnershipRange(snes_x, &istart, &iend)); | |
| PetscInt istart; | |
| PetscInt iend; |
| if (have_constraints) { | ||
| // CreatePETSc-native index sets representing the two parts of your DAE. | ||
| PetscInt istart, iend; | ||
| PetscCall(VecGetOwnershipRange(snes_x, &istart, &iend)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: variable 'iend' is not initialized [cppcoreguidelines-init-variables]
PetscInt istart, iend;
^this fix will not be applied because it overlaps with another fix
| if (have_constraints) { | ||
| // CreatePETSc-native index sets representing the two parts of your DAE. | ||
| PetscInt istart, iend; | ||
| PetscCall(VecGetOwnershipRange(snes_x, &istart, &iend)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: variable 'istart' is not initialized [cppcoreguidelines-init-variables]
PetscInt istart, iend;
^this fix will not be applied because it overlaps with another fix
| } | ||
|
|
||
| PetscCall(ISCreateGeneral(BoutComm::get(), diff_idx.size(), diff_idx.data(), | ||
| PETSC_COPY_VALUES, &is_diff)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: no header providing "ISCreateGeneral" is directly included [misc-include-cleaner]
src/solver/impls/snes/snes.cxx:1:
+ #include <petscis.h>| // Use PETSc fieldsplit | ||
| PetscCall(PCSetType(pc, PCFIELDSPLIT)); | ||
| exit(0); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: no header providing "PCFIELDSPLIT" is directly included [misc-include-cleaner]
PetscCall(PCSetType(pc, PCFIELDSPLIT));
^|
|
||
| Vec x_diff, x0_diff, f_diff; | ||
|
|
||
| PetscCall(VecGetSubVector(x, is_diff, &x_diff)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: variable 'x0_diff' is not initialized [cppcoreguidelines-init-variables]
ints
^this fix will not be applied because it overlaps with another fix
|
|
||
| Vec x_diff, x0_diff, f_diff; | ||
|
|
||
| PetscCall(VecGetSubVector(x, is_diff, &x_diff)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: variable 'x_diff' is not initialized [cppcoreguidelines-init-variables]
ints
^this fix will not be applied because it overlaps with another fix
|
|
||
| PetscCall(VecGetSubVector(x, is_diff, &x_diff)); | ||
| PetscCall(VecGetSubVector(x0, is_diff, &x0_diff)); | ||
| PetscCall(VecGetSubVector(f, is_diff, &f_diff)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: multiple declarations in a single statement reduces readability [readability-isolate-declaration]
| PetscCall(VecGetSubVector(f, is_diff, &f_diff)); | |
| ints | |
| diff; | |
| iVec x_diff; | |
| Vec x0_diff; | |
| Vec f_diff; |
| int neq; ///< Number of variables in total | ||
|
|
||
| bool have_constraints; ///< Are there any constraint variables? | ||
| Array<BoutReal> is_dae; ///< If using constraints, 1 -> DAE, 0 -> AE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: no header providing "Array" is directly included [misc-include-cleaner]
src/solver/impls/snes/snes.hxx:30:
- #include <bout/build_defines.hxx>
+ #include "bout/array.hxx"
+ #include <bout/build_defines.hxx>| bool have_constraints; ///< Are there any constraint variables? | ||
| Array<BoutReal> is_dae; ///< If using constraints, 1 -> DAE, 0 -> AE | ||
|
|
||
| IS is_diff = nullptr; // is_dae == 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: no header providing "IS" is directly included [misc-include-cleaner]
src/solver/impls/snes/snes.hxx:32:
+ #include <petscistypes.h>221deee to
74a5480
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang-tidy made some suggestions
| // Use PETSc fieldsplit | ||
| PetscCall(PCSetType(pc, PCFIELDSPLIT)); | ||
|
|
||
| // Give PETSc the index sets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: no header providing "PCFIELDSPLIT" is directly included [misc-include-cleaner]
PetscCall(PCSetType(pc, PCFIELDSPLIT));
^|
|
||
| Vec x_diff, x0_diff, f_diff; | ||
|
|
||
| PetscCall(VecGetSubVector(x, is_diff, &x_diff)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: variable 'f_diff' is not initialized [cppcoreguidelines-init-variables]
ints
^this fix will not be applied because it overlaps with another fix
|
|
||
| Vec x_diff, x0_diff, f_diff; | ||
|
|
||
| PetscCall(VecGetSubVector(x, is_diff, &x_diff)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: variable 'x0_diff' is not initialized [cppcoreguidelines-init-variables]
ints
^this fix will not be applied because it overlaps with another fix
|
|
||
| Vec x_diff, x0_diff, f_diff; | ||
|
|
||
| PetscCall(VecGetSubVector(x, is_diff, &x_diff)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: variable 'x_diff' is not initialized [cppcoreguidelines-init-variables]
ints
^this fix will not be applied because it overlaps with another fix
|
|
||
| PetscCall(VecGetSubVector(x, is_diff, &x_diff)); | ||
| PetscCall(VecGetSubVector(x0, is_diff, &x0_diff)); | ||
| PetscCall(VecGetSubVector(f, is_diff, &f_diff)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: multiple declarations in a single statement reduces readability [readability-isolate-declaration]
| PetscCall(VecGetSubVector(f, is_diff, &f_diff)); | |
| ints | |
| diff; | |
| iVec x_diff; | |
| Vec x0_diff; | |
| Vec f_diff; |
|
Hi @malamast, this looks exciting! I'd like to make sure I understand it. What are these constraints and what do they do? What do you mean by preconditioner splitting? |
Hi @mikekryjak , by constraints here I mean algebraic equations in a differential–algebraic equation (DAE) system. In our case, this is used to include the electrostatic potential φ directly in the SNES state vector and to solve its Poisson-like equation (linking φ to vorticity) implicitly together with the rest of the time-dependent plasma equations. This is to be used along with this PR: boutproject/hermes-3#470 Previously, φ was computed inside the RHS by explicitly inverting a Laplacian at every residual evaluation (to recover φ from vorticity). That approach is expensive for 2D and also makes the nonlinear solve harder, since the Poisson solve is hidden inside the residual. With this change, φ is treated as an unknown with an algebraic constraint (its Poisson-like equation), while the other fields remain governed by differential equations. SNES then solves the coupled DAE system in one nonlinear solve, avoiding repeated Laplacian inversions in the RHS and reducing the overall computational cost. By preconditioner splitting, I mean separating the Jacobian into blocks corresponding to:
This allows applying a different (and more appropriate) preconditioner to the φ block (e.g. one tuned for elliptic/Poisson-like operators) while keeping the existing preconditioner for the rest of the system. I've tried to use Hypre/BoomerAMG for phi but with no success so far. |
Work in progress.
Added some functionality to SNES solver to support constraints (solving an differential algebraic equation DAE). I based the implementation from other solvers:
Solvers which can include constraints in BOUT++ are:
IDA, from the SUNDIALS suite
IMEX-BDF2, which uses PETSc SNES
Currently, the constraints only work with equation_form = backward_euler. We will update the rest of the options later.
I added an option to split the pc and apply a different preconditioner for the algebraic equation.
I named the splited vectors as "diff" and "alg"
To enable the split, set in the imput file pc_type = fieldsplit
In the input file, one can do something like this and explore different petsc options: