LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
whitney_two_hodge_laplacian.h
1#ifndef HLDO_SPHERE_OPERATORS_WHITNEY_TWO_HODGE_LAPLACE_H
2#define HLDO_SPHERE_OPERATORS_WHITNEY_TWO_HODEE_LAPLACE_H
3
10#include <lf/assemble/assembler.h>
11#include <lf/assemble/coomatrix.h>
12#include <lf/assemble/dofhandler.h>
13#include <lf/mesh/entity.h>
14#include <lf/mesh/hybrid2d/mesh.h>
15#include <lf/mesh/hybrid2d/mesh_factory.h>
16#include <lf/mesh/mesh_interface.h>
17#include <lf/quad/quad.h>
18#include <load_vector_provider.h>
19#include <mass_matrix_provider.h>
20#include <rot_whitney_one_div_matrix_provider.h>
21#include <sphere_triag_mesh_builder.h>
22#include <whitney_one_mass_matrix_provider.h>
23#include <whitney_two_vector_provider.h>
24
25#include <Eigen/Dense>
26#include <cmath>
27#include <iomanip>
28#include <iostream>
29
30namespace projects::hldo_sphere {
31
32namespace operators {
33
53template <typename SCALAR>
55 public:
63 : coo_matrix_(lf::assemble::COOMatrix<SCALAR>(1, 1)),
64 f_([](Eigen::Matrix<double, 3, 1> x) -> SCALAR { return 0; }),
65 phi_(Eigen::VectorXd::Zero(0)) {
66 // create mesh factory for basic mesh
67 std::unique_ptr<lf::mesh::MeshFactory> factory =
68 std::make_unique<lf::mesh::hybrid2d::MeshFactory>(3);
69
70 std::shared_ptr<projects::hldo_sphere::mesh::SphereTriagMeshBuilder>
71 sphere = std::make_shared<
73 std::move(factory));
74
75 sphere->setRefinementLevel(0);
76 sphere->setRadius(1);
77
78 mesh_p_ = sphere->Build();
79 }
80
88 void Compute() {
89 // create element matrix provider
91 matrix_dot_provider;
92
94 matrix_curl_provider;
95
96 const lf::assemble::DofHandler &dof_handler_div =
99
100 const lf::assemble::DofHandler &dof_handler_const =
102 {{lf::base::RefEl::kTria(), 1}});
103
104 // create COO Matrix
105 const lf::assemble::size_type n_dofs_div(dof_handler_div.NumDofs());
106 const lf::assemble::size_type n_dofs_const(dof_handler_const.NumDofs());
107
108 lf::assemble::COOMatrix<double> coo_A_11(n_dofs_div, n_dofs_div);
109 coo_A_11.setZero();
110 lf::assemble::COOMatrix<double> coo_A_12(n_dofs_div, n_dofs_const);
111 coo_A_12.setZero();
112
113 lf::assemble::AssembleMatrixLocally<lf::assemble::COOMatrix<double>>(
114 0, dof_handler_div, dof_handler_div, matrix_dot_provider, coo_A_11);
115
116 lf::assemble::AssembleMatrixLocally<lf::assemble::COOMatrix<double>>(
117 0, dof_handler_const, dof_handler_div, matrix_curl_provider, coo_A_12);
118
119 // create full matrix
120 lf::assemble::COOMatrix<SCALAR> full_matrix(n_dofs_div + n_dofs_const,
121 n_dofs_div + n_dofs_const);
122 full_matrix.setZero();
123
124 // iterate over all triplets of the previously computed matrices and add up
125 // entries
126 const std::vector<Eigen::Triplet<double>> triplets_A_11 =
127 coo_A_11.triplets();
128
129 const std::vector<Eigen::Triplet<double>> triplets_A_12 =
130 coo_A_12.triplets();
131
132 // Add A_11
133 for (Eigen::Triplet<double> triplet : triplets_A_11) {
134 int col = triplet.col();
135 int row = triplet.row();
136 SCALAR val = triplet.value();
137 full_matrix.AddToEntry(row, col, val);
138 }
139
140 // Add A_12 and A_21
141 for (Eigen::Triplet<double> triplet : triplets_A_12) {
142 int row = triplet.row();
143 int col = triplet.col() + n_dofs_div;
144 SCALAR val = triplet.value();
145
146 // Add A_12
147 full_matrix.AddToEntry(row, col, val);
148
149 // Add A_21
150 full_matrix.AddToEntry(col, row, -val);
151 }
152
153 coo_matrix_ = full_matrix;
154
155 // create element vector provider
157 vector_provider(f_);
158
159 // create load vector
160 Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> phi(n_dofs_const);
161 phi.setZero();
162
163 // assemble the global vector over entities with codim=0:
164 lf::assemble::AssembleVectorLocally(0, dof_handler_const, vector_provider,
165 phi);
166
167 // create full vector
168 Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> full_vec(n_dofs_div +
169 n_dofs_const);
170 full_vec.setZero();
171 full_vec.tail(n_dofs_const) = phi;
172
173 // set the class attributes
174 phi_ = full_vec;
175 }
176
184 void SetMesh(std::shared_ptr<const lf::mesh::Mesh> mesh_p) {
185 // check if cells are triagles
186 for (const lf::mesh::Entity *tria : mesh_p->Entities(0)) {
187 LF_ASSERT_MSG(
188 tria->RefEl() == lf::base::RefEl::kTria(),
189 "Mesh must be Triangular, unsupported cell " << tria->RefEl());
190 }
191
192 // check if dimension of the mesh is 3
193 LF_ASSERT_MSG(mesh_p->DimWorld() == 3,
194 "World Dimension must be 3 but is" << mesh_p->DimWorld());
195
196 // set mesh
197 mesh_p_ = mesh_p;
198 }
199
210 std::function<SCALAR(const Eigen::Matrix<double, 3, 1> &)> &f) {
211 f_ = f;
212 }
213
223 Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> GetLoadVector() { return phi_; }
224
235
236 private:
237 std::shared_ptr<const lf::mesh::Mesh> mesh_p_;
238 std::function<SCALAR(const Eigen::Matrix<double, 3, 1> &)> f_;
240 Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> phi_;
241};
242
243} // namespace operators
244
245} // namespace projects::hldo_sphere
246
247#endif // HLDO_SPHERE_OPERATORS_WHITNEY_TWO_HODGE_LAPLACE_H
A temporary data structure for matrix in COO format.
Definition: coomatrix.h:52
void setZero()
Erase all entries of the matrix.
Definition: coomatrix.h:98
TripletVec & triplets()
Gives access to the vector of triplets.
Definition: coomatrix.h:124
A general (interface) class for DOF handling, see Lecture Document Paragraph 2.7.4....
Definition: dofhandler.h:109
virtual size_type NumDofs() const =0
total number of dof's handled by the object
Dofhandler for uniform finite element spaces.
Definition: dofhandler.h:257
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
static constexpr RefEl kTria()
Returns the reference triangle.
Definition: ref_el.h:158
Interface class representing a topological entity in a cellular complex
Definition: entity.h:39
Element matrix provider for the Whitney one mass matrix that is the dot product of two Whitney one ba...
Element vector provider for piecewise constant whitney two forms.
void setRefinementLevel(lf::base::size_type n)
Set the refinement level.
Computes the Galerkin LSE for the Hodge Laplacian of the whitney two form.
void SetMesh(std::shared_ptr< const lf::mesh::Mesh > mesh_p)
Sets the mesh and creates dof_handler.
lf::assemble::COOMatrix< SCALAR > GetGalerkinMatrix()
returns the Galerkin Matrix
void SetLoadFunction(std::function< SCALAR(const Eigen::Matrix< double, 3, 1 > &)> &f)
Sets the load function.
std::function< SCALAR(const Eigen::Matrix< double, 3, 1 > &)> f_
WhitneyTwoHodgeLaplace()
Constructor initializes basic mesh (Octaeder with radius 1.0) initializes zerovalued function f.
Eigen::Matrix< SCALAR, Eigen::Dynamic, 1 > GetLoadVector()
returns the Loadvector
void AssembleVectorLocally(dim_t codim, const DofHandler &dof_handler, ENTITY_VECTOR_PROVIDER &entity_vector_provider, VECTOR &resultvector)
entity-local assembly of (right-hand-side) vectors from element vectors
Definition: assembler.h:297
lf::base::size_type size_type
Definition: assemble.h:30
Implementation of the thesis Hogde Laplacians and Dirac Operators on the surface of the 3-Sphere.
Definition: assemble.h:15