LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
whitney_one_mass_matrix_provider.cc
1#include "whitney_one_mass_matrix_provider.h"
2
3#include <lf/uscalfe/lagr_fe.h>
4
5#include <cmath>
6#include <iomanip>
7#include <iostream>
8
10
12 const lf::mesh::Entity &entity) const {
13 // Only triangles are supported
14 LF_VERIFY_MSG(entity.RefEl() == lf::base::RefEl::kTria(),
15 "Unsupported cell type " << entity.RefEl());
16
17 // Get the geometry of the entity
18 const auto *geom = entity.Geometry();
19
20 // Compute the global vertex coordinates
21 Eigen::MatrixXd vertices = geom->Global(entity.RefEl().NodeCoords());
22
23 // Construct the basis functions from curl of the standard hat functions
25 // The gradients are constant on the triangle
26 const Eigen::MatrixXd ref_grads =
27 hat_func.GradientsReferenceShapeFunctions(Eigen::VectorXd::Zero(2))
28 .transpose();
29 // The JacobianInverseGramian is constant on the triangle
30 const Eigen::MatrixXd J_inv_trans =
31 geom->JacobianInverseGramian(Eigen::VectorXd::Zero(2));
32
33 // Compute gradients
34 Eigen::MatrixXd grads = J_inv_trans * ref_grads;
35
36 // correct for orientation
37 auto edgeOrientations = entity.RelativeOrientations();
38 Eigen::VectorXd s(3);
39 s << lf::mesh::to_sign(edgeOrientations[0]),
40 lf::mesh::to_sign(edgeOrientations[1]),
41 lf::mesh::to_sign(edgeOrientations[2]);
42
43 // Compute the element matrix for the product of baricentric functions
44 std::vector<Eigen::Matrix3d> elem_mats(4);
45 // clang-format off
46 elem_mats[0] << 2, 1, 1,
47 1, 2, 1,
48 1, 1, 2;
49 elem_mats[1] << 1, 1, 2,
50 2, 1, 1,
51 1, 2, 1;
52 elem_mats[1] *= -1;
53 elem_mats[2] << 1, 2, 1,
54 1, 1, 2,
55 2, 1, 1;
56 elem_mats[2] *= -1;
57 elem_mats[3] << 2, 1, 1,
58 1, 2, 1,
59 1, 1, 2;
60 // clang-format on
61
62 for (int i = 0; i < 4; i++) {
63 elem_mats[i] *= lf::geometry::Volume(*geom) / 12.;
64 }
65
66 // index modulo three
67 auto index = [](int i) -> int { return i % 3; };
68
69 // compute the contributions of gradients for the first term
70 for (int i = 0; i < 3; i++) {
71 for (int k = 0; k < 3; k++) {
72 elem_mats[0](i, k) *=
73 (grads.col(index(i + 1)).transpose() * grads.col(index(k + 1)));
74 elem_mats[0](i, k) *= s(i) * s(k);
75 }
76 }
77
78 // compute the contributions of gradients for the second term
79 for (int i = 0; i < 3; i++) {
80 for (int k = 0; k < 3; k++) {
81 elem_mats[1](i, k) *=
82 (grads.col(index(i + 1)).transpose() * grads.col(index(k)));
83 elem_mats[1](i, k) *= s(i) * s(k);
84 }
85 }
86
87 // compute the contributions of gradients for the third term
88 for (int i = 0; i < 3; i++) {
89 for (int k = 0; k < 3; k++) {
90 elem_mats[2](i, k) *=
91 (grads.col(index(i)).transpose() * grads.col(index(k + 1)));
92 elem_mats[2](i, k) *= s(i) * s(k);
93 }
94 }
95
96 // compute the contributions of gradients for the fourth term
97 for (int i = 0; i < 3; i++) {
98 for (int k = 0; k < 3; k++) {
99 elem_mats[3](i, k) *=
100 (grads.col(index(i)).transpose() * grads.col(index(k)));
101 elem_mats[3](i, k) *= s(i) * s(k);
102 }
103 }
104
105 // sum up all the four contributions
106 Eigen::Matrix3d elem_mat = Eigen::MatrixXd::Zero(3, 3);
107 for (int i = 0; i < 4; i++) {
108 elem_mat += elem_mats[i];
109 }
110
111 return elem_mat;
112}
113
114} // namespace projects::hldo_sphere::assemble
const Eigen::MatrixXd & NodeCoords() const
Get the coordinates of the nodes of this reference element.
Definition: ref_el.h:238
static constexpr RefEl kTria()
Returns the reference triangle.
Definition: ref_el.h:158
virtual Eigen::MatrixXd Global(const Eigen::MatrixXd &local) const =0
Map a number of points in local coordinates into the global coordinate system.
Interface class representing a topological entity in a cellular complex
Definition: entity.h:39
virtual const geometry::Geometry * Geometry() const =0
Describes the geometry of this entity.
virtual nonstd::span< const Orientation > RelativeOrientations() const =0
return span of relative orientations of sub-entities of the next higher co-dimension.
virtual base::RefEl RefEl() const =0
Describes the reference element type of this entity.
Linear Lagrange finite element on triangular reference element.
Definition: lagr_fe.h:58
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > GradientsReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Computation of the gradients of all reference shape functions in a number of points.
Definition: lagr_fe.h:117
Eigen::MatrixXd Eval(const lf::mesh::Entity &entity) const
Compute the element matrix for a given cell of a mesh.
double Volume(const Geometry &geo)
Compute the (approximate) volume (area) of a shape.
int to_sign(Orientation o)
Definition: entity.cc:7
Collection of matrix and vector element providers.
Definition: assemble.h:26