Skip to content

Conversation

MarcelKoch
Copy link
Member

@MarcelKoch MarcelKoch commented Jul 22, 2021

This PR adds support for linear systems Ax=b with constraints of the form x[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:

ConstraintsHandler handler(idxs, A, values, b, /*optional*/ x, /*optional*/ std::make_shared<ZeroRowStrategy>());

auto cons_A = handler.get_operator();  // cons_A is a shared_ptr
auto cons_b = handler.get_right_hand_side();  //cons_b is a bare ptr
auto cons_x = handler.get_get_initial_guess();  //cons_x is a bare_ptr

auto solver = factory->generate(lend(cons_A));
solver->apply(cons_b, cons_x);
handler.correct_solution(cons_x);

Alternatively, the handler can be constructed just from idxs, A only, which requires setting at least the right-hand-side and the constrained values using

handler.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:

  • Should the ConstraintsHandler use pointer or value semantics? By that I mean, if it should use a create method similarly to many of ginkgo's classes.
  • If pointer semantics are used, should the class hold an executor to use the EnableCreateMethod? Currently, that would be pointless, since I'm always using the executors of the vectors or matrix.
  • I'm throwing an NotSupported error, if the get_* methods are used while the handler is in an incomplete state. Should a more descriptive exception (e.g. InvalidState) be added?
  • Ideally, I would like to change the type of the constraint indices to the index set from Add an IndexSet class. #676
  • How should different matrix formats be supported? Currently, only CSR is supported, and some implementations are really specific to it, since they access the underlying arrays.

Old Description

This PR will add support for linear systems Ax=b with constraints of the form x[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:

ConstrainedHandler cons_handler(idxs, values);

cons_handler.setup(A, b, x);

auto cons_A = cons_handler.get_operator();
auto cons_b = cons_handler.get_right_hand_side();
auto cons_x = cons_handler.get_get_initial_guess();

auto solver = factory->generate(lend(cons_A));
solver->apply(lend(cons_b), lend(cons_x));

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.

@MarcelKoch MarcelKoch added is:new-feature A request or implementation of a feature that does not exist yet. is:proposal Maybe we should do something this way. type:solver This is related to the solvers 1:ST:WIP This PR is a work in progress. Not ready for review. labels Jul 22, 2021
@MarcelKoch MarcelKoch self-assigned this Jul 22, 2021
@MarcelKoch MarcelKoch force-pushed the constraint-handling branch from 5cc07bd to c0b8afc Compare July 22, 2021 13:35
@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@fritzgoebel
Copy link
Collaborator

This looks very useful! The interface looks quite similar to what is there in opencarp for handling Dirichlet boundary conditions. They have a dbc_manager which is tied to a matrix and some stimuli that are either active or inactive. Depending on which stimuli are active, the boundary conditions are updated with an update function. It looks very close to what you're suggesting.

@MarcelKoch
Copy link
Member Author

I've been thinking a bit about what the invariants of the ConstraintHandler should be. The current interface would suggest that only the constraint indices are invariants. But I think that is too general. I would suggest that both the indices and the system matrix are invariant.

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.
For the matrix, I don't think there is a reasonable scenario where only the system matrix changes, while the rest stays the same. Additionally, changing the system matrix requires recomputing everything else, so one might as well just create a new handler.

@MarcelKoch
Copy link
Member Author

MarcelKoch commented Jul 28, 2021

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));
}

@MarcelKoch
Copy link
Member Author

I'm currently a bit unsure how to integrate this into ginkgo's class hierarchy. Using the EnablePolymorphicObject mixin seems reasonable, with the objection that this would inject an executor into the class. But I don't think that an executor is useful for this interface. The only use I can see is to check that it's using the same executor as the operator, indices, etc. Other than that, I don't know what to do with it. Nevertheless, I would be nice to have the same semantics (i.e. pointer semantic) as the rest of ginkgo.

@MarcelKoch
Copy link
Member Author

I think the interface is now where I'm satisfied with it. @fritzgoebel, @greole do you think you can use that in your implementations?

@MarcelKoch MarcelKoch force-pushed the constraint-handling branch from bd44ab4 to 2cf36f2 Compare July 29, 2021 13:59
@fritzgoebel
Copy link
Collaborator

fritzgoebel commented Aug 4, 2021

I think the interface is now where I'm satisfied with it. @fritzgoebel, @greole do you think you can use that in your implementations?

Yes, I think I will be able to use this.
Also: I agree that we can assume the system matrix to be invariant. The constraint handler looks like it will be quite light-weight, so when a new system matrix has to be computed creating a new constraint handler won't matter too much.

@MarcelKoch MarcelKoch force-pushed the constraint-handling branch 4 times, most recently from 33fff07 to dcc7141 Compare October 5, 2021 09:51
@MarcelKoch MarcelKoch added 1:ST:ready-for-review This PR is ready for review and removed 1:ST:WIP This PR is a work in progress. Not ready for review. labels Oct 5, 2021
@MarcelKoch
Copy link
Member Author

@fritzgoebel, @greole would you mind looking into this, if it could be used in your cases?

@MarcelKoch MarcelKoch requested a review from a team October 5, 2021 11:13
@MarcelKoch MarcelKoch changed the title WIP: Add support for constrained systems Add support for constrained systems Oct 5, 2021
@MarcelKoch MarcelKoch added the 1:ST:need-feedback The PR is somewhat ready but feedback on a blocking topic is required before a proper review. label Oct 11, 2021
// Alternatively the handler could be created with
// ```cpp
// gko::constraints::ConstraintsHandler<ValueType, IndexType>
// handler(dir_indices, matrix); handler.with_constrained_values(dir_vals)
Copy link
Collaborator

@greole greole Oct 11, 2021

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.

@MarcelKoch MarcelKoch removed the 1:ST:ready-for-review This PR is ready for review label Oct 11, 2021
* get_right_hand_side, and get_initial_guess. If no initial guess was
* provided, the guess will be set to zero.
*/
void reconstruct_system();
Copy link
Collaborator

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();

Copy link
Member Author

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_); }
Copy link
Collaborator

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?

Copy link
Member Author

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.

MarcelKoch and others added 19 commits January 7, 2022 11:05
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.
@MarcelKoch MarcelKoch force-pushed the constraint-handling branch from b2182ac to d7b1e78 Compare January 7, 2022 10:07
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.
@ginkgo-bot
Copy link
Member

Error: The following files need to be formatted:

core/constraints/utility_kernels.hpp
include/ginkgo/ginkgo.hpp
reference/test/constraints/constraints_handler.cpp
reference/test/constraints/zero_rows.cpp

You can find a formatting patch under Artifacts here or run format! if you have write access to Ginkgo

@ginkgo-bot
Copy link
Member

Note: This PR changes the Ginkgo ABI:

Functions changes summary: 106 Removed, 2 Changed, 524 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

For details check the full ABI diff under Artifacts here

@MarcelKoch MarcelKoch added 1:ST:need-feedback The PR is somewhat ready but feedback on a blocking topic is required before a proper review. and removed 1:ST:ready-for-review This PR is ready for review labels Mar 17, 2022
@MarcelKoch MarcelKoch added the 1:ST:WIP This PR is a work in progress. Not ready for review. label Apr 25, 2022
@MarcelKoch MarcelKoch marked this pull request as draft January 26, 2024 16:06
@upsj upsj mentioned this pull request Sep 18, 2024
@MarcelKoch
Copy link
Member Author

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.

@MarcelKoch MarcelKoch closed this Feb 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1:ST:need-feedback The PR is somewhat ready but feedback on a blocking topic is required before a proper review. 1:ST:WIP This PR is a work in progress. Not ready for review. is:new-feature A request or implementation of a feature that does not exist yet. is:proposal Maybe we should do something this way. type:solver This is related to the solvers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants