Reference documentation for deal.II version 9.3.2
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
fe_collection.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2003 - 2021 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
18 
20 
22 
23 namespace hp
24 {
25  template <int dim, int spacedim>
26  std::set<unsigned int>
28  const std::set<unsigned int> &fes,
29  const unsigned int codim) const
30  {
31 #ifdef DEBUG
32  // Validate user inputs.
33  Assert(codim <= dim, ExcImpossibleInDim(dim));
34  Assert(this->size() > 0, ExcEmptyObject());
35  for (const auto &fe : fes)
36  AssertIndexRange(fe, this->size());
37 #endif
38 
39  // Check if any element of this FECollection is able to dominate all
40  // elements of @p fes. If one was found, we add it to the set of
41  // dominating elements.
42  std::set<unsigned int> dominating_fes;
43  for (unsigned int current_fe = 0; current_fe < this->size(); ++current_fe)
44  {
45  // Check if current_fe can dominate all elements in @p fes.
48  for (const auto &other_fe : fes)
49  domination =
50  domination &
51  this->operator[](current_fe)
52  .compare_for_domination(this->operator[](other_fe), codim);
53 
54  // If current_fe dominates, add it to the set.
57  /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
58  dominating_fes.insert(current_fe);
59  }
60  return dominating_fes;
61  }
62 
63 
64 
65  template <int dim, int spacedim>
66  std::set<unsigned int>
68  const std::set<unsigned int> &fes,
69  const unsigned int codim) const
70  {
71 #ifdef DEBUG
72  // Validate user inputs.
73  Assert(codim <= dim, ExcImpossibleInDim(dim));
74  Assert(this->size() > 0, ExcEmptyObject());
75  for (const auto &fe : fes)
76  AssertIndexRange(fe, this->size());
77 #endif
78 
79  // Check if any element of this FECollection is dominated by all
80  // elements of @p fes. If one was found, we add it to the set of
81  // dominated elements.
82  std::set<unsigned int> dominated_fes;
83  for (unsigned int current_fe = 0; current_fe < this->size(); ++current_fe)
84  {
85  // Check if current_fe is dominated by all other elements in @p fes.
88  for (const auto &other_fe : fes)
89  domination =
90  domination &
91  this->operator[](current_fe)
92  .compare_for_domination(this->operator[](other_fe), codim);
93 
94  // If current_fe is dominated, add it to the set.
97  /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
98  dominated_fes.insert(current_fe);
99  }
100  return dominated_fes;
101  }
102 
103 
104 
105  template <int dim, int spacedim>
106  unsigned int
108  const std::set<unsigned int> &fes,
109  const unsigned int codim) const
110  {
111  // If the set of elements contains only a single element,
112  // then this very element is considered to be the dominating one.
113  if (fes.size() == 1)
114  return *fes.begin();
115 
116 #ifdef DEBUG
117  // Validate user inputs.
118  Assert(codim <= dim, ExcImpossibleInDim(dim));
119  Assert(this->size() > 0, ExcEmptyObject());
120  for (const auto &fe : fes)
121  AssertIndexRange(fe, this->size());
122 #endif
123 
124  // There may also be others, in which case we'll check if any of these
125  // elements is able to dominate all others. If one was found, we stop
126  // looking further and return the dominating element.
127  for (const auto &current_fe : fes)
128  {
129  // Check if current_fe can dominate all elements in @p fes.
132  for (const auto &other_fe : fes)
133  if (current_fe != other_fe)
134  domination =
135  domination &
136  this->operator[](current_fe)
137  .compare_for_domination(this->operator[](other_fe), codim);
138 
139  // If current_fe dominates, return its index.
142  /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
143  return current_fe;
144  }
145 
146  // If we couldn't find the dominating object, return an invalid one.
148  }
149 
150 
151 
152  template <int dim, int spacedim>
153  unsigned int
155  const std::set<unsigned int> &fes,
156  const unsigned int codim) const
157  {
158  // If the set of elements contains only a single element,
159  // then this very element is considered to be the dominated one.
160  if (fes.size() == 1)
161  return *fes.begin();
162 
163 #ifdef DEBUG
164  // Validate user inputs.
165  Assert(codim <= dim, ExcImpossibleInDim(dim));
166  Assert(this->size() > 0, ExcEmptyObject());
167  for (const auto &fe : fes)
168  AssertIndexRange(fe, this->size());
169 #endif
170 
171  // There may also be others, in which case we'll check if any of these
172  // elements is dominated by all others. If one was found, we stop
173  // looking further and return the dominated element.
174  for (const auto &current_fe : fes)
175  {
176  // Check if current_fe is dominated by all other elements in @p fes.
179  for (const auto &other_fe : fes)
180  if (current_fe != other_fe)
181  domination =
182  domination &
183  this->operator[](current_fe)
184  .compare_for_domination(this->operator[](other_fe), codim);
185 
186  // If current_fe is dominated, return its index.
189  /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
190  return current_fe;
191  }
192 
193  // If we couldn't find the dominated object, return an invalid one.
195  }
196 
197 
198 
199  template <int dim, int spacedim>
200  unsigned int
202  const std::set<unsigned int> &fes,
203  const unsigned int codim) const
204  {
205  unsigned int fe_index = find_dominating_fe(fes, codim);
206 
207  if (fe_index == numbers::invalid_unsigned_int)
208  {
209  const std::set<unsigned int> dominating_fes =
210  find_common_fes(fes, codim);
211  fe_index = find_dominated_fe(dominating_fes, codim);
212  }
213 
214  return fe_index;
215  }
216 
217 
218 
219  template <int dim, int spacedim>
220  unsigned int
222  const std::set<unsigned int> &fes,
223  const unsigned int codim) const
224  {
225  unsigned int fe_index = find_dominated_fe(fes, codim);
226 
227  if (fe_index == numbers::invalid_unsigned_int)
228  {
229  const std::set<unsigned int> dominated_fes =
230  find_enclosing_fes(fes, codim);
231  fe_index = find_dominating_fe(dominated_fes, codim);
232  }
233 
234  return fe_index;
235  }
236 
237 
238 
239  template <int dim, int spacedim>
241  {
242  set_default_hierarchy();
243  }
244 
245 
246 
247  template <int dim, int spacedim>
250  : FECollection()
251  {
252  push_back(fe);
253  }
254 
255 
256 
257  template <int dim, int spacedim>
259  const std::vector<const FiniteElement<dim, spacedim> *> &fes)
260  : FECollection()
261  {
262  Assert(fes.size() > 0,
263  ExcMessage("Need to pass at least one finite element."));
264 
265  for (unsigned int i = 0; i < fes.size(); ++i)
266  push_back(*fes[i]);
267  }
268 
269 
270 
271  template <int dim, int spacedim>
272  void
274  const FiniteElement<dim, spacedim> &new_fe)
275  {
276  // check that the new element has the right number of components. only check
277  // with the first element, since all the other elements have already passed
278  // the test against the first element
279  Assert(this->size() == 0 ||
280  new_fe.n_components() == this->operator[](0).n_components(),
281  ExcMessage("All elements inside a collection need to have the "
282  "same number of vector components!"));
283 
284  Collection<FiniteElement<dim, spacedim>>::push_back(new_fe.clone());
285  }
286 
287 
288 
289  template <int dim, int spacedim>
290  void
292  const std::function<
293  unsigned int(const typename hp::FECollection<dim, spacedim> &,
294  const unsigned int)> &next,
295  const std::function<
296  unsigned int(const typename hp::FECollection<dim, spacedim> &,
297  const unsigned int)> &prev)
298  {
299  // copy hierarchy functions
300  hierarchy_next = next;
301  hierarchy_prev = prev;
302  }
303 
304 
305 
306  template <int dim, int spacedim>
307  void
309  {
310  // establish hierarchy corresponding to order of indices
311  set_hierarchy(&DefaultHierarchy::next_index,
312  &DefaultHierarchy::previous_index);
313  }
314 
315 
316 
317  template <int dim, int spacedim>
318  std::vector<unsigned int>
320  const unsigned int fe_index) const
321  {
322  AssertIndexRange(fe_index, this->size());
323 
324  std::deque<unsigned int> sequence = {fe_index};
325 
326  // get predecessors
327  {
328  unsigned int front = sequence.front();
329  unsigned int previous;
330  while ((previous = previous_in_hierarchy(front)) != front)
331  {
332  sequence.push_front(previous);
333  front = previous;
334 
335  Assert(sequence.size() <= this->size(),
336  ExcMessage(
337  "The registered hierarchy is not terminated: "
338  "previous_in_hierarchy() does not stop at a final index."));
339  }
340  }
341 
342  // get successors
343  {
344  unsigned int back = sequence.back();
345  unsigned int next;
346  while ((next = next_in_hierarchy(back)) != back)
347  {
348  sequence.push_back(next);
349  back = next;
350 
351  Assert(sequence.size() <= this->size(),
352  ExcMessage(
353  "The registered hierarchy is not terminated: "
354  "next_in_hierarchy() does not stop at a final index."));
355  }
356  }
357 
358  return {sequence.begin(), sequence.end()};
359  }
360 
361 
362 
363  template <int dim, int spacedim>
364  unsigned int
366  const unsigned int fe_index) const
367  {
368  AssertIndexRange(fe_index, this->size());
369 
370  const unsigned int new_fe_index = hierarchy_next(*this, fe_index);
371  AssertIndexRange(new_fe_index, this->size());
372 
373  return new_fe_index;
374  }
375 
376 
377 
378  template <int dim, int spacedim>
379  unsigned int
381  const unsigned int fe_index) const
382  {
383  AssertIndexRange(fe_index, this->size());
384 
385  const unsigned int new_fe_index = hierarchy_prev(*this, fe_index);
386  AssertIndexRange(new_fe_index, this->size());
387 
388  return new_fe_index;
389  }
390 
391 
392 
393  template <int dim, int spacedim>
396  const FEValuesExtractors::Scalar &scalar) const
397  {
398  Assert(this->size() > 0,
399  ExcMessage("This collection contains no finite element."));
400 
401  // get the mask from the first element of the collection
402  const ComponentMask mask = (*this)[0].component_mask(scalar);
403 
404  // but then also verify that the other elements of the collection
405  // would return the same mask
406  for (unsigned int c = 1; c < this->size(); ++c)
407  Assert(mask == (*this)[c].component_mask(scalar), ExcInternalError());
408 
409  return mask;
410  }
411 
412 
413  template <int dim, int spacedim>
416  const FEValuesExtractors::Vector &vector) const
417  {
418  Assert(this->size() > 0,
419  ExcMessage("This collection contains no finite element."));
420 
421  // get the mask from the first element of the collection
422  const ComponentMask mask = (*this)[0].component_mask(vector);
423 
424  // but then also verify that the other elements of the collection
425  // would return the same mask
426  for (unsigned int c = 1; c < this->size(); ++c)
427  Assert(mask == (*this)[c].component_mask(vector), ExcInternalError());
428 
429  return mask;
430  }
431 
432 
433  template <int dim, int spacedim>
436  const FEValuesExtractors::SymmetricTensor<2> &sym_tensor) const
437  {
438  Assert(this->size() > 0,
439  ExcMessage("This collection contains no finite element."));
440 
441  // get the mask from the first element of the collection
442  const ComponentMask mask = (*this)[0].component_mask(sym_tensor);
443 
444  // but then also verify that the other elements of the collection
445  // would return the same mask
446  for (unsigned int c = 1; c < this->size(); ++c)
447  Assert(mask == (*this)[c].component_mask(sym_tensor), ExcInternalError());
448 
449  return mask;
450  }
451 
452 
453  template <int dim, int spacedim>
456  {
457  Assert(this->size() > 0,
458  ExcMessage("This collection contains no finite element."));
459 
460  // get the mask from the first element of the collection
461  const ComponentMask mask = (*this)[0].component_mask(block_mask);
462 
463  // but then also verify that the other elements of the collection
464  // would return the same mask
465  for (unsigned int c = 1; c < this->size(); ++c)
466  Assert(mask == (*this)[c].component_mask(block_mask),
467  ExcMessage("Not all elements of this collection agree on what "
468  "the appropriate mask should be."));
469 
470  return mask;
471  }
472 
473 
474  template <int dim, int spacedim>
475  BlockMask
477  const FEValuesExtractors::Scalar &scalar) const
478  {
479  Assert(this->size() > 0,
480  ExcMessage("This collection contains no finite element."));
481 
482  // get the mask from the first element of the collection
483  const BlockMask mask = (*this)[0].block_mask(scalar);
484 
485  // but then also verify that the other elements of the collection
486  // would return the same mask
487  for (unsigned int c = 1; c < this->size(); ++c)
488  Assert(mask == (*this)[c].block_mask(scalar),
489  ExcMessage("Not all elements of this collection agree on what "
490  "the appropriate mask should be."));
491 
492  return mask;
493  }
494 
495 
496  template <int dim, int spacedim>
497  BlockMask
499  const FEValuesExtractors::Vector &vector) const
500  {
501  Assert(this->size() > 0,
502  ExcMessage("This collection contains no finite element."));
503 
504  // get the mask from the first element of the collection
505  const BlockMask mask = (*this)[0].block_mask(vector);
506 
507  // but then also verify that the other elements of the collection
508  // would return the same mask
509  for (unsigned int c = 1; c < this->size(); ++c)
510  Assert(mask == (*this)[c].block_mask(vector),
511  ExcMessage("Not all elements of this collection agree on what "
512  "the appropriate mask should be."));
513 
514  return mask;
515  }
516 
517 
518  template <int dim, int spacedim>
519  BlockMask
521  const FEValuesExtractors::SymmetricTensor<2> &sym_tensor) const
522  {
523  Assert(this->size() > 0,
524  ExcMessage("This collection contains no finite element."));
525 
526  // get the mask from the first element of the collection
527  const BlockMask mask = (*this)[0].block_mask(sym_tensor);
528 
529  // but then also verify that the other elements of the collection
530  // would return the same mask
531  for (unsigned int c = 1; c < this->size(); ++c)
532  Assert(mask == (*this)[c].block_mask(sym_tensor),
533  ExcMessage("Not all elements of this collection agree on what "
534  "the appropriate mask should be."));
535 
536  return mask;
537  }
538 
539 
540 
541  template <int dim, int spacedim>
542  BlockMask
544  const ComponentMask &component_mask) const
545  {
546  Assert(this->size() > 0,
547  ExcMessage("This collection contains no finite element."));
548 
549  // get the mask from the first element of the collection
550  const BlockMask mask = (*this)[0].block_mask(component_mask);
551 
552  // but then also verify that the other elements of the collection
553  // would return the same mask
554  for (unsigned int c = 1; c < this->size(); ++c)
555  Assert(mask == (*this)[c].block_mask(component_mask),
556  ExcMessage("Not all elements of this collection agree on what "
557  "the appropriate mask should be."));
558 
559  return mask;
560  }
561 
562 
563 
564  template <int dim, int spacedim>
565  unsigned int
567  {
568  Assert(this->size() > 0, ExcNoFiniteElements());
569 
570  const unsigned int nb = this->operator[](0).n_blocks();
571  for (unsigned int i = 1; i < this->size(); ++i)
572  Assert(this->operator[](i).n_blocks() == nb,
573  ExcMessage("Not all finite elements in this collection have "
574  "the same number of components."));
575 
576  return nb;
577  }
578 } // namespace hp
579 
580 
581 
582 // explicit instantiations
583 #include "fe_collection.inst"
584 
585 
std::vector< bool > block_mask
Definition: block_mask.h:213
std::vector< bool > component_mask
unsigned int n_components() const
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const =0
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)
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:396
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:397
static ::ExceptionBase & ExcInternalError()
#define Assert(cond, exc)
Definition: exceptions.h:1465
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
static ::ExceptionBase & ExcEmptyObject()
#define AssertIndexRange(index, range)
Definition: exceptions.h:1690
static ::ExceptionBase & ExcMessage(std::string arg1)
std::enable_if< IsBlockVector< VectorType >::value, unsigned int >::type n_blocks(const VectorType &vector)
Definition: operators.h:49
Definition: hp.h:118
static const unsigned int invalid_unsigned_int
Definition: types.h:196