PolyFEM
Loading...
Searching...
No Matches
TestProblem.cpp
Go to the documentation of this file.
1
2#include "TestProblem.hpp"
3#include <iostream>
5
6namespace polyfem
7{
8 namespace problem
9 {
10 namespace
11 {
12
13 // -----------------------------------------------------------------------------
14
15 template <typename T>
16 inline T pow2(T x) { return x * x; }
17
18 // -----------------------------------------------------------------------------
19
20 template <typename T>
21 T reentrant_corner(T x, T y, double omega)
22 {
23 const double alpha = M_PI / omega;
24 const T r = sqrt(x * x + y * y);
25 const T theta = atan2(y, x) + (y < 0 ? 2.0 * M_PI : 0.0);
26 return pow(r, alpha) * sin(alpha * theta);
27 }
28
29 template <typename T>
30 std::array<T, 2> linear_elasticity_mode_1(T x, T y, double nu, double E, double lambda, double Q)
31 {
32 const double kappa = 3.0 - 4.0 * nu;
33 const double G = E / (2.0 * (1.0 + nu));
34 const T r = sqrt(x * x + y * y);
35 const T theta = atan2(y, x) + (y < 0 ? 2.0 * M_PI : 0.0);
36 return {{
37 1.0 / (2.0 * G) * pow(r, lambda) * ((kappa - Q * (lambda + 1)) * cos(lambda * theta) - lambda * cos((lambda - 2) * theta)),
38 1.0 / (2.0 * G) * pow(r, lambda) * ((kappa + Q * (lambda + 1)) * sin(lambda * theta) + lambda * sin((lambda - 2) * theta)),
39 }};
40 }
41
42 template <typename T>
43 std::array<T, 2> linear_elasticity_mode_2(T x, T y, double nu, double E, double lambda, double Q)
44 {
45 const double kappa = 3.0 - 4.0 * nu;
46 const double G = E / (2.0 * (1.0 + nu));
47 const T r = sqrt(x * x + y * y);
48 const T theta = atan2(y, x) + (y < 0 ? 2.0 * M_PI : 0.0);
49 return {{
50 1.0 / (2.0 * G) * pow(r, lambda) * ((kappa - Q * (lambda + 1)) * sin(lambda * theta) - lambda * sin((lambda - 2) * theta)),
51 1.0 / (2.0 * G) * pow(r, lambda) * ((kappa + Q * (lambda + 1)) * cos(lambda * theta) + lambda * cos((lambda - 2) * theta)),
52 }};
53 }
54
55 template <typename T>
56 T peak(T x, T y, double x_c, double y_c, double alpha)
57 {
58 return exp(-alpha * (pow2(x - x_c) + pow2(y - y_c)));
59 }
60
61 template <typename T>
62 T boundary_line_singularity(T x, T y, double alpha)
63 {
64 return pow(x, alpha);
65 }
66
67 template <typename T>
68 T wave_front(T x, T y, double x_c, double y_c, double r_0, double alpha)
69 {
70 const T r = sqrt(pow2(x - x_c) + pow2(y - y_c));
71 return atan2(alpha * (r - r_0), T(1.0));
72 }
73
74 template <typename T>
75 T interior_line_singularity(T x, T y, double alpha, double beta)
76 {
77 if (x <= beta * (y + 1))
78 {
79 return cos(M_PI * y / 2);
80 }
81 else
82 {
83 return cos(M_PI * y / 2) + pow(x - beta * (y + 1), alpha);
84 }
85 }
86
87 template <typename T>
88 T multiple_difficulties(T x, T y, double omega, double x_w, double y_w, double r_0, double alpha_w,
89 double x_p, double y_p, double alpha_p, double eps)
90 {
91 const T r = sqrt(x * x + y * y);
92 const T theta = atan2(y, x) + (y < 0 ? 2.0 * M_PI : 0.0);
93 return pow(r, M_PI / omega) * sin(theta * M_PI / omega)
94 + atan2(alpha_w * (sqrt(pow2(x - x_w) + pow2(y - y_w)) - r_0), T(1.0))
95 + exp(-alpha_p * (pow2(x - x_p) + pow2(y - y_p)))
96 + exp(-(1 + y) / eps);
97 }
98
99 // -----------------------------------------------------------------------------
100
101 } // anonymous namespace
102
104
105#define PARAM(x) (params_[#x].get<double>())
106
108
109 TestProblem::TestProblem(const std::string &name)
110 : ProblemWithSolution(name)
111 {
112 params_ = {
113 {"type", "reentrant_corner"},
114 {"omega", 7.0 * M_PI / 4.0},
115 {"is_scalar", true}};
116 }
117
118 template <typename T>
119 T TestProblem::eval_impl(const T &pt) const
120 {
121 T res(is_scalar() ? 1 : 2);
122 if (params_["type"] == "reentrant_corner")
123 {
124 res(0) = reentrant_corner(pt(0), pt(1), PARAM(omega));
125 }
126 else if (params_["type"] == "linear_elasticity_mode_1")
127 {
128 auto uv = linear_elasticity_mode_1(pt(0), pt(1), PARAM(nu), PARAM(E), PARAM(lambda), PARAM(Q));
129 res(0) = uv[0];
130 res(1) = uv[1];
131 }
132 else if (params_["type"] == "linear_elasticity_mode_2")
133 {
134 auto uv = linear_elasticity_mode_2(pt(0), pt(1), PARAM(nu), PARAM(E), PARAM(lambda), PARAM(Q));
135 res(0) = uv[0];
136 res(1) = uv[1];
137 }
138 else if (params_["type"] == "peak")
139 {
140 res(0) = peak(pt(0), pt(1), PARAM(x_c), PARAM(y_c), PARAM(alpha));
141 }
142 else if (params_["type"] == "boundary_line_singularity")
143 {
144 res(0) = boundary_line_singularity(pt(0), pt(1), PARAM(alpha));
145 }
146 else if (params_["type"] == "wave_front")
147 {
148 res(0) = wave_front(pt(0), pt(1), PARAM(x_c), PARAM(y_c), PARAM(r_0), PARAM(alpha));
149 }
150 else if (params_["type"] == "interior_line_singularity")
151 {
152 res(0) = interior_line_singularity(pt(0), pt(1), PARAM(alpha), PARAM(beta));
153 }
154 else if (params_["type"] == "multiple_difficulties")
155 {
156 res(0) = multiple_difficulties(pt(0), pt(1),
157 PARAM(omega), PARAM(x_w), PARAM(y_w), PARAM(r_0), PARAM(alpha_w),
158 PARAM(x_p), PARAM(y_p), PARAM(alpha_p), PARAM(eps));
159 }
160 return res;
161 }
162
164 {
165 // j_original.update(j_patch);
166 assert(!params.is_null());
167 params_.merge_patch(params);
168 }
169 } // namespace problem
170} // namespace polyfem
int y
int x
#define PARAM(x)
T eval_impl(const T &pt) const
bool is_scalar() const override
TestProblem(const std::string &name)
void set_parameters(const json &params) override
nlohmann::json json
Definition Common.hpp:9