Reference documentation for deal.II version Git a285ab78cc 2020-08-04 19:09:24 +0200
\(\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 - 2020 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  // Validate user inputs.
32  Assert(codim <= dim, ExcImpossibleInDim(dim));
33  for (const auto &fe : fes)
34  {
35  (void)fe;
36  AssertIndexRange(fe, finite_elements.size());
37  }
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 < finite_elements.size();
44  ++current_fe)
45  {
46  // Check if current_fe can dominate all elements in @p fes.
49  for (const auto &other_fe : fes)
50  domination =
51  domination & finite_elements[current_fe]->compare_for_domination(
52  *finite_elements[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  // Validate user inputs.
72  Assert(codim <= dim, ExcImpossibleInDim(dim));
73  for (const auto &fe : fes)
74  {
75  (void)fe;
76  AssertIndexRange(fe, finite_elements.size());
77  }
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 < finite_elements.size();
84  ++current_fe)
85  {
86  // Check if current_fe is dominated by all other elements in @p fes.
89  for (const auto &other_fe : fes)
90  domination =
91  domination & finite_elements[current_fe]->compare_for_domination(
92  *finite_elements[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  // Validate user inputs.
112  Assert(codim <= dim, ExcImpossibleInDim(dim));
113  for (const auto &fe : fes)
114  {
115  (void)fe;
116  AssertIndexRange(fe, finite_elements.size());
117  }
118 
119  // If the set of elements contains only a single element,
120  // then this very element is considered to be the dominating one.
121  if (fes.size() == 1)
122  return *fes.begin();
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 & finite_elements[current_fe]->compare_for_domination(
136  *finite_elements[other_fe], codim);
137 
138  // If current_fe dominates, return its index.
141  /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
142  return current_fe;
143  }
144 
145  // If we couldn't find the dominating object, return an invalid one.
147  }
148 
149 
150 
151  template <int dim, int spacedim>
152  unsigned int
154  const std::set<unsigned int> &fes,
155  const unsigned int codim) const
156  {
157  // Validate user inputs.
158  Assert(codim <= dim, ExcImpossibleInDim(dim));
159  for (const auto &fe : fes)
160  {
161  (void)fe;
162  AssertIndexRange(fe, finite_elements.size());
163  }
164 
165  // If the set of elements contains only a single element,
166  // then this very element is considered to be the dominated one.
167  if (fes.size() == 1)
168  return *fes.begin();
169 
170  // There may also be others, in which case we'll check if any of these
171  // elements is dominated by all others. If one was found, we stop
172  // looking further and return the dominated element.
173  for (const auto &current_fe : fes)
174  {
175  // Check if current_fe is dominated by all other elements in @p fes.
178  for (const auto &other_fe : fes)
179  if (current_fe != other_fe)
180  domination =
181  domination & finite_elements[current_fe]->compare_for_domination(
182  *finite_elements[other_fe], codim);
183 
184  // If current_fe is dominated, return its index.
187  /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
188  return current_fe;
189  }
190 
191  // If we couldn't find the dominated object, return an invalid one.
193  }
194 
195 
196 
197  template <int dim, int spacedim>
198  unsigned int
200  const std::set<unsigned int> &fes,
201  const unsigned int codim) const
202  {
203  unsigned int fe_index = find_dominating_fe(fes, codim);
204 
205  if (fe_index == numbers::invalid_unsigned_int)
206  {
207  const std::set<unsigned int> dominating_fes =
208  find_common_fes(fes, codim);
209  fe_index = find_dominated_fe(dominating_fes, codim);
210  }
211 
212  return fe_index;
213  }
214 
215 
216 
217  template <int dim, int spacedim>
218  unsigned int
220  const std::set<unsigned int> &fes,
221  const unsigned int codim) const
222  {
223  unsigned int fe_index = find_dominated_fe(fes, codim);
224 
225  if (fe_index == numbers::invalid_unsigned_int)
226  {
227  const std::set<unsigned int> dominated_fes =
228  find_enclosing_fes(fes, codim);
229  fe_index = find_dominating_fe(dominated_fes, codim);
230  }
231 
232  return fe_index;
233  }
234 
235 
236 
237  template <int dim, int spacedim>
239  {
240  set_default_hierarchy();
241  }
242 
243 
244 
245  template <int dim, int spacedim>
248  : FECollection()
249  {
250  push_back(fe);
251  }
252 
253 
254 
255  template <int dim, int spacedim>
257  const std::vector<const FiniteElement<dim, spacedim> *> &fes)
258  : FECollection()
259  {
260  Assert(fes.size() > 0,
261  ExcMessage("Need to pass at least one finite element."));
262 
263  for (unsigned int i = 0; i < fes.size(); ++i)
264  push_back(*fes[i]);
265  }
266 
267 
268 
269  template <int dim, int spacedim>
270  void
272  const FiniteElement<dim, spacedim> &new_fe)
273  {
274  // check that the new element has the right
275  // number of components. only check with
276  // the first element, since all the other
277  // elements have already passed the test
278  // against the first element
279  if (finite_elements.size() != 0)
280  Assert(new_fe.n_components() == finite_elements[0]->n_components(),
281  ExcMessage("All elements inside a collection need to have the "
282  "same number of vector components!"));
283 
284  finite_elements.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  unsigned int
320  const unsigned int fe_index) const
321  {
322  AssertIndexRange(fe_index, size());
323 
324  const unsigned int new_fe_index = hierarchy_next(*this, fe_index);
325  AssertIndexRange(new_fe_index, size());
326 
327  return new_fe_index;
328  }
329 
330 
331 
332  template <int dim, int spacedim>
333  unsigned int
335  const unsigned int fe_index) const
336  {
337  AssertIndexRange(fe_index, size());
338 
339  const unsigned int new_fe_index = hierarchy_prev(*this, fe_index);
340  AssertIndexRange(new_fe_index, size());
341 
342  return new_fe_index;
343  }
344 
345 
346 
347  template <int dim, int spacedim>
350  const FEValuesExtractors::Scalar &scalar) const
351  {
352  Assert(size() > 0,
353  ExcMessage("This collection contains no finite element."));
354 
355  // get the mask from the first element of the collection
356  const ComponentMask mask = (*this)[0].component_mask(scalar);
357 
358  // but then also verify that the other elements of the collection
359  // would return the same mask
360  for (unsigned int c = 1; c < size(); ++c)
361  Assert(mask == (*this)[c].component_mask(scalar), ExcInternalError());
362 
363  return mask;
364  }
365 
366 
367  template <int dim, int spacedim>
370  const FEValuesExtractors::Vector &vector) const
371  {
372  Assert(size() > 0,
373  ExcMessage("This collection contains no finite element."));
374 
375  // get the mask from the first element of the collection
376  const ComponentMask mask = (*this)[0].component_mask(vector);
377 
378  // but then also verify that the other elements of the collection
379  // would return the same mask
380  for (unsigned int c = 1; c < size(); ++c)
381  Assert(mask == (*this)[c].component_mask(vector), ExcInternalError());
382 
383  return mask;
384  }
385 
386 
387  template <int dim, int spacedim>
390  const FEValuesExtractors::SymmetricTensor<2> &sym_tensor) const
391  {
392  Assert(size() > 0,
393  ExcMessage("This collection contains no finite element."));
394 
395  // get the mask from the first element of the collection
396  const ComponentMask mask = (*this)[0].component_mask(sym_tensor);
397 
398  // but then also verify that the other elements of the collection
399  // would return the same mask
400  for (unsigned int c = 1; c < size(); ++c)
401  Assert(mask == (*this)[c].component_mask(sym_tensor), ExcInternalError());
402 
403  return mask;
404  }
405 
406 
407  template <int dim, int spacedim>
410  {
411  Assert(size() > 0,
412  ExcMessage("This collection contains no finite element."));
413 
414  // get the mask from the first element of the collection
415  const ComponentMask mask = (*this)[0].component_mask(block_mask);
416 
417  // but then also verify that the other elements of the collection
418  // would return the same mask
419  for (unsigned int c = 1; c < size(); ++c)
420  Assert(mask == (*this)[c].component_mask(block_mask),
421  ExcMessage("Not all elements of this collection agree on what "
422  "the appropriate mask should be."));
423 
424  return mask;
425  }
426 
427 
428  template <int dim, int spacedim>
429  BlockMask
431  const FEValuesExtractors::Scalar &scalar) const
432  {
433  Assert(size() > 0,
434  ExcMessage("This collection contains no finite element."));
435 
436  // get the mask from the first element of the collection
437  const BlockMask mask = (*this)[0].block_mask(scalar);
438 
439  // but then also verify that the other elements of the collection
440  // would return the same mask
441  for (unsigned int c = 1; c < size(); ++c)
442  Assert(mask == (*this)[c].block_mask(scalar),
443  ExcMessage("Not all elements of this collection agree on what "
444  "the appropriate mask should be."));
445 
446  return mask;
447  }
448 
449 
450  template <int dim, int spacedim>
451  BlockMask
453  const FEValuesExtractors::Vector &vector) const
454  {
455  Assert(size() > 0,
456  ExcMessage("This collection contains no finite element."));
457 
458  // get the mask from the first element of the collection
459  const BlockMask mask = (*this)[0].block_mask(vector);
460 
461  // but then also verify that the other elements of the collection
462  // would return the same mask
463  for (unsigned int c = 1; c < size(); ++c)
464  Assert(mask == (*this)[c].block_mask(vector),
465  ExcMessage("Not all elements of this collection agree on what "
466  "the appropriate mask should be."));
467 
468  return mask;
469  }
470 
471 
472  template <int dim, int spacedim>
473  BlockMask
475  const FEValuesExtractors::SymmetricTensor<2> &sym_tensor) const
476  {
477  Assert(size() > 0,
478  ExcMessage("This collection contains no finite element."));
479 
480  // get the mask from the first element of the collection
481  const BlockMask mask = (*this)[0].block_mask(sym_tensor);
482 
483  // but then also verify that the other elements of the collection
484  // would return the same mask
485  for (unsigned int c = 1; c < size(); ++c)
486  Assert(mask == (*this)[c].block_mask(sym_tensor),
487  ExcMessage("Not all elements of this collection agree on what "
488  "the appropriate mask should be."));
489 
490  return mask;
491  }
492 
493 
494 
495  template <int dim, int spacedim>
496  BlockMask
498  const ComponentMask &component_mask) const
499  {
500  Assert(size() > 0,
501  ExcMessage("This collection contains no finite element."));
502 
503  // get the mask from the first element of the collection
504  const BlockMask mask = (*this)[0].block_mask(component_mask);
505 
506  // but then also verify that the other elements of the collection
507  // would return the same mask
508  for (unsigned int c = 1; c < size(); ++c)
509  Assert(mask == (*this)[c].block_mask(component_mask),
510  ExcMessage("Not all elements of this collection agree on what "
511  "the appropriate mask should be."));
512 
513  return mask;
514  }
515 
516 
517 
518  template <int dim, int spacedim>
519  unsigned int
521  {
522  Assert(finite_elements.size() > 0, ExcNoFiniteElements());
523 
524  const unsigned int nb = finite_elements[0]->n_blocks();
525  for (unsigned int i = 1; i < finite_elements.size(); ++i)
526  Assert(finite_elements[i]->n_blocks() == nb,
527  ExcMessage("Not all finite elements in this collection have "
528  "the same number of components."));
529 
530  return nb;
531  }
532 
533 
534 
535  template <int dim, int spacedim>
536  std::size_t
538  {
539  std::size_t mem =
540  (sizeof(*this) + MemoryConsumption::memory_consumption(finite_elements));
541  for (unsigned int i = 0; i < finite_elements.size(); ++i)
542  mem += finite_elements[i]->memory_consumption();
543 
544  return mem;
545  }
546 } // namespace hp
547 
548 
549 
550 // explicit instantiations
551 #include "fe_collection.inst"
552 
553 
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:196
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:1636
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const =0
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:1411
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:363
std::enable_if< IsBlockVector< VectorType >::value, unsigned int >::type n_blocks(const VectorType &vector)
Definition: operators.h:49
Definition: hp.h:117
std::vector< bool > block_mask
Definition: block_mask.h:213
unsigned int n_components() const
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:362
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()