25 #ifndef NIHU_DOUBLE_INTEGRAL_HPP_INCLUDED
26 #define NIHU_DOUBLE_INTEGRAL_HPP_INCLUDED
28 #include "../util/matrix_traits.hpp"
29 #include "../util/product_type.hpp"
30 #include "../util/plain_type.hpp"
31 #include "../util/block_product.hpp"
32 #include "../library/location_normal.hpp"
33 #include "../library/weighted_input.hpp"
34 #include "../tmp/control.hpp"
35 #include "../util/store_pattern.hpp"
45 #include "singular_integral_shortcut.hpp"
71 template <
class SingularityDimension>
76 template <
class result_t,
class Kernel,
class TestField,
class TrialField>
88 static bool printed =
false;
92 "Singular shortcut switch called for mtch dim: " <<
94 ", sing val: " << SingularityDimension::value << std::endl;
99 result, kernel, test_field, trial_field, mtch);
110 template <
class Kernel,
class TestField,
class TrialField>
115 typename TestField::nset_t::shape_t,
116 typename Kernel::result_t,
117 typename TrialField::nset_t::shape_t
130 class Kernel,
class TestField,
class TrialField,
142 template <
class Kernel,
class TestField,
class TrialField>
148 typedef std::true_type WITH_SINGULARITY_CHECK;
149 typedef std::false_type WITHOUT_SINGULARITY_CHECK;
180 template <
class dual_iterator_t>
190 for (; it != end; ++it)
196 test_field.eval(it.get_first()->get_xi()) *
197 (test_input.get_jacobian() * it.get_first()->get_w()),
198 kernel(test_input, trial_input),
199 trial_field.eval(it.get_second()->get_xi()) *
200 (trial_input.get_jacobian() * it.get_second()->get_w())
212 template <
class singular_accelerator_t,
class dummy>
213 struct eval_singular_on_accelerator
224 template <
class singular_iterator_t>
230 singular_iterator_t begin,
231 singular_iterator_t end)
233 for (; begin != end; ++begin)
239 test_field.eval(begin.get_test_quadrature_elem().get_xi()) *
240 (test_input.get_jacobian() * begin.get_test_quadrature_elem().get_w()),
241 kernel(test_input, trial_input),
242 trial_field.eval(begin.get_trial_quadrature_elem().get_xi()) *
243 (trial_input.get_jacobian() * begin.get_trial_quadrature_elem().get_w())
254 template <
class dummy>
260 template <
class singular_iterator_t>
269 throw std::runtime_error(
"Invalid general singular quadrature");
283 WITHOUT_SINGULARITY_CHECK,
289 #if NIHU_MEX_DEBUGGING
290 static bool printed =
false;
293 mexPrintf(
"double_integral::eval without singularity check called on elements %d <- %d\n",
310 TestField, TrialField,
311 typename Kernel::estimator_t
312 >::eval(test_field, trial_field);
314 auto acc(create_dual_field_type_accelerator(
315 test_store_t::get_data()[degree], trial_store_t::get_data()[degree],
iteration::diadic()));
317 return eval_on_accelerator(
318 result, kernel, test_field, trial_field, acc.begin(), acc.end());
330 WITH_SINGULARITY_CHECK,
340 if (mtch.get_match_dimension() == -1)
341 return eval(WITHOUT_SINGULARITY_CHECK(), result, kernel, test_field, trial_field);
346 if (!tmp::call_until<
347 possible_match_types,
354 >(result, kernel, test_field, trial_field, mtch))
355 std::cerr <<
"UNHANDLED GALERKIN SINGULARITY TYPE: " << mtch.get_match_dimension() << std::endl;
367 template <
class OnSameMesh>
374 static bool const sing_check_needed =
380 return eval(std::integral_constant<bool, sing_check_needed>(),
381 result, kernel, test_field, trial_field);
394 template <
class Kernel,
class TestField,
class TrialField>
401 typedef std::true_type WITH_SINGULARITY_CHECK;
402 typedef std::false_type WITHOUT_SINGULARITY_CHECK;
445 template <
class dual_iterator_t>
451 dual_iterator_t first,
452 dual_iterator_t last)
454 for (; first != last; ++first)
468 first.get_first()->get_N() * (first.get_first()->get_w()),
469 kernel(test_input, trial_input),
470 trial_field.eval(first.get_second()->get_xi()) * (trial_input.get_jacobian() * first.get_second()->get_w())
483 template <
class singular_accelerator_t,
class dummy>
484 struct eval_singular_on_accelerator
499 singular_accelerator_t
const &sa)
501 for (
unsigned idx = 0; idx < test_nset_t::num_nodes; ++idx)
505 for (
auto const &q : sa.get_trial_quadrature(idx))
509 result.template block<kernel_rows, kernel_cols*trial_nset_t::num_nodes>(idx*kernel_rows, 0)
511 kernel(collocation_point, trial_input),
512 trial_field.eval(q.get_xi()) * trial_input.get_jacobian() * q.get_w()
524 template <
class dummy>
539 throw std::runtime_error(
"Invalid quadrature returned by eval_singular_on_accelerator");
553 WITHOUT_SINGULARITY_CHECK,
561 kernel, test_field, trial_field))
563 result, kernel, test_field, trial_field);
567 TestField, TrialField,
568 typename Kernel::estimator_t
569 >::eval(test_field, trial_field);
571 #if NIHU_MEX_DEBUGGING
572 static bool printed =
false;
575 mexPrintf(
"double_integral::eval without singularity check called on elements %d <- %d\n",
577 mexPrintf(
"Regular integral with degree %d\n", degree);
583 throw std::out_of_range(
"Too high quadrature degree selected for collocational integration");
593 auto acc(create_dual_field_type_accelerator(
594 test_store_t::get_data()[degree], trial_store_t::get_data()[degree],
iteration::diadic()));
596 return eval_on_accelerator(
597 result, kernel, test_field, trial_field, acc.begin(), acc.end());
609 WITH_SINGULARITY_CHECK,
618 if (mtch.get_match_dimension() == -1)
619 return eval(WITHOUT_SINGULARITY_CHECK(), result, kernel, test_field, trial_field);
623 static bool printed =
false;
625 std::cout <<
"Now checking singular shortcuts" << std::endl;
630 if (!tmp::call_until<
631 possible_match_types,
638 >(result, kernel, test_field, trial_field, mtch))
640 std::cerr <<
"UNHANDLED COLLOCATIONAL SINGULARITY TYPE: " << mtch.get_match_dimension() << std::endl;
659 template <
class OnSameMesh>
670 static bool const sing_check_needed =
673 #if NIHU_MEX_DEBUGGING
674 static bool printed =
false;
685 std::integral_constant<bool, sing_check_needed>(),
686 result, kernel, test_field, trial_field);
689 for (
unsigned corner_idx = 0; corner_idx < num_test_corners; ++corner_idx)
691 double weight = test_field.get_corner_angle(corner_idx);
693 result.template block<kernel_rows, kernel_cols*trial_nset_t::num_nodes>(corner_idx*kernel_rows, 0) *= weight;
708 template <
class Kernel,
class TestField,
class TrialField,
class SingularityDimension,
class Enable>
712 typedef void unspecialised;
718 Kernel, TestField, TrialField, SingularityDimension
723 template <
class result_t>
724 static result_t &eval_impl(
732 return double_integral_t::template eval_singular_on_accelerator<singular_accelerator_t, void>::eval(
733 result, kernel, test_field, trial_field,
738 template <
class result_t>
739 static result_t &eval_impl(
748 static bool printed =
false;
750 std::cout <<
"General version of singular_integral_shortcut called" << std::endl;
754 #if NIHU_MEX_DEBUGGING
757 static bool printed =
false;
760 mexPrintf(
"General singular integral shortcut for collocation called\n");
765 return double_integral_t::template eval_singular_on_accelerator<singular_accelerator_t, void>::eval(
779 template <
class result_t>
787 #if NIHU_MEX_DEBUGGING
788 static bool printed =
false;
791 mexPrintf(
"General singular integral shortcut called\n");
795 return eval_impl(formalism_t(), result, kernel, test_field, trial_field, match);