LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
hodge_and_dirac_experiment.h
1#ifndef THESIS_EXPERIMENTS_HODGE_AND_DIRAC_H
2#define THESIS_EXPERIMENTS_HODGE_AND_DIRAC_H
3
7#include <dirac_operator_source_problem.h>
8#include <hodge_laplacians_source_problems.h>
9#include <lf/io/vtk_writer.h>
10#include <lf/mesh/hybrid2d/mesh_factory.h>
11#include <lf/mesh/utils/tp_triag_mesh_builder.h>
12#include <lf/mesh/utils/utils.h>
13#include <lf/quad/quad.h>
14#include <lf/refinement/refinement.h>
15#include <lf/uscalfe/uscalfe.h>
16#include <mesh_function_whitney_one.h>
17#include <mesh_function_whitney_two.h>
18#include <mesh_function_whitney_zero.h>
19#include <norms.h>
20#include <results_processing.h>
21#include <sphere_triag_mesh_builder.h>
22
23#include <cstdlib>
24#include <cstring>
25#include <iostream>
26#include <string>
27#include <vector>
28
30
31using complex = std::complex<double>;
32
52 public:
70 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_zero_dirac,
71 std::function<
72 Eigen::Matrix<complex, 3, 1>(const Eigen::Matrix<double, 3, 1> &)>
73 f_one_dirac,
74 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_two_dirac,
75 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_zero,
76 std::function<
77 Eigen::Matrix<complex, 3, 1>(const Eigen::Matrix<double, 3, 1> &)>
78 f_one,
79 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_two,
80 double &k, std::string name)
81 : f_zero_dirac_(f_zero_dirac),
82 f_one_dirac_(f_one_dirac),
83 f_two_dirac_(f_two_dirac),
84 f_zero_(f_zero),
85 f_one_(f_one),
86 f_two_(f_two),
87 k_(k),
88 name_(name) {}
89
99 void Compute(std::vector<unsigned> refinement_levels,
100 std::vector<double> ks) {
101 int nl = refinement_levels.size();
102 int nk = ks.size();
103
104 // Initialize solution wrapper
106 solutions_lap;
107 solutions_lap.k = ks;
108 solutions_lap.levels = refinement_levels;
109 solutions_lap.mesh = std::vector<std::shared_ptr<const lf::mesh::Mesh>>(nl);
110 solutions_lap.solutions = std::vector<
112
114 solutions_dirac;
115 solutions_dirac.k = ks;
116 solutions_dirac.levels = refinement_levels;
117 solutions_dirac.mesh =
118 std::vector<std::shared_ptr<const lf::mesh::Mesh>>(nl);
119 solutions_dirac.solutions = std::vector<
121
123 hodge_builder;
124
126
127 // functions are passed by reference hence changing the k still influences
128 // the functions
130 dirac_builder.SetLoadFunctions(f_zero_, f_one_, f_two_);
131
132 // Read the mesh from the gmsh file
133 std::unique_ptr<lf::mesh::MeshFactory> factory =
134 std::make_unique<lf::mesh::hybrid2d::MeshFactory>(3);
135
138
139 // we always take the same radius
140 sphere.setRadius(1.);
141
142 // start timer for total time
143 std::chrono::steady_clock::time_point start_time_total =
144 std::chrono::steady_clock::now();
145
146 for (unsigned il = 0; il < nl; ++il) {
147 unsigned lvl = refinement_levels[il];
148 // Initialize solution vectors
149 solutions_lap.solutions[il].mu_zero.resize(nk);
150 solutions_lap.solutions[il].mu_one.resize(nk);
151 solutions_lap.solutions[il].mu_two.resize(nk);
152
153 solutions_dirac.solutions[il].mu_zero.resize(nk);
154 solutions_dirac.solutions[il].mu_one.resize(nk);
155 solutions_dirac.solutions[il].mu_two.resize(nk);
156
157 for (int ik = 0; ik < nk; ik++) {
158 k_ = ks[ik];
159 std::cout << "\nStart computation of refinement_level " << lvl
160 << " and k = " << k_ << std::flush;
161
162 // start timer
163 std::chrono::steady_clock::time_point start_time =
164 std::chrono::steady_clock::now();
165
166 // get mesh
167 sphere.setRefinementLevel(lvl);
168 const std::shared_ptr<lf::mesh::Mesh> mesh = sphere.Build();
169
170 // end timer
171 std::chrono::steady_clock::time_point end_time =
172 std::chrono::steady_clock::now();
173 double elapsed_sec =
174 std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
175 start_time)
176 .count() /
177 1000.;
178
179 std::cout << " -> Built Mesh " << elapsed_sec << " [s] " << std::flush;
180
181 solutions_lap.mesh[lvl] = mesh;
182 solutions_dirac.mesh[lvl] = mesh;
183
184 // setup the problem
185 hodge_builder.SetMesh(mesh);
186 hodge_builder.SetK(k_);
187
188 dirac_builder.SetMesh(mesh);
189 dirac_builder.SetK(k_);
190
191 // start timer
192 start_time = std::chrono::steady_clock::now();
193
194 // compute the system
195 hodge_builder.Compute();
196 dirac_builder.Compute();
197
198 // end timer
199 end_time = std::chrono::steady_clock::now();
200 elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(
201 end_time - start_time)
202 .count() /
203 1000.;
204
205 std::cout << " -> Computed LSE " << elapsed_sec << " [s] "
206 << std::flush;
207
208 // start timer
209 start_time = std::chrono::steady_clock::now();
210
211 // solve the system
212 hodge_builder.Solve();
213 dirac_builder.Solve();
214
215 // end timer
216 end_time = std::chrono::steady_clock::now();
217
218 elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(
219 end_time - start_time)
220 .count() /
221 1000.;
222
223 std::cout << " -> Solved System " << elapsed_sec << " [s] "
224 << std::flush;
225
226 // store solutions
227 solutions_lap.solutions[lvl].mu_zero[ik] = hodge_builder.GetMuZero();
228 solutions_lap.solutions[lvl].mu_one[ik] =
229 std::get<0>(hodge_builder.GetMuOne());
230 solutions_lap.solutions[lvl].mu_two[ik] =
231 std::get<1>(hodge_builder.GetMuTwo());
232
233 solutions_dirac.solutions[lvl].mu_zero[ik] = dirac_builder.GetMu(0);
234 solutions_dirac.solutions[lvl].mu_one[ik] = dirac_builder.GetMu(1);
235 solutions_dirac.solutions[lvl].mu_two[ik] = dirac_builder.GetMu(2);
236
237 } // end loop k
238 } // end loop level
239
240 // end timer total
241 std::chrono::steady_clock::time_point end_time_total =
242 std::chrono::steady_clock::now();
243 double elapsed_sec_total =
244 std::chrono::duration_cast<std::chrono::milliseconds>(end_time_total -
245 start_time_total)
246 .count() /
247 1000.;
248
249 std::cout << "\nTotal computation time for all levels " << elapsed_sec_total
250 << " [s]\n";
251
252 projects::hldo_sphere::post_processing::compare_results<complex>(
253 name_, solutions_lap, solutions_dirac);
254 }
255
256 private:
257 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_zero_;
258 std::function<Eigen::Matrix<complex, 3, 1>(
259 const Eigen::Matrix<double, 3, 1> &)>
261 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_two_;
262 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_zero_dirac_;
263 std::function<Eigen::Matrix<complex, 3, 1>(
264 const Eigen::Matrix<double, 3, 1> &)>
266 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_two_dirac_;
267 double &k_;
268 std::string name_;
269};
270
271} // namespace projects::hldo_sphere::experiments
272
273#endif // THESIS_EXPERIMENTS_HODGE_AND_DIRAC_H
Creates and solves the discretised Hodge Laplacian source problems and the Dirac operator source Prob...
std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f_two_dirac_
std::function< Eigen::Matrix< complex, 3, 1 >(const Eigen::Matrix< double, 3, 1 > &)> f_one_dirac_
std::function< Eigen::Matrix< complex, 3, 1 >(const Eigen::Matrix< double, 3, 1 > &)> f_one_
std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f_zero_
std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f_two_
void Compute(std::vector< unsigned > refinement_levels, std::vector< double > ks)
Solves the Hodge Laplacian and the Dirac operator source problems for the tensor product of passed re...
std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f_zero_dirac_
HodgeAndDiracExperiment(std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f_zero_dirac, std::function< Eigen::Matrix< complex, 3, 1 >(const Eigen::Matrix< double, 3, 1 > &)> f_one_dirac, std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f_two_dirac, std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f_zero, std::function< Eigen::Matrix< complex, 3, 1 >(const Eigen::Matrix< double, 3, 1 > &)> f_one, std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f_two, double &k, std::string name)
Constructor setting all the functions and the reference k.
void setRefinementLevel(lf::base::size_type n)
Set the refinement level.
std::shared_ptr< lf::mesh::Mesh > Build()
Build the mesh.
Computes the Galerkin LSE for the Dirac Operator source problem.
void Compute()
Computes the Galerkin LSE for the dirac operator source problem.
Eigen::Matrix< double, Eigen::Dynamic, 1 > GetMu(int index)
retunrs the basis expansion coefficiants for the solution of the source problem
void SetLoadFunctions(std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f0, std::function< Eigen::Matrix< complex, 3, 1 >(const Eigen::Matrix< double, 3, 1 > &)> f1, std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f2)
Sets the load functions.
void SetMesh(std::shared_ptr< const lf::mesh::Mesh > mesh_p)
Sets the mesh.
Creates and solves the discretised Hodge Laplacian source problems.
Wrapper classes for experiments.
stores solutions for several k and one refinement level
stores solutions and setupinformation for a list of refinement levels and k values
std::vector< std::shared_ptr< const lf::mesh::Mesh > > mesh