1 #ifndef _RHEOLEF_FORM_EXPR_VARIATIONAL_H
2 #define _RHEOLEF_FORM_EXPR_VARIATIONAL_H
48 #include "rheolef/field_expr_variational.h"
69 template<
class UnaryFunction,
class Expr>
79 typename Expr::value_type
115 _expr.initialize (pops, iopt);
118 _expr.initialize (
gh, pops, iopt);
120 template<
class Result>
124 Eigen::Tensor<Result,3>&
value)
const
135 template<
class Result>
153 #define _RHEOLEF_make_form_expr_v2_variational_unary(FUNCTION,FUNCTOR) \
154 template<class Expr> \
158 details::is_form_expr_v2_variational_arg<Expr>::value \
159 ,details::form_expr_v2_variational_unary< \
164 FUNCTION (const Expr& expr) \
166 return details::form_expr_v2_variational_unary <FUNCTOR,Expr> (FUNCTOR(), expr); \
171 #undef _RHEOLEF_make_form_expr_v2_variational_unary
183 template<
class BinaryFunction,
class Expr1,
class Expr2>
192 typename Expr1::value_type
195 typename Expr1::value_type
196 ,
typename Expr2::value_type
202 typename Expr1::vf_tag_type,
208 typename Expr2::dual_self_type>
210 typedef typename and_type<
typename Expr1::maybe_symmetric::type,
211 typename Expr2::maybe_symmetric::type>
::type
240 _expr1.initialize (pops, iopt);
241 _expr2.initialize (pops, iopt);
248 template<
class Result>
252 Eigen::Tensor<Result,3>&
value)
const
258 Eigen::Tensor<float_type,3> value1;
_expr1.evaluate (omega_K, K, value1);
259 Eigen::Tensor<float_type,3> value2;
_expr2.evaluate (omega_K, K, value2);
260 value.resize (value1.dimension(0), value1.dimension(1), value1.dimension(2));
261 check_macro (value1.dimension(0) == value2.dimension(0) &&
262 value1.dimension(1) == value2.dimension(1) &&
263 value1.dimension(2) == value2.dimension(2),
264 "invalid sizes value1("
265 << value1.dimension(0) <<
","<< value1.dimension(1) <<
","<< value1.dimension(2) <<
") and value2("
266 << value2.dimension(0) <<
","<< value2.dimension(1) <<
","<< value2.dimension(2) <<
")");
270 value(i,j,k) =
_f (value1(i,j,k), value2(i,j,k));
273 template<
class Result>
278 Eigen::Tensor<Result,3>&
value)
const
284 Eigen::Tensor<float_type,3> value1;
_expr1.evaluate_on_side (omega_K, K, sid, value1);
285 Eigen::Tensor<float_type,3> value2;
_expr2.evaluate_on_side (omega_K, K, sid, value2);
286 value.resize (value1.dimension(0), value1.dimension(1), value1.dimension(2));
287 check_macro (value1.dimension(0) == value2.dimension(0) &&
288 value1.dimension(1) == value2.dimension(1) &&
289 value1.dimension(2) == value2.dimension(2),
290 "invalid sizes value1("
291 << value1.dimension(0) <<
","<< value1.dimension(1) <<
","<< value1.dimension(2) <<
") and value2("
292 << value2.dimension(0) <<
","<< value2.dimension(1) <<
","<< value2.dimension(2) <<
")");
296 value(i,j,k) =
_f (value1(i,j,k), value2(i,j,k));
299 template<
class Result>
322 #define _RHEOLEF_form_expr_v2_variational_binary(FUNCTION,FUNCTOR) \
323 template <class Expr1, class Expr2> \
327 details::is_form_expr_v2_variational_arg <Expr1>::value \
328 && details::is_form_expr_v2_variational_arg <Expr2>::value \
329 ,details::form_expr_v2_variational_binary< \
335 FUNCTION (const Expr1& expr1, const Expr2& expr2) \
337 return details::form_expr_v2_variational_binary \
338 <FUNCTOR, Expr1, Expr2> \
339 (FUNCTOR(), expr1, expr2); \
345 #undef _RHEOLEF_form_expr_v2_variational_binary
355 template<
class BinaryFunction,
class Expr1,
class Expr2>
364 typename Expr1::value_type
367 typename Expr1::value_type
368 ,
typename Expr2::value_type
374 typename Expr1::vf_tag_type,
418 _expr1.initialize (pops, iopt);
419 _expr2.initialize (pops, iopt);
430 template<
class ValueType,
class Arg1,
class Arg2>
434 Eigen::Tensor<ValueType,3>&
value)
const
436 typedef long int eig_idx_t;
439 Eigen::Matrix<Arg2,Eigen::Dynamic,Eigen::Dynamic> v_test;
_expr2.evaluate (omega_K, K, v_test);
440 Eigen::Matrix<Arg1,Eigen::Dynamic,Eigen::Dynamic> u_trial;
_expr1.evaluate (omega_K, K, u_trial);
441 check_macro(u_trial.rows() == v_test.rows(),
"invalid sizes u_trial("
442 <<u_trial.rows()<<
","<<u_trial.cols() <<
") and v_test("
443 <<v_test.rows() <<
","<<v_test.cols()<<
")");
444 eig_idx_t nq = u_trial.rows();
445 eig_idx_t ni = v_test.cols();
446 eig_idx_t nj = u_trial.cols();
447 value.resize(nq,ni,nj);
448 for (eig_idx_t q = 0; q < nq; ++q) {
449 for (eig_idx_t i = 0; i < ni; ++i) {
450 for (eig_idx_t j = 0; j < nj; ++j) {
451 value(q,i,j) =
_f (u_trial(q,j), v_test(q,i));
455 Eigen::Matrix<Arg2,Eigen::Dynamic,Eigen::Dynamic> v_test;
_expr1.evaluate (omega_K, K, v_test);
456 Eigen::Matrix<Arg1,Eigen::Dynamic,Eigen::Dynamic> u_trial;
_expr2.evaluate (omega_K, K, u_trial);
457 check_macro(u_trial.rows() == v_test.rows(),
"binary: invalid sizes");
458 eig_idx_t nq = u_trial.rows();
459 eig_idx_t ni = v_test.cols();
460 eig_idx_t nj = u_trial.cols();
461 value.resize(nq,ni,nj);
462 for (eig_idx_t q = 0; q < nq; ++q) {
463 for (eig_idx_t i = 0; i < ni; ++i) {
464 for (eig_idx_t j = 0; j < nj; ++j) {
465 value(q,i,j) =
_f (u_trial(q,j), v_test(q,i));
469 template<
class ValueType,
class Arg1,
class Arg2>
474 Eigen::Tensor<ValueType,3>&
value)
const
476 typedef long int eig_idx_t;
477 bool do_local_component_assembly =
true;
480 Eigen::Matrix<Arg2,Eigen::Dynamic,Eigen::Dynamic> v_test;
_expr2.evaluate_on_side (omega_K, K, sid, v_test, do_local_component_assembly);
481 Eigen::Matrix<Arg1,Eigen::Dynamic,Eigen::Dynamic> u_trial;
_expr1.evaluate_on_side (omega_K, K, sid, u_trial, do_local_component_assembly);
482 check_macro(u_trial.rows() == v_test.rows(),
"invalid sizes u_trial("
483 <<u_trial.rows()<<
","<<u_trial.cols() <<
") and v_test("
484 <<v_test.rows() <<
","<<v_test.cols()<<
")");
485 eig_idx_t nq = u_trial.rows();
486 eig_idx_t ni = v_test.cols();
487 eig_idx_t nj = u_trial.cols();
488 value.resize(nq,ni,nj);
489 for (eig_idx_t q = 0; q < nq; ++q) {
490 for (eig_idx_t i = 0; i < ni; ++i) {
491 for (eig_idx_t j = 0; j < nj; ++j) {
492 value(q,i,j) =
_f (u_trial(q,j), v_test(q,i));
496 Eigen::Matrix<Arg2,Eigen::Dynamic,Eigen::Dynamic> v_test;
_expr1.evaluate_on_side (omega_K, K, sid, v_test, do_local_component_assembly);
497 Eigen::Matrix<Arg1,Eigen::Dynamic,Eigen::Dynamic> u_trial;
_expr2.evaluate_on_side (omega_K, K, sid, u_trial, do_local_component_assembly);
498 check_macro(u_trial.rows() == v_test.rows(),
"binary: invalid sizes");
499 eig_idx_t nq = u_trial.rows();
500 eig_idx_t ni = v_test.cols();
501 eig_idx_t nj = u_trial.cols();
502 value.resize(nq,ni,nj);
503 for (eig_idx_t q = 0; q < nq; ++q) {
504 for (eig_idx_t i = 0; i < ni; ++i) {
505 for (eig_idx_t j = 0; j < nj; ++j) {
506 value(q,i,j) =
_f (u_trial(q,j), v_test(q,i));
511 template<
class This,
class ValueType,
521 Eigen::Tensor<ValueType,3>&
value)
const
523 obj.template evaluate_internal<ValueType, Arg1, Arg2> (omega_K, K,
value);
530 Eigen::Tensor<ValueType,3>&
value)
const
532 obj.template evaluate_on_side_internal<ValueType, Arg1, Arg2> (omega_K, K, sid,
value);
535 template<
class ValueType>
539 Eigen::Tensor<ValueType,3>&
value)
const
542 typename Expr1::value_type
543 ,
typename Expr2::value_type
544 ,ValueType>::first_argument_type first_argument_type;
546 typename Expr1::value_type
547 ,
typename Expr2::value_type
548 ,ValueType>::second_argument_type second_argument_type;
552 first_argument_type, first_argument_tag,
553 second_argument_type, second_argument_tag> eval;
554 eval (*
this, omega_K, K,
value);
556 template<
class ValueType>
561 Eigen::Tensor<ValueType,3>&
value)
const
564 typename Expr1::value_type
565 ,
typename Expr2::value_type
566 ,ValueType>::first_argument_type first_argument_type;
568 typename Expr1::value_type
569 ,
typename Expr2::value_type
570 ,ValueType>::second_argument_type second_argument_type;
574 first_argument_type, first_argument_tag,
575 second_argument_type, second_argument_tag> eval;
576 eval (*
this, omega_K, K, sid,
value);
578 template<
class ValueType>
581 typename Expr1::value_type
582 ,
typename Expr2::value_type
583 ,ValueType>::first_argument_type A1;
585 typename Expr1::value_type
586 ,
typename Expr2::value_type
587 ,ValueType>::second_argument_type A2;
606 template<
class Expr1,
class Expr2,
class Sfinae =
void>
609 template <
class Expr1,
class Expr2>
615 is_field_expr_v2_variational_arg<Expr1>::value
616 && is_field_expr_v2_variational_arg<Expr2>::value
620 is_field_expr_v2_variational_arg<Expr1>
621 ,is_field_expr_v2_variational_arg<Expr2>
623 typename Expr1::vf_tag_type
624 ,typename dual_vf_tag<typename Expr2::vf_tag_type>::type
631 #define _RHEOLEF_form_expr_v2_variational_binary_field(FUNCTION,FUNCTOR) \
632 template <class Expr1, class Expr2> \
636 details::is_form_expr_v2_variational_binary_field <Expr1,Expr2>::value \
637 ,details::form_expr_v2_variational_binary_field< \
643 FUNCTION (const Expr1& expr1, const Expr2& expr2) \
645 return details::form_expr_v2_variational_binary_field \
646 <FUNCTOR, Expr1, Expr2> \
647 (FUNCTOR(), expr1, expr2); \
654 #undef _RHEOLEF_form_expr_v2_variational_binary_field
665 template<
class BinaryFunction,
class NLExpr,
class VFExpr>
666 class form_expr_v2_variational_binary_binded {
673 typedef typename details::generic_binary_traits<BinaryFunction>::template result_hint<
674 typename NLExpr::value_type
675 ,
typename VFExpr::value_type>
::type result_hint;
676 typedef typename details::generic_binary_traits<BinaryFunction>::template hint<
677 typename NLExpr::value_type
678 ,
typename VFExpr::value_type
685 typename VFExpr::vf_tag_type>
::type vf_tag_type;
688 typedef form_expr_v2_variational_binary_binded <BinaryFunction,NLExpr,VFExpr> self_type;
689 typedef form_expr_v2_variational_binary_binded <BinaryFunction,NLExpr,typename VFExpr::dual_self_type>
691 typedef typename VFExpr::maybe_symmetric::type maybe_symmetric;
701 const NLExpr& nl_expr,
702 const VFExpr& vf_expr)
710 const space_type& get_trial_space()
const {
return _vf_expr.get_trial_space(); }
711 const space_type& get_test_space()
const {
return _vf_expr.get_test_space(); }
712 size_type n_derivative()
const {
return _vf_expr.n_derivative(); }
717 _nl_expr.initialize (pops, iopt);
718 _vf_expr.initialize (pops, iopt);
721 _nl_expr.initialize ( pops, iopt);
722 _vf_expr.initialize (
gh, pops, iopt);
727 template<
class Result>
731 Eigen::Tensor<Result,3>&
value)
const
735 Eigen::Matrix<Arg1,Eigen::Dynamic,1> value1; _nl_expr.evaluate (omega_K, K, value1);
736 Eigen::Tensor<float_type,3> value2; _vf_expr.evaluate (omega_K, K, value2);
737 check_macro (value1.size() == value2.dimension(0),
"invalid sizes");
738 size_type loc_nnod = value2.dimension(0);
739 size_type loc_ndof1 = value2.dimension(1);
740 size_type loc_ndof2 = value2.dimension(2);
741 value.resize(loc_nnod,loc_ndof1,loc_ndof2);
742 for (
size_type loc_inod = 0; loc_inod < loc_nnod; ++loc_inod) {
743 for (
size_type loc_jdof = 0; loc_jdof < loc_ndof1; ++loc_jdof) {
744 for (
size_type loc_kdof = 0; loc_kdof < loc_ndof2; ++loc_kdof) {
745 value(loc_inod,loc_jdof,loc_kdof)
746 =
_f (value1(loc_inod,loc_jdof), value2(loc_inod,loc_jdof,loc_kdof));
749 template<
class Result>
764 template<
class F,
class Expr1,
class Expr2>
struct is_form_expr_v2_variational_arg <form_expr_v2_variational_binary_binded<F,
Expr1,Expr2> > : std::true_type {};
773 template<
class Expr1,
class Expr2,
class Sfinae =
void>
776 template<
class Expr1,
class Expr2>
782 is_field_expr_v2_nonlinear_arg <Expr1>::value
783 && ! is_rheolef_arithmetic <Expr1>::value
784 && is_form_expr_v2_variational_arg<Expr2>::value
790 template<
class Expr1,
class Expr2>
796 #define _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_left(FUNCTION,FUNCTOR) \
797 template<class Expr1, class Expr2> \
801 details::is_form_expr_v2_variational_binary_multiplies_divides_left <Expr1,Expr2>::value \
802 ,details::form_expr_v2_variational_binary_binded< \
804 ,typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type \
808 FUNCTION (const Expr1& expr1, const Expr2& expr2) \
810 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr1>::type wrap1_t; \
811 return details::form_expr_v2_variational_binary_binded \
812 <FUNCTOR, wrap1_t, Expr2> \
813 (FUNCTOR(), wrap1_t(expr1), expr2); \
816 #define _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_right(FUNCTION,FUNCTOR) \
817 template<class Expr1, class Expr2> \
821 details::is_form_expr_v2_variational_binary_multiplies_divides_right <Expr1,Expr2>::value \
822 ,details::form_expr_v2_variational_binary_binded< \
823 details::swapper<FUNCTOR> \
824 , typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type \
828 FUNCTION (const Expr1& expr1, const Expr2& expr2) \
830 typedef typename details::field_expr_v2_nonlinear_terminal_wrapper_traits<Expr2>::type wrap2_t; \
831 return details::form_expr_v2_variational_binary_binded \
832 <details::swapper<FUNCTOR>, wrap2_t, Expr1> \
833 (details::swapper<FUNCTOR>(FUNCTOR()), wrap2_t(expr2), expr1); \
835 #define _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides(FUNCTION,FUNCTOR) \
836 _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_left (FUNCTION,FUNCTOR) \
837 _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_right (FUNCTION,FUNCTOR)
843 #undef _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_left
844 #undef _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_right
845 #undef _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides
852 template<
class Expr1,
class Expr2,
class Sfinae =
void>
855 template<
class Expr1,
class Expr2>
861 is_rheolef_arithmetic <Expr1>::value
862 && is_form_expr_v2_variational_arg<Expr2>::value
868 template<
class Expr1,
class Expr2>
874 #define _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_constant_left(FUNCTION,FUNCTOR) \
875 template<class Expr1, class Expr2> \
879 details::is_form_expr_v2_variational_binary_multiplies_divides_constant_left <Expr1,Expr2>::value \
880 ,details::form_expr_v2_variational_unary< \
881 details::binder_first <FUNCTOR, Expr1> \
885 FUNCTION (const Expr1& expr1, const Expr2& expr2) \
887 return details::form_expr_v2_variational_unary \
888 <details::binder_first <FUNCTOR,Expr1>, Expr2> \
889 (details::binder_first <FUNCTOR,Expr1> (FUNCTOR(), expr1), expr2); \
892 #define _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_constant_right(FUNCTION,FUNCTOR) \
893 template<class Expr1, class Expr2> \
897 details::is_form_expr_v2_variational_binary_multiplies_divides_constant_right <Expr1,Expr2>::value \
898 ,details::form_expr_v2_variational_unary< \
899 details::binder_second <FUNCTOR, Expr2> \
903 FUNCTION (const Expr1& expr1, const Expr2& expr2) \
905 return details::form_expr_v2_variational_unary \
906 <details::binder_second <FUNCTOR,Expr2>, Expr1> \
907 (details::binder_second <FUNCTOR,Expr2> (FUNCTOR(), expr2), expr1); \
910 #define _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_constant(FUNCTION,FUNCTOR) \
911 _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_constant_left (FUNCTION,FUNCTOR) \
912 _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_constant_right (FUNCTION,FUNCTOR)
920 #undef _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_constant_right
921 #undef _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_constant_left
922 #undef _RHEOLEF_make_form_expr_v2_variational_binary_operator_multiplies_divides_constant
925 #endif // _RHEOLEF_FORM_EXPR_VARIATIONAL_H