30 template <
int dim,
int spacedim>
33 set_default_hierarchy();
38 template <
int dim,
int spacedim>
48 template <
int dim,
int spacedim>
54 ExcMessage(
"Need to pass at least one finite element."));
56 for (
unsigned int i = 0; i < fes.size(); ++i)
62 template <
int dim,
int spacedim>
71 new_fe.
n_components() == this->operator[](0).n_components(),
72 ExcMessage(
"All elements inside a collection need to have the "
73 "same number of vector components!"));
80 template <
int dim,
int spacedim>
84 Assert(this->
size() > 0, ExcNoFiniteElements());
95 if (!reference_cell_default_linear_mapping ||
96 reference_cell_default_linear_mapping->size() != this->size())
101 std::make_shared<MappingCollection<dim, spacedim>>();
103 for (
const auto &fe : *
this)
104 this_nc.reference_cell_default_linear_mapping->push_back(
106 .template get_default_linear_mapping<dim, spacedim>());
109 return *reference_cell_default_linear_mapping;
114 template <
int dim,
int spacedim>
115 std::set<unsigned int>
117 const std::set<unsigned int> &fes,
118 const unsigned int codim)
const
124 for (
const auto &fe : fes)
131 std::set<unsigned int> dominating_fes;
132 for (
unsigned int current_fe = 0; current_fe < this->
size(); ++current_fe)
137 for (
const auto &other_fe : fes)
140 this->operator[](current_fe)
141 .compare_for_domination(this->operator[](other_fe), codim);
147 dominating_fes.insert(current_fe);
149 return dominating_fes;
154 template <
int dim,
int spacedim>
155 std::set<unsigned int>
157 const std::set<unsigned int> &fes,
158 const unsigned int codim)
const
164 for (
const auto &fe : fes)
171 std::set<unsigned int> dominated_fes;
172 for (
unsigned int current_fe = 0; current_fe < this->
size(); ++current_fe)
177 for (
const auto &other_fe : fes)
180 this->
operator[](current_fe)
181 .compare_for_domination(this->
operator[](other_fe), codim);
187 dominated_fes.insert(current_fe);
189 return dominated_fes;
194 template <
int dim,
int spacedim>
197 const std::set<unsigned int> &fes,
198 const unsigned int codim)
const
209 for (
const auto &fe : fes)
216 for (
const auto ¤t_fe : fes)
221 for (
const auto &other_fe : fes)
222 if (current_fe != other_fe)
225 this->operator[](current_fe)
226 .compare_for_domination(this->
operator[](other_fe), codim);
241 template <
int dim,
int spacedim>
244 const std::set<unsigned int> &fes,
245 const unsigned int codim)
const
256 for (
const auto &fe : fes)
263 for (
const auto ¤t_fe : fes)
268 for (
const auto &other_fe : fes)
269 if (current_fe != other_fe)
272 this->operator[](current_fe)
273 .compare_for_domination(this->
operator[](other_fe), codim);
288 template <
int dim,
int spacedim>
291 const std::set<unsigned int> &fes,
292 const unsigned int codim)
const
294 unsigned int fe_index = find_dominating_fe(fes, codim);
298 const std::set<unsigned int> dominating_fes =
299 find_common_fes(fes, codim);
300 fe_index = find_dominated_fe(dominating_fes, codim);
308 template <
int dim,
int spacedim>
311 const std::set<unsigned int> &fes,
312 const unsigned int codim)
const
314 unsigned int fe_index = find_dominated_fe(fes, codim);
318 const std::set<unsigned int> dominated_fes =
319 find_enclosing_fes(fes, codim);
320 fe_index = find_dominating_fe(dominated_fes, codim);
334 std::vector<std::map<unsigned int, unsigned int>>
335 compute_hp_dof_identities(
336 const std::set<unsigned int> &fes,
337 const std::function<std::vector<std::pair<unsigned int, unsigned int>>(
339 const unsigned int)> &query_identities)
351 const unsigned int fe_index_1 = *fes.begin();
352 const unsigned int fe_index_2 = *(++fes.begin());
353 const auto reduced_identities =
354 query_identities(fe_index_1, fe_index_2);
356 std::vector<std::map<unsigned int, unsigned int>> complete_identities;
358 for (
const auto &reduced_identity : reduced_identities)
363 std::map<unsigned int, unsigned int> complete_identity = {
364 {fe_index_1, reduced_identity.first},
365 {fe_index_2, reduced_identity.second}};
366 complete_identities.emplace_back(std::move(complete_identity));
369 return complete_identities;
380 using Node = std::pair<unsigned int, unsigned int>;
381 using Edge = std::pair<Node, Node>;
382 using Graph = std::set<Edge>;
384 Graph identities_graph;
385 for (
const unsigned int fe_index_1 : fes)
386 for (const unsigned
int fe_index_2 : fes)
387 if (fe_index_1 != fe_index_2)
389 query_identities(fe_index_1, fe_index_2))
399 for (
const auto &edge : identities_graph)
400 Assert(identities_graph.find({edge.second, edge.first}) !=
401 identities_graph.end(),
453 std::vector<std::map<unsigned int, unsigned int>> identities;
454 while (identities_graph.size() > 0)
457 std::set<Node> sub_graph_nodes;
459 sub_graph.emplace(*identities_graph.begin());
460 sub_graph_nodes.emplace(identities_graph.begin()->first);
461 sub_graph_nodes.emplace(identities_graph.begin()->second);
463 for (
const Edge &e : identities_graph)
464 if ((sub_graph_nodes.find(e.first) != sub_graph_nodes.end()) ||
465 (sub_graph_nodes.find(e.second) != sub_graph_nodes.end()))
468 sub_graph_nodes.insert(e.first);
469 sub_graph_nodes.insert(e.second);
474 for (
const Edge &e : sub_graph)
475 identities_graph.erase(e);
481 for (
const auto &edge : sub_graph)
482 Assert(sub_graph.find({edge.second, edge.first}) != sub_graph.end(),
491 for (
const Node &n : sub_graph_nodes)
492 for (const Edge &e : identities_graph)
499 Assert(sub_graph.size() ==
500 sub_graph_nodes.size() * (sub_graph_nodes.size() - 1),
513 identities.emplace_back(sub_graph_nodes.begin(),
514 sub_graph_nodes.end());
515 Assert(identities.back().size() == sub_graph_nodes.size(),
525 template <
int dim,
int spacedim>
526 std::vector<std::map<unsigned int, unsigned int>>
528 const std::set<unsigned int> &fes)
const
530 auto query_vertex_dof_identities = [
this](
const unsigned int fe_index_1,
531 const unsigned int fe_index_2) {
532 return (*
this)[fe_index_1].hp_vertex_dof_identities((*
this)[fe_index_2]);
534 return compute_hp_dof_identities(fes, query_vertex_dof_identities);
539 template <
int dim,
int spacedim>
540 std::vector<std::map<unsigned int, unsigned int>>
542 const std::set<unsigned int> &fes)
const
544 auto query_line_dof_identities = [
this](
const unsigned int fe_index_1,
545 const unsigned int fe_index_2) {
546 return (*
this)[fe_index_1].hp_line_dof_identities((*
this)[fe_index_2]);
548 return compute_hp_dof_identities(fes, query_line_dof_identities);
553 template <
int dim,
int spacedim>
554 std::vector<std::map<unsigned int, unsigned int>>
556 const std::set<unsigned int> &fes,
557 const unsigned int face_no)
const
559 auto query_quad_dof_identities = [
this,
560 face_no](
const unsigned int fe_index_1,
561 const unsigned int fe_index_2) {
562 return (*
this)[fe_index_1].hp_quad_dof_identities((*
this)[fe_index_2],
565 return compute_hp_dof_identities(fes, query_quad_dof_identities);
570 template <
int dim,
int spacedim>
575 const unsigned int)> &next,
578 const unsigned int)> &prev)
581 hierarchy_next = next;
582 hierarchy_prev = prev;
587 template <
int dim,
int spacedim>
592 set_hierarchy(&DefaultHierarchy::next_index,
593 &DefaultHierarchy::previous_index);
598 template <
int dim,
int spacedim>
599 std::vector<unsigned int>
601 const unsigned int fe_index)
const
605 std::deque<unsigned int> sequence = {fe_index};
609 unsigned int front = sequence.front();
610 unsigned int previous;
611 while ((previous = previous_in_hierarchy(front)) != front)
613 sequence.push_front(previous);
616 Assert(sequence.size() <= this->size(),
618 "The registered hierarchy is not terminated: "
619 "previous_in_hierarchy() does not stop at a final index."));
625 unsigned int back = sequence.back();
627 while ((next = next_in_hierarchy(back)) != back)
629 sequence.push_back(next);
632 Assert(sequence.size() <= this->size(),
634 "The registered hierarchy is not terminated: "
635 "next_in_hierarchy() does not stop at a final index."));
639 return {sequence.begin(), sequence.end()};
644 template <
int dim,
int spacedim>
647 const unsigned int fe_index)
const
651 const unsigned int new_fe_index = hierarchy_next(*
this, fe_index);
659 template <
int dim,
int spacedim>
662 const unsigned int fe_index)
const
666 const unsigned int new_fe_index = hierarchy_prev(*
this, fe_index);
674 template <
int dim,
int spacedim>
680 ExcMessage(
"This collection contains no finite element."));
683 const ComponentMask mask = (*this)[0].component_mask(scalar);
687 for (
unsigned int c = 1; c < this->
size(); ++c)
694 template <
int dim,
int spacedim>
700 ExcMessage(
"This collection contains no finite element."));
703 const ComponentMask mask = (*this)[0].component_mask(vector);
707 for (
unsigned int c = 1; c < this->
size(); ++c)
714 template <
int dim,
int spacedim>
720 ExcMessage(
"This collection contains no finite element."));
723 const ComponentMask mask = (*this)[0].component_mask(sym_tensor);
727 for (
unsigned int c = 1; c < this->
size(); ++c)
734 template <
int dim,
int spacedim>
739 ExcMessage(
"This collection contains no finite element."));
742 const ComponentMask mask = (*this)[0].component_mask(block_mask);
746 for (
unsigned int c = 1; c < this->
size(); ++c)
747 Assert(mask == (*
this)[c].component_mask(block_mask),
748 ExcMessage(
"Not all elements of this collection agree on what "
749 "the appropriate mask should be."));
755 template <
int dim,
int spacedim>
761 ExcMessage(
"This collection contains no finite element."));
764 const BlockMask mask = (*this)[0].block_mask(scalar);
768 for (
unsigned int c = 1; c < this->
size(); ++c)
769 Assert(mask == (*
this)[c].block_mask(scalar),
770 ExcMessage(
"Not all elements of this collection agree on what "
771 "the appropriate mask should be."));
777 template <
int dim,
int spacedim>
783 ExcMessage(
"This collection contains no finite element."));
786 const BlockMask mask = (*this)[0].block_mask(vector);
790 for (
unsigned int c = 1; c < this->
size(); ++c)
791 Assert(mask == (*
this)[c].block_mask(vector),
792 ExcMessage(
"Not all elements of this collection agree on what "
793 "the appropriate mask should be."));
799 template <
int dim,
int spacedim>
805 ExcMessage(
"This collection contains no finite element."));
808 const BlockMask mask = (*this)[0].block_mask(sym_tensor);
812 for (
unsigned int c = 1; c < this->
size(); ++c)
813 Assert(mask == (*
this)[c].block_mask(sym_tensor),
814 ExcMessage(
"Not all elements of this collection agree on what "
815 "the appropriate mask should be."));
822 template <
int dim,
int spacedim>
828 ExcMessage(
"This collection contains no finite element."));
831 const BlockMask mask = (*this)[0].block_mask(component_mask);
835 for (
unsigned int c = 1; c < this->
size(); ++c)
836 Assert(mask == (*
this)[c].block_mask(component_mask),
837 ExcMessage(
"Not all elements of this collection agree on what "
838 "the appropriate mask should be."));
845 template <
int dim,
int spacedim>
849 Assert(this->
size() > 0, ExcNoFiniteElements());
851 const unsigned int nb = this->operator[](0).n_blocks();
852 for (
unsigned int i = 1; i < this->
size(); ++i)
853 Assert(this->
operator[](i).n_blocks() == nb,
854 ExcMessage(
"Not all finite elements in this collection have "
855 "the same number of components."));
864#include "fe_collection.inst"
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
#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
const types::fe_index invalid_fe_index