31 template <
int dim,
int spacedim>
34 set_default_hierarchy();
39 template <
int dim,
int spacedim>
49 template <
int dim,
int spacedim>
55 ExcMessage(
"Need to pass at least one finite element."));
57 for (
unsigned int i = 0; i < fes.size(); ++i)
63 template <
int dim,
int spacedim>
72 new_fe.
n_components() == this->operator[](0).n_components(),
73 ExcMessage(
"All elements inside a collection need to have the "
74 "same number of vector components!"));
81 template <
int dim,
int spacedim>
85 Assert(this->
size() > 0, ExcNoFiniteElements());
96 if (!reference_cell_default_linear_mapping ||
97 reference_cell_default_linear_mapping->size() != this->size())
102 std::make_shared<MappingCollection<dim, spacedim>>();
104 for (
const auto &fe : *
this)
105 this_nc.reference_cell_default_linear_mapping->push_back(
107 .template get_default_linear_mapping<dim, spacedim>());
110 return *reference_cell_default_linear_mapping;
115 template <
int dim,
int spacedim>
116 std::set<unsigned int>
118 const std::set<unsigned int> &fes,
119 const unsigned int codim)
const
126 for (
const auto &fe : fes)
133 std::set<unsigned int> dominating_fes;
134 for (
unsigned int current_fe = 0; current_fe < this->
size(); ++current_fe)
139 for (
const auto &other_fe : fes)
142 this->operator[](current_fe)
143 .compare_for_domination(this->operator[](other_fe), codim);
149 dominating_fes.insert(current_fe);
151 return dominating_fes;
156 template <
int dim,
int spacedim>
157 std::set<unsigned int>
159 const std::set<unsigned int> &fes,
160 const unsigned int codim)
const
167 for (
const auto &fe : fes)
174 std::set<unsigned int> dominated_fes;
175 for (
unsigned int current_fe = 0; current_fe < this->
size(); ++current_fe)
180 for (
const auto &other_fe : fes)
183 this->
operator[](current_fe)
184 .compare_for_domination(this->
operator[](other_fe), codim);
190 dominated_fes.insert(current_fe);
192 return dominated_fes;
197 template <
int dim,
int spacedim>
200 const std::set<unsigned int> &fes,
201 const unsigned int codim)
const
213 for (
const auto &fe : fes)
220 for (
const auto ¤t_fe : fes)
225 for (
const auto &other_fe : fes)
226 if (current_fe != other_fe)
229 this->operator[](current_fe)
230 .compare_for_domination(this->
operator[](other_fe), codim);
245 template <
int dim,
int spacedim>
248 const std::set<unsigned int> &fes,
249 const unsigned int codim)
const
261 for (
const auto &fe : fes)
268 for (
const auto ¤t_fe : fes)
273 for (
const auto &other_fe : fes)
274 if (current_fe != other_fe)
277 this->operator[](current_fe)
278 .compare_for_domination(this->
operator[](other_fe), codim);
293 template <
int dim,
int spacedim>
296 const std::set<unsigned int> &fes,
297 const unsigned int codim)
const
299 unsigned int fe_index = find_dominating_fe(fes, codim);
303 const std::set<unsigned int> dominating_fes =
304 find_common_fes(fes, codim);
305 fe_index = find_dominated_fe(dominating_fes, codim);
313 template <
int dim,
int spacedim>
316 const std::set<unsigned int> &fes,
317 const unsigned int codim)
const
319 unsigned int fe_index = find_dominated_fe(fes, codim);
323 const std::set<unsigned int> dominated_fes =
324 find_enclosing_fes(fes, codim);
325 fe_index = find_dominating_fe(dominated_fes, codim);
339 std::vector<std::map<unsigned int, unsigned int>>
340 compute_hp_dof_identities(
341 const std::set<unsigned int> &fes,
342 const std::function<std::vector<std::pair<unsigned int, unsigned int>>(
344 const unsigned int)> &query_identities)
356 const unsigned int fe_index_1 = *fes.begin();
357 const unsigned int fe_index_2 = *(++fes.begin());
358 const auto reduced_identities =
359 query_identities(fe_index_1, fe_index_2);
361 std::vector<std::map<unsigned int, unsigned int>> complete_identities;
363 for (
const auto &reduced_identity : reduced_identities)
368 std::map<unsigned int, unsigned int> complete_identity = {
369 {fe_index_1, reduced_identity.first},
370 {fe_index_2, reduced_identity.second}};
371 complete_identities.emplace_back(std::move(complete_identity));
374 return complete_identities;
385 using Node = std::pair<unsigned int, unsigned int>;
386 using Edge = std::pair<Node, Node>;
387 using Graph = std::set<Edge>;
389 Graph identities_graph;
390 for (
const unsigned int fe_index_1 : fes)
391 for (const unsigned
int fe_index_2 : fes)
392 if (fe_index_1 != fe_index_2)
394 query_identities(fe_index_1, fe_index_2))
405 for (
const auto &edge : identities_graph)
406 Assert(identities_graph.find({edge.second, edge.first}) !=
407 identities_graph.end(),
459 std::vector<std::map<unsigned int, unsigned int>> identities;
460 while (identities_graph.size() > 0)
463 std::set<Node> sub_graph_nodes;
465 sub_graph.emplace(*identities_graph.begin());
466 sub_graph_nodes.emplace(identities_graph.begin()->first);
467 sub_graph_nodes.emplace(identities_graph.begin()->second);
469 for (
const Edge &e : identities_graph)
470 if ((sub_graph_nodes.find(e.first) != sub_graph_nodes.end()) ||
471 (sub_graph_nodes.find(e.second) != sub_graph_nodes.end()))
474 sub_graph_nodes.insert(e.first);
475 sub_graph_nodes.insert(e.second);
480 for (
const Edge &e : sub_graph)
481 identities_graph.erase(e);
489 for (
const auto &edge : sub_graph)
490 Assert(sub_graph.find({edge.second, edge.first}) !=
500 for (
const Node &n : sub_graph_nodes)
501 for (
const Edge &e : identities_graph)
508 Assert(sub_graph.size() ==
509 sub_graph_nodes.size() * (sub_graph_nodes.size() - 1),
522 identities.emplace_back(sub_graph_nodes.begin(),
523 sub_graph_nodes.end());
524 Assert(identities.back().size() == sub_graph_nodes.size(),
534 template <
int dim,
int spacedim>
535 std::vector<std::map<unsigned int, unsigned int>>
537 const std::set<unsigned int> &fes)
const
539 auto query_vertex_dof_identities = [
this](
const unsigned int fe_index_1,
540 const unsigned int fe_index_2) {
541 return (*
this)[fe_index_1].hp_vertex_dof_identities((*
this)[fe_index_2]);
543 return compute_hp_dof_identities(fes, query_vertex_dof_identities);
548 template <
int dim,
int spacedim>
549 std::vector<std::map<unsigned int, unsigned int>>
551 const std::set<unsigned int> &fes)
const
553 auto query_line_dof_identities = [
this](
const unsigned int fe_index_1,
554 const unsigned int fe_index_2) {
555 return (*
this)[fe_index_1].hp_line_dof_identities((*
this)[fe_index_2]);
557 return compute_hp_dof_identities(fes, query_line_dof_identities);
562 template <
int dim,
int spacedim>
563 std::vector<std::map<unsigned int, unsigned int>>
565 const std::set<unsigned int> &fes,
566 const unsigned int face_no)
const
568 auto query_quad_dof_identities = [
this,
569 face_no](
const unsigned int fe_index_1,
570 const unsigned int fe_index_2) {
571 return (*
this)[fe_index_1].hp_quad_dof_identities((*
this)[fe_index_2],
574 return compute_hp_dof_identities(fes, query_quad_dof_identities);
579 template <
int dim,
int spacedim>
584 const unsigned int)> &next,
587 const unsigned int)> &
prev)
590 hierarchy_next = next;
591 hierarchy_prev =
prev;
596 template <
int dim,
int spacedim>
601 set_hierarchy(&DefaultHierarchy::next_index,
602 &DefaultHierarchy::previous_index);
607 template <
int dim,
int spacedim>
608 std::vector<unsigned int>
610 const unsigned int fe_index)
const
614 std::deque<unsigned int> sequence = {fe_index};
618 unsigned int front = sequence.front();
619 unsigned int previous;
620 while ((previous = previous_in_hierarchy(front)) != front)
622 sequence.push_front(previous);
625 Assert(sequence.size() <= this->size(),
627 "The registered hierarchy is not terminated: "
628 "previous_in_hierarchy() does not stop at a final index."));
634 unsigned int back = sequence.back();
636 while ((next = next_in_hierarchy(back)) != back)
638 sequence.push_back(next);
641 Assert(sequence.size() <= this->size(),
643 "The registered hierarchy is not terminated: "
644 "next_in_hierarchy() does not stop at a final index."));
648 return {sequence.begin(), sequence.end()};
653 template <
int dim,
int spacedim>
656 const unsigned int fe_index)
const
660 const unsigned int new_fe_index = hierarchy_next(*
this, fe_index);
668 template <
int dim,
int spacedim>
671 const unsigned int fe_index)
const
675 const unsigned int new_fe_index = hierarchy_prev(*
this, fe_index);
683 template <
int dim,
int spacedim>
689 ExcMessage(
"This collection contains no finite element."));
692 const ComponentMask mask = (*this)[0].component_mask(scalar);
696 for (
unsigned int c = 1; c < this->
size(); ++c)
703 template <
int dim,
int spacedim>
709 ExcMessage(
"This collection contains no finite element."));
712 const ComponentMask mask = (*this)[0].component_mask(vector);
716 for (
unsigned int c = 1; c < this->
size(); ++c)
723 template <
int dim,
int spacedim>
729 ExcMessage(
"This collection contains no finite element."));
732 const ComponentMask mask = (*this)[0].component_mask(sym_tensor);
736 for (
unsigned int c = 1; c < this->
size(); ++c)
743 template <
int dim,
int spacedim>
748 ExcMessage(
"This collection contains no finite element."));
751 const ComponentMask mask = (*this)[0].component_mask(block_mask);
755 for (
unsigned int c = 1; c < this->
size(); ++c)
756 Assert(mask == (*
this)[c].component_mask(block_mask),
757 ExcMessage(
"Not all elements of this collection agree on what "
758 "the appropriate mask should be."));
764 template <
int dim,
int spacedim>
770 ExcMessage(
"This collection contains no finite element."));
773 const BlockMask mask = (*this)[0].block_mask(scalar);
777 for (
unsigned int c = 1; c < this->
size(); ++c)
778 Assert(mask == (*
this)[c].block_mask(scalar),
779 ExcMessage(
"Not all elements of this collection agree on what "
780 "the appropriate mask should be."));
786 template <
int dim,
int spacedim>
792 ExcMessage(
"This collection contains no finite element."));
795 const BlockMask mask = (*this)[0].block_mask(vector);
799 for (
unsigned int c = 1; c < this->
size(); ++c)
800 Assert(mask == (*
this)[c].block_mask(vector),
801 ExcMessage(
"Not all elements of this collection agree on what "
802 "the appropriate mask should be."));
808 template <
int dim,
int spacedim>
814 ExcMessage(
"This collection contains no finite element."));
817 const BlockMask mask = (*this)[0].block_mask(sym_tensor);
821 for (
unsigned int c = 1; c < this->
size(); ++c)
822 Assert(mask == (*
this)[c].block_mask(sym_tensor),
823 ExcMessage(
"Not all elements of this collection agree on what "
824 "the appropriate mask should be."));
831 template <
int dim,
int spacedim>
837 ExcMessage(
"This collection contains no finite element."));
840 const BlockMask mask = (*this)[0].block_mask(component_mask);
844 for (
unsigned int c = 1; c < this->
size(); ++c)
845 Assert(mask == (*
this)[c].block_mask(component_mask),
846 ExcMessage(
"Not all elements of this collection agree on what "
847 "the appropriate mask should be."));
854 template <
int dim,
int spacedim>
858 Assert(this->
size() > 0, ExcNoFiniteElements());
860 const unsigned int nb = this->operator[](0).n_blocks();
861 for (
unsigned int i = 1; i < this->
size(); ++i)
862 Assert(this->
operator[](i).n_blocks() == nb,
863 ExcMessage(
"Not all finite elements in this collection have "
864 "the same number of components."));
873#include "hp/fe_collection.inst"
563 std::vector<std::map<unsigned int, unsigned int>> {
…}
535 std::vector<std::map<unsigned int, unsigned int>> {
…}
509 sub_graph_nodes.size() * (sub_graph_nodes.size() - 1), {
…}
385 using Node = std::pair<unsigned int, unsigned int>; {
…}
359 query_identities(fe_index_1, fe_index_2); {
…}
229 this->operator[](current_fe) {
…}
190 dominated_fes.insert(current_fe); {
…}
119 const unsigned int codim)
const {
…}
unsigned int n_components() const
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const =0
std::vector< std::map< unsigned int, unsigned int > > hp_vertex_dof_identities(const std::set< unsigned int > &fes) const
unsigned int previous_in_hierarchy(const unsigned int fe_index) const
std::vector< unsigned int > get_hierarchy_sequence(const unsigned int fe_index=0) const
unsigned int find_dominating_fe_extended(const std::set< unsigned int > &fes, const unsigned int codim=0) const
const MappingCollection< dim, spacedim > & get_reference_cell_default_linear_mapping() const
std::set< unsigned int > find_common_fes(const std::set< unsigned int > &fes, const unsigned int codim=0) const
void push_back(const FiniteElement< dim, spacedim > &new_fe)
unsigned int next_in_hierarchy(const unsigned int fe_index) const
void set_default_hierarchy()
std::shared_ptr< MappingCollection< dim, spacedim > > reference_cell_default_linear_mapping
unsigned int find_dominating_fe(const std::set< unsigned int > &fes, const unsigned int codim=0) const
std::set< unsigned int > find_enclosing_fes(const std::set< unsigned int > &fes, const unsigned int codim=0) const
unsigned int find_dominated_fe(const std::set< unsigned int > &fes, const unsigned int codim=0) const
ComponentMask component_mask(const FEValuesExtractors::Scalar &scalar) const
std::vector< std::map< unsigned int, unsigned int > > hp_line_dof_identities(const std::set< unsigned int > &fes) const
void set_hierarchy(const std::function< unsigned int(const typename hp::FECollection< dim, spacedim > &, const unsigned int)> &next, const std::function< unsigned int(const typename hp::FECollection< dim, spacedim > &, const unsigned int)> &prev)
unsigned int find_dominated_fe_extended(const std::set< unsigned int > &fes, const unsigned int codim=0) const
unsigned int n_blocks() const
std::vector< std::map< unsigned int, unsigned int > > hp_quad_dof_identities(const std::set< unsigned int > &fes, const unsigned int face_no=0) const
BlockMask block_mask(const FEValuesExtractors::Scalar &scalar) const
#define DEAL_II_NAMESPACE_OPEN
constexpr bool running_in_debug_mode()
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcEmptyObject()
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
@ either_element_can_dominate
@ other_element_dominates
constexpr types::fe_index invalid_fe_index
void prev(std::tuple< I1, I2 > &t)