Rheolef  7.2
an efficient C++ finite element environment
newton_add_missing.h
Go to the documentation of this file.
1 #ifndef _RHEOLEF_NEWTON_ADD_MISSING_H
2 #define _RHEOLEF_NEWTON_ADD_MISSING_H
23 // there are two versions of this algorithm
24 // - one with imbeded mesh adaptation loop
25 // - one without this feature
26 // the algorithm is automatically selected when there is an adapt() method
27 // in the supplied problem definition
28 //
29 #include "rheolef/continuation_option.h"
30 #include "rheolef/damped_newton.h"
31 #include <type_traits>
32 
33 namespace rheolef { namespace details {
34 
35 // -----------------------------------------------------------------------------
36 // predicates: have some member functions ?
37 // -----------------------------------------------------------------------------
38 // => will provides a default behavior when the member is missing
39 //
40 // solution from:
41 // https://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions
42 // note: it works with derived classes but do not check yet
43 // whether the named member is a data or a function
44 // and do not check for its profile.
45 //
46 #define _RHEOLEF_has_inherited_member_macro(NAME) \
47 template <typename Type> \
48 class has_inherited_member_##NAME { \
49  class yes { char m;}; \
50  class no { yes m[2];}; \
51  struct base_mixin { void NAME(){} }; \
52  struct base : public Type, public base_mixin {}; \
53  template <typename T, T t> class helper{}; \
54  template <typename U> \
55  static no deduce(U*, helper<void (base_mixin::*)(), &U::NAME>* = 0); \
56  static yes deduce(...); \
57 public: \
58  static const bool value = sizeof(yes) == sizeof(deduce((base*)(0))); \
59  typedef std::integral_constant<bool, value> type; \
60 };
61 
62 // -----------------------------------------------------------------------------
63 // void adapt (const value_type&, const adapt_option&);
64 // -----------------------------------------------------------------------------
66 
67 template<class Problem, class Sfinae = typename has_inherited_member_adapt<Problem>::type>
68 struct add_adapt{};
69 
70 template<class Problem>
71 class add_adapt<Problem,std::true_type>: public virtual Problem {
72 public:
73  typedef typename Problem::float_type float_type;
74  typedef typename Problem::value_type value_type;
75  add_adapt(const add_adapt& f) : Problem(f) {}
76  explicit add_adapt(const Problem& f) : Problem(f) {}
77  add_adapt<Problem>& operator= (add_adapt<Problem>&& f) {
78  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
79  return *this;
80  }
81 };
82 template<class Problem>
83 class add_adapt<Problem,std::false_type>: public virtual Problem {
84 public:
85  typedef typename Problem::float_type float_type;
86  typedef typename Problem::value_type value_type;
87  add_adapt(const add_adapt& f) : Problem(f) {}
88  explicit add_adapt(const Problem& f) : Problem(f) {}
89  void adapt (const value_type&, const adapt_option&) const {}
90  void reset_geo (const value_type&) {}
91  value_type reinterpolate (const value_type& uh) { return uh; }
92  add_adapt<Problem>& operator= (add_adapt<Problem>&& f) {
93  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
94  return *this;
95  }
96 };
97 // -----------------------------------------------------------------------------
98 // void refresh (float_type, const value_type&, const value_type&) const;
99 // -----------------------------------------------------------------------------
100 // note: used by the keller continuation method
101 
103 
104 template<class Problem, class Sfinae = typename has_inherited_member_refresh<Problem>::type>
105 struct add_refresh{};
106 
107 template<class Problem>
108 class add_refresh<Problem,std::true_type>: public virtual Problem {
109 public:
110  typedef typename Problem::float_type float_type;
111  typedef typename Problem::value_type value_type;
112  add_refresh(const add_refresh& f) : Problem(f) {}
113  explicit add_refresh(const Problem& f) : Problem(f) {}
114  add_refresh<Problem>& operator= (add_refresh<Problem>&& f) {
115  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
116  return *this;
117  }
118 };
119 template<class Problem>
120 class add_refresh<Problem,std::false_type>: public virtual Problem {
121 public:
122  typedef typename Problem::float_type float_type;
123  typedef typename Problem::value_type value_type;
124  add_refresh(const add_refresh& f) : Problem(f) {}
125  explicit add_refresh(const Problem& f) : Problem(f) {}
126  void refresh (float_type, const value_type&, const value_type&) const {}
127  add_refresh<Problem>& operator= (add_refresh<Problem>&& f) {
128  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
129  return *this;
130  }
131 };
132 // -----------------------------------------------------------------------------
133 // value_type direction (const value_type&) const;
134 // -----------------------------------------------------------------------------
135 // used by the continuation method ; redefined by keller
136 
138 
139 template<class Problem, class Sfinae = typename has_inherited_member_direction<Problem>::type>
140 struct add_direction{};
141 
142 template<class Problem>
143 class add_direction<Problem,std::true_type>: public virtual Problem {
144 public:
145  typedef typename Problem::float_type float_type;
146  typedef typename Problem::value_type value_type;
147  add_direction(const add_direction& f) : Problem(f) {}
148  explicit add_direction(const Problem& f) : Problem(f) {}
149  add_direction<Problem>& operator= (add_direction<Problem>&& f) {
150  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
151  return *this;
152  }
153 };
154 template<class Problem>
155 class add_direction<Problem,std::false_type>: public virtual Problem {
156 public:
157  typedef typename Problem::float_type float_type;
158  typedef typename Problem::value_type value_type;
159  add_direction(const add_direction& f) : Problem(f) {}
160  explicit add_direction(const Problem& f) : Problem(f) {}
161  value_type direction (const value_type& uh) const {
162  Problem::update_derivative (uh);
163  return - Problem::derivative_solve (Problem::derivative_versus_parameter(uh));
164  }
165  add_direction<Problem>& operator= (add_direction<Problem>&& f) {
166  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
167  return *this;
168  }
169 };
170 // -----------------------------------------------------------------------------
171 // float_type space_norm (const value_type&) const;
172 // -----------------------------------------------------------------------------
173 
175 
176 template<class Problem, class Sfinae = typename has_inherited_member_space_norm<Problem>::type>
177 struct add_space_norm{};
178 
179 template<class Problem>
180 class add_space_norm<Problem,std::true_type>: public virtual Problem {
181 public:
182  typedef typename Problem::float_type float_type;
183  typedef typename Problem::value_type value_type;
184  add_space_norm(const add_space_norm& f) : Problem(f) {}
185  explicit add_space_norm(const Problem& f) : Problem(f) {}
186  add_space_norm<Problem>& operator= (add_space_norm<Problem>&& f) {
187  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
188  return *this;
189  }
190 };
191 template<class Problem>
192 class add_space_norm<Problem,std::false_type>: public virtual Problem {
193 public:
194  typedef typename Problem::float_type float_type;
195  typedef typename Problem::value_type value_type;
196  add_space_norm(const add_space_norm& f) : Problem(f) {}
197  explicit add_space_norm(const Problem& f) : Problem(f) {}
198  float_type space_norm (const value_type& uh) const {
199  return sqrt(Problem::space_dot (uh,uh));
200  }
201  add_space_norm<Problem>& operator= (add_space_norm<Problem>&& f) {
202  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
203  return *this;
204  }
205 };
206 // -----------------------------------------------------------------------------
207 // float_type dual_space_norm (const value_type&) const;
208 // -----------------------------------------------------------------------------
209 
211 
212 template<class Problem, class Sfinae = typename details::has_inherited_member_dual_space_norm<Problem>::type>
213 struct add_dual_space_norm{};
214 
215 template<class Problem>
216 class add_dual_space_norm<Problem,std::true_type>: public virtual Problem {
217 public:
218  typedef typename Problem::float_type float_type;
219  typedef typename Problem::value_type value_type;
220  add_dual_space_norm(const add_dual_space_norm& f) : Problem(f) {}
221  explicit add_dual_space_norm(const Problem& f) : Problem(f) {}
222  add_dual_space_norm<Problem>& operator= (add_dual_space_norm<Problem>&& f) {
223  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
224  return *this;
225  }
226 };
227 template<class Problem>
228 class add_dual_space_norm<Problem,std::false_type>: public virtual Problem {
229 public:
230  typedef typename Problem::float_type float_type;
231  typedef typename Problem::value_type value_type;
232  add_dual_space_norm(const add_dual_space_norm& f) : Problem(f) {}
233  explicit add_dual_space_norm(const Problem& f) : Problem(f) {}
235  return sqrt(Problem::dual_space_dot (uh,uh));
236  }
237  add_dual_space_norm<Problem>& operator= (add_dual_space_norm<Problem>&& f) {
238  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
239  return *this;
240  }
241 };
242 // -----------------------------------------------------------------------------
243 // add_missing: complete the problem class used by the continuation method
244 // -----------------------------------------------------------------------------
245 template<class Problem>
247  public virtual add_space_norm<Problem>
248  ,public virtual add_dual_space_norm<Problem>
249 {
250 public:
251  typedef typename Problem::float_type float_type;
252  typedef typename Problem::value_type value_type;
254  Problem(f)
255  ,add_space_norm<Problem>(f)
256  ,add_dual_space_norm<Problem>(f)
257  {}
258  add_missing_damped_newton(const Problem& f) :
259  Problem(f)
260  ,add_space_norm<Problem>(f)
261  ,add_dual_space_norm<Problem>(f)
262  {}
264  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
265  return *this;
266  }
267 };
268 template<class Problem>
270  public virtual add_adapt <Problem>
271  ,public virtual add_refresh <Problem>
272  ,public virtual add_direction <Problem>
273  ,public virtual add_space_norm<Problem>
274  ,public virtual add_dual_space_norm<Problem>
275 {
276 public:
277  typedef typename Problem::float_type float_type;
278  typedef typename Problem::value_type value_type;
280  Problem(f)
281  ,add_adapt<Problem>(f)
282  ,add_refresh<Problem>(f)
283  ,add_direction<Problem>(f)
284  ,add_space_norm<Problem>(f)
285  ,add_dual_space_norm<Problem>(f)
286  {}
287  add_missing_continuation(const Problem& f) :
288  Problem(f)
289  ,add_adapt<Problem>(f)
290  ,add_refresh<Problem>(f)
291  ,add_direction<Problem>(f)
292  ,add_space_norm<Problem>(f)
293  ,add_dual_space_norm<Problem>(f)
294  {}
296  static_cast<Problem&>(*this) = static_cast<Problem&&>(f);
297  return *this;
298  }
299 };
300 
301 #undef _RHEOLEF_has_inherited_member_macro
302 
303 }} // namespace rheolef::details
304 #endif // _RHEOLEF_NEWTON_ADD_MISSING_H
void adapt(const value_type &, const adapt_option &) const
add_missing_continuation< Problem > & operator=(add_missing_continuation< Problem > &&f)
add_missing_continuation(const add_missing_continuation< Problem > &f)
add_missing_damped_newton< Problem > & operator=(add_missing_damped_newton< Problem > &&f)
add_missing_damped_newton(const add_missing_damped_newton< Problem > &f)
void refresh(float_type, const value_type &, const value_type &) const
_RHEOLEF_has_inherited_member_macro(adapt) template< class Problem
This file is part of Rheolef.
geo_basic< T, M > adapt(const field_basic< T, M > &uh, const adapt_option &opts)
adapt(uh,opts): see the adapt page for the full documentation
Definition: adapt.cc:179
Definition: cavity_dg.h:29
adapt_option: see the adapt page for the full documentation
Definition: adapt.h:147