LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
dpg_tools.cc
1
9#include "dpg_tools.h"
10
11namespace projects::dpg {
12
13std::vector<lf::quad::QuadRule> BoundaryQuadRule(lf::base::RefEl ref_el,
14 const lf::quad::QuadRule& qr) {
15 // construct the geometry of the reference element
16 std::shared_ptr<lf::geometry::Geometry> geo_ptr;
17 switch (ref_el) {
19 geo_ptr = std::make_shared<lf::geometry::TriaO1>(
20 lf::base::RefEl::kTria().NodeCoords());
21 break;
23 geo_ptr = std::make_shared<lf::geometry::QuadO1>(
24 lf::base::RefEl::kQuad().NodeCoords());
25 break;
26 default:
27 LF_ASSERT_MSG(false, ref_el << "unsupported reference element.");
28 }
29
30 // query the number of edges
31 int numSegments = ref_el.NumSubEntities(1);
32 std::vector<lf::quad::QuadRule> BoundaryQuadRules(numSegments);
33
34 // iterate over edges
35 for (int segment = 0; segment < numSegments; ++segment) {
36 // query edge geometry and transform weights
37 auto edge_ptr = geo_ptr->SubGeometry(1, segment);
38 Eigen::MatrixXd Points = edge_ptr->Global(qr.Points());
39 Eigen::VectorXd Weights =
40 qr.Weights() *
41 edge_ptr->IntegrationElement((Eigen::VectorXd(1) << 0.5).finished());
42 lf::quad::QuadRule bqr(ref_el, Points, Weights, 0);
43 BoundaryQuadRules[segment] = bqr;
44 }
45
46 return BoundaryQuadRules;
47}
48
49Eigen::MatrixXd OuterNormals(const lf::geometry::Geometry& geometry) {
50 // check, that the reference element is supported:
51 lf::base::RefEl refEl = geometry.RefEl();
52 LF_ASSERT_MSG(
53 refEl == lf::base::RefEl::kTria() || refEl == lf::base::RefEl::kQuad(),
54 "invalid reference element: " << refEl);
55
56 // retrive the corners of the geometry object.
57 Eigen::MatrixXd corners = lf::geometry::Corners(geometry);
58 int n_corners = corners.cols();
59 int n_edges = n_corners;
60
61 // determine, if the numbering of corners is
62 // counterclockwise or clockwise. This is needed to conclude
63 // in which direction the edge vectors have to be turned to
64 // retrive the OUTER normal.
65 int orientation;
66 if (refEl == lf::base::RefEl::kTria()) {
67 // check sign of the JacobianDeterminant to deduce
68 // if the orientation of the numbering has changed.
69 // since the Jacobian is constant, it can be evaluated in any
70 // point of the reference triangle.
71 Eigen::MatrixXd point = Eigen::MatrixXd::Zero(2, 1);
72 Eigen::MatrixXd Jacobian = geometry.Jacobian(point);
73 double JacobianDeterminant = Jacobian.determinant();
74 orientation = JacobianDeterminant > 0 ? 1 : -1;
75
76 } else {
77 // in the case of a quadrilateral element it can
78 // happen, that the resulting global quadrialteral
79 // is non convex, then evaluation of the (non constant)
80 // Jacobian determinant in one point is no longer enough to determine the
81 // orientation. instead the Jacobian is evaluated in all corners of the
82 // reference element.
83 Eigen::MatrixXd Jacobians = geometry.Jacobian(refEl.NodeCoords());
84
85 // Count the number of Jacobian evaluations with a positive determinant.
86 int positiveJacobianDeterminantCount = 0;
87 for (int i = 0; i < 4; ++i) {
88 Eigen::MatrixXd Jacobian = Jacobians.block(0, 2 * i, 2, 2);
89 double JacobianDeterminant = Jacobian.determinant();
90 if (JacobianDeterminant > 0) {
91 positiveJacobianDeterminantCount++;
92 }
93 }
94 // Jacobian determinant is positive in all points:
95 //--> convex quadrilateral, counterclockwise orientation.
96 // Jacobian determinant is positive in all but one point:
97 //--> concave quadrilateral, counterclickwise orientation.
98 // Jacobian determinant negative in all points:
99 //--> convex quadrilateral, clockwise orientation.
100 // Jacobian determinant positive in only one point:
101 //--> concave quadrilateral, clockwise orientationi.
102 orientation = positiveJacobianDeterminantCount >= 3 ? 1 : -1;
103 }
104
105 // calculate "edge" direction vectors:
106 Eigen::MatrixXd edges(2, n_edges);
107 for (int i = 0; i < n_edges; ++i) {
108 edges.col(i) = corners.col(refEl.SubSubEntity2SubEntity(1, i, 1, 1)) -
109 corners.col(refEl.SubSubEntity2SubEntity(1, i, 1, 0));
110 }
111
112 // calculate normal vectors and normalize them.
113 // take into account the possible clockwise orientation of numbering on
114 // the triangle, in which case the normal vector has to be flipped.
115 Eigen::MatrixXd normals(2, n_edges);
116 for (int i = 0; i < n_edges; ++i) {
117 Eigen::Vector2d normal;
118 normal(0) = edges(1, i) * orientation;
119 normal(1) = -edges(0, i) * orientation;
120 normal.normalize();
121 normals.col(i) = normal;
122 }
123 return normals;
124}
125
126// initializes the maximum element data set:*/
128 LF_ASSERT_MSG((mesh_ptr_ != nullptr), "invalid mesh (nullptr)");
129
131 // find the maximum index of cells to which any given edge belongs.
132 for (const lf::mesh::Entity* const e : mesh_ptr_->Entities(0)) {
133 int entity_idx = mesh_ptr_->Index(*e);
134 for (const lf::mesh::Entity* const subent : e->SubEntities(1)) {
135 LF_ASSERT_MSG(maxElement.DefinedOn(*subent),
136 "maxElement_ not defined on subentity" << *subent);
137 maxElement(*subent) = std::max(maxElement(*subent), entity_idx);
138 }
139 }
140}
141
142// evaluate the prescribed sign using the described maximum rule.
144 const lf::mesh::Entity& edge) const {
146 LF_ASSERT_MSG(maxElement.DefinedOn(edge),
147 "maxElement_ not defined on edge " << edge);
148 return mesh_ptr_->Index(element) == maxElement(edge) ? 1 : -1;
149}
150
151} // namespace projects::dpg
Represents a reference element with all its properties.
Definition: ref_el.h:106
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
const Eigen::MatrixXd & NodeCoords() const
Get the coordinates of the nodes of this reference element.
Definition: ref_el.h:238
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
static constexpr RefEl kTria()
Returns the reference triangle.
Definition: ref_el.h:158
static constexpr RefEl kQuad()
Returns the reference quadrilateral.
Definition: ref_el.h:166
Interface class for shape information on a mesh cell in the spirit of parametric finite element metho...
virtual base::RefEl RefEl() const =0
The Reference element that defines the domain of this mapping.
virtual Eigen::MatrixXd Jacobian(const Eigen::MatrixXd &local) const =0
Evaluate the jacobian of the mapping simultaneously at numPoints points.
Interface class representing a topological entity in a cellular complex
Definition: entity.h:39
virtual nonstd::span< const Entity *const > SubEntities(unsigned rel_codim) const =0
Return all sub entities of this entity that have the given codimension (w.r.t. this entity!...
A MeshDataSet that attaches data of type T to every entity of a mesh that has a specified codimension...
bool DefinedOn(const Entity &e) const override
Does the dataset store information with this entity?
Represents a Quadrature Rule over one of the Reference Elements.
Definition: quad_rule.h:58
const Eigen::VectorXd & Weights() const
All quadrature weights as a vector.
Definition: quad_rule.h:152
const Eigen::MatrixXd & Points() const
All quadrature points as column vectors.
Definition: quad_rule.h:145
int PrescribedSign(const lf::mesh::Entity &element, const lf::mesh::Entity &edge) const
evaluates the the function at the midpoint of the edge of cell
Definition: dpg_tools.cc:143
std::shared_ptr< const lf::mesh::Mesh > mesh_ptr_
Definition: dpg_tools.h:127
std::shared_ptr< lf::mesh::utils::CodimMeshDataSet< int > > maxElement_ptr_
Definition: dpg_tools.h:135
Eigen::MatrixXd Corners(const Geometry &geo)
The corners of a shape with piecewise smooth boundary.
Contains functionality for the implementation of DPG methods.
Definition: primal_dpg.h:33
std::vector< lf::quad::QuadRule > BoundaryQuadRule(lf::base::RefEl ref_el, const lf::quad::QuadRule &qr)
Constructs a quadrature rule on the boundary of a reference element.
Definition: dpg_tools.cc:13
Eigen::MatrixXd OuterNormals(const lf::geometry::Geometry &geometry)
Compute the outer normals of a geometry object.
Definition: dpg_tools.cc:49