LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
dirac_operator_experiment.h
1#ifndef HLDO_SPHERE_EXPERIMENTS_DIRAC_OPERATOR_EXAMPLE_H
2#define HLDO_SPHERE_EXPERIMENTS_DIRAC_OPERATOR_EXAMPLE_H
3
11#include <dirac_operator_source_problem.h>
12#include <lf/io/vtk_writer.h>
13#include <lf/mesh/hybrid2d/mesh_factory.h>
14#include <lf/mesh/utils/tp_triag_mesh_builder.h>
15#include <lf/mesh/utils/utils.h>
16#include <lf/quad/quad.h>
17#include <lf/refinement/refinement.h>
18#include <lf/uscalfe/uscalfe.h>
19#include <mesh_function_whitney_one.h>
20#include <mesh_function_whitney_two.h>
21#include <mesh_function_whitney_zero.h>
22#include <norms.h>
23#include <results_processing.h>
24#include <sphere_triag_mesh_builder.h>
25
26#include <cstdlib>
27#include <cstring>
28#include <iostream>
29#include <string>
30#include <vector>
31
33
34using complex = std::complex<double>;
35
46 public:
64 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> u_zero,
65 std::function<
66 Eigen::Matrix<complex, 3, 1>(const Eigen::Matrix<double, 3, 1> &)>
67 u_one,
68 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> u_two,
69 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_zero,
70 std::function<
71 Eigen::Matrix<complex, 3, 1>(const Eigen::Matrix<double, 3, 1> &)>
72 f_one,
73 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_two,
74 double &k, std::string name)
75 : u_zero_(u_zero),
76 u_one_(u_one),
77 u_two_(u_two),
78 f_zero_(f_zero),
79 f_one_(f_one),
80 f_two_(f_two),
81 k_(k),
82 name_(name) {}
83
93 void Compute(std::vector<unsigned> refinement_levels,
94 std::vector<double> ks) {
95 int nl = refinement_levels.size();
96 int nk = ks.size();
97
98 // Initialize solution wrapper
100 solutions;
101 solutions.k = ks;
102 solutions.levels = refinement_levels;
103 solutions.mesh = std::vector<std::shared_ptr<const lf::mesh::Mesh>>(nl);
104 solutions.solutions = std::vector<
106
108
109 // functions are passed by reference hence changing the k still influences
110 // the functions
111 lse_builder.SetLoadFunctions(f_zero_, f_one_, f_two_);
112
113 // Read the mesh from the gmsh file
114 std::unique_ptr<lf::mesh::MeshFactory> factory =
115 std::make_unique<lf::mesh::hybrid2d::MeshFactory>(3);
116
119
120 // we always take the same radius
121 sphere.setRadius(1.);
122
123 // start timer for total time
124 std::chrono::steady_clock::time_point start_time_total =
125 std::chrono::steady_clock::now();
126
127 for (unsigned il = 0; il < nl; ++il) {
128 unsigned lvl = refinement_levels[il];
129 // Initialize solution vectors
130 solutions.solutions[il].mu_zero.resize(nk);
131 solutions.solutions[il].mu_one.resize(nk);
132 solutions.solutions[il].mu_two.resize(nk);
133
134 for (int ik = 0; ik < nk; ik++) {
135 k_ = ks[ik];
136 std::cout << "\nStart computation of refinement_level " << lvl
137 << " and k = " << k_ << std::flush;
138
139 // start timer
140 std::chrono::steady_clock::time_point start_time =
141 std::chrono::steady_clock::now();
142
143 // get mesh
144 sphere.setRefinementLevel(lvl);
145 const std::shared_ptr<lf::mesh::Mesh> mesh = sphere.Build();
146
147 // end timer
148 std::chrono::steady_clock::time_point end_time =
149 std::chrono::steady_clock::now();
150 double elapsed_sec =
151 std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
152 start_time)
153 .count() /
154 1000.;
155
156 std::cout << " -> Built Mesh " << elapsed_sec << " [s] " << std::flush;
157
158 solutions.mesh[lvl] = mesh;
159
160 // setup the problem
161 lse_builder.SetMesh(mesh);
162 lse_builder.SetK(k_);
163
164 // start timer
165 start_time = std::chrono::steady_clock::now();
166
167 // compute the system
168 lse_builder.Compute();
169
170 // end timer
171 end_time = std::chrono::steady_clock::now();
172 elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(
173 end_time - start_time)
174 .count() /
175 1000.;
176
177 std::cout << " -> Computed LSE " << elapsed_sec << " [s] "
178 << std::flush;
179
180 // start timer
181 start_time = std::chrono::steady_clock::now();
182
183 // solve the system
184 lse_builder.Solve();
185
186 // end timer
187 end_time = std::chrono::steady_clock::now();
188
189 elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(
190 end_time - start_time)
191 .count() /
192 1000.;
193
194 std::cout << " -> Solved System " << elapsed_sec << " [s] "
195 << std::flush;
196
197 // store solutions
198 solutions.solutions[lvl].mu_zero[ik] = lse_builder.GetMu(0);
199 solutions.solutions[lvl].mu_one[ik] = lse_builder.GetMu(1);
200 solutions.solutions[lvl].mu_two[ik] = lse_builder.GetMu(2);
201 } // end loop k
202 } // end loop level
203
204 // end timer total
205 std::chrono::steady_clock::time_point end_time_total =
206 std::chrono::steady_clock::now();
207 double elapsed_sec_total =
208 std::chrono::duration_cast<std::chrono::milliseconds>(end_time_total -
209 start_time_total)
210 .count() /
211 1000.;
212
213 std::cout << "\nTotal computation time for all levels " << elapsed_sec_total
214 << " [s]\n";
215
217 decltype(u_zero_), decltype(u_one_), decltype(u_two_), complex>(
218 name_, solutions, u_zero_, u_one_, u_two_, k_);
219 }
220
221 private:
222 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> u_zero_;
223 std::function<Eigen::Matrix<complex, 3, 1>(
224 const Eigen::Matrix<double, 3, 1> &)>
226 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> u_two_;
227 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_zero_;
228 std::function<Eigen::Matrix<complex, 3, 1>(
229 const Eigen::Matrix<double, 3, 1> &)>
231 std::function<complex(const Eigen::Matrix<double, 3, 1> &)> f_two_;
232 double &k_;
233 std::string name_;
234};
235
236} // namespace projects::hldo_sphere::experiments
237
238#endif // HLDO_SPHERE_EXPERIMENTS_DIRAC_OPERATOR_EXAMPLE_H
Creates and solves the discretised Dirac Operator source problems for a given list of levels and valu...
std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> u_two_
std::function< Eigen::Matrix< complex, 3, 1 >(const Eigen::Matrix< double, 3, 1 > &)> u_one_
std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f_zero_
void Compute(std::vector< unsigned > refinement_levels, std::vector< double > ks)
Solves the hodge laplacian source problems for the tensor product of passed refinement levels and ks.
std::function< Eigen::Matrix< complex, 3, 1 >(const Eigen::Matrix< double, 3, 1 > &)> f_one_
DiracOperatorExperiment(std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> u_zero, std::function< Eigen::Matrix< complex, 3, 1 >(const Eigen::Matrix< double, 3, 1 > &)> u_one, std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> u_two, 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.
std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> f_two_
std::function< complex(const Eigen::Matrix< double, 3, 1 > &)> u_zero_
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 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.
Wrapper classes for experiments.
void process_results(std::string name, ProblemSolutionWrapper< SCALAR > &results, U_ZERO &u_zero, U_ONE &u_one, U_TWO &u_two, double &k)
Generate vtk files containing meshdata and a csv table with results.
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