Rheolef  7.2
an efficient C++ finite element environment
field_lazy_node.h
Go to the documentation of this file.
1 # ifndef _RHEOLEF_FIELD_LAZY_NODE_H
2 # define _RHEOLEF_FIELD_LAZY_NODE_H
3 //
4 // This file is part of Rheolef.
5 //
6 // Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
7 //
8 // Rheolef is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // Rheolef is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with Rheolef; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 //
22 // =========================================================================
23 // field_lazy = un-assembled field
24 // as returned by lazy_integrate, lazy_interpolate or encapsulated field_basic
25 // here, they are combined with +- operators
26 // AUTHOR: Pierre.Saramito@imag.fr
27 // DATE: 6 april 1920
28 
29 // SUMMARY: see also "field_lazy_terminal.h"
30 // 3. unary expressions
31 // 3.1. unary_minus & unary_plus
32 // 4. binary expressions
33 // 4.1. add & minus
34 //
35 #include "rheolef/field_lazy_terminal.h"
36 
37 namespace rheolef {
38 
39 // -------------------------------------------------------------------
40 // 3. unary expressions
41 // -------------------------------------------------------------------
42 // 3.1. unary_minus & unary_plus
43 // -------------------------------------------------------------------
44 namespace details {
45 
46 template<class Unop, class Expr>
47 class field_lazy_unop: public field_lazy_base<field_lazy_unop<Unop,Expr>> {
48 public :
49 // definitions:
50 
53  using memory_type = typename Expr::memory_type;
54  using scalar_type = typename Expr::scalar_type;
55  using space_type = typename Expr::space_type;
56  using geo_type = typename Expr::geo_type;
59  using vector_element_type = Eigen::Matrix<scalar_type,Eigen::Dynamic,1>;
60 
61 // allocator:
62 
63  field_lazy_unop (const Unop& unop, const Expr& expr)
64  : base(),
65  _unop(unop),
66  _expr(expr)
67  {}
68 
69 // accessors:
70 
71  const geo_type& get_geo() const { return _expr.get_geo(); }
72  const space_type& get_space() const { return _expr.get_space(); }
73  bool is_on_band() const { return _expr.is_on_band(); }
74  band_type get_band() const { return _expr.get_band(); }
75 
76  void initialize (const geo_type& omega_K) { _expr.initialize (omega_K); }
77 
78  void evaluate (
79  const geo_type& omega_K,
80  const geo_element& K,
81  vector_element_type& uk) const;
82 // data:
83 protected:
84  Unop _unop;
85  Expr _expr;
86 };
87 // concept;
88 template<class Unop, class Expr>
89 struct is_field_lazy <field_lazy_unop<Unop,Expr> > : std::true_type {};
90 
91 // inlined:
92 template<class Unop, class Expr>
93 void
95  const geo_type& omega_K,
96  const geo_element& K,
97  vector_element_type& uk) const
98 {
99  _expr.evaluate (omega_K, K, uk);
100  uk = uk.unaryExpr(_unop);
101 }
102 
103 }// namespace details
104 
106 #define _RHEOLEF_field_lazy_unop(OP,NAME) \
107 template<class Expr, class Sfinae = typename std::enable_if<details::is_field_lazy<Expr>::value, Expr>::type> \
108 details::field_lazy_unop<NAME,Expr> \
109 operator OP (const Expr& u) \
110 { \
111  return details::field_lazy_unop<NAME,Expr> (NAME(),u); \
112 }
115 #undef _RHEOLEF_field_lazy_unop
116 // -------------------------------------------------------------------
117 // 4. binary expressions
118 // -------------------------------------------------------------------
119 // 4.1. add & minus
120 // -------------------------------------------------------------------
121 namespace details {
122 
123 template<class Binop, class Expr1, class Expr2>
124 class field_lazy_add: public field_lazy_base<field_lazy_add<Binop,Expr1,Expr2>> {
125 public :
126 // definitions:
127 
130  using memory_type = typename Expr1::memory_type;
131  using scalar_type = typename Expr1::scalar_type;
132  using space_type = typename Expr1::space_type;
133  using geo_type = typename Expr1::geo_type;
136  using vector_element_type = Eigen::Matrix<scalar_type,Eigen::Dynamic,1>;
137 
138 // allocator:
139 
140  field_lazy_add (const Expr1& expr1, const Expr2& expr2)
141  : base(),
142  _binop(),
143  _expr1(expr1),
144  _expr2(expr2) {}
145 
146 // accessors:
147 
148  const geo_type& get_geo() const;
149  const space_type& get_space() const { return _expr1.get_space(); }
150  bool is_on_band() const { return _expr1.is_on_band(); }
151  band_type get_band() const { return _expr1.get_band(); }
152 
153  void initialize (const geo_type& omega_K);
154 
155  void evaluate (
156  const geo_type& omega_K,
157  const geo_element& K,
158  vector_element_type& uk) const;
159 // data:
160 protected:
161  Binop _binop;
163  Expr2 _expr2;
164 };
165 // concept;
166 template<class Binop, class Expr1, class Expr2>
167 struct is_field_lazy <field_lazy_add<Binop,Expr1,Expr2> > : std::true_type {};
168 
169 // inlined:
170 template<class Binop, class Expr1, class Expr2>
173 {
174  // TODO: improve the automatic determination of the domain
175  // by an union that operates recursively
176  const geo_type& dom1 = _expr1.get_geo();
177  const geo_type& dom2 = _expr2.get_geo();
178  if (dom1 == dom2 || dom1 == dom2.get_background_geo() || dom1.is_broken()) {
179  trace_macro("lazy_add: union("<<dom1.name()<<","<<dom2.name()<<")="<<dom1.name());
180  return dom1;
181  } else if (dom2 == dom1.get_background_geo() || dom2.is_broken()) {
182  trace_macro("lazy_add: union("<<dom1.name()<<","<<dom2.name()<<")="<<dom2.name());
183  return dom2;
184  } else {
185  error_macro("lazy_add: incompatible domains \""<<dom1.name()
186  << "\" and \"" << dom2.name() << "\"");
187  return dom2;
188  }
189  check_macro (_expr1.is_on_band() == _expr2.is_on_band(),
190  "lazy_add: invalid combination of banded and non-banded geoetry");
191 }
192 template<class Binop, class Expr1, class Expr2>
193 void
195 {
196  check_macro (_expr1.get_space() == _expr2.get_space(),
197  "lazy_add: incompatible spaces "
198  << "\"" <<_expr1.get_space().name()<<"\" and \"" <<_expr2.get_space().name()<<"\"");
199 
200  _expr1.initialize (omega_K);
201  _expr2.initialize (omega_K);
202 }
203 template<class Binop, class Expr1, class Expr2>
204 void
206  const geo_type& omega_K,
207  const geo_element& K,
208  vector_element_type& wk) const
209 {
210  vector_element_type uk, vk;
211  _expr1.evaluate (omega_K, K, uk);
212  _expr2.evaluate (omega_K, K, vk);
213 #ifdef _RHEOLEF_PARANO
214  check_macro (uk.size() == vk.size(), "u+v: invalid sizes");
215 #endif // _RHEOLEF_PARANO
216  wk = uk.binaryExpr (vk, _binop);
217 }
218 
219 }// namespace details
220 
222 #define _RHEOLEF_field_lazy_add(OP,NAME) \
223 template<class Expr1, class Expr2, \
224  class Sfinae1 = typename std::enable_if<details::is_field_lazy<Expr1>::value, Expr1>::type, \
225  class Sfinae2 = typename std::enable_if<details::is_field_lazy<Expr2>::value, Expr2>::type> \
226 details::field_lazy_add<details::NAME,Expr1,Expr2> \
227 operator OP (const Expr1& u, const Expr2& v) \
228 { \
229  return details::field_lazy_add<details::NAME,Expr1,Expr2> (u,v); \
230 } \
231 template<class Expr1, \
232  class Sfinae1 = typename std::enable_if<details::is_field_lazy<Expr1>::value, Expr1>::type> \
233 details::field_lazy_add< \
234  details::NAME \
235  ,Expr1 \
236  ,details::field_lazy_terminal_field<typename Expr1::scalar_type,typename Expr1::memory_type> \
237 > \
238 operator OP (const Expr1& u, const field_basic<typename Expr1::scalar_type,typename Expr1::memory_type>& v) \
239 { \
240  using Expr2 = details::field_lazy_terminal_field<typename Expr1::scalar_type,typename Expr1::memory_type>; \
241  return details::field_lazy_add<details::NAME,Expr1,Expr2> (u,Expr2(v)); \
242 } \
243 template<class Expr2, \
244  class Sfinae2 = typename std::enable_if<details::is_field_lazy<Expr2>::value, Expr2>::type> \
245 details::field_lazy_add< \
246  details::NAME \
247  ,details::field_lazy_terminal_field<typename Expr2::scalar_type,typename Expr2::memory_type> \
248  ,Expr2 \
249 > \
250 operator OP (const field_basic<typename Expr2::scalar_type,typename Expr2::memory_type>& u, const Expr2& v) \
251 { \
252  using Expr1 = details::field_lazy_terminal_field<typename Expr2::scalar_type,typename Expr2::memory_type>; \
253  return details::field_lazy_add<details::NAME,Expr1,Expr2> (Expr1(u),v); \
254 }
257 #undef _RHEOLEF_field_lazy_add
258 
259 }// namespace rheolef
260 # endif /* _RHEOLEF_FIELD_LAZY_NODE_H */
const space_type & get_space() const
geo_element::size_type size_type
typename Expr1::scalar_type scalar_type
typename Expr1::memory_type memory_type
void evaluate(const geo_type &omega_K, const geo_element &K, vector_element_type &uk) const
void initialize(const geo_type &omega_K)
const geo_type & get_geo() const
Eigen::Matrix< scalar_type, Eigen::Dynamic, 1 > vector_element_type
typename float_traits< scalar_type >::type float_type
typename Expr1::space_type space_type
typename Expr1::geo_type geo_type
field_lazy_add(const Expr1 &expr1, const Expr2 &expr2)
const space_type & get_space() const
geo_element::size_type size_type
void evaluate(const geo_type &omega_K, const geo_element &K, vector_element_type &uk) const
const geo_type & get_geo() const
void initialize(const geo_type &omega_K)
typename Expr::geo_type geo_type
typename Expr::scalar_type scalar_type
typename Expr::memory_type memory_type
Eigen::Matrix< scalar_type, Eigen::Dynamic, 1 > vector_element_type
typename float_traits< scalar_type >::type float_type
typename Expr::space_type space_type
field_lazy_unop(const Unop &unop, const Expr &expr)
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
rheolef::std Expr1
dot(x,y): see the expression page for the full documentation
#define trace_macro(message)
Definition: dis_macros.h:111
#define error_macro(message)
Definition: dis_macros.h:49
check_macro(expr1.have_homogeneous_space(Xh1), "dual(expr1,expr2); expr1 should have homogeneous space. HINT: use dual(interpolate(Xh, expr1),expr2)")
This file is part of Rheolef.
_RHEOLEF_field_lazy_unop(+, details::unary_plus) _RHEOLEF_field_lazy_unop(-
_RHEOLEF_field_lazy_add(+, plus) _RHEOLEF_field_lazy_add(-