Rheolef  7.2
an efficient C++ finite element environment
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 
49 namespace rheolef {
50 
51 // -------------------------------------------
52 // 1. unary operations
53 // -------------------------------------------
54 // 1.1. unary node
55 // -------------------------------------------
56 namespace details {
57 
58 template<class UnaryFunction, class Expr>
60 public:
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:
103  struct const_iterator {
104  using iterator_category = std::forward_iterator_tag;
105  using value_type = typename Expr::scalar_type;
107  using pointer = value_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 
129  }
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 
145  void initialize (
146  const piola_on_pointset<float_type>& pops,
147  const integrate_option& iopt)
148  { _expr.initialize (pops, iopt); }
149 
150  void initialize (
152  const piola_on_pointset<float_type>& pops,
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>
260  struct evaluate_switch {};
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  }
379 protected:
380 // data:
381  UnaryFunction _f;
382  Expr _expr;
383 // working area:
384 public:
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>
400 };
401 
402 template<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 
416 template<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 {};
418 template<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) \
432 template<class Expr> \
433 inline \
434 typename \
435 std::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 \
444 FUNCTION (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) \
458 template<class Expr> \
459 inline \
460 typename \
461 std::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 \
470 FUNCTION (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 
511 template<class Function, class Expr>
512 inline
513 typename
514 std::enable_if<
519  >
520 >::type
521 compose (const Function& f, const Expr& expr)
522 {
526 }
527 // ---------------------------------------------------------------------------
528 // 2. binary operations
529 // ---------------------------------------------------------------------------
530 // 2.1. binary node
531 // -------------------------------------------
532 namespace details {
533 
534 template<class BinaryFunction, class Expr1, class Expr2>
536 public:
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;
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:
594  struct const_iterator {
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;
600  using pointer = value_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:
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 
620 
623  }
624 
625 // initializers:
626 
627  void initialize (
628  const piola_on_pointset<float_type>& pops,
629  const integrate_option& iopt)
630  {
631  _expr1.initialize (pops, iopt);
632  _expr2.initialize (pops, iopt);
633  }
634  void initialize (
636  const piola_on_pointset<float_type>& pops,
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>
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>
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>
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>
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,
777  template<class M>
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) {
792  return obj.template evaluate_call<Result, T1, T2> (omega_K, K, value); break;
794  return obj.template evaluate_call<Result, T1, point_basic<T2> > (omega_K, K, value); break;
797  return obj.template evaluate_call<Result, T1, tensor_basic<T2> > (omega_K, K, value); break;
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) {
807  return obj.template evaluate_call<Result, point_basic<T1>, T2> (omega_K, K, value); break;
809  return obj.template evaluate_call<Result, point_basic<T1>, point_basic<T2> > (omega_K, K, value); break;
812  return obj.template evaluate_call<Result, point_basic<T1>, tensor_basic<T2> > (omega_K, K, value); break;
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  }
821  switch (arg2_valued_tag) {
823  return obj.template evaluate_call<Result, tensor_basic<T1>, T2> (omega_K, K, value); break;
825  return obj.template evaluate_call<Result, tensor_basic<T1>, point_basic<T2> > (omega_K, K, value); break;
828  return obj.template evaluate_call<Result, tensor_basic<T1>, tensor_basic<T2> > (omega_K, K, value); break;
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  }
836  switch (arg2_valued_tag) {
838  return obj.template evaluate_call<Result, tensor3_basic<T1>, T2> (omega_K, K, value); break;
840  return obj.template evaluate_call<Result, tensor3_basic<T1>, point_basic<T2> > (omega_K, K, value); break;
843  return obj.template evaluate_call<Result, tensor3_basic<T1>, tensor_basic<T2> > (omega_K, K, value); break;
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>
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) {
872  return obj.template evaluate_call<Result, Arg1, T2> (omega_K, K, value); break;
874  return obj.template evaluate_call<Result, Arg1, point_basic<T2> > (omega_K, K, value); break;
877  return obj.template evaluate_call<Result, Arg1, tensor_basic<T2> > (omega_K, K, value); break;
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>
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) {
902  return obj.template evaluate_call<Result, T1, Arg2> (omega_K, K, value); break;
904  return obj.template evaluate_call<Result, point_basic<T1>, Arg2> (omega_K, K, value); break;
907  return obj.template evaluate_call<Result, tensor_basic<T1>, Arg2> (omega_K, K, value); break;
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;
930  typedef field_expr_v2_nonlinear_node_binary<BinaryFunction, Expr1, Expr2> This;
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;
952  typedef field_expr_v2_nonlinear_node_binary<BinaryFunction, Expr1, Expr2> This;
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 
972 protected:
973 // data:
976  Expr2 _expr2;
977 };
978 template<class BinaryFunction, class Expr1, class Expr2>
980  const BinaryFunction& f,
981  const Expr1& expr1,
982  const Expr2& expr2)
983  : _f(f),
984  _expr1(expr1),
985  _expr2(expr2)
986 {
987 }
988 
989 template<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 {};
991 template<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) \
1045 template<class Expr1, class Expr2> \
1046 inline \
1047 typename \
1048 std::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 \
1059 FUNCTION (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 } \
1066 template<class Expr1, class Expr2> \
1067 inline \
1068 typename \
1069 std::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 \
1086 FUNCTION (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 } \
1097 template<class Expr1, class Expr2> \
1098 inline \
1099 typename \
1100 std::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 \
1117 FUNCTION (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) \
1137 template<class Expr1, class Expr2> \
1138 inline \
1139 typename \
1140 std::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 \
1151 FUNCTION (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 } \
1158 template<class Expr1, class Expr2> \
1159 inline \
1160 typename \
1161 std::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 \
1178 FUNCTION (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 } \
1189 template<class Expr1, class Expr2> \
1190 inline \
1191 typename \
1192 std::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 \
1209 FUNCTION (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) \
1227 template<class Expr1, class Expr2> \
1228 inline \
1229 typename \
1230 std::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 \
1241 FUNCTION (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 } \
1248 template<class Expr1, class Expr2> \
1249 inline \
1250 typename \
1251 std::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 \
1266 FUNCTION (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 } \
1277 template<class Expr1, class Expr2> \
1278 inline \
1279 typename \
1280 std::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 \
1297 FUNCTION (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) \
1315 template<class Expr1, class Expr2> \
1316 inline \
1317 typename \
1318 std::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 \
1329 FUNCTION (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 } \
1336 template<class Expr1, class Expr2> \
1337 inline \
1338 typename \
1339 std::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 \
1354 FUNCTION (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 } \
1365 template<class Expr1, class Expr2> \
1366 inline \
1367 typename \
1368 std::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 \
1383 FUNCTION (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
1418 template<class Function, class Expr1, class Expr2>
1419 inline
1420 typename
1421 std::enable_if<
1430  >
1431 >::type
1432 compose (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;
1439  (fun_wrap_t(f), expr1_wrap_t(expr1), expr2_wrap_t(expr2));
1440 }
1441 // left arg is a constant
1442 template <class Function, class Expr1, class Expr2>
1443 inline
1444 typename
1445 std::enable_if<
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
1460 compose (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
1474 template <class Function, class Expr1, class Expr2>
1475 inline
1476 typename
1477 std::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
1492 compose (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;
1499  typedef details::binder_second<wrap_fun_t,value_type> binded_fun_t;
1500  typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type wrap1_t;
1501  return details::field_expr_v2_nonlinear_node_unary
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
band_basic< float_type, memory_type > band_type
typename scalar_traits< value_type >::type scalar_type
typename details::generic_unary_traits< UnaryFunction >::template result_hint< typename Expr::result_type >::type result_type
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
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
Definition: geo_element.h:102
reference_element::size_type size_type
Definition: geo_element.h:125
see the integrate_option page for the full documentation
static const variant_type max_variant
tensor_basic< T > tensor3_basic< T >
Definition: piola_fem.h:137
typename scalar_traits< value_type >::type scalar_type
typename float_traits< value_type >::type float_type
typename Expr1::memory_type memory_type
rheolef::std type
point_basic< T >
Definition: piola_fem.h:135
typename details::generic_binary_traits< BinaryFunction >::template result_hint< typename Expr1::result_type, typename Expr2::result_type >::type result_type
static const space_constant::valued_type valued_hint
rheolef::std BinaryFunction
rheolef::std value
BinaryFunction _f
result_type value_type
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
rheolef::std Function
rheolef::std Expr1
dot(x,y): see the expression page for the full documentation
#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
pair_with_linear_algebra< T1, T2 > operator*(const T0 &k, const pair_with_linear_algebra< T1, T2 > &x)
rheolef::details::is_vec dot
This file is part of Rheolef.
void initialize(const piola_on_pointset< float_type > &pops, const integrate_option &iopt)
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
t operator()(const t &a, const t &b)
Definition: space.cc:386
T dddot(const tensor3_basic< T > &a, const tensor3_basic< T > &b)
Definition: tensor3.cc:94
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
bool valued_check() 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
void evaluate(const geo_basic< float_type, M > &omega_K, const geo_element &K, Eigen::Matrix< Result, Eigen::Dynamic, 1 > &value) const
T norm2(const vec< T, M > &x)
norm2(x): see the expression page for the full documentation
Definition: vec.h:379
U tr(const tensor_basic< U > &a, size_t d=3)
T ddot(const tensor_basic< T > &a, const tensor_basic< T > &b)
ddot(x,y): see the expression page for the full documentation
Definition: tensor.cc:278
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_internal2(const geo_basic< float_type, M > &omega_K, const geo_element &K, Eigen::Matrix< Result, Eigen::Dynamic, 1 > &value) const
space_mult_list< T, M > pow(const space_basic< T, M > &X, size_t n)
Definition: space_mult.h:120
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
rheolef::std enable_if ::type compose const Function f, const Expr1 expr1, const Expr2 expr2 compose(const Function &f, const Expr1 &expr1, const Expr2 &expr2)
const_iterator begin_dof() const
tensor_basic< T > exp(const tensor_basic< T > &a, size_t d)
Definition: tensor-exp.cc:92
_RHEOLEF_make_field_expr_v2_nonlinear_unary_operator(operator+, details::unary_plus) _RHEOLEF_make_field_expr_v2_nonlinear_unary_operator(operator-
_RHEOLEF_make_field_expr_v2_nonlinear_unary_function(cos) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(sin) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(tan) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(acos) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(asin) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(atan) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(cosh) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(sinh) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(tanh) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(exp) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(log) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(log10) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(sqrt) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(abs) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(fabs) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(floor) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(ceil) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(sqr) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(norm) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(norm2) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(tr) _RHEOLEF_make_field_expr_v2_nonlinear_unary_function(trans) template< class Function
space_constant::valued_type valued_tag() const
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, space_constant::valued_type)
Definition: expression.h:422
static space_constant::valued_type valued_tag(space_constant::valued_type)
Definition: expression.h:200