Reference documentation for deal.II version 9.1.1
\(\newcommand{\dealcoloneq}{\mathrel{\vcenter{:}}=}\)
fe_collection.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2003 - 2019 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 
17 #include <deal.II/base/memory_consumption.h>
18 
19 #include <deal.II/hp/fe_collection.h>
20 
21 DEAL_II_NAMESPACE_OPEN
22 
23 namespace hp
24 {
25  template <int dim, int spacedim>
26  unsigned int
28  const std::set<unsigned int> &fes) const
29  {
30  return find_dominated_fe(find_common_fes(fes, /*codim*/ 1),
31  /*codim*/ 1);
32  }
33 
34 
35 
36  template <int dim, int spacedim>
37  std::set<unsigned int>
39  const std::set<unsigned int> &fes,
40  const unsigned int codim) const
41  {
42  // Validate user inputs.
43  Assert(codim <= dim, ExcImpossibleInDim(dim));
44  for (const auto &fe : fes)
45  {
46  (void)fe;
47  AssertIndexRange(fe, finite_elements.size());
48  }
49 
50  // Check if any element of this FECollection is able to dominate all
51  // elements of @p fes. If one was found, we add it to the set of
52  // dominating elements.
53  std::set<unsigned int> dominating_fes;
54  for (unsigned int current_fe = 0; current_fe < finite_elements.size();
55  ++current_fe)
56  {
57  // Check if current_fe can dominate all elements in @p fes.
60  for (const auto &other_fe : fes)
61  domination =
62  domination & finite_elements[current_fe]->compare_for_domination(
63  *finite_elements[other_fe], codim);
64 
65  // If current_fe dominates, add it to the set.
68  /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
69  dominating_fes.insert(current_fe);
70  }
71  return dominating_fes;
72  }
73 
74 
75 
76  template <int dim, int spacedim>
77  std::set<unsigned int>
79  const std::set<unsigned int> &fes,
80  const unsigned int codim) const
81  {
82  // Validate user inputs.
83  Assert(codim <= dim, ExcImpossibleInDim(dim));
84  for (const auto &fe : fes)
85  {
86  (void)fe;
87  AssertIndexRange(fe, finite_elements.size());
88  }
89 
90  // Check if any element of this FECollection is dominated by all
91  // elements of @p fes. If one was found, we add it to the set of
92  // dominated elements.
93  std::set<unsigned int> dominated_fes;
94  for (unsigned int current_fe = 0; current_fe < finite_elements.size();
95  ++current_fe)
96  {
97  // Check if current_fe is dominated by all other elements in @p fes.
100  for (const auto &other_fe : fes)
101  domination =
102  domination & finite_elements[current_fe]->compare_for_domination(
103  *finite_elements[other_fe], codim);
104 
105  // If current_fe is dominated, add it to the set.
108  /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
109  dominated_fes.insert(current_fe);
110  }
111  return dominated_fes;
112  }
113 
114 
115 
116  template <int dim, int spacedim>
117  unsigned int
119  const std::set<unsigned int> &fes,
120  const unsigned int codim) const
121  {
122  // Validate user inputs.
123  Assert(codim <= dim, ExcImpossibleInDim(dim));
124  for (const auto &fe : fes)
125  {
126  (void)fe;
127  AssertIndexRange(fe, finite_elements.size());
128  }
129 
130  // If the set of elements contains only a single element,
131  // then this very element is considered to be the dominating one.
132  if (fes.size() == 1)
133  return *fes.begin();
134 
135  // There may also be others, in which case we'll check if any of these
136  // elements is able to dominate all others. If one was found, we stop
137  // looking further and return the dominating element.
138  for (const auto &current_fe : fes)
139  {
140  // Check if current_fe can dominate all elements in @p fes.
143  for (const auto &other_fe : fes)
144  if (current_fe != other_fe)
145  domination =
146  domination & finite_elements[current_fe]->compare_for_domination(
147  *finite_elements[other_fe], codim);
148 
149  // If current_fe dominates, return its index.
152  /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
153  return current_fe;
154  }
155 
156  // If we couldn't find the dominating object, return an invalid one.
158  }
159 
160 
161 
162  template <int dim, int spacedim>
163  unsigned int
165  const std::set<unsigned int> &fes,
166  const unsigned int codim) const
167  {
168  // Validate user inputs.
169  Assert(codim <= dim, ExcImpossibleInDim(dim));
170  for (const auto &fe : fes)
171  {
172  (void)fe;
173  AssertIndexRange(fe, finite_elements.size());
174  }
175 
176  // If the set of elements contains only a single element,
177  // then this very element is considered to be the dominated one.
178  if (fes.size() == 1)
179  return *fes.begin();
180 
181  // There may also be others, in which case we'll check if any of these
182  // elements is dominated by all others. If one was found, we stop
183  // looking further and return the dominated element.
184  for (const auto &current_fe : fes)
185  {
186  // Check if current_fe is dominated by all other elements in @p fes.
189  for (const auto &other_fe : fes)
190  if (current_fe != other_fe)
191  domination =
192  domination & finite_elements[current_fe]->compare_for_domination(
193  *finite_elements[other_fe], codim);
194 
195  // If current_fe is dominated, return its index.
198  /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
199  return current_fe;
200  }
201 
202  // If we couldn't find the dominated object, return an invalid one.
204  }
205 
206 
207 
208  template <int dim, int spacedim>
209  unsigned int
211  const std::set<unsigned int> &fes,
212  const unsigned int codim) const
213  {
214  unsigned int fe_index = find_dominating_fe(fes, codim);
215 
216  if (fe_index == numbers::invalid_unsigned_int)
217  {
218  const std::set<unsigned int> dominating_fes =
219  find_common_fes(fes, codim);
220  fe_index = find_dominated_fe(dominating_fes, codim);
221  }
222 
223  return fe_index;
224  }
225 
226 
227 
228  template <int dim, int spacedim>
229  unsigned int
231  const std::set<unsigned int> &fes,
232  const unsigned int codim) const
233  {
234  unsigned int fe_index = find_dominated_fe(fes, codim);
235 
236  if (fe_index == numbers::invalid_unsigned_int)
237  {
238  const std::set<unsigned int> dominated_fes =
239  find_enclosing_fes(fes, codim);
240  fe_index = find_dominating_fe(dominated_fes, codim);
241  }
242 
243  return fe_index;
244  }
245 
246 
247 
248  template <int dim, int spacedim>
250  {
251  set_default_hierarchy();
252  }
253 
254 
255 
256  template <int dim, int spacedim>
259  : FECollection()
260  {
261  push_back(fe);
262  }
263 
264 
265 
266  template <int dim, int spacedim>
268  const std::vector<const FiniteElement<dim, spacedim> *> &fes)
269  : FECollection()
270  {
271  Assert(fes.size() > 0,
272  ExcMessage("Need to pass at least one finite element."));
273 
274  for (unsigned int i = 0; i < fes.size(); ++i)
275  push_back(*fes[i]);
276  }
277 
278 
279 
280  template <int dim, int spacedim>
281  void
283  const FiniteElement<dim, spacedim> &new_fe)
284  {
285  // check that the new element has the right
286  // number of components. only check with
287  // the first element, since all the other
288  // elements have already passed the test
289  // against the first element
290  if (finite_elements.size() != 0)
291  Assert(new_fe.n_components() == finite_elements[0]->n_components(),
292  ExcMessage("All elements inside a collection need to have the "
293  "same number of vector components!"));
294 
295  finite_elements.push_back(new_fe.clone());
296  }
297 
298 
299 
300  template <int dim, int spacedim>
301  void
303  const std::function<
304  unsigned int(const typename hp::FECollection<dim, spacedim> &,
305  const unsigned int)> &next,
306  const std::function<
307  unsigned int(const typename hp::FECollection<dim, spacedim> &,
308  const unsigned int)> &prev)
309  {
310  // copy hierarchy functions
311  hierarchy_next = next;
312  hierarchy_prev = prev;
313  }
314 
315 
316 
317  template <int dim, int spacedim>
318  void
320  {
321  // establish hierarchy corresponding to order of indices
322  set_hierarchy(&DefaultHierarchy::next_index,
323  &DefaultHierarchy::previous_index);
324  }
325 
326 
327 
328  template <int dim, int spacedim>
329  unsigned int
331  const unsigned int fe_index) const
332  {
333  Assert(fe_index < size(), ExcIndexRange(fe_index, 0, size()));
334 
335  const unsigned int new_fe_index = hierarchy_next(*this, fe_index);
336  Assert(new_fe_index < size(), ExcIndexRange(new_fe_index, 0, size()));
337 
338  return new_fe_index;
339  }
340 
341 
342 
343  template <int dim, int spacedim>
344  unsigned int
346  const unsigned int fe_index) const
347  {
348  Assert(fe_index < size(), ExcIndexRange(fe_index, 0, size()));
349 
350  const unsigned int new_fe_index = hierarchy_prev(*this, fe_index);
351  Assert(new_fe_index < size(), ExcIndexRange(new_fe_index, 0, size()));
352 
353  return new_fe_index;
354  }
355 
356 
357 
358  template <int dim, int spacedim>
361  const FEValuesExtractors::Scalar &scalar) const
362  {
363  Assert(size() > 0,
364  ExcMessage("This collection contains no finite element."));
365 
366  // get the mask from the first element of the collection
367  const ComponentMask mask = (*this)[0].component_mask(scalar);
368 
369  // but then also verify that the other elements of the collection
370  // would return the same mask
371  for (unsigned int c = 1; c < size(); ++c)
372  Assert(mask == (*this)[c].component_mask(scalar), ExcInternalError());
373 
374  return mask;
375  }
376 
377 
378  template <int dim, int spacedim>
381  const FEValuesExtractors::Vector &vector) const
382  {
383  Assert(size() > 0,
384  ExcMessage("This collection contains no finite element."));
385 
386  // get the mask from the first element of the collection
387  const ComponentMask mask = (*this)[0].component_mask(vector);
388 
389  // but then also verify that the other elements of the collection
390  // would return the same mask
391  for (unsigned int c = 1; c < size(); ++c)
392  Assert(mask == (*this)[c].component_mask(vector), ExcInternalError());
393 
394  return mask;
395  }
396 
397 
398  template <int dim, int spacedim>
401  const FEValuesExtractors::SymmetricTensor<2> &sym_tensor) const
402  {
403  Assert(size() > 0,
404  ExcMessage("This collection contains no finite element."));
405 
406  // get the mask from the first element of the collection
407  const ComponentMask mask = (*this)[0].component_mask(sym_tensor);
408 
409  // but then also verify that the other elements of the collection
410  // would return the same mask
411  for (unsigned int c = 1; c < size(); ++c)
412  Assert(mask == (*this)[c].component_mask(sym_tensor), ExcInternalError());
413 
414  return mask;
415  }
416 
417 
418  template <int dim, int spacedim>
421  {
422  Assert(size() > 0,
423  ExcMessage("This collection contains no finite element."));
424 
425  // get the mask from the first element of the collection
426  const ComponentMask mask = (*this)[0].component_mask(block_mask);
427 
428  // but then also verify that the other elements of the collection
429  // would return the same mask
430  for (unsigned int c = 1; c < size(); ++c)
431  Assert(mask == (*this)[c].component_mask(block_mask),
432  ExcMessage("Not all elements of this collection agree on what "
433  "the appropriate mask should be."));
434 
435  return mask;
436  }
437 
438 
439  template <int dim, int spacedim>
440  BlockMask
442  const FEValuesExtractors::Scalar &scalar) const
443  {
444  Assert(size() > 0,
445  ExcMessage("This collection contains no finite element."));
446 
447  // get the mask from the first element of the collection
448  const BlockMask mask = (*this)[0].block_mask(scalar);
449 
450  // but then also verify that the other elements of the collection
451  // would return the same mask
452  for (unsigned int c = 1; c < size(); ++c)
453  Assert(mask == (*this)[c].block_mask(scalar),
454  ExcMessage("Not all elements of this collection agree on what "
455  "the appropriate mask should be."));
456 
457  return mask;
458  }
459 
460 
461  template <int dim, int spacedim>
462  BlockMask
464  const FEValuesExtractors::Vector &vector) const
465  {
466  Assert(size() > 0,
467  ExcMessage("This collection contains no finite element."));
468 
469  // get the mask from the first element of the collection
470  const BlockMask mask = (*this)[0].block_mask(vector);
471 
472  // but then also verify that the other elements of the collection
473  // would return the same mask
474  for (unsigned int c = 1; c < size(); ++c)
475  Assert(mask == (*this)[c].block_mask(vector),
476  ExcMessage("Not all elements of this collection agree on what "
477  "the appropriate mask should be."));
478 
479  return mask;
480  }
481 
482 
483  template <int dim, int spacedim>
484  BlockMask
486  const FEValuesExtractors::SymmetricTensor<2> &sym_tensor) const
487  {
488  Assert(size() > 0,
489  ExcMessage("This collection contains no finite element."));
490 
491  // get the mask from the first element of the collection
492  const BlockMask mask = (*this)[0].block_mask(sym_tensor);
493 
494  // but then also verify that the other elements of the collection
495  // would return the same mask
496  for (unsigned int c = 1; c < size(); ++c)
497  Assert(mask == (*this)[c].block_mask(sym_tensor),
498  ExcMessage("Not all elements of this collection agree on what "
499  "the appropriate mask should be."));
500 
501  return mask;
502  }
503 
504 
505 
506  template <int dim, int spacedim>
507  BlockMask
509  const ComponentMask &component_mask) const
510  {
511  Assert(size() > 0,
512  ExcMessage("This collection contains no finite element."));
513 
514  // get the mask from the first element of the collection
515  const BlockMask mask = (*this)[0].block_mask(component_mask);
516 
517  // but then also verify that the other elements of the collection
518  // would return the same mask
519  for (unsigned int c = 1; c < size(); ++c)
520  Assert(mask == (*this)[c].block_mask(component_mask),
521  ExcMessage("Not all elements of this collection agree on what "
522  "the appropriate mask should be."));
523 
524  return mask;
525  }
526 
527 
528 
529  template <int dim, int spacedim>
530  unsigned int
532  {
533  Assert(finite_elements.size() > 0, ExcNoFiniteElements());
534 
535  const unsigned int nb = finite_elements[0]->n_blocks();
536  for (unsigned int i = 1; i < finite_elements.size(); ++i)
537  Assert(finite_elements[i]->n_blocks() == nb,
538  ExcMessage("Not all finite elements in this collection have "
539  "the same number of components."));
540 
541  return nb;
542  }
543 
544 
545 
546  template <int dim, int spacedim>
547  std::size_t
549  {
550  std::size_t mem =
551  (sizeof(*this) + MemoryConsumption::memory_consumption(finite_elements));
552  for (unsigned int i = 0; i < finite_elements.size(); ++i)
553  mem += finite_elements[i]->memory_consumption();
554 
555  return mem;
556  }
557 } // namespace hp
558 
559 
560 
561 // explicit instantiations
562 #include "fe_collection.inst"
563 
564 
565 DEAL_II_NAMESPACE_CLOSE
unsigned int find_dominated_fe_extended(const std::set< unsigned int > &fes, const unsigned int codim=0) const
static const unsigned int invalid_unsigned_int
Definition: types.h:173
unsigned int find_least_face_dominating_fe(const std::set< unsigned int > &fes) const
unsigned int find_dominating_fe(const std::set< unsigned int > &fes, const unsigned int codim=0) const
std::vector< bool > component_mask
#define AssertIndexRange(index, range)
Definition: exceptions.h:1637
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const =0
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
unsigned int find_dominating_fe_extended(const std::set< unsigned int > &fes, const unsigned int codim=0) const
static ::ExceptionBase & ExcMessage(std::string arg1)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
#define Assert(cond, exc)
Definition: exceptions.h:1407
Definition: hp.h:117
std::vector< bool > block_mask
Definition: block_mask.h:215
unsigned int n_components() const
std::set< unsigned int > find_common_fes(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
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
static ::ExceptionBase & ExcInternalError()