-
Notifications
You must be signed in to change notification settings - Fork 99
Add support for constrained systems #842
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
Conversation
5cc07bd
to
c0b8afc
Compare
Kudos, SonarCloud Quality Gate passed!
|
This looks very useful! The interface looks quite similar to what is there in opencarp for handling Dirichlet boundary conditions. They have a |
I've been thinking a bit about what the invariants of the For the right-hand-side, the initial guess, and the constrained values I can think of scenarios, where they change, while the system matrix and the indices remain constant. |
I've updated the interface according to the previous comment. Here is an example which shows how the new interface could be used. ConstraintHandler ch(idxs, A);
auto cons_A = ch.get_operator();
auto solver = factory->generate(const_A);
for(int time_step=0; time_step < end; ++ time_step){
// compute new right-hand-side, dirichlet values, etc.
ch.with_constrained_values(dir_vals)
.with_right_hand_side(rhs);
auto cons_rhs = ch.get_right_hand_side();
auto const_x0 = ch.get_initial_guess();
solver->apply(lend(cons_rhs), lend(cons_x0));
ch.correct_solution(lend(cons_x0));
} |
I'm currently a bit unsure how to integrate this into ginkgo's class hierarchy. Using the |
I think the interface is now where I'm satisfied with it. @fritzgoebel, @greole do you think you can use that in your implementations? |
bd44ab4
to
2cf36f2
Compare
Yes, I think I will be able to use this. |
33fff07
to
dcc7141
Compare
@fritzgoebel, @greole would you mind looking into this, if it could be used in your cases? |
// Alternatively the handler could be created with | ||
// ```cpp | ||
// gko::constraints::ConstraintsHandler<ValueType, IndexType> | ||
// handler(dir_indices, matrix); handler.with_constrained_values(dir_vals) |
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.
That example looks broken, maybe it is just the missing line break between matrix);
and handler
. But also the use of the factory parameters like .with_constrained_values()
etc on the already existing instance of the ConstraintHandler
are somewhat confusing to me.
* get_right_hand_side, and get_initial_guess. If no initial guess was | ||
* provided, the guess will be set to zero. | ||
*/ | ||
void reconstruct_system(); |
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.
If this changes the state of the underlying system, is there any function to get whether the underlying system is reconstructed, ie bool is_reconstructed();
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.
When this is called, all internal vectors are reset, so it forces the recomputation of the constrained system (except for the operator).
|
||
const Array<IndexType>* get_constrained_indices() const { return &idxs_; } | ||
|
||
const Dense* get_constrained_values() const { return lend(values_); } |
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.
Is there a specific reason to return a raw pointer vs std::shared_ptr<const Dense>
here?
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.
Mostly to be more inline with how you would pass these vector along to other functions, e.g. apply
. Also I don't think there is any need to use shared_ptr here, as the lifetime of these objects is always handled by this class.
fix construction of rhs
this is necessary to distinguish between a user supplied initial guess and the default zero initial guess. if the user supplies an initial guess, it's assumed that the guess contains the current constrained values. if the user doesn't specify an initial guess, every time the constrained values are updated, the default initial guess has to be updated as well.
- fix formatting in example comment - add documentation - fix up documentation Co-authored-by: fritzgoebel <fritz.goebel@kit.edu> Co-authored-by: greole <gregor.olenik@web.de>
This doesn't work well for types that are not managed via smart pointers.
b2182ac
to
d7b1e78
Compare
The zero-rows constraints approach seeks an update for the provided initial guess, such that `initial guess + update` solve the original system. If the initial guess is already close to the solution, the update should be close to zero. Therefore, it is beneficial to start with an initial guess of zero for the constrained system.
Error: The following files need to be formatted:
You can find a formatting patch under Artifacts here or run |
Note: This PR changes the Ginkgo ABI:
For details check the full ABI diff under Artifacts here |
I'm closing this PR, since I will revisit this with a reduced approach. Instead of providing a single interface that does everything, only the underlying building blocks, necessary to enforce the constraints will be added. |
This PR adds support for linear systems
Ax=b
with constraints of the formx[i] = g[i], i in Idxs
. Since the PR already got somewhat large, I've only implemented reference kernels. Additionally, an example which shows the constraints handling in action is supplied.The usage of the handler looks like this:
Alternatively, the handler can be constructed just from
idxs, A
only, which requires setting at least the right-hand-side and the constrained values usinghandler.with_constrained_values(values) .with_right_hand_side(b) .with_initial_guess(x); // the last one is optional
With this approach the constrained vectors are only created when queried from
get_*
. Also, this allows for repeatedly solving the system with the same operator and the same index set, but with changing right-hand-sides, constrained values or both. An use-case for this could be time-dependent simulations.If the initial guess has not been specified, then a default one, filled with zero and constrained values, is created.
Some topics that might be discussed:
ConstraintsHandler
use pointer or value semantics? By that I mean, if it should use acreate
method similarly to many of ginkgo's classes.EnableCreateMethod
? Currently, that would be pointless, since I'm always using the executors of the vectors or matrix.NotSupported
error, if theget_*
methods are used while the handler is in an incomplete state. Should a more descriptive exception (e.g.InvalidState
) be added?Old Description
This PR will add support for linear systems
Ax=b
with constraints of the formx[i] = g[i], i in Idxs
. Currently, it only contains a first interface for a constraint handler, and acts more as a base for future discussions.The usage of the handler looks lilke this:
I've also added setters, which I called
update_*
to (hopefully) indicate that they do more than simply setting a member.I'm not sure if this interface will become abstract, or if one switches between different behaviors with a tag.
I'm also thinking about adding something like
ConstrainedSolver
which combines the handler and a solver for easier usage.