23 #ifndef SINGULAR_ACCELERATOR_HPP_INCLUDED
24 #define SINGULAR_ACCELERATOR_HPP_INCLUDED
32 #include "../tmp/control.hpp"
33 #include "../util/is_specialisation.hpp"
35 #include "singular_integral_shortcut.hpp"
37 #include "../util/dual_range.hpp"
50 template <
class test_iterator_t,
class trial_iterator_t>
52 public dual_iterator<iteration::diagonal, test_iterator_t, trial_iterator_t>
74 return *base_t::get_first();
82 return *base_t::get_second();
98 template <
class match>
108 template <
class match>
125 class =
typename get_formalism<TestField, TrialField>::type
145 "The kernel field must be derived from kernel_base<Kernel>");
147 "The test field must be derived from field_base<TestField>");
149 "The trial field must be derived from field_base<TrialField>");
175 static unsigned const domain_dimension = test_domain_t::dimension;
177 static_assert(domain_dimension == trial_domain_t::dimension,
178 "The test and trial domain dimensions must match");
181 static unsigned const n_test_corners = test_domain_t::num_corners;
183 static unsigned const n_trial_corners = trial_domain_t::num_corners;
188 static_assert(std::is_same<scalar_t, typename trial_domain_t::scalar_t>::value,
189 "The test and trial domain scalar types must match");
205 static_assert(std::is_same<quadrature_elem_t, typename trial_quadrature_t::quadrature_elem_t>::value,
206 "The trial and test quadrature elements must be of the same type");
210 typename test_quadrature_t::const_iterator,
211 typename trial_quadrature_t::const_iterator>
iterator;
214 static const bool face_match_possible = std::is_same<test_field_t, trial_field_t>::value;
226 case domain_dimension:
228 m_test_quadratures[domain_dimension][0].begin(),
229 m_trial_quadratures[domain_dimension][0].begin());
232 throw std::logic_error(
"Cannot return singular quadrature for NO_MATCH type");
235 unsigned test_domain_corner =
237 unsigned trial_domain_corner =
254 case domain_dimension:
256 m_test_quadratures[domain_dimension][0].end(),
257 m_trial_quadratures[domain_dimension][0].end());
260 throw std::logic_error(
"Cannot return singular quadrature for NO_MATCH type");
263 unsigned test_domain_corner =
265 unsigned trial_domain_corner =
275 template <
class Match>
276 void generate(Match, std::false_type)
278 int d = Match::value;
279 if (d == domain_dimension)
281 m_test_quadratures[d].push_back(test_quadrature_t());
282 m_trial_quadratures[d].push_back(trial_quadrature_t());
283 quad_factory_t::template generate<Match>(
284 m_test_quadratures[d][0],
285 m_trial_quadratures[d][0],
286 singular_quadrature_order);
290 test_quadrature_t test_q;
291 trial_quadrature_t trial_q;
292 quad_factory_t::template generate<Match>(
293 test_q, trial_q, singular_quadrature_order);
295 for (
unsigned i = 0; i < n_test_corners; ++i)
297 Eigen::Matrix<scalar_t, n_test_corners, domain_dimension> test_corners;
298 for (
unsigned k = 0; k < n_test_corners; ++k)
299 test_corners.row(k) = test_domain_t::get_corner((i+k) % n_test_corners);
300 m_test_quadratures[d].push_back(
301 test_q.template transform<isoparam_shape_set<test_domain_t>, !is_surface>(test_corners)
305 for (
unsigned i = 0; i < n_trial_corners; ++i)
307 Eigen::Matrix<scalar_t, n_trial_corners, domain_dimension> trial_corners;
308 for (
unsigned k = 0; k < n_trial_corners; ++k)
311 if (domain_dimension == 2 && d == 1)
312 idx = (i+1+n_trial_corners-k) % n_trial_corners;
314 idx = (i+k) % n_trial_corners;
315 trial_corners.row(k) = trial_domain_t::get_corner(idx);
317 m_trial_quadratures[d].push_back(
318 trial_q.template transform<isoparam_shape_set<trial_domain_t>, !is_surface>(trial_corners)
324 template <
class Match>
325 void generate(Match, std::true_type)
331 template <
class Match>
332 struct generate_wrapper {
struct type
340 obj.generate(Match(), spec());
350 generate_wrapper<tmp::_1>,
356 std::vector<test_quadrature_t> m_test_quadratures[domain_dimension + 1];
357 std::vector<trial_quadrature_t> m_trial_quadratures[domain_dimension + 1];
367 template <
class Kernel,
class TestField,
class TrialField>
372 "The kernel must be derived from kernel_base<Kernel>");
374 "The trial field must be derived from field_base<TrialField>");
421 typedef typename trial_quadrature_t::const_iterator
iterator;
425 static const bool face_match_possible = std::is_same<test_elem_t, trial_elem_t>::value;
433 return m_face_trial_quadratures[idx];
441 if (face_match_possible)
443 for (
unsigned idx = 0; idx < test_nset_t::num_nodes; ++idx)
444 m_face_trial_quadratures[idx] += trial_blind_t::on_face(
445 singular_quadrature_order, test_nset_t::corner_at(idx));
458 class SingularityDimension,
463 template <
class TestField,
class TrialField,
class SingularityDimension>
465 : std::integral_constant<int,
466 TestField::elem_t::domain_t::dimension + TrialField::elem_t::domain_t::dimension - SingularityDimension::value
470 template <
class TestField,
class TrialField,
class SingularityDimension>
472 : std::integral_constant<unsigned,
473 TrialField::elem_t::domain_t::dimension
482 template <
class Kernel,
class TestField,
class TrialField,
class SingularityDimension,
class =
void>
494 template <
class Kernel,
class TestField,
class TrialField,
class SingularityDimension>
496 minimal_reference_dimension<
497 typename singular_kernel_traits<Kernel>::singularity_type_t
498 >::value <= double_integral_free_dimensions<TestField, TrialField, SingularityDimension>::value
506 #endif // SINGULAR_ACCELERATOR_HPP_INCLUDED