Reference documentation for deal.II version 9.3.3
\(\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
23namespace 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 }
103
104
105 template <int dim, int spacedim>
106 unsigned int
108 const std::set<unsigned int> &fes,
109 const unsigned int codim) const
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)
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);
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
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)
332 sequence.push_front(previous);
333 front = previous;
334
335 Assert(sequence.size() <= this->size(),
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(),
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
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);
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;
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>
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 }
473
474 template <int dim, int spacedim>
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>
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>
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>
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:402
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:403
static ::ExceptionBase & ExcEmptyObject()
#define Assert(cond, exc)
Definition: exceptions.h:1465
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
#define AssertIndexRange(index, range)
Definition: exceptions.h:1690
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
std::enable_if< IsBlockVector< VectorType >::value, unsignedint >::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