-
Notifications
You must be signed in to change notification settings - Fork 242
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
allow different base_elements for compositional fields #5802
Conversation
This one if for you @bangerth . :-) |
There are numerous errors such as these:
I would assume that you get those on your machine too? |
fb601c0
to
7fdefbc
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.
First part.
include/aspect/introspection.h
Outdated
/** | ||
* Return a vector with all used indices of base elements of the deal.II FiniteElement | ||
* that are used for compositional fields. If several fields are the same type, they | ||
* share base elements. | ||
*/ | ||
std::vector<unsigned int> | ||
get_compositional_field_base_element_indices() const; |
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.
Am I correct that the output array has length # of compositional fields
? If so, would you mind adding that.
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.
No, currently it has length 1, which I thought is obvious from the comment. I will make it more clear.
include/aspect/introspection.h
Outdated
/** | ||
* Return a vector with all compositional field indices that belong to a given | ||
* base element index. | ||
*/ | ||
std::vector<unsigned int> | ||
get_compositional_field_indices_with_base_element(const unsigned int base_element_index) const; |
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 this indexed starting at the zeroth compositional element? Or at the velocity?
Or perhaps you are saying that the argument must be an element of the array that get_compositional_field_base_element_indices()
returns? If so, please add that. (And assert?)
for (unsigned int i=0; i<this->get_fe().base_element(this->introspection().base_elements.compositional_fields).dofs_per_cell; ++i) | ||
for (unsigned int i=0; i<in.n_evaluation_points(); ++i) |
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.
I would accept this commit separately if it's cumbersome to carry around.
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.
see #5816
7774d04
to
86d521f
Compare
Updated and rebased. |
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.
Close.
source/simulator/helper_functions.cc
Outdated
|
||
for (unsigned int i=0; i<points.size(); ++i) | ||
{ | ||
const auto &it = std::find(unique_support_points.begin(), unique_support_points.end(), points[i]); |
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.
You don't want a reference to a temporary.
const auto &it = std::find(unique_support_points.begin(), unique_support_points.end(), points[i]); | |
const auto it = std::find(unique_support_points.begin(), unique_support_points.end(), points[i]); |
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.
I think lifetime extension makes this work, but I agree.
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.
I think this is way better than it was before, I really like it! In a few places, I found it hard to follow what all the different indices are, but it's a clear improvement on my original version.
// refining, so anything >1 should work. (note that the gradient | ||
// itself scales like 1/h, so multiplying it with any factor h^s, s>1 | ||
// will yield convergence of the error indicators to zero as h->0) | ||
this_indicator *= std::pow(cell->diameter(), power); |
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 this still the same as before? You're not resetting your this_indicator
variable in the loop. So it would add up from the different compositional fields with the same base index.
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.
Thank you!
source/simulator/helper_functions.cc
Outdated
HeatingModel::HeatingModelOutputs heating_model_outputs_C(quadrature_C.size(), introspection.n_compositional_fields); | ||
// First compute the union of all support points (temperature and compositions): | ||
std::vector<Point<dim>> unique_support_points; | ||
// For each field (T or composition) store a list of indices of support points (unique_support_points): |
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.
So these are, for each support point of a given field, the index that this support point has in the unique_support_points
vector? I think that did not quite become clear to me from reading just the comment.
// on every cell, compute the update, and then on every cell put the result into the | ||
// distributed_vector vector. Only after the loop over all cells do we copy distributed_vector | ||
// back onto the solution vector. | ||
// So even though we touch some DoF more than once, we always start from the same value, compute the | ||
// same value, and then overwrite the same value in distributed_vector. | ||
// TODO: make this more efficient. | ||
// TODO: make this even more efficient. |
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.
😄
Introspection<dim>::is_composition_component (const unsigned int component_index) const | ||
{ | ||
// All compositions live at the end. Just to be sure, there are no other components | ||
// in our system after compositional fields, right? |
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.
Does that work in models with melt transport? We do have the melt velocity, fluid pressure etc. before the temperature, right?
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.
Yes, that is correct. But I added an Assert here just in case somebody messes with the order later on.
source/simulator/helper_functions.cc
Outdated
// the how-manyth dof is that for the current component and where do we find this in the list | ||
// of evaluation points? | ||
const unsigned int index_within = comp_pair.second; | ||
const unsigned int field_index = component_idx-component_idx_T; | ||
const unsigned int idx = support_point_index_by_field[field_index][index_within]; |
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.
I find this hard to follow. I understand the general concept, but if you could add another sentence of explanation (either here, or where you fill the support_point_index_by_field vector) I think that would be helpful.
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.
better?
Updated. Thank you for the comments! 👍 |
12f4781
to
7831a79
Compare
Fingers crossed, this might be good to go now. |
The two tests are changing very slightly due to the reordering of the loops in the composition mesh refinement plugin. |
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.
Looks all correct, but could you look into my comments about the documentation? I think the current text is slightly confusing. Also some small suggestions for performance improvements.
include/aspect/introspection.h
Outdated
* Return a vector with all used indices of base elements of the deal.II FiniteElement | ||
* that are used for compositional fields. If several fields are the same type, they |
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.
This documentation is not clear to me. Do you mean: Return a vector with as many entries as compositional fields. Each entry of the vector represents the index of the base element that is used for this compositional field.
?
EDIT: After reading the function I understood. What about rewording to: Return a vector that contains the base element indices of the deal.II FiniteElement that are used for compositional fields. Note that compositional fields can share the same base element, so this vector can (and usually will) be smaller than the number of compositional fields. The function get_compositional_field_indices_with_base_element() can be used to translate from base element index to compositional field indices.
Also in the second sentence the phrase are the same type
suggests a relation with the compositional_field_types
feature, but you probably mean If several fields use the same finite element and degree, they share base elements
.
@@ -19,6 +19,7 @@ | |||
*/ | |||
|
|||
|
|||
#include <aspect/simulator.h> |
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.
Ah, we really need to find a solution to put AdvectionField
out of the simulator.h
header. Including simulator.h
in a lot of places is not a clean design. Not for this PR though.
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.
agreed, see #5887
if (dof_handler.locally_owned_dofs().is_element(local_dof_indices[temperature_idx])) | ||
const auto comp_pair = dof_handler.get_fe().system_to_component_index(dof_idx); | ||
const unsigned int component_idx = comp_pair.first; | ||
if (component_idx>=component_idx_T) // ignore velocity, pressure, etc. |
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.
This relies on implicit knowledge about the component ordering. What about:
if (component_idx>=component_idx_T) // ignore velocity, pressure, etc. | |
if (introspection.is_stokes_component(component_idx) == false) // ignore velocity, pressure, etc. |
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.
Neat idea, but this won't work with melt or other FE modifications, I think.
source/simulator/introspection.cc
Outdated
std::vector<unsigned int> result; | ||
const unsigned int first = this->base_elements.compositional_fields[0]; | ||
const unsigned int last = *std::max_element(this->base_elements.compositional_fields.begin(), this->base_elements.compositional_fields.end()); | ||
for (unsigned int i = first; i<=last; ++i) | ||
result.emplace_back(i); | ||
return result; |
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.
Save a few allocations:
std::vector<unsigned int> result; | |
const unsigned int first = this->base_elements.compositional_fields[0]; | |
const unsigned int last = *std::max_element(this->base_elements.compositional_fields.begin(), this->base_elements.compositional_fields.end()); | |
for (unsigned int i = first; i<=last; ++i) | |
result.emplace_back(i); | |
return result; | |
const unsigned int first = this->base_elements.compositional_fields[0]; | |
const unsigned int last = *std::max_element(this->base_elements.compositional_fields.begin(), this->base_elements.compositional_fields.end()); | |
std::vector<unsigned int> result(last-first); | |
std::iota(result.begin(), result.end(), first); | |
return result; |
Even better: I reworked some parts of introspection to cache this information (see get_names_for_fields_of_type()
). This way we can avoid allocating a vector in tight loops (the caller of this function might not know it is expensive).
source/simulator/introspection.cc
Outdated
std::vector<unsigned int> result; | ||
Assert(base_element_index <= get_compositional_field_base_element_indices().back(), | ||
ExcMessage("Invalid base_element_index specified.")); | ||
|
||
unsigned int idx = 0; | ||
for (const auto base_idx : this->base_elements.compositional_fields) | ||
{ | ||
if (base_idx == base_element_index) | ||
result.emplace_back(idx); | ||
|
||
++idx; | ||
} |
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.
Also here, I think it would be better if this could be computed in the constructor once and then just returned by reference (it is called from a loop over all base elements x over all cells). I think of introspection
as a sort of cache for internal information so it would be ok to precompute things.
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.
are you ok with a std::map? See the last commit.
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.
I am ok with it until it shows up in a profiling run ;-) ... we can keep it for now. But can you change both functions to return references to vectors? Also I think you need to indent.
updated. |
We now store different base_element indices in introspection (one index for each compositional field). This is no functional change, as we do not support different FiniteElements so far.
To be able to make this change, I had to fix various places that use base_elements or assume that all compositional fields have the same base element.
part of #5748