9#include <kernel/cubature/rule.hpp>
20 typename Shape_ =
typename Rule_::ShapeType>
28 template<
typename Shape_,
typename Weight_,
typename Coord_,
typename Po
int_>
32 Index num_refines = 1)
35 typedef Intern::RuleRefinery<RuleType> RefineryType;
39 rule = std::move(rule_in.clone());
41 else if(num_refines == 1)
44 "refine:" + rule_in.get_name());
45 RefineryType::refine(rule, rule_in);
50 rule = std::move(rule_in.clone());
51 for(
Index i(0); i < num_refines; ++i)
53 RuleType rule_tmp(rule.get_num_points() * RefineryType::count,
54 "refine*" +
stringify(i+1) +
":" + rule_in.get_name());
55 RefineryType::refine(rule_tmp, rule);
56 rule = std::move(rule_tmp);
62 template<
typename Factory_>
67 typedef Factory_ FactoryType;
68 typedef typename Factory_::ShapeType ShapeType;
102 using BaseClass::create;
104 template<
typename Weight_,
typename Coord_,
typename Po
int_>
108 String::size_type k = name.find_first_of(
':');
113 String head(name.substr(0, k));
114 String tail(name.substr(k + 1));
117 Index num_refines = 1;
120 k = head.find_first_of(
'*');
128 head = head.substr(0, k);
137 if(!FactoryType::create(rule_in, tail.
trim()))
141 create(rule, rule_in, num_refines);
148 bool variadic_ = Factory_::variadic>
151 template<
typename Factory_>
156 typedef Factory_ FactoryType;
157 typedef typename Factory_::ShapeType ShapeType;
159 static constexpr bool variadic =
false;
160 static constexpr int num_points = FactoryType::num_points;
167 _num_refines(num_refines)
171 using BaseClass::create;
173 template<
typename Weight_,
typename Coord_,
typename Po
int_>
176 create(rule, _num_refines);
179 template<
typename Weight_,
typename Coord_,
typename Po
int_>
183 FactoryType::create(rule_in);
184 create(rule, rule_in, num_refines);
188 template<
typename Factory_>
193 typedef Factory_ FactoryType;
194 typedef typename Factory_::ShapeType ShapeType;
196 static constexpr bool variadic =
true;
197 static constexpr int min_points = FactoryType::min_points;
198 static constexpr int max_points = FactoryType::max_points;
206 _num_points(num_points),
207 _num_refines(num_refines)
211 using BaseClass::create;
213 template<
typename Weight_,
typename Coord_,
typename Po
int_>
216 create(rule, _num_points, _num_refines);
219 template<
typename Weight_,
typename Coord_,
typename Po
int_>
223 FactoryType::create(rule_in, num_points);
224 create(rule, rule_in, num_refines);
231 template<
typename Rule_>
232 class RuleRefinery<Rule_, Shape::Simplex<1> >
235 typedef typename Rule_::WeightType Weight_;
236 typedef typename Rule_::CoordType Coord_;
237 static constexpr int count = 2;
239 static void refine(Rule_& rule,
const Rule_& rule_in)
241 int n = rule_in.get_num_points();
242 for(
int i(0); i < n; ++i)
244 rule.get_coord( i, 0) = Coord_(0.5) * rule_in.get_coord(i,0);
245 rule.get_coord(n+i, 0) = Coord_(0.5) * (rule_in.get_coord(i,0) + Coord_(1));
246 rule.get_weight( i) = Weight_(0.5) * rule_in.get_weight(i);
247 rule.get_weight(n+i) = Weight_(0.5) * rule_in.get_weight(i);
252 template<
typename Rule_>
253 class RuleRefinery<Rule_, Shape::Simplex<2> >
256 typedef typename Rule_::WeightType Weight_;
257 typedef typename Rule_::CoordType Coord_;
258 static constexpr int count = 4;
260 static void refine(Rule_& rule,
const Rule_& rule_in)
262 int n = rule_in.get_num_points();
266 v[0][0][0] = Coord_(0);
267 v[0][0][1] = Coord_(0);
268 v[0][1][0] = Coord_(1)/Coord_(2);
269 v[0][1][1] = Coord_(0);
270 v[0][2][0] = Coord_(0);
271 v[0][2][1] = Coord_(1)/Coord_(2);
273 v[1][0][0] = Coord_(1)/Coord_(2);
274 v[1][0][1] = Coord_(0);
275 v[1][1][0] = Coord_(1);
276 v[1][1][1] = Coord_(0);
277 v[1][2][0] = Coord_(1)/Coord_(2);
278 v[1][2][1] = Coord_(1)/Coord_(2);
280 v[2][0][0] = Coord_(0);
281 v[2][0][1] = Coord_(1)/Coord_(2);
282 v[2][1][0] = Coord_(1)/Coord_(2);
283 v[2][1][1] = Coord_(1)/Coord_(2);
284 v[2][2][0] = Coord_(0);
285 v[2][2][1] = Coord_(1);
287 v[3][0][0] = Coord_(1)/Coord_(2);
288 v[3][0][1] = Coord_(1)/Coord_(2);
289 v[3][1][0] = Coord_(0);
290 v[3][1][1] = Coord_(1)/Coord_(2);
291 v[3][2][0] = Coord_(1)/Coord_(2);
292 v[3][2][1] = Coord_(0);
295 for(
int i(0); i <= 3; ++i)
297 for(
int j(0); j < n; ++j)
299 Coord_ x = rule_in.get_coord(j,0);
300 Coord_ y = rule_in.get_coord(j,1);
301 Coord_ w = Coord_(1) - x - y;
302 rule.get_coord(i*n + j, 0) = w*v[i][0][0] + x*v[i][1][0] + y*v[i][2][0];
303 rule.get_coord(i*n + j, 1) = w*v[i][0][1] + x*v[i][1][1] + y*v[i][2][1];
304 rule.get_weight(i*n + j) = Weight_(0.25) * rule_in.get_weight(j);
310 template<
typename Rule_>
311 class RuleRefinery<Rule_, Shape::Simplex<3> >
314 typedef typename Rule_::WeightType Weight_;
315 typedef typename Rule_::CoordType Coord_;
316 static constexpr int count = 12;
318 static void refine(Rule_& rule,
const Rule_& rule_in)
326 v[0][0][0] = Coord_(1)/Coord_(2);
327 v[0][0][1] = Coord_(0);
328 v[0][0][2] = Coord_(0);
331 v[0][1][0] = Coord_(0);
332 v[0][1][1] = Coord_(0);
333 v[0][1][2] = Coord_(1)/Coord_(2);
336 v[0][2][0] = Coord_(0);
337 v[0][2][1] = Coord_(1)/Coord_(2);
338 v[0][2][2] = Coord_(0);
341 v[0][3][0] = Coord_(0);
342 v[0][3][1] = Coord_(0);
343 v[0][3][2] = Coord_(0);
349 v[1][0][0] = Coord_(1)/Coord_(2);
350 v[1][0][1] = Coord_(0);
351 v[1][0][2] = Coord_(0);
354 v[1][1][0] = Coord_(0);
355 v[1][1][1] = Coord_(1)/Coord_(2);
356 v[1][1][2] = Coord_(0);
359 v[1][2][0] = Coord_(0);
360 v[1][2][1] = Coord_(0);
361 v[1][2][2] = Coord_(1)/Coord_(2);
364 v[1][3][0] = Coord_(1)/Coord_(4);
365 v[1][3][1] = Coord_(1)/Coord_(4);
366 v[1][3][2] = Coord_(1)/Coord_(4);
372 v[2][0][0] = Coord_(1)/Coord_(2);
373 v[2][0][1] = Coord_(0);
374 v[2][0][2] = Coord_(0);
377 v[2][1][0] = Coord_(1)/Coord_(2);
378 v[2][1][1] = Coord_(1)/Coord_(2);
379 v[2][1][2] = Coord_(0);
382 v[2][2][0] = Coord_(1)/Coord_(2);
383 v[2][2][1] = Coord_(0);
384 v[2][2][2] = Coord_(1)/Coord_(2);
387 v[2][3][0] = Coord_(1);
388 v[2][3][1] = Coord_(0);
389 v[2][3][2] = Coord_(0);
395 v[3][0][0] = Coord_(1)/Coord_(2);
396 v[3][0][1] = Coord_(0);
397 v[3][0][2] = Coord_(0);
400 v[3][1][0] = Coord_(1)/Coord_(2);
401 v[3][1][1] = Coord_(0);
402 v[3][1][2] = Coord_(1)/Coord_(2);
405 v[3][2][0] = Coord_(1)/Coord_(2);
406 v[3][2][1] = Coord_(1)/Coord_(2);
407 v[3][2][2] = Coord_(0);
410 v[3][3][0] = Coord_(1)/Coord_(4);
411 v[3][3][1] = Coord_(1)/Coord_(4);
412 v[3][3][2] = Coord_(1)/Coord_(4);
418 v[4][0][0] = Coord_(0);
419 v[4][0][1] = Coord_(1)/Coord_(2);
420 v[4][0][2] = Coord_(0);
423 v[4][1][0] = Coord_(0);
424 v[4][1][1] = Coord_(1)/Coord_(2);
425 v[4][1][2] = Coord_(1)/Coord_(2);
428 v[4][2][0] = Coord_(1)/Coord_(2);
429 v[4][2][1] = Coord_(1)/Coord_(2);
430 v[4][2][2] = Coord_(0);
433 v[4][3][0] = Coord_(0);
434 v[4][3][1] = Coord_(1);
435 v[4][3][2] = Coord_(0);
441 v[5][0][0] = Coord_(0);
442 v[5][0][1] = Coord_(1)/Coord_(2);
443 v[5][0][2] = Coord_(0);
446 v[5][1][0] = Coord_(1)/Coord_(2);
447 v[5][1][1] = Coord_(1)/Coord_(2);
448 v[5][1][2] = Coord_(0);
451 v[5][2][0] = Coord_(0);
452 v[5][2][1] = Coord_(1)/Coord_(2);
453 v[5][2][2] = Coord_(1)/Coord_(2);
456 v[5][3][0] = Coord_(1)/Coord_(4);
457 v[5][3][1] = Coord_(1)/Coord_(4);
458 v[5][3][2] = Coord_(1)/Coord_(4);
464 v[6][0][0] = Coord_(0);
465 v[6][0][1] = Coord_(0);
466 v[6][0][2] = Coord_(1)/Coord_(2);
469 v[6][1][0] = Coord_(1)/Coord_(2);
470 v[6][1][1] = Coord_(0);
471 v[6][1][2] = Coord_(1)/Coord_(2);
474 v[6][2][0] = Coord_(0);
475 v[6][2][1] = Coord_(1)/Coord_(2);
476 v[6][2][2] = Coord_(1)/Coord_(2);
479 v[6][3][0] = Coord_(0);
480 v[6][3][1] = Coord_(0);
481 v[6][3][2] = Coord_(1);
487 v[7][0][0] = Coord_(0);
488 v[7][0][1] = Coord_(0);
489 v[7][0][2] = Coord_(1)/Coord_(2);
492 v[7][1][0] = Coord_(0);
493 v[7][1][1] = Coord_(1)/Coord_(2);
494 v[7][1][2] = Coord_(1)/Coord_(2);
497 v[7][2][0] = Coord_(1)/Coord_(2);
498 v[7][2][1] = Coord_(0);
499 v[7][2][2] = Coord_(1)/Coord_(2);
502 v[7][3][0] = Coord_(1)/Coord_(4);
503 v[7][3][1] = Coord_(1)/Coord_(4);
504 v[7][3][2] = Coord_(1)/Coord_(4);
510 v[8][0][0] = Coord_(1)/Coord_(2);
511 v[8][0][1] = Coord_(1)/Coord_(2);
512 v[8][0][2] = Coord_(0);
515 v[8][1][0] = Coord_(1)/Coord_(2);
516 v[8][1][1] = Coord_(0);
517 v[8][1][2] = Coord_(1)/Coord_(2);
520 v[8][2][0] = Coord_(0);
521 v[8][2][1] = Coord_(1)/Coord_(2);
522 v[8][2][2] = Coord_(1)/Coord_(2);
525 v[8][3][0] = Coord_(1)/Coord_(4);
526 v[8][3][1] = Coord_(1)/Coord_(4);
527 v[8][3][2] = Coord_(1)/Coord_(4);
533 v[9][0][0] = Coord_(0);
534 v[9][0][1] = Coord_(1)/Coord_(2);
535 v[9][0][2] = Coord_(0);
538 v[9][1][0] = Coord_(0);
539 v[9][1][1] = Coord_(1)/Coord_(2);
540 v[9][1][2] = Coord_(1)/Coord_(2);
543 v[9][2][0] = Coord_(0);
544 v[9][2][1] = Coord_(0);
545 v[9][2][2] = Coord_(1)/Coord_(2);
548 v[9][3][0] = Coord_(1)/Coord_(4);
549 v[9][3][1] = Coord_(1)/Coord_(4);
550 v[9][3][2] = Coord_(1)/Coord_(4);
556 v[10][0][0] = Coord_(1)/Coord_(2);
557 v[10][0][1] = Coord_(0);
558 v[10][0][2] = Coord_(0);
561 v[10][1][0] = Coord_(0);
562 v[10][1][1] = Coord_(0);
563 v[10][1][2] = Coord_(1)/Coord_(2);
566 v[10][2][0] = Coord_(1)/Coord_(2);
567 v[10][2][1] = Coord_(0);
568 v[10][2][2] = Coord_(1)/Coord_(2);
571 v[10][3][0] = Coord_(1)/Coord_(4);
572 v[10][3][1] = Coord_(1)/Coord_(4);
573 v[10][3][2] = Coord_(1)/Coord_(4);
579 v[11][0][0] = Coord_(1)/Coord_(2);
580 v[11][0][1] = Coord_(0);
581 v[11][0][2] = Coord_(0);
584 v[11][1][0] = Coord_(1)/Coord_(2);
585 v[11][1][1] = Coord_(1)/Coord_(2);
586 v[11][1][2] = Coord_(0);
589 v[11][2][0] = Coord_(0);
590 v[11][2][1] = Coord_(1)/Coord_(2);
591 v[11][2][2] = Coord_(0);
594 v[11][3][0] = Coord_(1)/Coord_(4);
595 v[11][3][1] = Coord_(1)/Coord_(4);
596 v[11][3][2] = Coord_(1)/Coord_(4);
599 int n = rule_in.get_num_points();
603 for(
int i(0); i <= 11; ++i)
605 for(
int j(0); j < n; ++j)
607 Coord_ x = rule_in.get_coord(j,0);
608 Coord_ y = rule_in.get_coord(j,1);
609 Coord_ z = rule_in.get_coord(j,2);
610 Coord_ w = Coord_(1) - x - y - z;
611 rule.get_coord(i*n + j, 0) = w*v[i][0][0] + x*v[i][1][0] + y*v[i][2][0] + z*v[i][3][0];
612 rule.get_coord(i*n + j, 1) = w*v[i][0][1] + x*v[i][1][1] + y*v[i][2][1] + z*v[i][3][1];
613 rule.get_coord(i*n + j, 2) = w*v[i][0][2] + x*v[i][1][2] + y*v[i][2][2] + z*v[i][3][2];
624 if(i == 0 || i == 2 || i == 4|| i == 6)
626 vol = Weight_(1)/Weight_(8);
630 vol = Weight_(1)/Weight_(16);
633 rule.get_weight(i*n + j) = rule_in.get_weight(j)*Math::abs(vol);
639 template<
typename Rule_>
640 class RuleRefinery<Rule_, Shape::Hypercube<1> >
643 typedef typename Rule_::WeightType Weight_;
644 typedef typename Rule_::CoordType Coord_;
645 static constexpr int count = 2;
647 static void refine(Rule_& rule,
const Rule_& rule_in)
649 int n = rule_in.get_num_points();
650 for(
int i(0); i < n; ++i)
652 rule.get_coord( i, 0) = Coord_(0.5) * rule_in.get_coord(i,0) - Coord_(0.5);
653 rule.get_coord(n+i, 0) = Coord_(0.5) * rule_in.get_coord(i,0) + Coord_(0.5);
654 rule.get_weight( i) = Weight_(0.5) * rule_in.get_weight(i);
655 rule.get_weight(n+i) = Weight_(0.5) * rule_in.get_weight(i);
661 template<
typename Rule_>
662 class RuleRefinery<Rule_, Shape::Hypercube<2> >
665 typedef typename Rule_::WeightType Weight_;
666 typedef typename Rule_::CoordType Coord_;
667 static constexpr int count = 4;
669 static void refine(Rule_& rule,
const Rule_& rule_in)
672 int n = rule_in.get_num_points();
675 for(
int i(0); i <= 3; ++i)
678 Coord_ dx = Coord_(0);
679 Coord_ dy = Coord_(0);
683 dx = -Coord_(1)/Coord_(2);
684 dy = -Coord_(1)/Coord_(2);
688 dx = Coord_(1)/Coord_(2);
689 dy = -Coord_(1)/Coord_(2);
693 dx = -Coord_(1)/Coord_(2);
694 dy = Coord_(1)/Coord_(2);
698 dx = Coord_(1)/Coord_(2);
699 dy = Coord_(1)/Coord_(2);
702 for(
int j(0); j < n; ++j)
704 rule.get_coord(i*n + j, 0) = Coord_(0.5) * rule_in.get_coord(j,0) + dx;
705 rule.get_coord(i*n + j, 1) = Coord_(0.5) * rule_in.get_coord(j,1) + dy;
706 rule.get_weight(i*n + j) = rule_in.get_weight(j)/Weight_(4);
712 template<
typename Rule_>
713 class RuleRefinery<Rule_, Shape::Hypercube<3> >
716 typedef typename Rule_::WeightType Weight_;
717 typedef typename Rule_::CoordType Coord_;
718 static constexpr int count = 8;
720 static void refine(Rule_& rule,
const Rule_& rule_in)
723 int n = rule_in.get_num_points();
726 for(
int i(0); i <= 7; ++i)
729 Coord_ dx = Coord_(0);
730 Coord_ dy = Coord_(0);
731 Coord_ dz = Coord_(0);
735 dx = -Coord_(1)/Coord_(2);
736 dy = -Coord_(1)/Coord_(2);
737 dz = -Coord_(1)/Coord_(2);
741 dx = Coord_(1)/Coord_(2);
742 dy = -Coord_(1)/Coord_(2);
743 dz = -Coord_(1)/Coord_(2);
747 dx = -Coord_(1)/Coord_(2);
748 dy = Coord_(1)/Coord_(2);
749 dz = -Coord_(1)/Coord_(2);
753 dx = Coord_(1)/Coord_(2);
754 dy = Coord_(1)/Coord_(2);
755 dz = -Coord_(1)/Coord_(2);
759 dx = -Coord_(1)/Coord_(2);
760 dy = -Coord_(1)/Coord_(2);
761 dz = Coord_(1)/Coord_(2);
765 dx = Coord_(1)/Coord_(2);
766 dy = -Coord_(1)/Coord_(2);
767 dz = Coord_(1)/Coord_(2);
771 dx = -Coord_(1)/Coord_(2);
772 dy = Coord_(1)/Coord_(2);
773 dz = Coord_(1)/Coord_(2);
777 dx = Coord_(1)/Coord_(2);
778 dy = Coord_(1)/Coord_(2);
779 dz = Coord_(1)/Coord_(2);
782 for(
int j(0); j < n; ++j)
784 rule.get_coord(i*n + j, 0) = Coord_(0.5) * rule_in.get_coord(j,0) + dx;
785 rule.get_coord(i*n + j, 1) = Coord_(0.5) * rule_in.get_coord(j,1) + dy;
786 rule.get_coord(i*n + j, 2) = Coord_(0.5) * rule_in.get_coord(j,2) + dz;
787 rule.get_weight(i*n + j) = rule_in.get_weight(j)/Weight_(8);
Cubature Rule class template.
String class implementation.
bool parse(T_ &t) const
Parses the string and stores its value in the provided variable.
int compare_no_case(const String &other) const
Compares two strings without regard to case.
String trim(const String &charset) const
Trims the string.
String stringify(const T_ &item)
Converts an item into a String.
std::uint64_t Index
Index data type.