18 #include <Eigen/Dense> 19 #include <gtest/gtest.h> 29 std::ostream& operator<<(std::ostream& os, const std::vector<double>& _vec)
31 for (
auto&& v : _vec )
37 const std::vector<Eigen::Vector2d>& _vec)
39 for (
auto&& v : _vec )
40 os << v.transpose() <<
", ";
48 TEST(Wavefield, WaveSolver1D)
58 auto dispersion = [=](
auto omega)
60 return omega * omega / 9.8;
63 auto wave = [=](
auto x,
auto t,
auto& wp)
65 const double theta = wp.k *
x - wp.omega * t;
66 const double s = std::sin(theta);
67 const double px =
x - wp.a * s;
71 auto wave_f = [=](
auto x,
auto p,
auto t,
auto& wp)
73 const double theta = wp.k *
x - wp.omega * t;
74 const double s = std::sin(theta);
75 const double f = p -
x + wp.a * s;
79 auto wave_df = [=](
auto x,
auto p,
auto t,
auto& wp)
81 const double theta = wp.k *
x - wp.omega * t;
82 const double c = std::cos(theta);
83 const double df = wp.a * wp.k * c - 1;
87 auto solver = [=](
auto& func,
auto& dfunc,
auto x0,
auto p,
88 auto t,
auto& wp,
auto tol,
auto nmax)
93 while (std::abs(err) > tol && n < nmax)
95 const double f = func(x0, p, t, wp);
96 const double df = dfunc(x0, p, t, wp);
97 const double d = -f/df;
108 wp.omega = 2*M_PI/4.0;
109 wp.k = dispersion(wp.omega);
115 double p = wave(x0, t, wp);
116 double f = wave_f(x0, p, t, wp);
117 double df = wave_df(x0, p, t, wp);
119 const double tol = 1E-8;
120 const double nmax = 20;
121 double x = solver(wave_f, wave_df, p, p, t, wp, tol, nmax);
123 const double eps = 1E-8;
124 EXPECT_NEAR(wp.a, 3.0, eps);
125 EXPECT_NEAR(wp.k, 0.251775622, eps);
126 EXPECT_NEAR(wp.omega, 1.570796327, eps);
127 EXPECT_NEAR(x0, 2.0, eps);
128 EXPECT_NEAR(p, 0.552382941, eps);
130 EXPECT_NEAR(df, -0.338428477, eps);
131 EXPECT_NEAR(x, 2.0, eps);
155 auto dispersion = [=](
auto omega)
157 return omega * omega / 9.8;
160 auto wave = [=](
auto x,
auto t,
auto& wp)
162 const double theta = wp.k *
x.dot(wp.dir) - wp.omega * t;
163 const double s = std::sin(theta);
164 const double c = std::cos(theta);
165 const double dx = wp.dir.x();
166 const double dy = wp.dir.y();
167 const Eigen::Vector3d p(
168 x.x() - wp.a * dx * s,
169 x.y() - wp.a * dy * s,
174 auto wave_f = [=](
auto x,
auto p,
auto t,
auto& wp)
176 const double theta = wp.k *
x.dot(wp.dir) - wp.omega * t;
177 const double s = std::sin(theta);
178 const double dx = wp.dir.x();
179 const double dy = wp.dir.y();
180 const Eigen::Vector2d
f(
181 p.x() -
x.x() + wp.a * dx * s,
182 p.y() -
x.y() + wp.a * dy * s);
186 auto wave_df = [=](
auto x,
auto p,
auto t,
auto& wp)
188 const double theta = wp.k *
x.dot(wp.dir) - wp.omega * t;
189 const double c = std::cos(theta);
190 const double dx = wp.dir.x();
191 const double dy = wp.dir.y();
192 const double akc = wp.a * wp.k * c;
193 const double df1x = akc * dx * dx - 1.0;
194 const double df1y = akc * dx * dy;
195 const double df2x = df1y;
196 const double df2y = akc * dy * dy - 1.0;
205 auto solver = [=](
auto& func,
auto& dfunc,
auto x0,
auto p,
206 auto t,
auto& wp,
auto tol,
auto nmax)
211 while (std::abs(err) > tol && n < nmax)
213 const auto F = func(x0, p, t, wp);
214 const auto J = dfunc(x0, p, t, wp);
215 xn = x0 - J.inverse() * F;
225 wp.omega = 2*M_PI/4.0;
226 wp.k = dispersion(wp.omega);
228 wp.dir = Eigen::Vector2d(1, 0);
231 Eigen::Vector2d x0(2.0, 3.0);
233 auto p3 = wave(x0, t, wp);
234 Eigen::Vector2d p(p3(0), p3(1));
235 auto F = wave_f(x0, p, t, wp);
236 auto J = wave_df(x0, p, t, wp);
238 const double tol = 1E-8;
239 const double nmax = 20;
240 auto x = solver(wave_f, wave_df, p, p, t, wp, tol, nmax);
242 const double eps = 1E-8;
243 EXPECT_NEAR(wp.a, 3.0, eps);
244 EXPECT_NEAR(wp.k, 0.251775622, eps);
245 EXPECT_NEAR(wp.omega, 1.570796327, eps);
246 EXPECT_DOUBLE_EQ(wp.dir.x(), 1.0);
247 EXPECT_DOUBLE_EQ(wp.dir.y(), 0.0);
248 EXPECT_DOUBLE_EQ(x0.x(), 2.0);
249 EXPECT_DOUBLE_EQ(x0.y(), 3.0);
250 EXPECT_DOUBLE_EQ(
x.x(), 2.0);
251 EXPECT_DOUBLE_EQ(
x.y(), 3.0);
252 EXPECT_LE(F.norm(), eps);
270 std::vector<double> a;
271 std::vector<double> k;
272 std::vector<double> omega;
273 std::vector<double> phi;
274 std::vector<Eigen::Vector2d> dir;
277 auto dispersion = [=](
auto omega)
279 return omega * omega / 9.8;
282 auto wave = [=](
auto x,
auto t,
auto& wp)
284 Eigen::Vector3d p(
x.x(),
x.y(), 0.0);
285 const size_t n = wp.a.size();
286 for (
auto&& i = 0; i < n; ++i)
288 const double theta = wp.k[i] *
x.dot(wp.dir[i]) - wp.omega[i] * t;
289 const double s = std::sin(theta);
290 const double c = std::cos(theta);
291 const double dx = wp.dir[i].x();
292 const double dy = wp.dir[i].y();
293 const double a = wp.a[i];
294 p += Eigen::Vector3d(
302 auto wave_f = [=](
auto x,
auto p,
auto t,
auto& wp)
304 Eigen::Vector2d
f(p.x() -
x.x(), p.y() -
x.y());
305 const size_t n = wp.a.size();
306 for (
auto&& i = 0; i < n; ++i)
308 const double theta = wp.k[i] *
x.dot(wp.dir[i]) - wp.omega[i] * t;
309 const double s = std::sin(theta);
310 const double dx = wp.dir[i].x();
311 const double dy = wp.dir[i].y();
312 const double a = wp.a[i];
313 f += Eigen::Vector2d(
320 auto wave_df = [=](
auto x,
auto p,
auto t,
auto& wp)
327 const size_t n = wp.a.size();
328 for (
auto&& i = 0; i < n; ++i)
330 const double theta = wp.k[i] *
x.dot(wp.dir[i]) - wp.omega[i] * t;
331 const double c = std::cos(theta);
332 const double dx = wp.dir[i].x();
333 const double dy = wp.dir[i].y();
334 const double akc = wp.a[i] * wp.k[i] * c;
335 const double df1x = akc * dx * dx;
336 const double df1y = akc * dx * dy;
337 const double df2x = df1y;
338 const double df2y = akc * dy * dy;
347 auto solver = [=](
auto& func,
auto& dfunc,
auto x0,
auto p,
348 auto t,
auto& wp,
auto tol,
auto nmax)
353 while (std::abs(err) > tol && n < nmax)
355 const auto F = func(x0, p, t, wp);
356 const auto J = dfunc(x0, p, t, wp);
357 xn = x0 - J.inverse() * F;
368 wp.a = { 1.0, 2.0, 3.0 };
369 wp.omega = { 2*M_PI/50.0, 2*M_PI/10.0, 2*M_PI/20.0 };
370 wp.k = { dispersion(wp.omega[0]), dispersion(wp.omega[1]),
371 dispersion(wp.omega[2]) };
372 wp.phi = { 0.0, 0.0, 0.0 };
373 wp.dir = { Eigen::Vector2d(1, 0), Eigen::Vector2d(1, 0),
374 Eigen::Vector2d(1, 0) };
377 Eigen::Vector2d x0(2.0, 3.0);
379 auto p3 = wave(x0, t, wp);
380 Eigen::Vector2d p(p3(0), p3(1));
381 auto F = wave_f(x0, p, t, wp);
382 auto J = wave_df(x0, p, t, wp);
384 const double tol = 1E-8;
385 const double nmax = 20;
386 auto x = solver(wave_f, wave_df, p, p, t, wp, tol, nmax);
388 const double eps = 1E-8;
389 EXPECT_DOUBLE_EQ(x0.x(), 2.0);
390 EXPECT_DOUBLE_EQ(x0.y(), 3.0);
391 EXPECT_DOUBLE_EQ(
x.x(), 2.0);
392 EXPECT_DOUBLE_EQ(
x.y(), 3.0);
393 EXPECT_LE(F.norm(), eps);
409 TEST(Wavefield, NWaveFdFSolver2D)
413 std::vector<double> a;
414 std::vector<double> k;
415 std::vector<double> omega;
416 std::vector<double> phi;
417 std::vector<Eigen::Vector2d> dir;
420 auto dispersion = [=](
auto omega)
422 return omega * omega / 9.8;
425 auto wave = [=](
auto x,
auto t,
auto& wp)
427 Eigen::Vector3d p(
x.x(),
x.y(), 0.0);
428 const size_t n = wp.a.size();
429 for (
auto&& i = 0; i < n; ++i)
431 const double theta = wp.k[i] *
x.dot(wp.dir[i]) - wp.omega[i] * t;
432 const double s = std::sin(theta);
433 const double c = std::cos(theta);
434 const double dx = wp.dir[i].x();
435 const double dy = wp.dir[i].y();
436 const double a = wp.a[i];
437 p += Eigen::Vector3d(
445 auto wave_fdf = [=](
auto x,
auto p,
auto t,
auto& wp,
auto& F,
auto& J)
447 F(0) = p.x() -
x.x();
448 F(1) = p.y() -
x.y();
453 const size_t n = wp.a.size();
454 for (
auto&& i = 0; i < n; ++i)
456 const double theta = wp.k[i] *
x.dot(wp.dir[i]) - wp.omega[i] * t;
457 const double s = std::sin(theta);
458 const double c = std::cos(theta);
459 const double dx = wp.dir[i].x();
460 const double dy = wp.dir[i].y();
461 const double a = wp.a[i];
462 const double akc = a * wp.k[i] * c;
463 const double df1x = akc * dx * dx;
464 const double df1y = akc * dx * dy;
465 const double df2x = df1y;
466 const double df2y = akc * dy * dy;
476 auto solver = [=](
auto& fdfunc,
auto x0,
auto p,
auto t,
auto& wp,
484 while (std::abs(err) > tol && n < nmax)
486 fdfunc(x0, p, t, wp, F, J);
487 xn = x0 - J.inverse() * F;
496 wp.a = { 1.0, 2.0, 3.0 };
497 wp.omega = { 2*M_PI/50.0, 2*M_PI/10.0, 2*M_PI/20.0 };
498 wp.k = { dispersion(wp.omega[0]), dispersion(wp.omega[1]),
499 dispersion(wp.omega[2]) };
500 wp.phi = { 0.0, 0.0, 0.0 };
501 wp.dir = { Eigen::Vector2d(1, 0), Eigen::Vector2d(1, 0),
502 Eigen::Vector2d(1, 0) };
505 Eigen::Vector2d x0(2.0, 3.0);
507 auto p3 = wave(x0, t, wp);
508 Eigen::Vector2d p(p3(0), p3(1));
511 wave_fdf(x0, p, t, wp, F, J);
513 const double tol = 1E-8;
514 const double nmax = 20;
515 auto x = solver(wave_fdf, p, p, t, wp, tol, nmax);
517 const double eps = 1E-8;
518 EXPECT_DOUBLE_EQ(x0.x(), 2.0);
519 EXPECT_DOUBLE_EQ(x0.y(), 3.0);
520 EXPECT_DOUBLE_EQ(
x.x(), 2.0);
521 EXPECT_DOUBLE_EQ(
x.y(), 3.0);
522 EXPECT_LE(F.norm(), eps);
528 int main(
int argc,
char **argv)
530 testing::InitGoogleTest(&argc, argv);
531 return RUN_ALL_TESTS();
std::ostream & operator<<(std::ostream &os, const std::vector< double > &_vec)
TEST(Wavefield, WaveSolver1D)
int main(int argc, char **argv)
TFSIMD_FORCE_INLINE const tfScalar & x() const
This file contains definitions for classes used to manage a wave field. This includes wave parameters...