LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
hodge_laplacian_test.cc
1
7#include <hodge_laplacian_experiment.h>
8
21int main(int argc, char *argv[]) {
22 if (argc != 4 && argc != 5) {
23 std::cerr << "Usage: " << argv[0]
24 << " max_refinement_level min_k max_k step=0.1 " << std::endl;
25 exit(1);
26 }
27
28 double min_k;
29 double max_k;
30 double step = 0.1;
31 const unsigned refinement_level = atoi(argv[1]);
32 sscanf(argv[2], "%lf", &min_k);
33 sscanf(argv[3], "%lf", &max_k);
34 if (argc == 5) sscanf(argv[4], "%lf", &step);
35 std::cout << "max_refinement_level : " << refinement_level << std::endl;
36 std::cout << "min_k : " << min_k << ", max_k = " << max_k
37 << " step = " << step << std::endl;
38
39 // needs to be a reference such that it can be reassigned
40 double &k = min_k;
41
42 std::vector<unsigned> refinement_levels(refinement_level + 1);
43 for (int i = 0; i < refinement_level + 1; i++) {
44 refinement_levels[i] = i;
45 }
46
47 std::vector<double> ks;
48 for (double i = min_k; i <= max_k; i += step) {
49 ks.push_back(sqrt(i));
50 }
51
52 // mathematica function output requries the following helpers
53 auto Power = [](double a, double b) -> double { return std::pow(a, b); };
54 auto Sin = [](double a) -> double { return std::sin(a); };
55 auto Cos = [](double a) -> double { return std::cos(a); };
56 auto Sqrt = [](double a) -> double { return std::sqrt(a); };
57
58 double r = 1.;
59
60 // righthandside for the zero and two form
61 auto f_zero = [&](const Eigen::Vector3d &x_vec) -> double {
62 // first scale to the sphere
63 Eigen::Vector3d x_ = x_vec;
64 double x = x_(0);
65 double y = x_(1);
66 double z = x_(2);
67
68 // autogenerated by mathematica
69 double ret =
70 Power(k, 2) * (Cos(z) + Sin(x) + Sin(y)) +
71 (2 * x * Cos(x) + 2 * y * Cos(y) + Power(x, 2) * Cos(z) +
72 Power(y, 2) * Cos(z) + Power(y, 2) * Sin(x) + Power(z, 2) * Sin(x) +
73 Power(x, 2) * Sin(y) + Power(z, 2) * Sin(y) - 2 * z * Sin(z)) /
74 (Power(x, 2) + Power(y, 2) + Power(z, 2));
75
76 return ret;
77 };
78
79 // righthandside for the one form
80 auto f_one = [&](const Eigen::Vector3d &x_vec) -> Eigen::VectorXd {
81 // first scale to the circle
82 Eigen::Vector3d x_ = x_vec;
83 double x = x_(0);
84 double y = x_(1);
85 double z = x_(2);
86
87 // autogenerated by mathematica
88 Eigen::VectorXd ret(3);
89 ret << (2 * z * (-Power(x, 2) + Power(y, 2) + Power(z, 2)) * Cos(x) +
90 2 * y * (-Power(x, 2) + Power(y, 2) + Power(z, 2)) * Cos(y) -
91 4 * x * y * z * Cos(z) - 2 * x * z * Sin(x) -
92 x * Power(y, 2) * z * Sin(x) - x * Power(z, 3) * Sin(x) +
93 2 * Power(y, 2) * Sin(y) + Power(x, 2) * Power(y, 2) * Sin(y) +
94 2 * Power(z, 2) * Sin(y) + Power(x, 2) * Power(z, 2) * Sin(y) +
95 Power(y, 2) * Power(z, 2) * Sin(y) + Power(z, 4) * Sin(y) -
96 2 * x * y * Sin(z) - Power(x, 3) * y * Sin(z) -
97 x * Power(y, 3) * Sin(z) +
98 Power(k, 2) * (Power(x, 2) + Power(y, 2) + Power(z, 2)) *
99 (-(x * z * Sin(x)) + (Power(y, 2) + Power(z, 2)) * Sin(y) -
100 x * y * Sin(z))) /
101 Power(Power(x, 2) + Power(y, 2) + Power(z, 2), 2),
102 (-4 * x * y * z * Cos(x) +
103 2 * x * (Power(x, 2) - Power(y, 2) + Power(z, 2)) * Cos(y) +
104 2 * Power(x, 2) * z * Cos(z) - 2 * Power(y, 2) * z * Cos(z) +
105 2 * Power(z, 3) * Cos(z) - 2 * y * z * Sin(x) -
106 Power(y, 3) * z * Sin(x) - y * Power(z, 3) * Sin(x) -
107 2 * x * y * Sin(y) - Power(x, 3) * y * Sin(y) -
108 x * y * Power(z, 2) * Sin(y) + 2 * Power(x, 2) * Sin(z) +
109 Power(x, 4) * Sin(z) + Power(x, 2) * Power(y, 2) * Sin(z) +
110 2 * Power(z, 2) * Sin(z) + Power(x, 2) * Power(z, 2) * Sin(z) +
111 Power(y, 2) * Power(z, 2) * Sin(z) +
112 Power(k, 2) * (Power(x, 2) + Power(y, 2) + Power(z, 2)) *
113 (-(y * z * Sin(x)) - x * y * Sin(y) +
114 (Power(x, 2) + Power(z, 2)) * Sin(z))) /
115 Power(Power(x, 2) + Power(y, 2) + Power(z, 2), 2),
116 (2 * x * (Power(x, 2) + Power(y, 2) - Power(z, 2)) * Cos(x) -
117 4 * x * y * z * Cos(y) + 2 * Power(x, 2) * y * Cos(z) +
118 2 * Power(y, 3) * Cos(z) - 2 * y * Power(z, 2) * Cos(z) +
119 2 * Power(x, 2) * Sin(x) + 2 * Power(y, 2) * Sin(x) +
120 Power(x, 2) * Power(y, 2) * Sin(x) + Power(y, 4) * Sin(x) +
121 Power(x, 2) * Power(z, 2) * Sin(x) +
122 Power(y, 2) * Power(z, 2) * Sin(x) - 2 * x * z * Sin(y) -
123 Power(x, 3) * z * Sin(y) - x * Power(z, 3) * Sin(y) -
124 2 * y * z * Sin(z) - Power(x, 2) * y * z * Sin(z) -
125 Power(y, 3) * z * Sin(z) +
126 Power(k, 2) * (Power(x, 2) + Power(y, 2) + Power(z, 2)) *
127 ((Power(x, 2) + Power(y, 2)) * Sin(x) -
128 z * (x * Sin(y) + y * Sin(z)))) /
129 Power(Power(x, 2) + Power(y, 2) + Power(z, 2), 2);
130 return ret;
131 };
132
133 // Compute the analytic solution of the problem
134 auto u_zero = [&](const Eigen::Vector3d x_vec) -> double {
135 // first scale to the circle
136 Eigen::Vector3d x_ = x_vec;
137 double x = x_(0);
138 double y = x_(1);
139 double z = x_(2);
140
141 return Cos(z) + Sin(x) + Sin(y);
142 };
143
144 // Compute the analytic solution of the problem
145 auto u_one = [&](const Eigen::Vector3d x_vec) -> Eigen::Vector3d {
146 // first scale to the circle
147 Eigen::Vector3d x_ = x_vec / x_vec.norm() * r;
148 double x = x_(0);
149 double y = x_(1);
150 double z = x_(2);
151
152 Eigen::VectorXd ret(3);
153
154 // mathematica autocompute
155 ret << (-(x * z * Sin(x)) + (Power(y, 2) + Power(z, 2)) * Sin(y) -
156 x * y * Sin(z)) /
157 (Power(x, 2) + Power(y, 2) + Power(z, 2)),
158 (-(y * z * Sin(x)) - x * y * Sin(y) +
159 (Power(x, 2) + Power(z, 2)) * Sin(z)) /
160 (Power(x, 2) + Power(y, 2) + Power(z, 2)),
161 ((Power(x, 2) + Power(y, 2)) * Sin(x) - z * (x * Sin(y) + y * Sin(z))) /
162 (Power(x, 2) + Power(y, 2) + Power(z, 2));
163
164 return ret;
165 };
166
168 experiment(u_zero, u_one, u_zero, f_zero, f_one, f_zero, k, "test");
169
170 experiment.Compute(refinement_levels, ks);
171
172 return 0;
173}
Creates and solves the discretised Hodge Laplacian source problems for a given list of levels and val...