Rheolef  7.2
an efficient C++ finite element environment
 
Loading...
Searching...
No Matches
field_expr_recursive.h
Go to the documentation of this file.
1#ifndef _RHEOLEF_FIELD_EXPR_RECURSIVE_H
2#define _RHEOLEF_FIELD_EXPR_RECURSIVE_H
23//
24// field-valued nonlinear expressions, as:
25//
26// field wh = interpolate (Xh, 1/uh - uh*(1-vh)):
27// Float Ih = integrate (omega, 1/uh - uh*(1-vh), qopt):
28//
29// author: Pierre.Saramito@imag.fr
30//
31// date: 15 september 2015
32//
33// Notes; use template expressions and SFINAE techiques
34// The interpolation operator is required, as in
35// 1/uh and uh*vh that do not belong to Xh when uh, vh in Xh
36//
37// SUMMARY:
38// 1. unary operations
39// 1.1. unary node
40// 1.2. unary calls
41// 1.3. unary compose
42// 2. binary operations
43// 2.1. binary node
44// 2.2. binary calls
45// 2.3. binary compose
46//
47#include "rheolef/field_expr_terminal.h"
48
49namespace rheolef {
50
51// -------------------------------------------
52// 1. unary operations
53// -------------------------------------------
54// 1.1. unary node
55// -------------------------------------------
56namespace details {
57
58template<class UnaryFunction, class Expr>
60public:
61// typedefs:
62
64 using memory_type = typename Expr::memory_type;
65 using result_type = typename details::generic_unary_traits<UnaryFunction>::template result_hint<typename Expr::result_type>::type;
73
74// alocators:
75
76 field_expr_v2_nonlinear_node_unary (const UnaryFunction& f, const Expr& expr);
77
78// --------------------------------------------
79// accessors for the affine & homogeneous case:
80// --------------------------------------------
81
83 = and_type<
84 or_type<
85 std::is_same<UnaryFunction,details::unary_plus>
86 ,std::is_same<UnaryFunction,details::negate>
87 ,std::is_same<UnaryFunction,details::binder_first <details::plus, scalar_type>>
88 ,std::is_same<UnaryFunction,details::binder_second<details::plus, scalar_type>>
89 ,std::is_same<UnaryFunction,details::binder_first <details::minus, scalar_type>>
90 ,std::is_same<UnaryFunction,details::binder_second<details::minus, scalar_type>>
91 ,std::is_same<UnaryFunction,details::binder_first <details::multiplies,scalar_type>>
92 ,std::is_same<UnaryFunction,details::binder_second<details::multiplies,scalar_type>>
93 ,std::is_same<UnaryFunction,details::binder_second<details::divides, scalar_type>>
94 >
96 >;
97
99 return is_affine_homogeneous::value
100 && _expr.have_homogeneous_space (Vh);
101 }
102 // minimal forward iterator interface:
104 using iterator_category = std::forward_iterator_tag;
105 using value_type = typename Expr::scalar_type;
108 using difference_type = std::ptrdiff_t;
109 const_iterator (UnaryFunction f, typename Expr::const_iterator expr_iter)
110 : _f(f), _expr_iter (expr_iter) {}
111 const_iterator& operator++ () { ++_expr_iter; return *this; }
112 value_type operator* () const { return _f (*_expr_iter); }
113 protected:
114 const UnaryFunction _f;
115 typename Expr::const_iterator _expr_iter;
116 };
117 const_iterator begin_dof() const { return const_iterator (_f, _expr.begin_dof()); }
118
119// --------------------------------------------
120// interface for the general nonlinear case:
121// --------------------------------------------
122// accessors:
123
125 const Expr& expr() const { return _expr; }
126
130
131#ifdef TO_CLEAN
132// field_lazy interface:
133
134 const geo_type& get_geo() const { return _expr.get_geo(); }
135 const band_type& get_band() const { return _expr.get_band(); }
136 const space_type& get_space() const { return _expr.get_space(); }
137 bool is_on_band () const { return _expr.is_on_band(); }
138 void initialize (const geo_type& omega_K) { _expr.initialize (omega_K); }
139#endif // TO_CLEAN
140
141// initializators:
142
143 // field_lazy interface:
144
147 const integrate_option& iopt)
148 { _expr.initialize (pops, iopt); }
149
153 const integrate_option& iopt)
154 { _expr.initialize (Xh, pops, iopt); }
155
156// -------------------------
157// run time check args types
158// -------------------------
159 template<class Result, class Arg, class Status>
161 template<class M>
163 const self_type& obj,
164 const geo_basic<float_type,M>& omega_K,
165 const geo_element& K,
166 Eigen::Matrix<Result,Eigen::Dynamic,1>& value)
167 {
168 fatal_macro ("invalid type resolution: Result="<<typename_macro(Result)
169 << ", Arg="<<typename_macro(Arg)
170 << ", UnaryFunction="<<typename_macro(UnaryFunction));
171 }
172 template<class M>
174 const self_type& obj,
175 const geo_basic<float_type,M>& omega_K,
176 const geo_element& K,
177 const side_information_type& sid,
178 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
179 {
180 fatal_macro ("invalid type resolution: Result="<<typename_macro(Result)
181 << ", Arg="<<typename_macro(Arg)
182 << ", UnaryFunction="<<typename_macro(UnaryFunction));
183 }
184 };
185 template<class Result, class Arg>
186 struct evaluate_call_check<Result,Arg,std::true_type> {
187 // in an element:
188 template<class M>
190 const self_type& obj,
191 const geo_basic<float_type,M>& omega_K,
192 const geo_element& K,
193 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
194 {
195 Eigen::Matrix<Arg,Eigen::Dynamic,1> value1;
196 obj._expr.evaluate (omega_K, K, value1);
197 value.resize(value1.size());
198 for (size_type i = 0, ni = value.rows(); i < ni; ++i) {
199 value[i] = obj._f (value1[i]);
200 }
201 }
202 // on a side:
203 template<class M>
205 const self_type& obj,
206 const geo_basic<float_type,M>& omega_K,
207 const geo_element& K,
208 const side_information_type& sid,
209 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
210 {
211 Eigen::Matrix<Arg,Eigen::Dynamic,1> value1;
212 obj._expr.evaluate_on_side (omega_K, K, sid, value1);
213 value.resize (value1.size());
214 for (size_type i = 0, ni = value.rows(); i < ni; ++i) {
215 value[i] = obj._f (value1[i]);
216 }
217 }
218 };
219// -------------------------------------------
220// evaluate in an element, with known arg type
221// -------------------------------------------
222 template<class Result, class Arg, class M>
224 const geo_basic<float_type,M>& omega_K,
225 const geo_element& K,
226 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
227 {
228 typedef typename details::generic_unary_traits<UnaryFunction>::template hint<Arg,Result>::result_type result_type;
229 typedef typename details::and_type<
232 >::type
233 status_t;
235 eval (*this, omega_K, K, value);
236 }
237// -------------------------------------------
238// evaluate on a side, with known arg type
239// -------------------------------------------
240 template<class Result, class Arg, class M>
242 const geo_basic<float_type,M>& omega_K,
243 const geo_element& K,
244 const side_information_type& sid,
245 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
246 {
247 typedef typename details::generic_unary_traits<UnaryFunction>::template hint<Arg,Result>::result_type result_type;
248 typedef typename details::and_type<
251 >::type
252 status_t;
254 eval (*this, omega_K, K, sid, value);
255 }
256// -------------------------------------------
257// determine args at compile-time or run-time:
258// -------------------------------------------
259 template<class This, class Result, class Arg, space_constant::valued_type ArgTag = space_constant::valued_tag_traits<Arg>::value>
261
262 // when arg is unknown at run-time:
263 template<class This, class Result, class Arg>
264 struct evaluate_switch<This, Result, Arg, space_constant::last_valued> {
265 template<class M>
266 void evaluate (
267 const This& obj,
268 const geo_basic<float_type,M>& omega_K,
269 const geo_element& K,
270 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
271 {
272 typedef typename scalar_traits<Arg>::type T;
273 space_constant::valued_type arg_valued_tag = obj._expr.valued_tag();
274 switch (arg_valued_tag) {
276 obj.template evaluate_call<Result,T,M> (omega_K, K, value); break;
278 obj.template evaluate_call<Result, point_basic<T> > (omega_K, K, value); break;
281 obj.template evaluate_call<Result, tensor_basic<T> > (omega_K, K, value); break;
282 default: { error_macro ("unexpected valued tag="<<arg_valued_tag); }
283 }
284 }
285 template<class M>
287 const This& obj,
288 const geo_basic<float_type,M>& omega_K,
289 const geo_element& K,
290 const side_information_type& sid,
291 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
292 {
293 typedef typename scalar_traits<Arg>::type T;
294 space_constant::valued_type arg_valued_tag = obj._expr.valued_tag();
295 switch (arg_valued_tag) {
297 obj.template evaluate_call<Result,T> (omega_K, K, sid, value); break;
299 obj.template evaluate_call<Result, point_basic<T> > (omega_K, K, value); break;
302 obj.template evaluate_call<Result, tensor_basic<T> > (omega_K, K, value); break;
303 default: { error_macro ("unexpected valued tag="<<arg_valued_tag); }
304 }
305 }
306 };
307 // specializations when arg is known at compile-time:
308#define _RHEOLEF_evaluate_switch_specialization(VALUED,VALUE) \
309 template<class This, class Result, class Arg> \
310 struct evaluate_switch <This, Result, Arg, VALUED> { \
311 typedef typename scalar_traits<Arg>::type T; \
312 typedef typename float_traits<Arg>::type float_type; \
313 \
314 void evaluate ( \
315 const This& obj, \
316 const geo_basic<float_type,memory_type>& omega_K, \
317 const geo_element& K, \
318 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const \
319 { obj.template evaluate_call<Result, VALUE> (omega_K, K, value); } \
320 \
321 template<class M> \
322 void evaluate_on_side ( \
323 const This& obj, \
324 const geo_basic<float_type,M>& omega_K, \
325 const geo_element& K, \
326 const side_information_type& sid, \
327 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const \
328 { obj.template evaluate_call<Result, VALUE> (omega_K, K, sid, value); } \
329 }; \
330
336#undef _RHEOLEF_evaluate_switch_specialization
337
338// ----------------------
339// evaluate in an element
340// ----------------------
341 template<class Result>
342 void
343 evaluate (
344 const geo_basic<float_type,memory_type>& omega_K,
345 const geo_element& K,
346 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
347 {
348 typedef field_expr_v2_nonlinear_node_unary<UnaryFunction, Expr> This;
349 typedef typename details::generic_unary_traits<UnaryFunction>::template hint<typename Expr::value_type,Result>::argument_type
350 A1;
351 evaluate_switch <This, Result, A1> helper;
352 helper.evaluate (*this, omega_K, K, value);
353 }
354// -------------------
355// evaluate on a side:
356// -------------------
357 template<class Result>
358 void
360 const geo_basic<float_type,memory_type>& omega_K,
361 const geo_element& K,
362 const side_information_type& sid,
363 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
364 {
365 typedef field_expr_v2_nonlinear_node_unary<UnaryFunction, Expr> This;
366 typedef typename details::generic_unary_traits<UnaryFunction>::template hint<typename Expr::value_type,Result>::argument_type
367 A1;
368 evaluate_switch <This, Result, A1> helper;
369 helper.evaluate_on_side (*this, omega_K, K, sid, value);
370 }
371
372 template<class Result>
373 bool valued_check() const {
374 typedef typename details::generic_unary_traits<UnaryFunction>::template hint<typename Expr::value_type,Result>::argument_type
375 A1;
376 if (! is_undeterminated<A1>::value) return _expr.template valued_check<A1>();
377 return true;
378 }
379protected:
380// data:
381 UnaryFunction _f;
382 Expr _expr;
383// working area:
384public:
385 mutable std::array<
386 Eigen::Matrix<scalar_type,Eigen::Dynamic,1>
388 mutable std::array<
389 Eigen::Matrix<point_basic<scalar_type>,Eigen::Dynamic,1>
391 mutable std::array<
392 Eigen::Matrix<tensor_basic<scalar_type>,Eigen::Dynamic,1>
394 mutable std::array<
395 Eigen::Matrix<tensor3_basic<scalar_type>,Eigen::Dynamic,1>
397 mutable std::array<
398 Eigen::Matrix<tensor4_basic<scalar_type>,Eigen::Dynamic,1>
401
402template<class UnaryFunction, class Expr>
404 const UnaryFunction& f,
405 const Expr& expr)
406 : _f(f),
407 _expr(expr),
408 _scalar_val(),
409 _vector_val(),
410 _tensor_val(),
411 _tensor3_val(),
412 _tensor4_val()
413{
414}
415
416template<class F, class Expr> struct is_field_expr_v2_nonlinear_arg <field_expr_v2_nonlinear_node_unary<F,Expr>> : std::true_type {};
417//template<class F, class Expr> struct has_field_lazy_interface <field_expr_v2_nonlinear_node_unary<F,Expr>> : std::true_type {};
418template<class F, class Expr> struct is_field_expr_affine_homogeneous<field_expr_v2_nonlinear_node_unary<F,Expr>, typename std::enable_if<
419 field_expr_v2_nonlinear_node_unary<F,Expr>::is_affine_homogeneous::value>::type>: std::true_type {};
420
421
422} // namespace details
423// -------------------------------------------
424// 1.2. unary calls
425// -------------------------------------------
426// unary operators +- and std::math
427
428// ------------------------
429// standard unary operators
430// ------------------------
431#define _RHEOLEF_make_field_expr_v2_nonlinear_unary_operator(FUNCTION,FUNCTOR) \
432template<class Expr> \
433inline \
434typename \
435std::enable_if< \
436 details::is_field_expr_v2_nonlinear_arg<Expr>::value \
437 && ! details::is_field_expr_v2_constant <Expr>::value \
438 && ! details::has_field_rdof_interface <Expr>::value \
439 ,details::field_expr_v2_nonlinear_node_unary< \
440 FUNCTOR \
441 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr>::type \
442 > \
443>::type \
444FUNCTION (const Expr& expr) \
445{ \
446 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr>::type wrap_t; \
447 return details::field_expr_v2_nonlinear_node_unary <FUNCTOR,wrap_t> (FUNCTOR(), wrap_t(expr)); \
448}
449
452#undef _RHEOLEF_make_field_expr_v2_nonlinear_unary_operator
453
454// ------------------------
455// std::cmath
456// ------------------------
457#define _RHEOLEF_make_field_expr_v2_nonlinear_unary_operator(FUNCTION,FUNCTOR) \
458template<class Expr> \
459inline \
460typename \
461std::enable_if< \
462 ( details::is_field_expr_v2_nonlinear_arg<Expr>::value \
463 || details::is_field<Expr>::value) \
464 && ! details::is_field_expr_v2_constant <Expr>::value \
465 ,details::field_expr_v2_nonlinear_node_unary< \
466 FUNCTOR \
467 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr>::type \
468 > \
469>::type \
470FUNCTION (const Expr& expr) \
471{ \
472 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr>::type wrap_t; \
473 return details::field_expr_v2_nonlinear_node_unary <FUNCTOR,wrap_t> (FUNCTOR(), wrap_t(expr)); \
474}
475#define _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(FUNCTION) \
476 _RHEOLEF_make_field_expr_v2_nonlinear_unary_operator(FUNCTION, details::FUNCTION##_)
477
495// rheolef extensions
499
500// tr(sigma_h) & trans(sigma_h) : trace & transpose of a tensor-valued field
503
504#undef _RHEOLEF_make_field_expr_v2_nonlinear_unary_function
505#undef _RHEOLEF_make_field_expr_v2_nonlinear_unary_operator
506
507// -------------------------------------------
508// 1.3. unary compose
509// -------------------------------------------
510
511template<class Function, class Expr>
512inline
513typename
514std::enable_if<
519 >
520>::type
521compose (const Function& f, const Expr& expr)
522{
525 return details::field_expr_v2_nonlinear_node_unary <fun_wrap_t, expr_wrap_t> (fun_wrap_t(f), expr_wrap_t(expr));
526}
527// ---------------------------------------------------------------------------
528// 2. binary operations
529// ---------------------------------------------------------------------------
530// 2.1. binary node
531// -------------------------------------------
532namespace details {
533
534template<class BinaryFunction, class Expr1, class Expr2>
536public:
537// typedefs:
538
540 using result_type = typename details::generic_binary_traits<BinaryFunction>::template result_hint<typename Expr1::result_type,typename Expr2::result_type>::type;
541 using value_type = result_type;
542 using scalar_type = typename scalar_traits<value_type>::type;
543 using float_type = typename float_traits<value_type>::type;
544 using memory_type = typename Expr1::memory_type;
545
546// alocators:
547
549 const BinaryFunction& f,
550 const Expr1& expr1,
551 const Expr2& expr2);
552
553// --------------------------------------------
554// accessors for the affine & homogeneous case:
555// --------------------------------------------
556
557 // the result expr is affine-homogeneous if and only if:
558 // binop expr1 expr2
559 // +- A|C A|C
560 // */ A C
561 // * C A
563 = or_type<
564 and_type<
565 or_type<
566 std::is_same<BinaryFunction,details::plus>
567 ,std::is_same<BinaryFunction,details::minus>
568 >
569 ,is_field_expr_affine_homogeneous<Expr1>
570 ,is_field_expr_affine_homogeneous<Expr2>
571 >
572 ,and_type<
573 or_type<
574 std::is_same<BinaryFunction,details::multiplies>
575 ,std::is_same<BinaryFunction,details::divides>
576 >
577 ,is_field_expr_affine_homogeneous<Expr1>
578 ,is_field_expr_v2_constant <Expr2>
579 >
580 ,and_type<
581 std::is_same<BinaryFunction,details::multiplies>
582 ,is_field_expr_v2_constant <Expr1>
583 ,is_field_expr_affine_homogeneous<Expr2>
584 >
585 >;
588 return is_affine_homogeneous::value
589 && _expr1.have_homogeneous_space (Vh)
590 && _expr2.have_homogeneous_space (Vh2)
591 && Vh.name() == Vh2.name();
592 }
593 // minimal forward iterator interface:
595 using iterator_category = std::forward_iterator_tag;
596 using value_type = typename promote<
597 typename Expr1::scalar_type,
598 typename Expr2::scalar_type>::type;
601 using difference_type = std::ptrdiff_t;
602 const_iterator (const BinaryFunction& f, typename Expr1::const_iterator iter1, typename Expr2::const_iterator iter2)
603 : _f(f), _iter1 (iter1), _iter2 (iter2) {}
604 const_iterator& operator++ () { ++_iter1; ++_iter2; return *this; }
605 value_type operator* () const { return _f (*_iter1, *_iter2); }
606 protected:
607 const BinaryFunction _f;
608 typename Expr1::const_iterator _iter1;
609 typename Expr2::const_iterator _iter2;
610 };
611 const_iterator begin_dof() const { return const_iterator (_f, _expr1.begin_dof(), _expr2.begin_dof()); }
612
613// --------------------------------------------
614// interface for the general nonlinear case:
615// --------------------------------------------
616
617// accessors:
618
619 static const space_constant::valued_type valued_hint = space_constant::valued_tag_traits<result_type>::value;
620
621 space_constant::valued_type valued_tag() const {
622 return details::generic_binary_traits<BinaryFunction>::valued_tag(_expr1.valued_tag(), _expr2.valued_tag());
623 }
624
625// initializers:
626
629 const integrate_option& iopt)
630 {
631 _expr1.initialize (pops, iopt);
632 _expr2.initialize (pops, iopt);
633 }
637 const integrate_option& iopt)
638 {
639 _expr1.initialize (Xh, pops, iopt);
640 _expr2.initialize (Xh, pops, iopt);
641 }
642
643// evaluators:
644
645 template<class Result, class Arg1, class Arg2, class M>
647 const geo_basic<float_type,M>& omega_K,
648 const geo_element& K,
649 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
650 {
651 Eigen::Matrix<Arg1,Eigen::Dynamic,1> value1; _expr1.evaluate (omega_K, K, value1);
652 Eigen::Matrix<Arg2,Eigen::Dynamic,1> value2; _expr2.evaluate (omega_K, K, value2);
653 value.resize (value1.size());
654 // TODO: DVT_EIGEN_BLAS1
655 for (size_t i = 0, ni = value.rows(); i < ni; ++i) {
656 value[i] = _f (value1[i], value2[i]);
657 }
658 }
659 template<class Result, class Arg1, class Arg2, class M>
661 const geo_basic<float_type,M>& omega_K,
662 const geo_element& K,
663 const side_information_type& sid,
664 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
665 {
666 Eigen::Matrix<Arg1,Eigen::Dynamic,1> value1; _expr1.evaluate_on_side (omega_K, K, sid, value1);
667 Eigen::Matrix<Arg2,Eigen::Dynamic,1> value2; _expr2.evaluate_on_side (omega_K, K, sid, value2);
668 value.resize (value1.size());
669 for (size_t i = 0, ni = value.rows(); i < ni; ++i) {
670 value[i] = _f (value1[i], value2[i]);
671 }
672 }
673 template<class This, class Result, class ReturnType, class Arg1, class Arg2>
674 struct evaluate_internal {
675 template<class M>
676 void operator() (
677 const This& obj,
678 const geo_basic<float_type,M>& omega_K,
679 const geo_element& K,
680 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
681 {
682 fatal_macro ("unexpected return type "
683 << pretty_typename_macro(ReturnType) << ": "
684 << pretty_typename_macro(Result) << " was expected for function "
685 << pretty_typename_macro(BinaryFunction) << "("
686 << pretty_typename_macro(Arg1) << ","
687 << pretty_typename_macro(Arg2) << ")");
688 }
689 template<class M>
690 void operator() (
691 const This& obj,
692 const geo_basic<float_type,M>& omega_K,
693 const geo_element& K,
694 const side_information_type& sid,
695 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
696 {
697 fatal_macro ("unexpected return type "
698 << pretty_typename_macro(ReturnType) << ": "
699 << pretty_typename_macro(Result) << " was expected for function "
700 << pretty_typename_macro(BinaryFunction) << "("
701 << pretty_typename_macro(Arg1) << ","
702 << pretty_typename_macro(Arg2) << ")");
703 }
704 };
705 template<class This, class Result, class Arg1, class Arg2>
706 struct evaluate_internal<This,Result,Result,Arg1,Arg2> {
707 template<class M>
708 void operator() (
709 const This& obj,
710 const geo_basic<float_type,M>& omega_K,
711 const geo_element& K,
712 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
713 { obj.template evaluate_internal2<Result,Arg1,Arg2,M> (omega_K, K, value); }
714
715 template<class M>
716 void operator() (
717 const This& obj,
718 const geo_basic<float_type,M>& omega_K,
719 const geo_element& K,
720 const side_information_type& sid,
721 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
722 { obj.template evaluate_internal2 <Result,Arg1,Arg2,M> (omega_K, K, sid, value);
723 }
724 };
725 template<class Result, class Arg1, class Arg2, class M>
727 const geo_basic<float_type,M>& omega_K,
728 const geo_element& K,
729 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
730 {
731 typedef typename details::generic_binary_traits<BinaryFunction>::template result_hint<Arg1,Arg2>::type ReturnType;
732 typedef field_expr_v2_nonlinear_node_binary<BinaryFunction, Expr1, Expr2> This;
733 evaluate_internal<This,Result,ReturnType,Arg1,Arg2> eval_int;
734 eval_int (*this, omega_K, K, value);
735 }
736 template<class Result, class Arg1, class Arg2, class M>
738 const geo_basic<float_type,M>& omega_K,
739 const geo_element& K,
740 const side_information_type& sid,
741 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
742 {
743 typedef typename details::generic_binary_traits<BinaryFunction>::template result_hint<Arg1,Arg2>::type ReturnType;
744 typedef field_expr_v2_nonlinear_node_binary<BinaryFunction, Expr1, Expr2> This;
745 evaluate_internal<This,Result,ReturnType,Arg1,Arg2> eval_int;
746 eval_int (*this, omega_K, K, sid, value);
747 }
748 // when both args are defined at compile time:
749 template<class This, class Result,
750 class Arg1, space_constant::valued_type Arg1Tag,
751 class Arg2, space_constant::valued_type Arg2Tag>
753 template<class M>
754 void operator() (
755 const This& obj,
756 const geo_basic<float_type,M>& omega_K,
757 const geo_element& K,
758 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
759 { obj.template evaluate_call<Result, Arg1, Arg2> (omega_K, K, value); }
760
761 template<class M>
762 void operator() (
763 const This& obj,
764 const geo_basic<float_type,M>& omega_K,
765 const geo_element& K,
766 const side_information_type& sid,
767 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
768 { obj.template evaluate_call<Result, Arg1, Arg2> (omega_K, K, sid, value); }
769 };
770 // specialization when both args are undefined at compile time:
771 template<class This, class Result,
772 class Arg1,
773 class Arg2>
774 struct evaluate_switch<This, Result,
775 Arg1, space_constant::last_valued,
776 Arg2, space_constant::last_valued> {
777 template<class M>
778 void operator() (
779 const This& obj,
780 const geo_basic<float_type,M>& omega_K,
781 const geo_element& K,
782 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
783 {
784 typedef typename scalar_traits<Arg1>::type T1;
785 typedef typename scalar_traits<Arg2>::type T2;
786 space_constant::valued_type arg1_valued_tag = obj._expr1.valued_tag();
787 space_constant::valued_type arg2_valued_tag = obj._expr2.valued_tag();
788 switch (arg1_valued_tag) {
789 case space_constant::scalar: {
790 switch (arg2_valued_tag) {
791 case space_constant::scalar:
792 return obj.template evaluate_call<Result, T1, T2> (omega_K, K, value); break;
793 case space_constant::vector:
794 return obj.template evaluate_call<Result, T1, point_basic<T2> > (omega_K, K, value); break;
795 case space_constant::tensor:
796 case space_constant::unsymmetric_tensor:
797 return obj.template evaluate_call<Result, T1, tensor_basic<T2> > (omega_K, K, value); break;
798 case space_constant::tensor3:
799 return obj.template evaluate_call<Result, T1, tensor3_basic<T2> >(omega_K, K, value); break;
800 default: error_macro ("unexpected second argument valued tag="<<arg2_valued_tag);
801 }
802 break;
803 }
804 case space_constant::vector: {
805 switch (arg2_valued_tag) {
806 case space_constant::scalar:
807 return obj.template evaluate_call<Result, point_basic<T1>, T2> (omega_K, K, value); break;
808 case space_constant::vector:
809 return obj.template evaluate_call<Result, point_basic<T1>, point_basic<T2> > (omega_K, K, value); break;
810 case space_constant::tensor:
811 case space_constant::unsymmetric_tensor:
812 return obj.template evaluate_call<Result, point_basic<T1>, tensor_basic<T2> > (omega_K, K, value); break;
813 case space_constant::tensor3:
814 return obj.template evaluate_call<Result, point_basic<T1>, tensor3_basic<T2> >(omega_K, K, value); break;
815 default: error_macro ("unexpected second argument valued tag="<<arg2_valued_tag);
816 }
817 break;
818 }
819 case space_constant::tensor:
820 case space_constant::unsymmetric_tensor: {
821 switch (arg2_valued_tag) {
822 case space_constant::scalar:
823 return obj.template evaluate_call<Result, tensor_basic<T1>, T2> (omega_K, K, value); break;
824 case space_constant::vector:
825 return obj.template evaluate_call<Result, tensor_basic<T1>, point_basic<T2> > (omega_K, K, value); break;
826 case space_constant::tensor:
827 case space_constant::unsymmetric_tensor:
828 return obj.template evaluate_call<Result, tensor_basic<T1>, tensor_basic<T2> > (omega_K, K, value); break;
829 case space_constant::tensor3:
830 return obj.template evaluate_call<Result, tensor_basic<T1>, tensor3_basic<T2> >(omega_K, K, value); break;
831 default: error_macro ("unexpected second argument valued tag="<<arg2_valued_tag);
832 }
833 break;
834 }
835 case space_constant::tensor3: {
836 switch (arg2_valued_tag) {
837 case space_constant::scalar:
838 return obj.template evaluate_call<Result, tensor3_basic<T1>, T2> (omega_K, K, value); break;
839 case space_constant::vector:
840 return obj.template evaluate_call<Result, tensor3_basic<T1>, point_basic<T2> > (omega_K, K, value); break;
841 case space_constant::tensor:
842 case space_constant::unsymmetric_tensor:
843 return obj.template evaluate_call<Result, tensor3_basic<T1>, tensor_basic<T2> > (omega_K, K, value); break;
844 case space_constant::tensor3:
845 return obj.template evaluate_call<Result, tensor3_basic<T1>, tensor3_basic<T2> >(omega_K, K, value); break;
846 default: error_macro ("unexpected second argument valued tag="<<arg2_valued_tag);
847 }
848 break;
849 }
850 default: error_macro ("unexpected first argument valued tag="<<arg1_valued_tag);
851 }
852 }
853 };
854 // specialization when only first arg is defined at compile time:
855 template<class This, class Result,
856 class Arg1, space_constant::valued_type Arg1Tag,
857 class Arg2>
858 struct evaluate_switch<This, Result,
859 Arg1, Arg1Tag,
860 Arg2, space_constant::last_valued> {
861 template<class M>
862 void operator() (
863 const This& obj,
864 const geo_basic<float_type,M>& omega_K,
865 const geo_element& K,
866 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
867 {
868 typedef typename scalar_traits<Arg2>::type T2;
869 space_constant::valued_type arg2_valued_tag = obj._expr2.valued_tag();
870 switch (arg2_valued_tag) {
871 case space_constant::scalar:
872 return obj.template evaluate_call<Result, Arg1, T2> (omega_K, K, value); break;
873 case space_constant::vector:
874 return obj.template evaluate_call<Result, Arg1, point_basic<T2> > (omega_K, K, value); break;
875 case space_constant::tensor:
876 case space_constant::unsymmetric_tensor:
877 return obj.template evaluate_call<Result, Arg1, tensor_basic<T2> > (omega_K, K, value); break;
878 case space_constant::tensor3:
879 return obj.template evaluate_call<Result, Arg1, tensor3_basic<T2> > (omega_K, K, value); break;
880 default: error_macro ("unexpected second argument valued tag="<<arg2_valued_tag);
881 }
882 }
883 };
884 // specialization when only second arg is defined at compile time:
885 template<class This, class Result,
886 class Arg1,
887 class Arg2, space_constant::valued_type Arg2Tag>
888 struct evaluate_switch<This, Result,
889 Arg1, space_constant::last_valued,
890 Arg2, Arg2Tag> {
891 template<class M>
892 void operator() (
893 const This& obj,
894 const geo_basic<float_type,M>& omega_K,
895 const geo_element& K,
896 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
897 {
898 typedef typename scalar_traits<Arg1>::type T1;
899 space_constant::valued_type arg1_valued_tag = obj._expr1.valued_tag();
900 switch (arg1_valued_tag) {
901 case space_constant::scalar:
902 return obj.template evaluate_call<Result, T1, Arg2> (omega_K, K, value); break;
903 case space_constant::vector:
904 return obj.template evaluate_call<Result, point_basic<T1>, Arg2> (omega_K, K, value); break;
905 case space_constant::tensor:
906 case space_constant::unsymmetric_tensor:
907 return obj.template evaluate_call<Result, tensor_basic<T1>, Arg2> (omega_K, K, value); break;
908 case space_constant::tensor3:
909 return obj.template evaluate_call<Result, tensor3_basic<T1>, Arg2>(omega_K, K, value); break;
910 default: error_macro ("unexpected first argument valued tag="<<arg1_valued_tag);
911 }
912 }
913 };
914 template<class Result, class M>
915 void evaluate (
916 const geo_basic<float_type,M>& omega_K,
917 const geo_element& K,
918 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
919 {
920 typedef typename details::generic_binary_traits<BinaryFunction>::template hint<
921 typename Expr1::value_type
922 ,typename Expr2::value_type
923 ,Result>::first_argument_type A1;
924 typedef typename details::generic_binary_traits<BinaryFunction>::template hint<
925 typename Expr1::value_type
926 ,typename Expr2::value_type
927 ,Result>::second_argument_type A2;
928 static const space_constant::valued_type first_argument_tag = space_constant::valued_tag_traits<A1>::value;
929 static const space_constant::valued_type second_argument_tag = space_constant::valued_tag_traits<A2>::value;
930 typedef field_expr_v2_nonlinear_node_binary<BinaryFunction, Expr1, Expr2> This;
931 evaluate_switch <This, Result, A1, first_argument_tag, A2, second_argument_tag> eval;
932 eval (*this, omega_K, K, value);
933 }
934 template<class Result, class M>
935 void
937 const geo_basic<float_type,M>& omega_K,
938 const geo_element& K,
939 const side_information_type& sid,
940 Eigen::Matrix<Result,Eigen::Dynamic,1>& value) const
941 {
942 typedef typename details::generic_binary_traits<BinaryFunction>::template hint<
943 typename Expr1::value_type
944 ,typename Expr2::value_type
945 ,Result>::first_argument_type A1;
946 typedef typename details::generic_binary_traits<BinaryFunction>::template hint<
947 typename Expr1::value_type
948 ,typename Expr2::value_type
949 ,Result>::second_argument_type A2;
950 static const space_constant::valued_type first_argument_tag = space_constant::valued_tag_traits<A1>::value;
951 static const space_constant::valued_type second_argument_tag = space_constant::valued_tag_traits<A2>::value;
952 typedef field_expr_v2_nonlinear_node_binary<BinaryFunction, Expr1, Expr2> This;
953 evaluate_switch <This, Result, A1, first_argument_tag, A2, second_argument_tag> eval;
954 eval (*this, omega_K, K, sid, value);
955 }
956 template<class Result>
957 bool valued_check() const {
958 typedef typename details::generic_binary_traits<BinaryFunction>::template hint<
959 typename Expr1::value_type
960 ,typename Expr2::value_type
961 ,Result>::first_argument_type A1;
962 typedef typename details::generic_binary_traits<BinaryFunction>::template hint<
963 typename Expr1::value_type
964 ,typename Expr2::value_type
965 ,Result>::second_argument_type A2;
966 bool status = true;
967 if (! is_undeterminated<A1>::value) status &= _expr1.template valued_check<A1>();
968 if (! is_undeterminated<A2>::value) status &= _expr2.template valued_check<A2>();
969 return status;
970 }
971
972protected:
973// data:
974 BinaryFunction _f;
975 Expr1 _expr1;
976 Expr2 _expr2;
977};
978template<class BinaryFunction, class Expr1, class Expr2>
979field_expr_v2_nonlinear_node_binary<BinaryFunction,Expr1,Expr2>::field_expr_v2_nonlinear_node_binary (
980 const BinaryFunction& f,
981 const Expr1& expr1,
982 const Expr2& expr2)
983 : _f(f),
984 _expr1(expr1),
985 _expr2(expr2)
986{
987}
988
989template<class F, class Expr1, class Expr2> struct is_field_expr_v2_nonlinear_arg <field_expr_v2_nonlinear_node_binary<F,Expr1,Expr2>> : std::true_type {};
990//template<class F, class Expr1, class Expr2> struct has_field_lazy_interface <field_expr_v2_nonlinear_node_binary<F,Expr1,Expr2>> : std::true_type {};
991template<class F, class Expr1, class Expr2> struct is_field_expr_affine_homogeneous<field_expr_v2_nonlinear_node_binary<F,Expr1,Expr2>, typename std::enable_if<
992 field_expr_v2_nonlinear_node_binary<F,Expr1,Expr2>::is_affine_homogeneous::value>::type>: std::true_type {};
993
994} // namespace details
995// -------------------------------------------
996// 2.2. binary calls
997// -------------------------------------------
998/*
999 combination table:
1000
1001 +- | c a n
1002 ---|-------
1003 c | C A N
1004 a | A A N
1005 n | N N N
1006
1007 * | c a n
1008 ---|-------
1009 c | C A N
1010 a | A N N
1011 n | N N N
1012
1013 / | c a n
1014 ---|-------
1015 c | C N N
1016 a | A N N
1017 n | N N N
1018
1019 argument:
1020 c : constant, as scalar, point, tensor, ect
1021 l : affine homogeneous expr argument: as field, field_rdof_indirect or field_expr_node::is_affine_homogeneous
1022 n : function, functor or ! field_expr_node::is_affine_homogeneous
1023 result:
1024 C : constant : this combination is not implemented here
1025 A,N : are implemented here
1026 rules:
1027 at least one of the two args is not of type "c"
1028 when c: c value is embeded in bind_first or bind_second
1029 and the operation reduces to an unary one
1030 when a: if it is a field_convertible, it should be wrapped
1031 in field_expr_v2_nonlinear_terminal_field
1032 when c: no wrapper is need
1033 implementation:
1034 The a and n cases are grouped, thanks to the wrapper_traits
1035 and it remains to cases :
1036 1) both args are field_expr_v2_nonlinear or a function
1037 2) one arg is a field_expr_v2_nonlinear or a function and the second argument is a constant
1038*/
1039
1040// -------------------------------------------
1041// binary+-
1042// -------------------------------------------
1043// TODO: remove rdof+-rdof when rdof_binary is available
1044#define _RHEOLEF_make_field_expr_v2_nonlinear_binary(FUNCTION,FUNCTOR) \
1045template<class Expr1, class Expr2> \
1046inline \
1047typename \
1048std::enable_if< \
1049 details::is_field_expr_v2_nonlinear_arg<Expr1>::value \
1050 && details::is_field_expr_v2_nonlinear_arg<Expr2>::value \
1051 && ! details::is_field_expr_v2_constant <Expr1>::value \
1052 && ! details::is_field_expr_v2_constant <Expr2>::value \
1053 ,details::field_expr_v2_nonlinear_node_binary< \
1054 FUNCTOR \
1055 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type \
1056 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type \
1057 > \
1058>::type \
1059FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1060{ \
1061 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type wrap1_t; \
1062 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type wrap2_t; \
1063 return details::field_expr_v2_nonlinear_node_binary <FUNCTOR,wrap1_t,wrap2_t> \
1064 (FUNCTOR(), wrap1_t(expr1), wrap2_t(expr2)); \
1065} \
1066template<class Expr1, class Expr2> \
1067inline \
1068typename \
1069std::enable_if< \
1070 details::is_field_expr_v2_constant <Expr1>::value \
1071 && details::is_field_expr_v2_nonlinear_arg<Expr2>::value \
1072 && ! details::is_field_expr_v2_constant <Expr2>::value \
1073 && !(details::has_field_rdof_interface <Expr2>::value \
1074 && details::is_rheolef_arithmetic <Expr1>::value) \
1075 ,details::field_expr_v2_nonlinear_node_unary< \
1076 details::binder_first< \
1077 FUNCTOR \
1078 ,typename details::field_promote_first_argument< \
1079 Expr1 \
1080 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type::value_type \
1081 >::type \
1082 > \
1083 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type \
1084 > \
1085>::type \
1086FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1087{ \
1088 typedef typename details::field_promote_first_argument< \
1089 Expr1 \
1090 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type::value_type \
1091 >::type \
1092 value_type; \
1093 typedef details::binder_first<FUNCTOR,value_type> fun_t; \
1094 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type wrap2_t; \
1095 return details::field_expr_v2_nonlinear_node_unary<fun_t,wrap2_t>(fun_t(FUNCTOR(), expr1), wrap2_t(expr2)); \
1096} \
1097template<class Expr1, class Expr2> \
1098inline \
1099typename \
1100std::enable_if< \
1101 details::is_field_expr_v2_constant <Expr2>::value \
1102 && details::is_field_expr_v2_nonlinear_arg<Expr1>::value \
1103 && ! details::is_field_expr_v2_constant <Expr1>::value \
1104 && !(details::has_field_rdof_interface <Expr1>::value \
1105 && details::is_rheolef_arithmetic <Expr2>::value) \
1106 ,details::field_expr_v2_nonlinear_node_unary< \
1107 details::binder_second< \
1108 FUNCTOR \
1109 ,typename details::field_promote_second_argument< \
1110 typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type::value_type \
1111 ,Expr2 \
1112 >::type \
1113 > \
1114 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type \
1115 > \
1116>::type \
1117FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1118{ \
1119 typedef typename details::field_promote_second_argument< \
1120 typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type::value_type \
1121 ,Expr2 \
1122 >::type \
1123 value_type; \
1124 typedef details::binder_second<FUNCTOR,value_type> fun_t; \
1125 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type wrap1_t; \
1126 return details::field_expr_v2_nonlinear_node_unary<fun_t,wrap1_t>(fun_t(FUNCTOR(), expr2), wrap1_t(expr1)); \
1127}
1128
1131#undef _RHEOLEF_make_field_expr_v2_nonlinear_binary
1132
1133// -------------------------------------------
1134// binary*
1135// -------------------------------------------
1136#define _RHEOLEF_make_field_expr_v2_nonlinear_binary(FUNCTION,FUNCTOR) \
1137template<class Expr1, class Expr2> \
1138inline \
1139typename \
1140std::enable_if< \
1141 details::is_field_expr_v2_nonlinear_arg<Expr1>::value \
1142 && details::is_field_expr_v2_nonlinear_arg<Expr2>::value \
1143 && ! details::is_field_expr_v2_constant <Expr1>::value \
1144 && ! details::is_field_expr_v2_constant <Expr2>::value \
1145 ,details::field_expr_v2_nonlinear_node_binary< \
1146 FUNCTOR \
1147 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type \
1148 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type \
1149 > \
1150>::type \
1151FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1152{ \
1153 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type wrap1_t; \
1154 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type wrap2_t; \
1155 return details::field_expr_v2_nonlinear_node_binary <FUNCTOR,wrap1_t,wrap2_t> \
1156 (FUNCTOR(), wrap1_t(expr1), wrap2_t(expr2)); \
1157} \
1158template<class Expr1, class Expr2> \
1159inline \
1160typename \
1161std::enable_if< \
1162 details::is_field_expr_v2_constant <Expr1>::value \
1163 && details::is_field_expr_v2_nonlinear_arg<Expr2>::value \
1164 && ! details::is_field_expr_v2_constant <Expr2>::value \
1165 && !(details::has_field_rdof_interface <Expr2>::value \
1166 && details::is_rheolef_arithmetic <Expr1>::value) \
1167 ,details::field_expr_v2_nonlinear_node_unary< \
1168 details::binder_first< \
1169 FUNCTOR \
1170 ,typename details::field_promote_first_argument< \
1171 Expr1 \
1172 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type::value_type \
1173 >::type \
1174 > \
1175 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type \
1176 > \
1177>::type \
1178FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1179{ \
1180 typedef typename details::field_promote_first_argument< \
1181 Expr1 \
1182 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type::value_type \
1183 >::type \
1184 value_type; \
1185 typedef details::binder_first<FUNCTOR,value_type> fun_t; \
1186 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type wrap2_t; \
1187 return details::field_expr_v2_nonlinear_node_unary<fun_t,wrap2_t>(fun_t(FUNCTOR(), expr1), wrap2_t(expr2)); \
1188} \
1189template<class Expr1, class Expr2> \
1190inline \
1191typename \
1192std::enable_if< \
1193 details::is_field_expr_v2_constant <Expr2>::value \
1194 && details::is_field_expr_v2_nonlinear_arg<Expr1>::value \
1195 && ! details::is_field_expr_v2_constant <Expr1>::value \
1196 && !(details::has_field_rdof_interface <Expr1>::value \
1197 && details::is_rheolef_arithmetic <Expr2>::value) \
1198 ,details::field_expr_v2_nonlinear_node_unary< \
1199 details::binder_second< \
1200 FUNCTOR \
1201 ,typename details::field_promote_second_argument< \
1202 typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type::value_type \
1203 ,Expr2 \
1204 >::type \
1205 > \
1206 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type \
1207 > \
1208>::type \
1209FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1210{ \
1211 typedef typename details::field_promote_second_argument< \
1212 typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type::value_type \
1213 ,Expr2 \
1214 >::type \
1215 value_type; \
1216 typedef details::binder_second<FUNCTOR,value_type> fun_t; \
1217 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type wrap1_t; \
1218 return details::field_expr_v2_nonlinear_node_unary<fun_t,wrap1_t>(fun_t(FUNCTOR(), expr2), wrap1_t(expr1)); \
1219}
1221#undef _RHEOLEF_make_field_expr_v2_nonlinear_binary
1222
1223// -------------------------------------------
1224// binary/
1225// -------------------------------------------
1226#define _RHEOLEF_make_field_expr_v2_nonlinear_binary(FUNCTION,FUNCTOR) \
1227template<class Expr1, class Expr2> \
1228inline \
1229typename \
1230std::enable_if< \
1231 details::is_field_expr_v2_nonlinear_arg<Expr1>::value \
1232 && details::is_field_expr_v2_nonlinear_arg<Expr2>::value \
1233 && ! details::is_field_expr_v2_constant <Expr1>::value \
1234 && ! details::is_field_expr_v2_constant <Expr2>::value \
1235 ,details::field_expr_v2_nonlinear_node_binary< \
1236 FUNCTOR \
1237 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type \
1238 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type \
1239 > \
1240>::type \
1241FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1242{ \
1243 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type wrap1_t; \
1244 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type wrap2_t; \
1245 return details::field_expr_v2_nonlinear_node_binary <FUNCTOR,wrap1_t,wrap2_t> \
1246 (FUNCTOR(), wrap1_t(expr1), wrap2_t(expr2)); \
1247} \
1248template<class Expr1, class Expr2> \
1249inline \
1250typename \
1251std::enable_if< \
1252 details::is_field_expr_v2_constant <Expr1>::value \
1253 && details::is_field_expr_v2_nonlinear_arg<Expr2>::value \
1254 && ! details::is_field_expr_v2_constant <Expr2>::value \
1255 ,details::field_expr_v2_nonlinear_node_unary< \
1256 details::binder_first< \
1257 FUNCTOR \
1258 ,typename details::field_promote_first_argument< \
1259 Expr1 \
1260 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type::value_type \
1261 >::type \
1262 > \
1263 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type \
1264 > \
1265>::type \
1266FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1267{ \
1268 typedef typename details::field_promote_first_argument< \
1269 Expr1 \
1270 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type::value_type \
1271 >::type \
1272 value_type; \
1273 typedef details::binder_first<FUNCTOR,value_type> fun_t; \
1274 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type wrap2_t; \
1275 return details::field_expr_v2_nonlinear_node_unary<fun_t,wrap2_t>(fun_t(FUNCTOR(), expr1), wrap2_t(expr2)); \
1276} \
1277template<class Expr1, class Expr2> \
1278inline \
1279typename \
1280std::enable_if< \
1281 details::is_field_expr_v2_constant <Expr2>::value \
1282 && details::is_field_expr_v2_nonlinear_arg<Expr1>::value \
1283 && ! details::is_field_expr_v2_constant <Expr1>::value \
1284 && !(details::has_field_rdof_interface <Expr1>::value \
1285 && details::is_rheolef_arithmetic <Expr2>::value) \
1286 ,details::field_expr_v2_nonlinear_node_unary< \
1287 details::binder_second< \
1288 FUNCTOR \
1289 ,typename details::field_promote_second_argument< \
1290 typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type::value_type \
1291 ,Expr2 \
1292 >::type \
1293 > \
1294 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type \
1295 > \
1296>::type \
1297FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1298{ \
1299 typedef typename details::field_promote_second_argument< \
1300 typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type::value_type \
1301 ,Expr2 \
1302 >::type \
1303 value_type; \
1304 typedef details::binder_second<FUNCTOR,value_type> fun_t; \
1305 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type wrap1_t; \
1306 return details::field_expr_v2_nonlinear_node_unary<fun_t,wrap1_t>(fun_t(FUNCTOR(), expr2), wrap1_t(expr1)); \
1307}
1309#undef _RHEOLEF_make_field_expr_v2_nonlinear_binary
1310
1311// -------------------------------------------
1312// std::maths
1313// -------------------------------------------
1314#define _RHEOLEF_make_field_expr_v2_nonlinear_binary(FUNCTION,FUNCTOR) \
1315template<class Expr1, class Expr2> \
1316inline \
1317typename \
1318std::enable_if< \
1319 details::is_field_expr_v2_nonlinear_arg<Expr1>::value \
1320 && details::is_field_expr_v2_nonlinear_arg<Expr2>::value \
1321 && ! details::is_field_expr_v2_constant <Expr1>::value \
1322 && ! details::is_field_expr_v2_constant <Expr2>::value \
1323 ,details::field_expr_v2_nonlinear_node_binary< \
1324 FUNCTOR \
1325 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type \
1326 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type \
1327 > \
1328>::type \
1329FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1330{ \
1331 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type wrap1_t; \
1332 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type wrap2_t; \
1333 return details::field_expr_v2_nonlinear_node_binary <FUNCTOR,wrap1_t,wrap2_t> \
1334 (FUNCTOR(), wrap1_t(expr1), wrap2_t(expr2)); \
1335} \
1336template<class Expr1, class Expr2> \
1337inline \
1338typename \
1339std::enable_if< \
1340 details::is_field_expr_v2_constant <Expr1>::value \
1341 && details::is_field_expr_v2_nonlinear_arg<Expr2>::value \
1342 && ! details::is_field_expr_v2_constant <Expr2>::value \
1343 ,details::field_expr_v2_nonlinear_node_unary< \
1344 details::binder_first< \
1345 FUNCTOR \
1346 ,typename details::field_promote_first_argument< \
1347 Expr1 \
1348 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type::value_type \
1349 >::type \
1350 > \
1351 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type \
1352 > \
1353>::type \
1354FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1355{ \
1356 typedef typename details::field_promote_first_argument< \
1357 Expr1 \
1358 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type::value_type \
1359 >::type \
1360 value_type; \
1361 typedef details::binder_first<FUNCTOR,value_type> fun_t; \
1362 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type wrap2_t; \
1363 return details::field_expr_v2_nonlinear_node_unary<fun_t,wrap2_t>(fun_t(FUNCTOR(), expr1), wrap2_t(expr2)); \
1364} \
1365template<class Expr1, class Expr2> \
1366inline \
1367typename \
1368std::enable_if< \
1369 details::is_field_expr_v2_constant <Expr2>::value \
1370 && details::is_field_expr_v2_nonlinear_arg<Expr1>::value \
1371 && ! details::is_field_expr_v2_constant <Expr1>::value \
1372 ,details::field_expr_v2_nonlinear_node_unary< \
1373 details::binder_second< \
1374 FUNCTOR \
1375 ,typename details::field_promote_second_argument< \
1376 typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type::value_type \
1377 ,Expr2 \
1378 >::type \
1379 > \
1380 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type \
1381 > \
1382>::type \
1383FUNCTION (const Expr1& expr1, const Expr2& expr2) \
1384{ \
1385 typedef typename details::field_promote_second_argument< \
1386 typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type::value_type \
1387 ,Expr2 \
1388 >::type \
1389 value_type; \
1390 typedef details::binder_second<FUNCTOR,value_type> fun_t; \
1391 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type wrap1_t; \
1392 return details::field_expr_v2_nonlinear_node_unary<fun_t,wrap1_t>(fun_t(FUNCTOR(), expr2), wrap1_t(expr1)); \
1393}
1394
1395#define _RHEOLEF_make_field_expr_v2_nonlinear_binary_function(FUNCTION) \
1396 _RHEOLEF_make_field_expr_v2_nonlinear_binary (FUNCTION, details::FUNCTION##_) \
1397
1406
1407#undef _RHEOLEF_make_field_expr_v2_nonlinear_binary_function
1408#undef _RHEOLEF_make_field_expr_v2_nonlinear_binary
1409
1410// -------------------------------------------
1411// 2.3. binary compose
1412// -------------------------------------------
1413// note: compose 1 & 2 are not reductible to n-ary
1414// as it uses deductible return types
1415// TODO: do not use deductible types => reduces to n-ary !!
1416
1417// two args are field-expressions
1418template<class Function, class Expr1, class Expr2>
1419inline
1420typename
1421std::enable_if<
1423 && ! details::is_field_expr_v2_constant <Expr1>::value
1425 && ! details::is_field_expr_v2_constant <Expr2>::value
1426 ,details::field_expr_v2_nonlinear_node_binary<
1430 >
1431>::type
1432compose (const Function& f, const Expr1& expr1, const Expr2& expr2)
1433{
1434 typedef typename details::function_traits<Function>::functor_type fun_wrap_t;
1435 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type expr1_wrap_t;
1436 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type expr2_wrap_t;
1437 return details::field_expr_v2_nonlinear_node_binary
1439 (fun_wrap_t(f), expr1_wrap_t(expr1), expr2_wrap_t(expr2));
1440}
1441// left arg is a constant
1442template <class Function, class Expr1, class Expr2>
1443inline
1444typename
1445std::enable_if<
1446 details::is_field_expr_v2_constant <Expr1>::value
1448 && ! details::is_field_expr_v2_constant <Expr2>::value
1450 details::binder_first<
1452 ,typename promote<
1453 Expr1
1454 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type::value_type
1455 >::type
1456 >
1458 >
1459>::type
1460compose (const Function& f, const Expr1& expr1, const Expr2& expr2)
1461{
1462 typedef typename promote<
1463 Expr1
1464 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type::value_type
1465 >::type value_type;
1466 typedef typename details::function_traits<Function>::functor_type wrap_fun_t;
1467 typedef details::binder_first<wrap_fun_t,value_type> binded_fun_t;
1470 <binded_fun_t, wrap2_t>
1471 (binded_fun_t(wrap_fun_t(f), expr1), wrap2_t(expr2));
1472}
1473// right arg is a constant
1474template <class Function, class Expr1, class Expr2>
1475inline
1476typename
1477std::enable_if<
1478 details::is_field_expr_v2_nonlinear_arg<Expr1>::value
1479 && ! details::is_field_expr_v2_constant <Expr1>::value
1480 && details::is_field_expr_v2_constant <Expr2>::value
1481 ,details::field_expr_v2_nonlinear_node_unary<
1482 details::binder_second<
1483 typename details::function_traits<Function>::functor_type
1484 ,typename promote<
1485 typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type::value_type
1486 ,Expr2
1487 >::type
1488 >
1489 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type
1490 >
1491>::type
1492compose (const Function& f, const Expr1& expr1, const Expr2& expr2)
1493{
1494 typedef typename promote<
1495 typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type::value_type
1496 ,Expr2
1497 >::type value_type;
1498 typedef typename details::function_traits<Function>::functor_type wrap_fun_t;
1502 <binded_fun_t, wrap1_t>
1503 (binded_fun_t(wrap_fun_t(f), expr2), wrap1_t(expr1));
1504}
1505
1506} // namespace rheolef
1507#endif // _RHEOLEF_FIELD_EXPR_RECURSIVE_H
field::size_type size_type
Definition branch.cc:430
std::array< Eigen::Matrix< tensor_basic< scalar_type >, Eigen::Dynamic, 1 >,reference_element::max_variant > _tensor_val
typename scalar_traits< value_type >::type scalar_type
typename details::generic_unary_traits< UnaryFunction >::template result_hint< typename Expr::result_type >::type result_type
and_type< or_type< std::is_same< UnaryFunction, details::unary_plus >,std::is_same< UnaryFunction, details::negate >,std::is_same< UnaryFunction, details::binder_first< details::plus, scalar_type > >,std::is_same< UnaryFunction, details::binder_second< details::plus, scalar_type > >,std::is_same< UnaryFunction, details::binder_first< details::minus, scalar_type > >,std::is_same< UnaryFunction, details::binder_second< details::minus, scalar_type > >,std::is_same< UnaryFunction, details::binder_first< details::multiplies, scalar_type > >,std::is_same< UnaryFunction, details::binder_second< details::multiplies, scalar_type > >,std::is_same< UnaryFunction, details::binder_second< details::divides, scalar_type > > >,is_field_expr_affine_homogeneous< Expr > > is_affine_homogeneous
std::array< Eigen::Matrix< tensor3_basic< scalar_type >, Eigen::Dynamic, 1 >,reference_element::max_variant > _tensor3_val
void initialize(const piola_on_pointset< float_type > &pops, const integrate_option &iopt)
std::array< Eigen::Matrix< tensor4_basic< scalar_type >, Eigen::Dynamic, 1 >,reference_element::max_variant > _tensor4_val
field_expr_v2_nonlinear_node_unary< UnaryFunction, Expr > self_type
std::array< Eigen::Matrix< scalar_type, Eigen::Dynamic, 1 >,reference_element::max_variant > _scalar_val
static const space_constant::valued_type valued_hint
std::array< Eigen::Matrix< point_basic< scalar_type >, Eigen::Dynamic, 1 >,reference_element::max_variant > _vector_val
void evaluate_call(const geo_basic< float_type, M > &omega_K, const geo_element &K, Eigen::Matrix< Result, Eigen::Dynamic, 1 > &value) const
void evaluate_call(const geo_basic< float_type, M > &omega_K, const geo_element &K, const side_information_type &sid, Eigen::Matrix< Result, Eigen::Dynamic, 1 > &value) const
bool have_homogeneous_space(space_basic< scalar_type, memory_type > &Vh) const
typename float_traits< scalar_type >::type float_type
_RHEOLEF_evaluate_switch_specialization(space_constant::scalar, T) _RHEOLEF_evaluate_switch_specialization(space_constant Expr _expr
void initialize(const space_basic< float_type, memory_type > &Xh, const piola_on_pointset< float_type > &pops, const integrate_option &iopt)
field_expr_v2_nonlinear_node_unary(const UnaryFunction &f, const Expr &expr)
space_basic< float_type, memory_type > space_type
see the geo_element page for the full documentation
reference_element::size_type size_type
see the integrate_option page for the full documentation
static const variant_type max_variant
typename scalar_traits< value_type >::type scalar_type
typename Expr1::memory_type memory_type
typename details::generic_binary_traits< BinaryFunction >::template result_hint< typename Expr1::result_type, typename Expr2::result_type >::type result_type
BinaryFunction _f
or_type< and_type< or_type< std::is_same< BinaryFunction, details::plus >,std::is_same< BinaryFunction, details::minus > >,is_field_expr_affine_homogeneous< Expr1 >,is_field_expr_affine_homogeneous< Expr2 > >,and_type< or_type< std::is_same< BinaryFunction, details::multiplies >,std::is_same< BinaryFunction, details::divides > >,is_field_expr_affine_homogeneous< Expr1 >,is_field_expr_v2_constant< Expr2 > >,and_type< std::is_same< BinaryFunction, details::multiplies >,is_field_expr_v2_constant< Expr1 >,is_field_expr_affine_homogeneous< Expr2 > > > is_affine_homogeneous
#define error_macro(message)
Definition dis_macros.h:49
#define fatal_macro(message)
Definition dis_macros.h:33
void get_geo(istream &in, my_geo &omega)
Expr1::float_type T
Definition field_expr.h:230
details::field_expr_v2_nonlinear_terminal_wrapper_traits< Expr1 >::type expr1_wrap_t
details::function_traits< Function >::functor_type fun_wrap_t
#define _RHEOLEF_make_field_expr_v2_nonlinear_binary_function(FUNCTION)
#define _RHEOLEF_make_field_expr_v2_nonlinear_binary(FUNCTION, FUNCTOR)
#define _RHEOLEF_evaluate_switch_specialization(VALUED, VALUE)
details::field_expr_v2_nonlinear_terminal_wrapper_traits< Expr2 >::type expr2_wrap_t
#define _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(FUNCTION)
#define _RHEOLEF_make_field_expr_v2_nonlinear_unary_operator(FUNCTION, FUNCTOR)
This file is part of Rheolef.
bool valued_check() const
void initialize(const piola_on_pointset< float_type > &pops, const integrate_option &iopt)
U tr(const tensor_basic< U > &a, size_t d=3)
T norm2(const vec< T, M > &x)
norm2(x): see the expression page for the full documentation
Definition vec.h:379
const_iterator begin_dof() const
void evaluate(const geo_basic< float_type, M > &omega_K, const geo_element &K, Eigen::Matrix< Result, Eigen::Dynamic, 1 > &value) const
void evaluate_on_side(const geo_basic< float_type, M > &omega_K, const geo_element &K, const side_information_type &sid, Eigen::Matrix< Result, Eigen::Dynamic, 1 > &value) const
field_expr_v2_nonlinear_node_binary(const BinaryFunction &f, const Expr1 &expr1, const Expr2 &expr2)
bool have_homogeneous_space(space_basic< scalar_type, memory_type > &Vh) const
void evaluate_internal2(const geo_basic< float_type, M > &omega_K, const geo_element &K, Eigen::Matrix< Result, Eigen::Dynamic, 1 > &value) const
csr< T, sequential > trans(const csr< T, sequential > &a)
trans(a): see the form page for the full documentation
Definition csr.h:455
T norm(const vec< T, M > &x)
norm(x): see the expression page for the full documentation
Definition vec.h:387
details::field_expr_v2_nonlinear_node_nary< typename details::function_traits< Function >::functor_type, typename details::field_expr_v2_nonlinear_terminal_wrapper_traits< Exprs >::type... > ::type compose(const Function &f, const Exprs &... exprs)
see the compose page for the full documentation
Definition compose.h:247
void evaluate_call(const geo_basic< float_type, M > &omega_K, const geo_element &K, Eigen::Matrix< Result, Eigen::Dynamic, 1 > &value) const
STL namespace.
Definition cavity_dg.h:29
std::forward_iterator_tag iterator_category
Expr2::const_iterator _iter2
typename promote< typename Expr1::scalar_type, typename Expr2::scalar_type >::type value_type
const_iterator(const BinaryFunction &f, typename Expr1::const_iterator iter1, typename Expr2::const_iterator iter2)
Expr1::const_iterator _iter1
const_iterator(UnaryFunction f, typename Expr::const_iterator expr_iter)
void operator()(const self_type &obj, const geo_basic< float_type, M > &omega_K, const geo_element &K, Eigen::Matrix< Result, Eigen::Dynamic, 1 > &value)
void evaluate_on_side(const This &obj, const geo_basic< float_type, M > &omega_K, const geo_element &K, const side_information_type &sid, Eigen::Matrix< Result, Eigen::Dynamic, 1 > &value) const
void evaluate(const This &obj, const geo_basic< float_type, M > &omega_K, const geo_element &K, Eigen::Matrix< Result, Eigen::Dynamic, 1 > &value) const
static space_constant::valued_type valued_tag(space_constant::valued_type)
Definition expression.h:200