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

Refactor HangingNodes::setup_constraints() #12977

Merged
merged 1 commit into from Nov 24, 2021

Conversation

peterrum
Copy link
Member

@peterrum peterrum commented Nov 20, 2021

With this PR, the algorithm is split up three steps:

// 1) check if finite elements support fast hanging-node algorithm
const auto component_masks =
compute_component_mask(cell->get_dof_handler().get_fe_collection());
if ([](const auto &outer) {
for (const auto &inner : outer)
for (const auto &i : inner)
if (i)
return true;
return false;
}(component_masks) == false)
return false;
// 2) determine the refinement configuration of the cell
const auto refinement_mask = compute_refinement_configuration(cell);
if (refinement_mask == ConstraintKinds::unconstrained)
return false;
// 3) update DoF indices of cell for specified components
update_dof_indices(cell,
partitioner,
lexicographic_mapping,
component_masks,
refinement_mask,
dof_indices);

(In follow up PRs, I would like to call the new functions at separate places to minimize redundant work).

The determination of the refinement configuration now consists of basic bit shifts of the form:

depends on #12979, #12980, #1298

@peterrum
Copy link
Member Author

/rebuild

Comment on lines 216 to 231
std::vector<std::vector<bool>>
compute_component_mask(const dealii::hp::FECollection<dim> &fe) const;

template <typename CellIterator>
ConstraintKinds
compute_refinement_configuration(const CellIterator &cell) const;

template <typename CellIterator>
void
update_dof_indices(
const CellIterator & cell,
const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner,
const std::vector<unsigned int> & lexicographic_mapping,
const std::vector<std::vector<bool>> &component_mask,
const ConstraintKinds & refinement_configuration,
std::vector<types::global_dof_index> &dof_indices) const;
Copy link
Member

Choose a reason for hiding this comment

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

Could you please document these functions? It is an internal class, but the other functions are.

@@ -345,24 +368,139 @@ namespace internal



template <int dim>
inline std::vector<std::vector<bool>>
HangingNodes<dim>::compute_component_mask(
Copy link
Member

Choose a reason for hiding this comment

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

Can you give this function a more expressive name, e.g.

Suggested change
HangingNodes<dim>::compute_component_mask(
HangingNodes<dim>::compute_supported_components(

Comment on lines 435 to 451
// ignore neighbors that are artificial or have the same level
if (neighbor->is_artificial() || neighbor->level() == cell->level())
continue;
Copy link
Member

Choose a reason for hiding this comment

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

It is a bit confusing to have the check for children (neighbor more refined) in a different places than the other case with the same property. How about moving all three cases involving the neighbor here?

.tensor_degree() +
1;
const unsigned int dofs_per_face =
Utilities::fixed_power<dim - 1>(n_dofs_1d);
Copy link
Member

Choose a reason for hiding this comment

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

nit-picking, but can you use

Suggested change
Utilities::fixed_power<dim - 1>(n_dofs_1d);
Utilities::pow(n_dofs_1d, dim - 1);

Comment on lines 736 to 762
if ([](const auto &outer) {
for (const auto &inner : outer)
for (const auto i : inner)
if (i)
return true;
return false;
}(component_masks) == false)
return false;
Copy link
Member

Choose a reason for hiding this comment

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

I think this is hard to follow, why not simply

Suggested change
if ([](const auto &outer) {
for (const auto &inner : outer)
for (const auto i : inner)
if (i)
return true;
return false;
}(component_masks) == false)
return false;
return std::none_of(component_mask.begin(), component_mask.end(),
[] (const auto &a) { return *std::max_element(a.begin(), a.end());});

Or write out the loops to find an entry with true (at the expense of an additional variable as we can't return from within the loop.

@peterrum
Copy link
Member Author

@kronbichler I have made the changes. I also have added a test that the algorithm works for (2D) mixed meshes (with a few additional changes).


// ignore neighbors that are artificial or have the same level or
// have children
if (cell->neighbor(face_no)->has_children() ||
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
if (cell->neighbor(face_no)->has_children() ||
if (neighbor->has_children() ||

Copy link
Member Author

Choose a reason for hiding this comment

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

Done!

@kronbichler kronbichler merged commit 96f8201 into dealii:master Nov 24, 2021
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

2 participants