1 #ifndef NIHU_CONVECTED_HELMHOLTZ_3D_KERNEL_HPP_INCLUDED
2 #define NIHU_CONVECTED_HELMHOLTZ_3D_KERNEL_HPP_INCLUDED
4 #include "../core/gaussian_quadrature.hpp"
5 #include "../core/kernel.hpp"
8 #include "../core/space.hpp"
10 #include "wave_number_kernel.hpp"
12 #include "Eigen/Geometry"
23 template <
class WaveNumber,
class Space>
28 typedef Space space_t;
29 typedef typename space_t::location_t x_t;
30 typedef WaveNumber wave_number_t;
31 typedef Eigen::Matrix3d rotation_matrix_t;
32 typedef Eigen::DiagonalMatrix<double, 3> scaling_matrix_t;
42 , m_mach_number_vector(mach_number_vector)
43 , m_normalized_mach_number_vector(m_mach_number_vector.normalized())
44 , m_mach_number(m_mach_number_vector.norm())
45 , m_kappa(this->get_wave_number() / (1 - m_mach_number*m_mach_number))
48 Eigen::Vector3d axis = m_normalized_mach_number_vector.cross(Eigen::Vector3d::UnitX());
49 if (m_mach_number > 1e-10 && axis.norm() > 1e-10) {
50 double angle = std::acos(m_normalized_mach_number_vector(0));
51 m_rot = Eigen::AngleAxis<double>(angle, axis.normalized()).matrix();
54 m_rot = rotation_matrix_t::Identity();
58 double Q = 1.0 - m_mach_number * m_mach_number;
60 m_scal.diagonal() << 1.0, std::sqrt(Q), std::sqrt(Q);
63 wave_number_t
const &get_kappa()
const
68 x_t
const &get_mach_number_vector()
const
70 return m_mach_number_vector;
73 double const &get_mach_number()
const
78 x_t
const &get_normalized_mach_number_vector()
const
80 return m_normalized_mach_number_vector;
83 rotation_matrix_t
const &get_rotation_matrix()
const
88 scaling_matrix_t
const &get_scaling_matrix()
const
94 x_t
const m_mach_number_vector;
95 x_t
const m_normalized_mach_number_vector;
96 double const m_mach_number;
97 wave_number_t
const m_kappa;
98 rotation_matrix_t m_rot;
99 scaling_matrix_t m_scal;
108 template <
class WaveNumber>
111 template <
class WaveNumber>
116 typedef std::complex<double>
result_t;
125 template <
class WaveNumber>
133 template <
class WaveNumber>
135 :
public kernel_base<convected_helmholtz_3d_SLP_kernel<WaveNumber>>
140 typedef typename wave_number_kernel<WaveNumber>::wave_number_t wave_number_t;
141 typedef typename traits_t::test_input_t test_input_t;
142 typedef typename traits_t::trial_input_t trial_input_t;
144 typedef typename traits_t::result_t result_t;
151 result_t operator()(x_t
const &x, x_t
const &y, x_t
const &ny)
const
153 using boost::math::double_constants::pi;
154 using namespace std::complex_literals;
156 double const &Ma = this->get_mach_number();
157 x_t
const &Ma_vec = this->get_mach_number_vector();
158 wave_number_t
const &kappa = this->get_kappa();
161 double M_dot_r = Ma_vec.dot(r_vec);
162 double R = std::sqrt((1.0 - Ma*Ma) * r_vec.squaredNorm() + (M_dot_r * M_dot_r));
163 result_t G = std::exp(-1i*kappa*(R+M_dot_r)) / (4 * pi * R);
164 double M_dot_ny = Ma_vec.dot(ny);
165 return G * (1.0 - M_dot_ny*M_dot_ny);
168 result_t operator()(test_input_t
const &x, trial_input_t
const &y)
const
170 return (*
this)(x.get_x(), y.get_x(), y.get_unit_normal());
176 template <
class WaveNumber>
179 template <
class WaveNumber>
184 typedef std::complex<double> result_t;
186 static bool const is_symmetric =
false;
190 static bool const is_singular =
true;
193 template <
class WaveNumber>
197 static unsigned const singular_quadrature_order = 7;
200 template <
class WaveNumber>
202 :
public kernel_base<convected_helmholtz_3d_DLP_kernel<WaveNumber>>
207 typedef typename wave_number_kernel<WaveNumber>::wave_number_t wave_number_t;
208 typedef typename traits_t::test_input_t test_intput_t;
209 typedef typename traits_t::trial_input_t trial_input_t;
211 typedef typename traits_t::result_t result_t;
218 result_t operator()(x_t
const &x, x_t
const &y, x_t
const &ny)
const
220 using boost::math::double_constants::pi;
221 using namespace std::complex_literals;
223 wave_number_t
const &k = this->get_wave_number();
224 wave_number_t
const& kappa = this->get_kappa();
225 double const &M = this->get_mach_number();
226 x_t
const &Ma_vec = this->get_mach_number_vector();
230 double M_dot_r = Ma_vec.dot(r_vec);
231 double M_dot_ny = Ma_vec.dot(ny);
232 double R = std::sqrt((1-M*M) * r_vec.squaredNorm() + (M_dot_r * M_dot_r));
234 std::complex<double> G = std::exp(-1i*kappa*(R + M_dot_r)) / (4. * pi * R);
235 Eigen::Matrix<std::complex<double>, 3, 1> gradG = -G * ((1. + 1i*kappa*R) / (R * R) * ((1-M*M)*r_vec + Ma_vec * M_dot_r) + 1i*kappa*Ma_vec);
236 std::complex<double> dGn = ny.dot(gradG);
237 std::complex<double> dGM = Ma_vec.dot(gradG);
239 return dGn + (2i*k*G - dGM) * M_dot_ny;
243 result_t operator()(test_intput_t
const &x, trial_input_t
const &y)
const
245 return (*
this)(x.get_x(), y.get_x(), y.get_unit_normal());
250 template <
class WaveNumber>
253 template <
class WaveNumber>
258 typedef std::complex<double> result_t;
260 static bool const is_symmetric =
false;
264 static bool const is_singular =
true;
267 template <
class WaveNumber>
271 static unsigned const singular_quadrature_order = 7;
274 template <
class WaveNumber>
276 :
public kernel_base<convected_helmholtz_3d_DLP_tan_kernel<WaveNumber>>
281 typedef typename wave_number_kernel<WaveNumber>::wave_number_t wave_number_t;
282 typedef typename traits_t::test_input_t test_intput_t;
283 typedef typename traits_t::trial_input_t trial_input_t;
285 typedef typename traits_t::result_t result_t;
292 result_t operator()(x_t
const &x, x_t
const &y, x_t
const &ny)
const
294 using boost::math::double_constants::pi;
295 using namespace std::complex_literals;
297 wave_number_t
const &kappa = this->get_kappa();
298 double const &M = this->get_mach_number();
299 x_t
const &Ma_vec = this->get_mach_number_vector();
303 double M_dot_r = Ma_vec.dot(rvec);
304 double M_dot_ny = Ma_vec.dot(ny);
305 double R = std::sqrt((1-M*M) * rvec.squaredNorm() + (M_dot_r * M_dot_r));
306 std::complex<double> G = std::exp(-1i*kappa*(R+M_dot_r)) / (4. * pi * R);
310 result_t operator()(test_intput_t
const &x, trial_input_t
const &y)
const
312 return (*
this)(x.get_x(), y.get_x(), y.get_unit_normal());
318 template <
class WaveNumber>
321 template <
class WaveNumber>
327 typedef std::complex<double> result_t;
329 static bool const is_symmetric =
false;
333 static bool const is_singular =
true;
336 template <
class WaveNumber>
340 static unsigned const singular_quadrature_order = 7;
344 template <
class WaveNumber>
346 :
public kernel_base<convected_helmholtz_3d_DLPt_kernel<WaveNumber>>
351 typedef typename wave_number_kernel<WaveNumber>::wave_number_t wave_number_t;
352 typedef typename traits_t::test_input_t test_intput_t;
353 typedef typename traits_t::trial_input_t trial_input_t;
355 typedef typename traits_t::result_t result_t;
362 result_t operator()(x_t
const &x, x_t
const& nx, x_t
const &y, x_t
const& ny)
const
364 using boost::math::double_constants::pi;
365 using namespace std::complex_literals;
367 wave_number_t
const& kappa = this->get_kappa();
368 double const &M = this->get_mach_number();
369 x_t
const &Ma_vec = this->get_mach_number_vector();
373 double M_dot_r = Ma_vec.dot(r_vec);
374 double M_dot_nx = Ma_vec.dot(nx);
376 double R = std::sqrt((1-M*M) * r_vec.squaredNorm() + (M_dot_r * M_dot_r));
378 std::complex<double> G = std::exp(-1i*kappa*(R + M_dot_r)) / (4. * pi * R);
379 Eigen::Matrix<std::complex<double>, 3, 1> gradG = -G * ((1. + 1i*kappa*R) / (R * R) * ((1-M*M)*r_vec + Ma_vec * M_dot_r) + 1i*kappa*Ma_vec);
380 std::complex<double> dGn = -nx.dot(gradG);
381 std::complex<double> dGM = -Ma_vec.dot(gradG);
383 double M_dot_ny = Ma_vec.dot(ny);
385 return (dGn - dGM*M_dot_nx) * (1 - M_dot_ny*M_dot_ny);
388 result_t operator()(test_intput_t
const &x, trial_input_t
const &y)
const
390 return (*
this)(x.get_x(), x.get_unit_normal(), y.get_x(), y.get_unit_normal());
395 template <
class WaveNumber>
398 template <
class WaveNumber>
404 typedef std::complex<double> result_t;
406 static bool const is_symmetric =
false;
410 static bool const is_singular =
true;
415 template <
class WaveNumber>
419 static unsigned const singular_quadrature_order = 7;
423 template <
class WaveNumber>
425 :
public kernel_base<convected_helmholtz_3d_DLPt_n_kernel<WaveNumber>>
430 typedef typename wave_number_kernel<WaveNumber>::wave_number_t wave_number_t;
431 typedef typename traits_t::test_input_t test_intput_t;
432 typedef typename traits_t::trial_input_t trial_input_t;
434 typedef typename traits_t::result_t result_t;
441 result_t operator()(x_t
const &x, x_t
const& nx, x_t
const &y, x_t
const& ny)
const
443 using boost::math::double_constants::pi;
444 using namespace std::complex_literals;
446 wave_number_t
const& kappa = this->get_kappa();
447 double const &M = this->get_mach_number();
448 x_t
const &Ma_vec = this->get_mach_number_vector();
452 double M_dot_r = Ma_vec.dot(r_vec);
453 double M_dot_nx = Ma_vec.dot(nx);
455 double R = std::sqrt((1-M*M) * r_vec.squaredNorm() + (M_dot_r * M_dot_r));
457 std::complex<double> G = std::exp(-1i*kappa*(R + M_dot_r)) / (4. * pi * R);
458 Eigen::Matrix<std::complex<double>, 3, 1> gradG = -G * ((1. + 1i*kappa*R) / (R * R) * ((1-M*M)*r_vec + Ma_vec * M_dot_r) + 1i*kappa*Ma_vec);
459 std::complex<double> dGn = -nx.dot(gradG);
460 std::complex<double> dGM = -Ma_vec.dot(gradG);
462 double M_dot_ny = Ma_vec.dot(ny);
464 return (dGn - dGM*M_dot_nx) * M_dot_ny;
467 result_t operator()(test_intput_t
const &x, trial_input_t
const &y)
const
469 return (*
this)(x.get_x(), x.get_unit_normal(), y.get_x(), y.get_unit_normal());
477 template <
class WaveNumber>
480 template <
class WaveNumber>
485 typedef std::complex<double> result_t;
487 static bool const is_symmetric =
false;
491 static bool const is_singular =
true;
494 template <
class WaveNumber>
498 static unsigned const singular_quadrature_order = 7;
503 template <
class WaveNumber>
505 :
public kernel_base<convected_helmholtz_3d_HSP_kernel<WaveNumber>>
510 typedef typename wave_number_kernel<WaveNumber>::wave_number_t wave_number_t;
511 typedef typename traits_t::test_input_t test_intput_t;
512 typedef typename traits_t::trial_input_t trial_input_t;
514 typedef typename traits_t::result_t result_t;
521 result_t operator()(x_t
const &x, x_t
const& nx, x_t
const &y, x_t
const& ny)
const
523 using boost::math::double_constants::pi;
524 using namespace std::complex_literals;
526 wave_number_t
const& kappa = this->get_kappa();
527 double const &M = this->get_mach_number();
528 x_t
const &Ma_vec = this->get_mach_number_vector();
531 double r = r_vec.norm();
533 double Q = 1.0 - M*M;
534 double M_dot_r = Ma_vec.dot(r_vec);
535 double M_dot_nx = Ma_vec.dot(nx);
536 double M_dot_ny = Ma_vec.dot(ny);
537 double R = std::sqrt((1-M*M) * r_vec.squaredNorm() + (M_dot_r * M_dot_r));
539 double r_per_R = r/R;
540 double nx_r_per_r = r_vec.dot(nx)/r;
541 double ny_r_per_r = r_vec.dot(ny)/r;
543 std::complex<double> G = std::exp(-1i*kappa*(R + M_dot_r)) / (4. * pi * R);
546 - Q * r_per_R*r_per_R * (3.0 + 3i*kappa*R - (kappa*R)*(kappa*R)) / (R*R) * nx_r_per_r * ny_r_per_r
547 - Q / R * r_per_R * 1i*kappa* (1.0 + 1i*kappa*R) * (M_dot_nx * ny_r_per_r + M_dot_ny * nx_r_per_r)
548 + 1.0 / (R*R) * (1.0 + 1i*kappa*R) * (ny.dot(nx) - M_dot_nx * M_dot_ny)
549 + Q * kappa*kappa * M_dot_nx * M_dot_ny
554 result_t operator()(test_intput_t
const &x, trial_input_t
const &y)
const
556 return (*
this)(x.get_x(), x.get_unit_normal(), y.get_x(), y.get_unit_normal());
561 template <
class WaveNumber>
567 template <
class guiggiani>
570 using boost::math::double_constants::pi;
571 using namespace std::complex_literals;
573 kernel_t const &kernel = obj.get_kernel();
575 double const M = kernel.get_mach_number();
576 double const Q = 1 - M*M;
578 auto const& Mav = kernel.get_mach_number_vector();
580 auto const& D = kernel.get_scaling_matrix();
581 auto const& T = kernel.get_rotation_matrix();
583 auto const& A_vec = obj.get_rvec_series(
_1());
584 auto A_hat_vec = D * T * A_vec;
585 double A = A_vec.norm();
586 double A_hat = A_hat_vec.norm();
588 auto const &J0_vec = obj.get_Jvec_series(
_0());
589 double J0 = std::sqrt(J0_vec.dot(J0_vec));
591 auto d0 = A_vec.normalized();
592 auto const &nx = obj.get_n0();
594 auto const &N0 = obj.get_shape_series(
_0());
596 double const M_n = nx.dot(Mav);
598 obj.set_laurent_coeff(
_m1(),
599 Q / (4.0 * pi) * A / std::pow(A_hat, 3) * nx.dot(d0) * J0 * N0 * (1 - M_n*M_n)
605 template <
class WaveNumber>
611 template <
class guiggiani>
614 using boost::math::double_constants::pi;
615 using namespace std::complex_literals;
617 kernel_t const &kernel = obj.get_kernel();
619 double const M = kernel.get_mach_number();
620 double const Q = 1 - M*M;
622 auto const& Mav = kernel.get_mach_number_vector();
624 auto const& D = kernel.get_scaling_matrix();
625 auto const& T = kernel.get_rotation_matrix();
627 auto const& A_vec = obj.get_rvec_series(
_1());
628 auto A_hat_vec = D * T * A_vec;
629 double A = A_vec.norm();
630 double A_hat = A_hat_vec.norm();
632 auto const &J0_vec = obj.get_Jvec_series(
_0());
633 double J0 = std::sqrt(J0_vec.dot(J0_vec));
635 auto d0 = A_vec.normalized();
636 auto const &nx = obj.get_n0();
638 auto const &N0 = obj.get_shape_series(
_0());
640 double const M_n = nx.dot(Mav);
642 obj.set_laurent_coeff(
_m1(),
643 Q / (4.0 * pi) * A / std::pow(A_hat, 3) * nx.dot(d0) * J0 * N0 * M_n
649 template <
class WaveNumber>
653 typedef WaveNumber wave_number_t;
656 template <
class guiggiani>
661 using boost::math::double_constants::pi;
662 using namespace std::complex_literals;
664 kernel_t const &kernel = obj.get_kernel();
666 double const M = kernel.get_mach_number();
667 double const Q = 1. - M*M;
668 wave_number_t
const &kappa = kernel.get_kappa();
669 auto const& Mav = kernel.get_mach_number_vector();
671 auto const& D = kernel.get_scaling_matrix();
672 auto const& T = kernel.get_rotation_matrix();
674 auto const& A_vec = obj.get_rvec_series(
_1());
675 auto const& B_vec = obj.get_rvec_series(
_2());
677 auto A_hat_vec = D * T * A_vec;
678 auto B_hat_vec = D * T * B_vec;
680 double A = A_vec.norm();
681 double A_hat = A_hat_vec.norm();
683 auto d0 = A_vec.normalized();
684 auto d1 = (B_vec - d0 * d0.dot(B_vec)) / A;
686 auto const &nx = obj.get_n0();
688 auto const &J0 = obj.get_Jvec_series(
_0());
689 auto const &J1 = obj.get_Jvec_series(
_1());
691 auto const &N0 = obj.get_shape_series(
_0());
692 auto const &N1 = obj.get_shape_series(
_1());
695 obj.set_laurent_coeff(
_m1(),
696 -Q*Q / (4.0 * pi) * 3.0 * A*A / std::pow(A_hat, 5) * (d0.dot(nx)) * (d1.dot(J0) + d0.dot(J1)) * N0
697 -Q*Q / (4.0 * pi) * A / std::pow(A_hat, 3) * (1i*kappa) * (J0.dot(Mav)) * (d0.dot(nx)) * N0
698 +Q / (4.0 * pi) / std::pow(A_hat, 3) * (J1.dot(nx) - nx.dot(Mav) * J1.dot(Mav)) * N0
699 +Q / (4.0 * pi) / std::pow(A_hat, 3) * (J0.dot(nx) - nx.dot(Mav) * J0.dot(Mav)) * N1
700 +Q / (4.0 * pi) * (-3. * A_hat_vec.dot(B_hat_vec) / std::pow(A_hat, 5) - 1i*kappa*A_vec.dot(Mav)/std::pow(A_hat, 3)) * (J0.dot(nx) - nx.dot(Mav) * J0.dot(Mav)) * N0
703 obj.set_laurent_coeff(
_m2(),
704 Q / (4.0 * pi) / std::pow(A_hat, 3) * (J0.dot(nx) - nx.dot(Mav) * J0.dot(Mav)) * N0
713 #endif // NIHU_CONVECTED_HELMHOLTZ_3D_KERNEL_HPP_INCLUDED