LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
ref_el.h
1
2
3#ifndef __96e6ff0ee0034f4584fcdfc7e9c53f82
4#define __96e6ff0ee0034f4584fcdfc7e9c53f82
5
6#include <array>
7#include <vector>
8
9//#include <boost/range.hpp>
10
11#include "base.h"
12#include "lf_assert.h"
13
14namespace lf::base {
15
28enum class RefElType : unsigned char {
29 kPoint = 1,
31 kSegment = 2,
33 kTria = 3,
35 kQuad = 4,
37};
38
39namespace internal {
40// Some utility methods that are needed to deduce compile time return types:
41constexpr dim_t DimensionImpl(RefElType type) {
42 switch (type) {
44 return 0;
46 return 1;
49 return 2;
50 default:
51 throw std::runtime_error(
52 "RefEl::Dimension() not implemented for this RefEl type.");
53 }
54}
55} // namespace internal
56
106class RefEl {
107 // Node coordinates as dynamic eigen matrices:
108 static const Eigen::MatrixXd ncoords_point_dynamic_;
109 static const Eigen::MatrixXd ncoords_segment_dynamic_;
110 static const Eigen::MatrixXd ncoords_tria_dynamic_;
111 static const Eigen::MatrixXd ncoords_quad_dynamic_;
112
113 // Node coordinates as fixed eigen matrices:
114 static const std::vector<Eigen::Matrix<double, 0, 1>> ncoords_point_static_;
115 static const std::vector<Eigen::Matrix<double, 1, 1>> ncoords_segment_static_;
116 static const std::vector<Eigen::Vector2d> ncoords_tria_static_;
117 static const std::vector<Eigen::Vector2d> ncoords_quad_static_;
118
119 // Member variable
121
122 // subSubEntities, used by SubSubEntity2SubEntity
123 static constexpr std::array<std::array<base::dim_t, 2>, 3>
124 sub_sub_entity_index_tria_ = {{{0, 1}, {1, 2}, {2, 0}}};
125 static constexpr std::array<std::array<base::dim_t, 2>, 4>
126 sub_sub_entity_index_quad_ = {{{0, 1}, {1, 2}, {2, 3}, {3, 0}}};
127
128 public:
129 using dim_t = unsigned int;
134 template <RefElType type>
136 Eigen::Matrix<double, internal::DimensionImpl(type), 1>;
137
141 static constexpr RefEl kPoint() { return RefEl(RefElType::kPoint); }
142
150 static constexpr RefEl kSegment() { return RefEl(RefElType::kSegment); }
151
158 static constexpr RefEl kTria() { return RefEl(RefElType::kTria); }
159
166 static constexpr RefEl kQuad() { return RefEl(RefElType::kQuad); }
167
172 explicit constexpr RefEl(RefElType type) noexcept : type_(type) {}
173
175 constexpr RefEl(const RefEl&) = default;
176
178 constexpr RefEl(RefEl&&) = default;
179
181 // NOLINTNEXTLINE(modernize-use-equals-default,hicpp-use-equals-default,cert-oop54-cpp)
182 constexpr RefEl& operator=(const RefEl& rhs) {
183 type_ = rhs.type_;
184 return *this;
185 }
186
188 constexpr RefEl& operator=(RefEl&& rhs) noexcept {
189 type_ = rhs.type_;
190 return *this;
191 }
192
201 [[nodiscard]] constexpr dim_t Dimension() const {
202 return internal::DimensionImpl(type_);
203 }
204
210 [[nodiscard]] constexpr size_type NumNodes() const {
211 switch (type_) {
213 return 1;
215 return 2;
216 case RefElType::kTria:
217 return 3;
218 case RefElType::kQuad:
219 return 4;
220 default:
221 throw std::runtime_error(
222 "RefEl::NumNodes() not implemented for this RefEl type.");
223 }
224 }
225
238 [[nodiscard]] const Eigen::MatrixXd& NodeCoords() const {
239 switch (type_) {
244 case RefElType::kTria:
246 case RefElType::kQuad:
248 default:
249 LF_VERIFY_MSG(
250 false, "RefEl::NodeCoords() not implemented for this RefEl type.");
251 }
252 }
253
270 template <RefElType type>
271 static const std::vector<NodeCoordVector<type>>& NodeCoords() {
272 // NOLINTNEXTLINE
273 if constexpr (type == RefElType::kPoint) {
275 }
276 // NOLINTNEXTLINE
277 if constexpr (type == RefElType::kSegment) {
279 }
280 // NOLINTNEXTLINE
281 if constexpr (type == RefElType::kTria) {
283 }
284 // NOLINTNEXTLINE
285 if constexpr (type == RefElType::kQuad) {
287 }
288 LF_VERIFY_MSG(false,
289 "RefEl::NodeCoords<>() not implemented for this RefEl type.");
290 }
291
305 [[nodiscard]] constexpr size_type NumSubEntities(dim_t sub_codim) const {
306 LF_ASSERT_MSG_CONSTEXPR(sub_codim >= 0, "sub_codim is negative");
307 LF_ASSERT_MSG_CONSTEXPR(sub_codim <= Dimension(),
308 "sub_codim > Dimension()");
309 if (sub_codim == 0) {
310 return 1;
311 }
312 switch (type_) {
314 return 2; // sub_codim=1
315 case RefElType::kTria:
316 return 3; // sub_codim=1,2
317 case RefElType::kQuad:
318 return 4; // sub_codim=1,2
319 default:
320 LF_ASSERT_MSG_CONSTEXPR(
321 false,
322 "RefEl::NumSubEntities() not implemented for this RefElType.");
323 }
324 return 0; // prevent warnings from compilers
325 }
326
348 [[nodiscard]] constexpr RefEl SubType(dim_t sub_codim,
349 dim_t sub_index) const {
350 LF_ASSERT_MSG_CONSTEXPR(sub_codim >= 0, "sub_codim is negative");
351 LF_ASSERT_MSG_CONSTEXPR(sub_codim <= Dimension(),
352 "sub_codim > Dimension()");
353 LF_ASSERT_MSG_CONSTEXPR(sub_index >= 0, "sub_index is negative");
354 LF_ASSERT_MSG_CONSTEXPR(sub_index < NumSubEntities(sub_codim),
355 "sub_index >= NumSubEntities");
356
357 if (sub_codim == 0) {
358 return *this;
359 }
360 if (sub_codim == Dimension()) {
361 return kPoint();
362 }
363 if (Dimension() - sub_codim == 1) {
364 return kSegment();
365 } else { // NOLINT(readability-else-after-return)
366 LF_ASSERT_MSG_CONSTEXPR(false, "This code should never be reached.");
367 }
368
369 return kPoint(); // prevent warnings from compiler
370 }
371
409 [[nodiscard]] constexpr sub_idx_t SubSubEntity2SubEntity(
410 dim_t sub_codim, sub_idx_t sub_index, dim_t sub_rel_codim,
411 sub_idx_t sub_rel_index) const {
412 LF_ASSERT_MSG_CONSTEXPR(sub_codim >= 0, "sub_codim negative");
413 LF_ASSERT_MSG_CONSTEXPR(sub_codim <= Dimension(), "sub_codim > Dimension");
414 LF_ASSERT_MSG_CONSTEXPR(sub_index >= 0, "sub_index negative");
415 LF_ASSERT_MSG_CONSTEXPR(sub_index <= NumSubEntities(sub_codim),
416 "sub_index >= NumSubEntities");
417 LF_ASSERT_MSG_CONSTEXPR(sub_rel_codim >= 0, "sub_rel_codim negative.");
418 LF_ASSERT_MSG_CONSTEXPR(sub_rel_codim <= Dimension() - sub_codim,
419 "subSubCodim out of bounds.");
420 LF_ASSERT_MSG_CONSTEXPR(sub_rel_index >= 0, "sub_rel_index negative.");
421 LF_ASSERT_MSG_CONSTEXPR(
422 sub_rel_index <
423 SubType(sub_codim, sub_index).NumSubEntities(sub_rel_codim),
424 "sub_sub_index out of bounds.");
425
426 if (type_ == RefElType::kPoint) {
427 return 0;
428 }
429 if (sub_codim == 0) {
430 return sub_rel_index;
431 }
432 if (sub_codim == Dimension()) {
433 return sub_index;
434 }
435
436 // from here on, it must be a segment
437 switch (type_) {
438 case RefElType::kTria:
439 return sub_sub_entity_index_tria_[sub_index][sub_rel_index];
440 case RefElType::kQuad:
441 return sub_sub_entity_index_quad_[sub_index][sub_rel_index];
442 default:
443 LF_ASSERT_MSG_CONSTEXPR(false, "This code should never be reached.");
444 }
445
446 return 0; // Prevent warnings from compiler...
447 }
448
455 [[nodiscard]] std::string ToString() const {
456 switch (type_) {
458 return "NODE";
460 return "EDGE";
461 case RefElType::kTria:
462 return "TRIA";
463 case RefElType::kQuad:
464 return "QUAD";
465 default:
466 LF_VERIFY_MSG(false, "ToString() not implemented for this RefElType");
467 }
468 }
469
477 // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
478 [[nodiscard]] constexpr operator RefElType() const { return type_; }
479
490 // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
491 [[nodiscard]] constexpr unsigned int Id() const {
492 return static_cast<unsigned int>(type_);
493 }
494
495 ~RefEl() = default;
496
497}; // class RefEl
498
499// Declare print function
519void PrintInfo(std::ostream& o, const RefEl& ref_el, int output_ctrl = 0);
520
532inline std::ostream& operator<<(std::ostream& stream, const RefEl& ref_el) {
533 return stream << ref_el.ToString();
534}
535
536} // namespace lf::base
537
538#endif // __96e6ff0ee0034f4584fcdfc7e9c53f82
Represents a reference element with all its properties.
Definition: ref_el.h:106
static const Eigen::MatrixXd ncoords_quad_dynamic_
Definition: ref_el.h:111
constexpr sub_idx_t SubSubEntity2SubEntity(dim_t sub_codim, sub_idx_t sub_index, dim_t sub_rel_codim, sub_idx_t sub_rel_index) const
Identifies sub-entities of sub-entities (so-called sub-sub-entities) with sub-entities.
Definition: ref_el.h:409
static const std::vector< Eigen::Matrix< double, 0, 1 > > ncoords_point_static_
Definition: ref_el.h:114
~RefEl()=default
RefElType type_
Definition: ref_el.h:120
static constexpr RefEl kSegment()
Returns the (1-dimensional) reference segment.
Definition: ref_el.h:150
constexpr RefEl(RefElType type) noexcept
Create a RefEl from a lf::base::RefElType enum.
Definition: ref_el.h:172
unsigned int dim_t
Definition: ref_el.h:129
static const std::vector< Eigen::Matrix< double, 1, 1 > > ncoords_segment_static_
Definition: ref_el.h:115
static const std::vector< Eigen::Vector2d > ncoords_tria_static_
Definition: ref_el.h:116
constexpr RefEl(RefEl &&)=default
Default move constructor.
constexpr RefEl(const RefEl &)=default
Default copy constructor.
static const Eigen::MatrixXd ncoords_segment_dynamic_
Definition: ref_el.h:109
constexpr RefEl & operator=(const RefEl &rhs)
Default copy assignment operator.
Definition: ref_el.h:182
constexpr unsigned int Id() const
Return a unique id for this reference element.
Definition: ref_el.h:491
static constexpr std::array< std::array< base::dim_t, 2 >, 3 > sub_sub_entity_index_tria_
Definition: ref_el.h:124
const Eigen::MatrixXd & NodeCoords() const
Get the coordinates of the nodes of this reference element.
Definition: ref_el.h:238
constexpr RefEl & operator=(RefEl &&rhs) noexcept
Default move assignment operator.
Definition: ref_el.h:188
constexpr size_type NumSubEntities(dim_t sub_codim) const
Get the number of sub-entities of this RefEl with the given codimension.
Definition: ref_el.h:305
constexpr dim_t Dimension() const
Return the dimension of this reference element.
Definition: ref_el.h:201
static const Eigen::MatrixXd ncoords_tria_dynamic_
Definition: ref_el.h:110
static constexpr RefEl kPoint()
Returns the (0-dimensional) reference point.
Definition: ref_el.h:141
static const std::vector< NodeCoordVector< type > > & NodeCoords()
Get the coordinates of the nodes of a reference element.
Definition: ref_el.h:271
static constexpr std::array< std::array< base::dim_t, 2 >, 4 > sub_sub_entity_index_quad_
Definition: ref_el.h:126
static const Eigen::MatrixXd ncoords_point_dynamic_
Definition: ref_el.h:108
static constexpr RefEl kTria()
Returns the reference triangle.
Definition: ref_el.h:158
Eigen::Matrix< double, internal::DimensionImpl(type), 1 > NodeCoordVector
Type of the node coordinate iterator that is returned from NodeCoords()
Definition: ref_el.h:136
constexpr size_type NumNodes() const
The number of nodes of this reference element.
Definition: ref_el.h:210
static const std::vector< Eigen::Vector2d > ncoords_quad_static_
Definition: ref_el.h:117
static constexpr RefEl kQuad()
Returns the reference quadrilateral.
Definition: ref_el.h:166
std::string ToString() const
Return a string representation of this Reference element.
Definition: ref_el.h:455
constexpr RefEl SubType(dim_t sub_codim, dim_t sub_index) const
Return the RefEl of the sub-entity with codim sub_codim and index sub_index.
Definition: ref_el.h:348
unsigned int dim_t
type for dimensions and co-dimensions and numbers derived from them
Definition: base.h:36
unsigned int sub_idx_t
type for local indices of sub-entities
Definition: base.h:32
unsigned int size_type
general type for variables related to size of arrays
Definition: base.h:24
Contains basic functionality that is used by other parts of LehrFEM++.
Definition: base.h:15
RefElType
An enum that defines all possible RefEl types.
Definition: ref_el.h:28
@ kSegment
Returns the (1-dimensional) reference segment.
@ kPoint
Returns the (0-dimensional) reference point.
@ kTria
Returns the reference triangle.
@ kQuad
Returns the reference quadrilateral.
void PrintInfo(std::ostream &o, const RefEl &ref_el, int output_ctrl)
Definition: ref_el.cc:17
std::ostream & operator<<(std::ostream &stream, const RefEl &ref_el)
Operator overload to print a RefEl to a stream, such as std::cout
Definition: ref_el.h:532