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

Make reuse of mapping data in FEPointEvaluation safer #13245

Closed

Conversation

kronbichler
Copy link
Member

Follow-up to #12983: As discussed #12983 (comment), we should make sure that a user cannot mix up the order by which to provide the information. This PR achieves this by making the data structure a shared pointer of some internal struct that also remembers the cell which it was last initialized to. This makes sure we can update the data on demand.

@kronbichler
Copy link
Member Author

FYI @gassmoeller @peterrum

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.

This is a good step forward but I must I didn't get all the details.

As far as I understand, we have mapping data that is shared by different FPEs. Furthermore, each of them can modify it, which leads to some issues as pointed out in my comments. @kronbichler Could you comment if I understood the code correctly. If I see it correctly, the biggest obstacle to make the mapping data immutable are the mapping flags, that we cannot pre-collect.

* @p cell and @p unit_points that is required by the FEPointEvaluation
* class.
* Data structure that allows the computation of the mapping related data
* for the given @p mapping, @p cell and @p unit_points that us used by
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* for the given @p mapping, @p cell and @p unit_points that us used by
* for the given @p mapping, @p cell and @p unit_points that are used by

Comment on lines +389 to +405
/**
* The points for which the evaluation has been invoked by the last call
* to compute().
*/
std::vector<Point<dim>> unit_points;

/**
* The cell on which the evaluation has been invoked by the last call
* to compute().
*/
const typename Triangulation<dim, spacedim>::cell_iterator cell;

/**
* The data computed by this data structure.
*/
internal::FEValuesImplementation::MappingRelatedData<dim, spacedim> data;
};
Copy link
Member

Choose a reason for hiding this comment

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

Do we really have these public? As far as I see, the instance of this class returned by get_mapping_data() is mutable.

Comment on lines +417 to +426
bool needs_update =
(cell != this->cell) || unit_points.size() != this->unit_points.size();
// expensive check: make sure all points are really the same
if (!needs_update)
for (unsigned int i = 0; i < unit_points.size(); ++i)
if (unit_points[i].distance_square(this->unit_points[i]) > 1e-12)
{
needs_update = true;
break;
}
Copy link
Member

Choose a reason for hiding this comment

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

I guess this check is needed, because all FPE using the same mapping instance can modify it. Wouldn't it be better if there is a master FPE: this is updates the mapping info and returns a non-mutable mapping instance. Also, I am not completely sure about the two reinit functions:

reinit(cell, points) -> void
reinit(cell, points, mapping) -> void

As far as I understand from the documentation, the mapping object in the second reinit function already contains the precomputed mapping. That means we do not need cell and points in that case because it is already provided by the mapping object, isn't it? Or this mapping object filled (like in VT::point_values()) - in that case the documentation is out of date.

Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't it be better if there is a master FPE: this is updates the mapping info and returns a non-mutable mapping instance.

I agree with @peterrum. It is a nice thought to share the mapping data instead of creating copies (like the code does at the moment), but the shared data should be const, otherwise modifying a later FPE might change the behavior of the original one.

As far as I understand from the documentation, the mapping object in the second reinit function already contains the precomputed mapping.

That is correct. At the moment the second function assumes (and checks) that the mapping data has already been computed, handing over an empty object is not allowed.

Comment on lines +917 to +921
// As we got the data from the other field, we will typically not need
// to perform any operation, unless the user provided us with a
// `precomputed_mapping_data` that is not initialized to the present
// context.
mapping_data->compute(*mapping, cell, unit_points, update_flags_mapping);
Copy link
Member

Choose a reason for hiding this comment

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

OK. The flags might be different between FPEs that share the same mapping (additional fields are filled). But if cell and unit_points is different, this looks like a bug in the code. Also, does that mean that we are modifying the internal state of the other FPE that has called this function before? We don't have any way to signal that its that has been invalidated.

Copy link
Member

@gassmoeller gassmoeller left a comment

Choose a reason for hiding this comment

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

I agree with Peter's concerns. It is a nice addition to hide the internal type and to share the data between FPE's (instead of copying them), but we should not change the shared structure. I see that making it const is impractical when different FPE's need different mapping data (like jacobians), but maybe that is simply the limitation? If you need different mapping data for different FPE's you should not try to reuse their mapping data? Not sure how severe this limitation is in practice.

std::vector<Point<dim>> unit_points;

/**
* The cell on which the evaluation has been invoked by the last call
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* The cell on which the evaluation has been invoked by the last call
* The cell on which the evaluation has been invoked by the last call

Comment on lines +417 to +426
bool needs_update =
(cell != this->cell) || unit_points.size() != this->unit_points.size();
// expensive check: make sure all points are really the same
if (!needs_update)
for (unsigned int i = 0; i < unit_points.size(); ++i)
if (unit_points[i].distance_square(this->unit_points[i]) > 1e-12)
{
needs_update = true;
break;
}
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't it be better if there is a master FPE: this is updates the mapping info and returns a non-mutable mapping instance.

I agree with @peterrum. It is a nice thought to share the mapping data instead of creating copies (like the code does at the moment), but the shared data should be const, otherwise modifying a later FPE might change the behavior of the original one.

As far as I understand from the documentation, the mapping object in the second reinit function already contains the precomputed mapping.

That is correct. At the moment the second function assumes (and checks) that the mapping data has already been computed, handing over an empty object is not allowed.

@peterrum
Copy link
Member

@kronbichler How do we want to proceed here?

@peterrum peterrum added this to the Release 9.4 milestone Apr 24, 2022
@kronbichler
Copy link
Member Author

Just for the record, @bergbauer is working on a better replacement of this. Once we have the code posted (hopefully early next week), we can close this PR and thus remove it from the 9.4 milestone target, but before I would like to keep it on the milestone to have the awareness that something needs to be done now before the release.

@kronbichler
Copy link
Member Author

Closed in favor of #13835.

@kronbichler kronbichler deleted the improve_fe_point_evaluation branch September 5, 2022 12:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants