LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
segment_o2.cc
1
9#include "segment_o2.h"
10
11#include "point.h"
12
13namespace lf::geometry {
14
15SegmentO2::SegmentO2(Eigen::Matrix<double, Eigen::Dynamic, 3> coords)
16 : coords_(std::move(coords)),
17 alpha_squared_(0),
18 alpha_beta_(0),
19 beta_squared_(0) {
20 // polynomial of degree 2: alpha * x^2 + beta * x + gamma
21 alpha_ = 2. * (coords_.col(1) + coords_.col(0)) - 4. * coords_.col(2);
22 beta_ = 4. * coords_.col(2) - 3. * coords_.col(0) - coords_.col(1);
23 gamma_ = coords_.col(0);
24
25 // coefficients for JacobianInverseGramian and IntegrationElement
26 alpha_squared_ = alpha_.squaredNorm();
28 beta_squared_ = beta_.squaredNorm();
29}
30
31Eigen::MatrixXd SegmentO2::Global(const Eigen::MatrixXd& local) const {
32 LF_VERIFY_MSG((0. <= local.array()).all() && (local.array() <= 1.).all(),
33 "local coordinates out of bounds for reference element");
34
35 // evaluate polynomial with Horner scheme
36 Eigen::VectorXd local_vec = local.transpose();
37 auto tmp = ((alpha_ * local).colwise() + beta_).array().rowwise();
38
39 return (tmp * local_vec.transpose().array()).matrix().colwise() + gamma_;
40}
41
42Eigen::MatrixXd SegmentO2::Jacobian(const Eigen::MatrixXd& local) const {
43 LF_VERIFY_MSG((0. <= local.array()).all() && (local.array() <= 1.).all(),
44 "local coordinates out of bounds for reference element");
45
46 return (2. * alpha_ * local).colwise() + beta_;
47}
48
50 const Eigen::MatrixXd& local) const {
51 LF_VERIFY_MSG((0. <= local.array()).all() && (local.array() <= 1.).all(),
52 "local coordinates out of bounds for reference element");
53
54 auto jacobian = (2. * alpha_ * local).colwise() + beta_;
55
56 if (DimGlobal() == 1) {
57 return jacobian.cwiseInverse();
58 }
59
60 // evaluate polynomial with Horner scheme
61 const auto jTj =
62 4. * local.array() * (local.array() * alpha_squared_ + alpha_beta_) +
64 const Eigen::VectorXd jTj_inv = jTj.cwiseInverse().transpose();
65
66 return jacobian.array().rowwise() * jTj_inv.transpose().array();
67}
68
70 const Eigen::MatrixXd& local) const {
71 LF_VERIFY_MSG((0. <= local.array()).all() && (local.array() <= 1.).all(),
72 "local coordinates out of bounds for reference element");
73
74 const auto jTj =
75 4. * local.array() * (local.array() * alpha_squared_ + alpha_beta_) +
77
78 return jTj.cwiseSqrt().transpose();
79}
80
81std::unique_ptr<Geometry> SegmentO2::SubGeometry(dim_t codim, dim_t i) const {
82 if (codim == 0) {
83 LF_ASSERT_MSG(i == 0, "i is out of bounds");
84 return std::make_unique<SegmentO2>(coords_);
85 }
86 if (codim == 1) {
87 LF_ASSERT_MSG(0 <= i && i <= 2, "i is out of bounds");
88 return std::make_unique<Point>(coords_.col(i));
89 }
90 LF_VERIFY_MSG(false, "codim is out of bounds");
91}
92
93std::vector<std::unique_ptr<Geometry>> SegmentO2::ChildGeometry(
94 const RefinementPattern& ref_pat, base::dim_t codim) const {
95 LF_VERIFY_MSG(ref_pat.RefEl() == lf::base::RefEl::kSegment(),
96 "Refinement pattern for " << ref_pat.RefEl().ToString());
97 LF_VERIFY_MSG(codim < 2, "Illegal codim = " << codim);
98
99 const double hLattice = 1. / static_cast<double>(ref_pat.LatticeConst());
100 std::vector<std::unique_ptr<Geometry>> childGeoPtrs = {};
101
102 // get coordinates of childGeometries
103 std::vector<Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic>> childPolygons(
104 ref_pat.ChildPolygons(codim));
105
106 const size_t noChildren = childPolygons.size();
107 LF_VERIFY_MSG(
108 noChildren == ref_pat.NumChildren(codim),
109 "NumChildren " << noChildren << " <-> " << ref_pat.NumChildren(codim));
110
111 // create a geometry object for each child
112 for (size_t child = 0; child < noChildren; ++child) {
113 // codim == 0: a child segment is described by a polygon with three vertices
114 // codim == 1: a child point by a single point ("polygon with one corner")
115 LF_VERIFY_MSG(
116 childPolygons[child].rows() == 1,
117 "childPolygons[child].rows() = " << childPolygons[child].rows());
118 LF_VERIFY_MSG(
119 childPolygons[child].cols() == (2 - codim),
120 "childPolygons[child].cols() = " << childPolygons[child].cols());
121
122 Eigen::MatrixXd locCoords(1, 3 - 2 * codim);
123
124 switch (codim) {
125 case 0: {
126 // SegmentO2 requires the coordinate of the midpoint
127 locCoords << hLattice * childPolygons[child].cast<double>(),
128 (hLattice * childPolygons[child].cast<double>()).sum() / 2;
129 childGeoPtrs.push_back(std::make_unique<SegmentO2>(Global(locCoords)));
130
131 break;
132 }
133 case 1: {
134 locCoords << hLattice * childPolygons[child].cast<double>();
135 childGeoPtrs.push_back(std::make_unique<Point>(Global(locCoords)));
136
137 break;
138 }
139 default: {
140 LF_VERIFY_MSG(false, "Illegal co-dimension");
141 }
142 }
143 }
144
145 return childGeoPtrs;
146}
147
148} // namespace lf::geometry
static constexpr RefEl kSegment()
Returns the (1-dimensional) reference segment.
Definition: ref_el.h:150
std::string ToString() const
Return a string representation of this Reference element.
Definition: ref_el.h:455
base::RefEl::dim_t dim_t
Abstract interface class for encoding topological local refinement
lf::base::size_type LatticeConst() const
Provides information about lattice constant used.
virtual lf::base::size_type NumChildren(lf::base::dim_t codim) const =0
provide number of child entities of a given co-dimension to be created by refinement
virtual std::vector< Eigen::Matrix< int, Eigen::Dynamic, Eigen::Dynamic > > ChildPolygons(lf::base::dim_t codim) const =0
provide lattice reference coordinates of vertices of child polygons
lf::base::RefEl RefEl() const
Returns topological type of entity for which the current object is set up.
Eigen::VectorXd IntegrationElement(const Eigen::MatrixXd &local) const override
The integration element (factor appearing in integral transformation formula, see below) at number of...
Definition: segment_o2.cc:69
SegmentO2(Eigen::Matrix< double, Eigen::Dynamic, 3 > coords)
Constructor building segment from vertex/midpoint coordinates.
Definition: segment_o2.cc:15
std::vector< std::unique_ptr< Geometry > > ChildGeometry(const RefinementPattern &ref_pat, base::dim_t codim) const override
Generate geometry objects for child entities created in the course of refinement.
Definition: segment_o2.cc:93
Eigen::MatrixXd Global(const Eigen::MatrixXd &local) const override
Map a number of points in local coordinates into the global coordinate system.
Definition: segment_o2.cc:31
Eigen::Matrix< double, Eigen::Dynamic, 3 > coords_
Coordinates of the 3 vertices/midpoints, stored in matrix columns.
Definition: segment_o2.h:59
Eigen::Matrix< double, Eigen::Dynamic, 1 > beta_
Definition: segment_o2.h:66
Eigen::MatrixXd JacobianInverseGramian(const Eigen::MatrixXd &local) const override
Evaluate the Jacobian * Inverse Gramian ( ) simultaneously at numPoints.
Definition: segment_o2.cc:49
Eigen::Matrix< double, Eigen::Dynamic, 1 > gamma_
Definition: segment_o2.h:67
dim_t DimGlobal() const override
Dimension of the image of this mapping.
Definition: segment_o2.h:35
Eigen::Matrix< double, Eigen::Dynamic, 1 > alpha_
Definition: segment_o2.h:65
std::unique_ptr< Geometry > SubGeometry(dim_t codim, dim_t i) const override
Construct a new Geometry() object that describes the geometry of the i-th sub-entity with codimension...
Definition: segment_o2.cc:81
Eigen::MatrixXd Jacobian(const Eigen::MatrixXd &local) const override
Evaluate the jacobian of the mapping simultaneously at numPoints points.
Definition: segment_o2.cc:42
unsigned int dim_t
type for dimensions and co-dimensions and numbers derived from them
Definition: base.h:36
Defines the Geometry interface and provides a number of classes that implement this interface + addit...
Definition: compose.h:13