29 template <
int dim,
int spacedim>
32 set_default_hierarchy();
37 template <
int dim,
int spacedim>
47 template <
int dim,
int spacedim>
53 ExcMessage(
"Need to pass at least one finite element."));
55 for (
unsigned int i = 0; i < fes.size(); ++i)
61 template <
int dim,
int spacedim>
70 new_fe.
n_components() == this->operator[](0).n_components(),
71 ExcMessage(
"All elements inside a collection need to have the "
72 "same number of vector components!"));
79 template <
int dim,
int spacedim>
83 Assert(this->
size() > 0, ExcNoFiniteElements());
94 if (!reference_cell_default_linear_mapping ||
95 reference_cell_default_linear_mapping->size() != this->size())
100 std::make_shared<MappingCollection<dim, spacedim>>();
102 for (
const auto &fe : *
this)
103 this_nc.reference_cell_default_linear_mapping->push_back(
105 .template get_default_linear_mapping<spacedim>());
108 return *reference_cell_default_linear_mapping;
113 template <
int dim,
int spacedim>
114 std::set<unsigned int>
116 const std::set<unsigned int> &fes,
117 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
165 for (
const auto &fe : fes)
172 std::set<unsigned int> dominated_fes;
173 for (
unsigned int current_fe = 0; current_fe < this->
size(); ++current_fe)
178 for (
const auto &other_fe : fes)
181 this->
operator[](current_fe)
182 .compare_for_domination(this->
operator[](other_fe), codim);
188 dominated_fes.insert(current_fe);
190 return dominated_fes;
195 template <
int dim,
int spacedim>
198 const std::set<unsigned int> &fes,
199 const unsigned int codim)
const
211 for (
const auto &fe : fes)
218 for (
const auto ¤t_fe : fes)
223 for (
const auto &other_fe : fes)
224 if (current_fe != other_fe)
227 this->operator[](current_fe)
228 .compare_for_domination(this->
operator[](other_fe), codim);
243 template <
int dim,
int spacedim>
246 const std::set<unsigned int> &fes,
247 const unsigned int codim)
const
259 for (
const auto &fe : fes)
266 for (
const auto ¤t_fe : fes)
271 for (
const auto &other_fe : fes)
272 if (current_fe != other_fe)
275 this->operator[](current_fe)
276 .compare_for_domination(this->
operator[](other_fe), codim);
291 template <
int dim,
int spacedim>
294 const std::set<unsigned int> &fes,
295 const unsigned int codim)
const
297 unsigned int fe_index = find_dominating_fe(fes, codim);
301 const std::set<unsigned int> dominating_fes =
302 find_common_fes(fes, codim);
303 fe_index = find_dominated_fe(dominating_fes, codim);
311 template <
int dim,
int spacedim>
314 const std::set<unsigned int> &fes,
315 const unsigned int codim)
const
317 unsigned int fe_index = find_dominated_fe(fes, codim);
321 const std::set<unsigned int> dominated_fes =
322 find_enclosing_fes(fes, codim);
323 fe_index = find_dominating_fe(dominated_fes, codim);
337 std::vector<std::map<unsigned int, unsigned int>>
338 compute_hp_dof_identities(
339 const std::set<unsigned int> &fes,
340 const std::function<std::vector<std::pair<unsigned int, unsigned int>>(
342 const unsigned int)> &query_identities)
354 const unsigned int fe_index_1 = *fes.begin();
355 const unsigned int fe_index_2 = *(++fes.begin());
356 const auto reduced_identities =
357 query_identities(fe_index_1, fe_index_2);
359 std::vector<std::map<unsigned int, unsigned int>> complete_identities;
361 for (
const auto &reduced_identity : reduced_identities)
366 std::map<unsigned int, unsigned int> complete_identity = {
367 {fe_index_1, reduced_identity.first},
368 {fe_index_2, reduced_identity.second}};
369 complete_identities.emplace_back(std::move(complete_identity));
372 return complete_identities;
383 using Node = std::pair<unsigned int, unsigned int>;
384 using Edge = std::pair<Node, Node>;
385 using Graph = std::set<Edge>;
387 Graph identities_graph;
388 for (
const unsigned int fe_index_1 : fes)
389 for (const unsigned
int fe_index_2 : fes)
390 if (fe_index_1 != fe_index_2)
391 for (const auto &identity :
392 query_identities(fe_index_1, fe_index_2))
393 identities_graph.emplace(Node(fe_index_1, identity.
first),
394 Node(fe_index_2, identity.
second));
403 for (
const auto &edge : identities_graph)
404 Assert(identities_graph.find({edge.second, edge.first}) !=
405 identities_graph.end(),
457 std::vector<std::map<unsigned int, unsigned int>> identities;
458 while (identities_graph.size() > 0)
461 std::set<Node> sub_graph_nodes;
463 sub_graph.emplace(*identities_graph.begin());
464 sub_graph_nodes.emplace(identities_graph.begin()->first);
465 sub_graph_nodes.emplace(identities_graph.begin()->second);
467 for (
const Edge &e : identities_graph)
468 if ((sub_graph_nodes.find(e.first) != sub_graph_nodes.end()) ||
469 (sub_graph_nodes.find(e.second) != sub_graph_nodes.end()))
472 sub_graph_nodes.insert(e.first);
473 sub_graph_nodes.insert(e.second);
478 for (
const Edge &e : sub_graph)
479 identities_graph.erase(e);
487 for (
const auto &edge : sub_graph)
488 Assert(sub_graph.find({edge.second, edge.first}) !=
498 for (
const Node &n : sub_graph_nodes)
499 for (const Edge &e : identities_graph)
506 Assert(sub_graph.size() ==
507 sub_graph_nodes.size() * (sub_graph_nodes.size() - 1),
520 identities.emplace_back(sub_graph_nodes.begin(),
521 sub_graph_nodes.end());
522 Assert(identities.back().size() == sub_graph_nodes.size(),
532 template <
int dim,
int spacedim>
533 std::vector<std::map<unsigned int, unsigned int>>
535 const std::set<unsigned int> &fes)
const
537 auto query_vertex_dof_identities = [
this](
const unsigned int fe_index_1,
538 const unsigned int fe_index_2) {
539 return (*
this)[fe_index_1].hp_vertex_dof_identities((*
this)[fe_index_2]);
541 return compute_hp_dof_identities(fes, query_vertex_dof_identities);
546 template <
int dim,
int spacedim>
547 std::vector<std::map<unsigned int, unsigned int>>
549 const std::set<unsigned int> &fes)
const
551 auto query_line_dof_identities = [
this](
const unsigned int fe_index_1,
552 const unsigned int fe_index_2) {
553 return (*
this)[fe_index_1].hp_line_dof_identities((*
this)[fe_index_2]);
555 return compute_hp_dof_identities(fes, query_line_dof_identities);
560 template <
int dim,
int spacedim>
561 std::vector<std::map<unsigned int, unsigned int>>
563 const std::set<std::pair<unsigned int, unsigned int>> &fes_and_faces)
const
566 std::pair<unsigned int, unsigned int> fe_and_face_1 =
567 *fes_and_faces.begin();
568 std::pair<unsigned int, unsigned int> fe_and_face_2 =
569 *(++fes_and_faces.begin());
571 auto query_quad_dof_identities =
572 [
this, &fe_and_face_1, &fe_and_face_2](
const unsigned int fe_index_1,
573 const unsigned int fe_index_2) {
576 const unsigned int face_no = fe_index_1 == fe_and_face_1.first ?
577 fe_and_face_1.second :
578 fe_and_face_2.second;
579 return (*
this)[fe_index_1].hp_quad_dof_identities((*
this)[fe_index_2],
584 std::set<unsigned int> fe_indices_only;
585 for (
const auto &[fe_index, face_index] : fes_and_faces)
587 fe_indices_only.insert(fe_index);
591 return compute_hp_dof_identities(fe_indices_only,
592 query_quad_dof_identities);
597 template <
int dim,
int spacedim>
602 const unsigned int)> &next,
605 const unsigned int)> &
prev)
608 hierarchy_next = next;
609 hierarchy_prev =
prev;
614 template <
int dim,
int spacedim>
619 set_hierarchy(&DefaultHierarchy::next_index,
620 &DefaultHierarchy::previous_index);
625 template <
int dim,
int spacedim>
626 std::vector<unsigned int>
628 const unsigned int fe_index)
const
632 std::deque<unsigned int> sequence = {fe_index};
636 unsigned int front = sequence.front();
637 unsigned int previous;
638 while ((previous = previous_in_hierarchy(front)) != front)
640 sequence.push_front(previous);
643 Assert(sequence.size() <= this->size(),
645 "The registered hierarchy is not terminated: "
646 "previous_in_hierarchy() does not stop at a final index."));
652 unsigned int back = sequence.back();
654 while ((next = next_in_hierarchy(back)) != back)
656 sequence.push_back(next);
659 Assert(sequence.size() <= this->size(),
661 "The registered hierarchy is not terminated: "
662 "next_in_hierarchy() does not stop at a final index."));
666 return {sequence.begin(), sequence.end()};
671 template <
int dim,
int spacedim>
674 const unsigned int fe_index)
const
678 const unsigned int new_fe_index = hierarchy_next(*
this, fe_index);
686 template <
int dim,
int spacedim>
689 const unsigned int fe_index)
const
693 const unsigned int new_fe_index = hierarchy_prev(*
this, fe_index);
701 template <
int dim,
int spacedim>
707 ExcMessage(
"This collection contains no finite element."));
710 const ComponentMask mask = (*this)[0].component_mask(scalar);
714 for (
unsigned int c = 1; c < this->
size(); ++c)
721 template <
int dim,
int spacedim>
727 ExcMessage(
"This collection contains no finite element."));
730 const ComponentMask mask = (*this)[0].component_mask(vector);
734 for (
unsigned int c = 1; c < this->
size(); ++c)
741 template <
int dim,
int spacedim>
747 ExcMessage(
"This collection contains no finite element."));
750 const ComponentMask mask = (*this)[0].component_mask(sym_tensor);
754 for (
unsigned int c = 1; c < this->
size(); ++c)
761 template <
int dim,
int spacedim>
766 ExcMessage(
"This collection contains no finite element."));
769 const ComponentMask mask = (*this)[0].component_mask(block_mask);
773 for (
unsigned int c = 1; c < this->
size(); ++c)
774 Assert(mask == (*
this)[c].component_mask(block_mask),
775 ExcMessage(
"Not all elements of this collection agree on what "
776 "the appropriate mask should be."));
782 template <
int dim,
int spacedim>
788 ExcMessage(
"This collection contains no finite element."));
791 const BlockMask mask = (*this)[0].block_mask(scalar);
795 for (
unsigned int c = 1; c < this->
size(); ++c)
796 Assert(mask == (*
this)[c].block_mask(scalar),
797 ExcMessage(
"Not all elements of this collection agree on what "
798 "the appropriate mask should be."));
804 template <
int dim,
int spacedim>
810 ExcMessage(
"This collection contains no finite element."));
813 const BlockMask mask = (*this)[0].block_mask(vector);
817 for (
unsigned int c = 1; c < this->
size(); ++c)
818 Assert(mask == (*
this)[c].block_mask(vector),
819 ExcMessage(
"Not all elements of this collection agree on what "
820 "the appropriate mask should be."));
826 template <
int dim,
int spacedim>
832 ExcMessage(
"This collection contains no finite element."));
835 const BlockMask mask = (*this)[0].block_mask(sym_tensor);
839 for (
unsigned int c = 1; c < this->
size(); ++c)
840 Assert(mask == (*
this)[c].block_mask(sym_tensor),
841 ExcMessage(
"Not all elements of this collection agree on what "
842 "the appropriate mask should be."));
849 template <
int dim,
int spacedim>
855 ExcMessage(
"This collection contains no finite element."));
858 const BlockMask mask = (*this)[0].block_mask(component_mask);
862 for (
unsigned int c = 1; c < this->
size(); ++c)
863 Assert(mask == (*
this)[c].block_mask(component_mask),
864 ExcMessage(
"Not all elements of this collection agree on what "
865 "the appropriate mask should be."));
872 template <
int dim,
int spacedim>
876 Assert(this->
size() > 0, ExcNoFiniteElements());
878 const unsigned int nb = this->operator[](0).n_blocks();
879 for (
unsigned int i = 1; i < this->
size(); ++i)
880 Assert(this->
operator[](i).n_blocks() == nb,
881 ExcMessage(
"Not all finite elements in this collection have "
882 "the same number of components."));
891#include "hp/fe_collection.inst"
* * for(const auto &cell :triangulation.active_cell_iterators())
***mech_lbc_system increment_interpolation_handlers push_back(scale_z_handler)
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
std::vector< std::map< unsigned int, unsigned int > > hp_quad_dof_identities(const std::set< std::pair< unsigned int, unsigned int > > &fes_and_faces) 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
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)