Reference documentation for deal.II version 9.1.0-pre
fe_collection.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2003 - 2018 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  // If the set of elements to be dominated contains only a single element X,
31  // then by definition the dominating set contains this single element X
32  // (because each element can dominate itself). There may also be others,
33  // say Y1...YN. Next you have to find one or more elements in the dominating
34  // set {X,Y1...YN} that is the weakest. Well, you can't find one that is
35  // weaker than X because if it were, it would not dominate X. In other
36  // words, X is guaranteed to be in the subset of {X,Y1...YN} of weakest
37  // dominating elements. Since we only guarantee that the function returns
38  // one of them, we may as well return X right away.
39  if (fes.size() == 1)
40  return *fes.begin();
41 
42  const hp::FECollection<dim, spacedim> &fe_collection = *this;
43  std::set<unsigned int> candidate_fes;
44 
45  // first loop over all FEs and check which can dominate those given in @p fes:
46  for (unsigned int cur_fe = 0; cur_fe < fe_collection.size(); cur_fe++)
47  {
50  // check if cur_fe can dominate all FEs in @p fes:
51  for (std::set<unsigned int>::const_iterator it = fes.begin();
52  it != fes.end();
53  ++it)
54  {
55  Assert(*it < fe_collection.size(),
56  ExcIndexRangeType<unsigned int>(*it,
57  0,
58  fe_collection.size()));
59  domination =
60  domination & fe_collection[cur_fe].compare_for_face_domination(
61  fe_collection[*it]);
62  }
63 
64  // if we found dominating element, keep them in a set.
65  if (
67  domination == FiniteElementDomination::either_element_can_dominate /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/)
68  candidate_fes.insert(cur_fe);
69  }
70 
71  // among the ones we found, pick one that is dominated by all others and
72  // thus should represent the largest FE space.
73  if (candidate_fes.size() == 1)
74  {
75  return *candidate_fes.begin();
76  }
77  else
78  for (std::set<unsigned int>::const_iterator it = candidate_fes.begin();
79  it != candidate_fes.end();
80  ++it)
81  {
84  for (std::set<unsigned int>::const_iterator ito =
85  candidate_fes.begin();
86  ito != candidate_fes.end();
87  ++ito)
88  if (it != ito)
89  {
90  domination =
91  domination & fe_collection[*it].compare_for_face_domination(
92  fe_collection[*ito]);
93  }
94 
95  if (
97  domination == FiniteElementDomination::either_element_can_dominate /*covers cases like candidate_fes={Q1,Q1}*/)
98  return *it;
99  }
100  // We couldn't find the FE, return invalid_unsigned_int :
102  }
103 
104 
105 
106  template <int dim, int spacedim>
109  {
110  push_back(fe);
111  }
112 
113 
114 
115  template <int dim, int spacedim>
117  const std::vector<const FiniteElement<dim, spacedim> *> &fes)
118  {
119  Assert(fes.size() > 0,
120  ExcMessage("Need to pass at least one finite element."));
121 
122  for (unsigned int i = 0; i < fes.size(); ++i)
123  push_back(*fes[i]);
124  }
125 
126 
127 
128  template <int dim, int spacedim>
129  void
131  const FiniteElement<dim, spacedim> &new_fe)
132  {
133  // check that the new element has the right
134  // number of components. only check with
135  // the first element, since all the other
136  // elements have already passed the test
137  // against the first element
138  if (finite_elements.size() != 0)
139  Assert(new_fe.n_components() == finite_elements[0]->n_components(),
140  ExcMessage("All elements inside a collection need to have the "
141  "same number of vector components!"));
142 
143  finite_elements.push_back(new_fe.clone());
144  }
145 
146 
147 
148  template <int dim, int spacedim>
151  const FEValuesExtractors::Scalar &scalar) const
152  {
153  Assert(size() > 0,
154  ExcMessage("This collection contains no finite element."));
155 
156  // get the mask from the first element of the collection
157  const ComponentMask mask = (*this)[0].component_mask(scalar);
158 
159  // but then also verify that the other elements of the collection
160  // would return the same mask
161  for (unsigned int c = 1; c < size(); ++c)
162  Assert(mask == (*this)[c].component_mask(scalar), ExcInternalError());
163 
164  return mask;
165  }
166 
167 
168  template <int dim, int spacedim>
171  const FEValuesExtractors::Vector &vector) const
172  {
173  Assert(size() > 0,
174  ExcMessage("This collection contains no finite element."));
175 
176  // get the mask from the first element of the collection
177  const ComponentMask mask = (*this)[0].component_mask(vector);
178 
179  // but then also verify that the other elements of the collection
180  // would return the same mask
181  for (unsigned int c = 1; c < size(); ++c)
182  Assert(mask == (*this)[c].component_mask(vector), ExcInternalError());
183 
184  return mask;
185  }
186 
187 
188  template <int dim, int spacedim>
191  const FEValuesExtractors::SymmetricTensor<2> &sym_tensor) const
192  {
193  Assert(size() > 0,
194  ExcMessage("This collection contains no finite element."));
195 
196  // get the mask from the first element of the collection
197  const ComponentMask mask = (*this)[0].component_mask(sym_tensor);
198 
199  // but then also verify that the other elements of the collection
200  // would return the same mask
201  for (unsigned int c = 1; c < size(); ++c)
202  Assert(mask == (*this)[c].component_mask(sym_tensor), ExcInternalError());
203 
204  return mask;
205  }
206 
207 
208  template <int dim, int spacedim>
211  {
212  Assert(size() > 0,
213  ExcMessage("This collection contains no finite element."));
214 
215  // get the mask from the first element of the collection
216  const ComponentMask mask = (*this)[0].component_mask(block_mask);
217 
218  // but then also verify that the other elements of the collection
219  // would return the same mask
220  for (unsigned int c = 1; c < size(); ++c)
221  Assert(mask == (*this)[c].component_mask(block_mask),
222  ExcMessage("Not all elements of this collection agree on what "
223  "the appropriate mask should be."));
224 
225  return mask;
226  }
227 
228 
229  template <int dim, int spacedim>
230  BlockMask
232  const FEValuesExtractors::Scalar &scalar) const
233  {
234  Assert(size() > 0,
235  ExcMessage("This collection contains no finite element."));
236 
237  // get the mask from the first element of the collection
238  const BlockMask mask = (*this)[0].block_mask(scalar);
239 
240  // but then also verify that the other elements of the collection
241  // would return the same mask
242  for (unsigned int c = 1; c < size(); ++c)
243  Assert(mask == (*this)[c].block_mask(scalar),
244  ExcMessage("Not all elements of this collection agree on what "
245  "the appropriate mask should be."));
246 
247  return mask;
248  }
249 
250 
251  template <int dim, int spacedim>
252  BlockMask
254  const FEValuesExtractors::Vector &vector) const
255  {
256  Assert(size() > 0,
257  ExcMessage("This collection contains no finite element."));
258 
259  // get the mask from the first element of the collection
260  const BlockMask mask = (*this)[0].block_mask(vector);
261 
262  // but then also verify that the other elements of the collection
263  // would return the same mask
264  for (unsigned int c = 1; c < size(); ++c)
265  Assert(mask == (*this)[c].block_mask(vector),
266  ExcMessage("Not all elements of this collection agree on what "
267  "the appropriate mask should be."));
268 
269  return mask;
270  }
271 
272 
273  template <int dim, int spacedim>
274  BlockMask
276  const FEValuesExtractors::SymmetricTensor<2> &sym_tensor) const
277  {
278  Assert(size() > 0,
279  ExcMessage("This collection contains no finite element."));
280 
281  // get the mask from the first element of the collection
282  const BlockMask mask = (*this)[0].block_mask(sym_tensor);
283 
284  // but then also verify that the other elements of the collection
285  // would return the same mask
286  for (unsigned int c = 1; c < size(); ++c)
287  Assert(mask == (*this)[c].block_mask(sym_tensor),
288  ExcMessage("Not all elements of this collection agree on what "
289  "the appropriate mask should be."));
290 
291  return mask;
292  }
293 
294 
295 
296  template <int dim, int spacedim>
297  BlockMask
299  const ComponentMask &component_mask) const
300  {
301  Assert(size() > 0,
302  ExcMessage("This collection contains no finite element."));
303 
304  // get the mask from the first element of the collection
305  const BlockMask mask = (*this)[0].block_mask(component_mask);
306 
307  // but then also verify that the other elements of the collection
308  // would return the same mask
309  for (unsigned int c = 1; c < size(); ++c)
310  Assert(mask == (*this)[c].block_mask(component_mask),
311  ExcMessage("Not all elements of this collection agree on what "
312  "the appropriate mask should be."));
313 
314  return mask;
315  }
316 
317 
318 
319  template <int dim, int spacedim>
320  unsigned int
322  {
323  Assert(finite_elements.size() > 0, ExcNoFiniteElements());
324 
325  const unsigned int nb = finite_elements[0]->n_blocks();
326  for (unsigned int i = 1; i < finite_elements.size(); ++i)
327  Assert(finite_elements[i]->n_blocks() == nb,
328  ExcMessage("Not all finite elements in this collection have "
329  "the same number of components."));
330 
331  return nb;
332  }
333 
334 
335 
336  template <int dim, int spacedim>
337  std::size_t
339  {
340  std::size_t mem =
341  (sizeof(*this) + MemoryConsumption::memory_consumption(finite_elements));
342  for (unsigned int i = 0; i < finite_elements.size(); ++i)
343  mem += finite_elements[i]->memory_consumption();
344 
345  return mem;
346  }
347 } // namespace hp
348 
349 
350 
351 // explicit instantiations
352 #include "fe_collection.inst"
353 
354 
355 DEAL_II_NAMESPACE_CLOSE
ComponentMask component_mask(const FEValuesExtractors::Scalar &scalar) const
static const unsigned int invalid_unsigned_int
Definition: types.h:173
BlockMask block_mask(const FEValuesExtractors::Scalar &scalar) const
std::vector< bool > component_mask
unsigned int size() const
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const =0
static::ExceptionBase & ExcMessage(std::string arg1)
void push_back(const FiniteElement< dim, spacedim > &new_fe)
#define Assert(cond, exc)
Definition: exceptions.h:1227
unsigned int n_blocks() const
unsigned int n_components() const
Definition: hp.h:102
std::vector< bool > block_mask
Definition: block_mask.h:214
FECollection()=default
unsigned int find_least_face_dominating_fe(const std::set< unsigned int > &fes) const
std::size_t memory_consumption() const
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
static::ExceptionBase & ExcInternalError()