Skip to content
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

Introduce SUNDIALS N_Vector module #11395

Merged
merged 2 commits into from
Jan 22, 2021
Merged

Conversation

sebproell
Copy link
Contributor

@sebproell sebproell commented Dec 18, 2020

This PR proposes a dealii wrapper for the SUNDIALS' N_Vector module as part of #11380. All of the functionality is in internal because the conversion between vectors is not of interest for a user of a SUNDIALS integrator. I tried to further separate the only relevant functions for an author of the ARKODE, IDA, etc. wrapper into n_vector.h. The functions are: NVectorView, a class to view a VectorType as an N_Vector and unwrap_nvector() and unwrap_nvector_const() which are used to retrieve the internally stored dealii vector from an N_Vector.

This PR doesn't yet make use of the new functionality in any time integrator. I will wait for #11278 to do so but I have already checked that it works (for ARKode at least). Also, there are tests for all the vector operations that are already supported.

Commit b3f1761 contains the relevant changes. The later commits are to (hopefully) fix the tests. I suggest to rebase when #11278 is merged. Note that the tests are not actually run here since they currently require SUNDIALS > 5.0.0. I can later backport functionality or, if support for older versions will be ended in the foreseeable future, we can keep the old copying mechanism for those versions.

Copy link
Contributor Author

@sebproell sebproell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I highlighted some comments and questions

*/
template <typename VectorType>
const VectorType *
unwrap_nvector_const(N_Vector v);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if the calls should explicitly mention the const-ness. Alternative would be to enable something like unwrap_nvector<const VectorType>(...) but this feels unintuitive to me.

AssertDimension(x_dealii->size(), z_dealii->size());
AssertDimension(x_dealii->size(), y_dealii->size());

std::transform(x_dealii->begin(),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an example of a vector operation that is not easily translated to the dealii vector interface. I went for this naive implementation for now to have a working version in place.

Comment on lines +779 to +788
// v->ops->nvwrmsnormmask = undef;
// v->ops->nvmin = undef;
// v->ops->nvwl2norm = undef;
// v->ops->nvl1norm = undef;
// v->ops->nvcompare = undef;
// v->ops->nvinvtest = undef;
// v->ops->nvconstrmask = undef;
// v->ops->nvminquotient = undef;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, I put some further operations that could be implemented here. In a quick test with the ARKode tests they didn't seem to be necessary.

// ---------------------------------------------------------------------

// serial Vector and BlockVector
for (S : REAL_SCALARS; V : DEAL_II_VEC_TEMPLATES)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went for a suite of vectors that I thought are representative and use myself. Extension to more vectors should be straight-forward.

Comment on lines 206 to 207
NVectorView<VectorType> n_vector(vector);
auto id = N_VGetVectorID(n_vector);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines demonstrate the usage of NVectorView. After creating the view, it can be passed to a SUNDIALS function where it implicitly converts to N_Vector. The view is cleaned up when going out of scope.

@sebproell sebproell marked this pull request as ready for review December 18, 2020 16:15
@sebproell
Copy link
Contributor Author

@kronbichler Can you have a look? This PR is all about dealii vectors, their operations and memory management. Virtually no SUNDIALS knowledge required;)

@luca-heltai luca-heltai added this to In Progress in SUNDIALS Interfaces Dec 29, 2020
@luca-heltai luca-heltai added this to the Release 9.3 milestone Dec 29, 2020
Copy link
Member

@peterrum peterrum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very mature already 🥇 It took some time to understand why so many indirections are needed. One creates a view on deal.II vector NVectorView, which internally creates a NVectorContent. The latter classes can have two states: either it only stores only a pointer to the original vector or it "stores" the actual vector (created by the clone function - or does it?).

Maybe you could provide a small code snippet which shows how unwrap_nvector(), unwrap_nvector_const(), and NVectorView will be used in the ARKODE classes. That might help the next reviewer.

tests/sundials/n_vector.cc Outdated Show resolved Hide resolved
include/deal.II/sundials/n_vector.h Outdated Show resolved Hide resolved
Comment on lines 71 to 72
* @note N_VDestroy() should not be called on the resulting N_Vector since
* this would lead to a double delete. Let the destructor do this work.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merge this into the paragraph before. Is there a check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No and I couldn't come up with an easy one. The problem is that destroy also calls free on the N_Vector.

include/deal.II/sundials/n_vector.h Outdated Show resolved Hide resolved
include/deal.II/sundials/n_vector.templates.h Outdated Show resolved Hide resolved
include/deal.II/sundials/n_vector.templates.h Outdated Show resolved Hide resolved
Copy link
Contributor Author

@sebproell sebproell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you could provide a small code snippet which shows how unwrap_nvector(), unwrap_nvector_const(), and NVectorView will be used in the ARKODE classes. That might help the next reviewer.

@peterrum I hope the first three comments in this review help.

In addition, I highlighted a new function make_nvector_view that could be used as a nicer(?) way to construct the view objects. However, it raises some other design questions for the NVectorView

Comment on lines +161 to +162
auto vector = create_test_vector<VectorType>();
const auto const_vector = create_test_vector<VectorType>();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usage of the new functionality (1/3)
Let's say we have two deal.II vectors vector and const_vector.

Comment on lines +163 to +164
auto n_vector = make_nvector_view(vector);
auto const_n_vector = make_nvector_view(const_vector);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usage of the new functionality (2/3)
Here, we create two view objects that can be passed to any SUNDIALS function that takes an N_Vector. One would use this approach e.g. to pass an initial solution vector to SUNDIALS.

Assert((const_n_vector)->content != nullptr, NVectorTestError());

// unwrap non-const as non-const
auto *vector_unwrapped = unwrap_nvector<VectorType>(n_vector);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usage of the new functionality (3/3)
This is the oppposite operation: a N_Vector is unwrapped to extract the underlying deal.ii vector. One would use this appraoch e.g. to pass on a dst vector from SUNDIALS to a deal.ii linear solver. Note that after the linear solve no copies or updates must be made since both n_vector and vector_unwrapped refer to the same memory.

*/
template <typename VectorType>
NVectorView<VectorType>
make_nvector_view(VectorType &vector);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I introduced this new function to utilize template parameter deduction.

* auto view = make_nvector_view(vector);
* @endcode
*/
NVectorView() = default;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the doc string. I am not 100% sure if this is required. With gcc 7.3.1 it also worked without a default constructor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to myself: seems that this is not required. I will remove it.

/**
* Constructor. Create view of @p vector.
*/
NVectorView(VectorType &vector);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be made private if make_nvector_view is declared as friend. Currently, one could still use the constructor.

@sebproell
Copy link
Contributor Author

It took some time to understand why so many indirections are needed. One creates a view on deal.II vector NVectorView, which internally creates a NVectorContent. The latter classes can have two states: either it only stores only a pointer to the original vector or it "stores" the actual vector (created by the clone function - or does it?).

Correct, to put it differently: the class NVectorContent is the type for objects that are attached to the void* content of the N_Vector type. It manages the memory of the underlying vector if necessary. SUNDIALS creates new vector with N_VClone on an existing vector, which will create an owning NVectorContent. The second class NVectorView is for convenience and takes over creation of a non-owning NVectorContent and attaches it to an empty N_Vector.

Only NVectorView would ever be used in SUNDIALS code by a deal author. A user of deal would ofc never see any of the stuff going on in this PR.

@sebproell
Copy link
Contributor Author

@peterrum @luca-heltai @kronbichler How should we proceed here?

@luca-heltai
Copy link
Member

/rebuild

@luca-heltai
Copy link
Member

I think we should merge this, and adjust later if necessary. With this, it should be much easier to interface with sundials, and I think it is a big step forward. I'm in favour of merging early, testing a bit the new interface, and then adjust later if necessary.

@sebproell
Copy link
Contributor Author

Okay! I already have some adaptions to the ARKode integrator to use the new N_Vector module. Will follow up with it soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

None yet

3 participants