Flow123d  3.9.0-d39db4f
field_model.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file field_model.hh
15  * @brief
16  */
17 
18 #ifndef FIELD_MODEL_HH_
19 #define FIELD_MODEL_HH_
20 
21 #include <armadillo>
22 #include <iostream>
23 #include <tuple>
24 #include <string>
25 #include <vector>
26 #include <utility>
27 #include <type_traits>
28 
29 #include "fields/field.hh"
30 #include "fields/field_common.hh"
32 #include "fields/field_values.hh"
34 #include "fields/field.hh"
35 #include "fields/multi_field.hh"
36 #include "system/fmt/posix.h" // for FMT_UNUSED
37 
38 template <int spacedim> class ElementAccessor;
39 
40 
41 /**
42  * Wrapper for resolution of the overloaded functions passed as a parameter to the FieldModel.
43  *
44  * Example:
45  @code
46  double product(double x, double y) {...}
47  Vec product(double x, Vec y) {...}
48  Model<3, FieldValue<3>::VectorFixed>::create(wrapper_overload(product), f_scal, f_vec);
49  @endcode
50  *
51  * Should automaticaly resolve the second model_cache_item::eval function.
52  */
53 #define wrap_overload(func) [](auto&&... ps){ return func( std::forward<decltype(ps)>(ps)... ); }
54 
55 namespace detail
56 {
57  /**
58  * Extract cached values on index i_cache from the input fields and call given function on these values.
59  */
60 
61  /// base case for building up arguments for the function call
62  template< typename CALLABLE, typename FIELD_TUPLE, int INDEX >
63  struct model_cache_item
64  {
65  template< typename... Vs >
66  static auto eval(int i_cache, CALLABLE f, FIELD_TUPLE fields, Vs&&... args) -> decltype(auto) {
67  const auto &single_field = std::get < INDEX - 1 > (std::forward<decltype(fields)>(fields));
69  i_cache, f, std::forward<decltype(fields)>(fields),
70  single_field[i_cache], std::forward<Vs>(args)...);
71 
72  }
73  };
74 
75  /// terminal case - do the actual function call
76  template< typename CALLABLE, typename FIELD_TUPLE >
77  struct model_cache_item< CALLABLE, FIELD_TUPLE, 0 >
78  {
79  template< typename... Vs >
80  static auto eval(FMT_UNUSED int i_cache, CALLABLE f, FMT_UNUSED FIELD_TUPLE fields, Vs&&... args) -> decltype(auto)
81  {
82  return f(std::forward<Vs>(args)...);
83  }
84  };
85 
86  /**
87  * Check common number of components of the input fields/multifields.
88  * Return number of components.
89  * Return 0 for no multifields.
90  * Throw for different number of components.
91  */
92  template<typename FIELD_TUPLE, int INDEX >
93  struct n_components {
94  static uint eval(FIELD_TUPLE fields, uint n_comp) {
95  const auto &single_field = std::get < INDEX - 1 > (std::forward<decltype(fields)>(fields));
96  uint n_comp_new = single_field.n_comp();
97  if (n_comp == 0) {
98  n_comp = n_comp_new;
99  } else {
100  ASSERT(n_comp == n_comp_new);
101  }
102  return n_components<FIELD_TUPLE, INDEX - 1>::eval(std::forward<decltype(fields)>(fields), n_comp);
103  };
104  };
105 
106  template<typename FIELD_TUPLE>
107  struct n_components<FIELD_TUPLE, 0> {
108  static uint eval(FMT_UNUSED FIELD_TUPLE fields, uint n_comp)
109  {
110  return n_comp;
111  };
112  };
113 
114 
115  /**
116  * Return component 'i_comp' of the multifield 'f' or the field 'f'.
117  */
118  /*template<class FIELD>
119  auto field_component(FIELD f, uint i_comp) -> decltype(auto)
120  {
121  if (f.is_multifield()) {
122  return f[i_comp];
123  } else {
124  return f;
125  }
126  }*/
127 
128  /**
129  * Return component 'i_comp' of the multifield 'f'.
130  */
131  template<int spacedim, class Value>
132  auto field_component(const MultiField<spacedim, Value> &f, uint i_comp) -> decltype(auto)
133  {
134  ASSERT_PERMANENT(f.is_multifield());
135  return f[i_comp];
136  }
137 
138  /**
139  * Return the field 'f'. Variant to previous method.
140  */
141  template<int spacedim, class Value>
142  auto field_component(const Field<spacedim, Value> &f, FMT_UNUSED uint i_comp) -> decltype(auto)
143  {
144  ASSERT_PERMANENT(!f.is_multifield());
145  return f;
146  }
147 
148  /**
149  * For given tuple of fields/multifields and given component index
150  * return the tuple of the selected components.
151  */
152  template<typename FIELD_TUPLE, int INDEX>
153  struct get_components {
154  static auto eval(FIELD_TUPLE fields, uint i_comp) -> decltype(auto)
155  {
156  const auto &single_field = std::get < INDEX - 1 > (std::forward<decltype(fields)>(fields));
157  return std::tuple_cat(
159  std::forward<decltype(fields)>(fields), i_comp),
160  std::forward_as_tuple(field_component(single_field, i_comp))
161  );
162  };
163  };
164 
165  template<typename FIELD_TUPLE>
166  struct get_components<FIELD_TUPLE, 0> {
167  static auto eval(FMT_UNUSED FIELD_TUPLE fields, FMT_UNUSED uint n_comp) -> decltype(auto)
168  {
169  return std::forward_as_tuple<>();
170  };
171  };
172 
173  /**
174  * Check common number of components of the input fields/multifields.
175  * Return number of components.
176  * Return 0 for no multifields.
177  * Throw for different number of components.
178  */
179  template<typename FIELD_TUPLE, int INDEX >
180  struct get_dependency {
181  static std::vector<const FieldCommon *> eval(FIELD_TUPLE fields) {
182  const auto &single_field = std::get < INDEX - 1 > (std::forward<decltype(fields)>(fields));
183  auto vec = get_dependency<FIELD_TUPLE, INDEX - 1>::eval(std::forward<decltype(fields)>(fields));
184  vec.push_back(&single_field);
185  return vec;
186  };
187  };
188 
189  template<typename FIELD_TUPLE>
190  struct get_dependency<FIELD_TUPLE, 0> {
192  {
194  };
195  };
196 
197 
198 
199  template< int spacedim, class Value, typename CALLABLE, typename FIELD_TUPLE, int INDEX >
200  struct field_value
201  {
203 
204  template< typename... Vs >
205  static auto eval(const Point &p, const ElementAccessor<spacedim> &elm, CALLABLE f, FIELD_TUPLE fields, Vs&&... args) -> decltype(auto) {
206  const auto &single_field = std::get < INDEX - 1 > (std::forward<decltype(fields)>(fields));
208  p, elm, f, std::forward<decltype(fields)>(fields),
209  single_field.value(p, elm), std::forward<Vs>(args)...);
210  }
211  };
212 
213 
214  /// terminal case - do the actual function call
215  template< int spacedim, class Value, typename CALLABLE, typename FIELD_TUPLE >
216  struct field_value< spacedim, Value, CALLABLE, FIELD_TUPLE, 0 >
217  {
219 
220  template< typename... Vs >
221  static auto eval(FMT_UNUSED const Point &p, FMT_UNUSED const ElementAccessor<spacedim> &elm, CALLABLE f, FMT_UNUSED FIELD_TUPLE fields,
222  Vs&&... args) -> decltype(auto)
223  {
224  return f(std::forward<Vs>(args)...);
225  }
226  };
227 
228 
229  template<typename Function, typename Tuple>
230  auto call(Function f, Tuple t)
231  {
232  }
233 }
234 
235 
236 /**
237  * Class representing field computing form results of other fields.
238  *
239  * Example of usage:
240  @code
241  // Functor class with defined operator ()
242  class FnProduct {
243  public:
244  Vector operator() (Scalar a, Vector v) {
245  return a(0) * v;
246  }
247  };
248 
249  ...
250 
251  // Create ElementCacheMap
252  std::shared_ptr<EvalPoints> eval_points = std::make_shared<EvalPoints>();
253  eval_poinzs->add_bulk<3>( quad ); // initialize EvalPoints
254  ElementCacheMap elm_cache_map;
255  elm_cache_map.init(eval_points);
256 
257  // Definition of fields
258  Field<3, FieldValue<3>::Scalar > f_scal;
259  Field<3, FieldValue<3>::VectorFixed > f_vec;
260  Field<3, FieldValue<3>::VectorFixed > result;
261  ... // fill data to fields f_scal, f_vec
262 
263  // create instance FieldModel class, use helper method Model::create to simply passsing of parameters
264  auto f_product = Model<3, FieldValue<3>::VectorFixed>::create(FnProduct(), f_scal, f_vec);
265  // set field on all regions
266  result.set_mesh( *mesh );
267  result.set(f_product, time);
268  result.cache_reallocate(elm_cache_map);
269  result.set_time(tg.step(), LimitSide::right);
270 
271  // cache_update
272  result.cache_update(elm_cache_map);
273  @endcode
274  *
275  */
276 template<int spacedim, class Value, typename Fn, class ... InputFields>
277 class FieldModel : public FieldAlgorithmBase<spacedim, Value>
278 {
279 private:
280  Fn fn;
281  typedef std::tuple<InputFields...> FieldsTuple;
283 
284 public:
286 
287  FieldModel(Fn func, InputFields... args)
288  : fn(func), input_fields( std::forward_as_tuple((args)...) )
289  {}
290 
291  /// Implements FieldAlgoBase::set_dependency
293  return detail::get_dependency<
294  decltype(input_fields),
296  >::eval(input_fields);
297  }
298 
299  /// Implements FieldAlgoBase::cache_update
301  ElementCacheMap &cache_map, unsigned int region_patch_idx) override {
302  unsigned int reg_chunk_begin = cache_map.region_chunk_begin(region_patch_idx);
303  unsigned int reg_chunk_end = cache_map.region_chunk_end(region_patch_idx);
304  for(unsigned int i_cache=reg_chunk_begin; i_cache<reg_chunk_end; ++i_cache) {
305  data_cache.set(i_cache) =
307  Fn,
308  decltype(input_fields),
310  >::eval(i_cache, fn, input_fields);
311  }
312  }
313 
314  /// Implementation of virtual method
315  typename Value::return_type const &value(const Point &p, const ElementAccessor<spacedim> &elm) override {
317  spacedim, Value, Fn, decltype(input_fields), std::tuple_size<FieldsTuple>::value
318  >::eval(p, elm, fn, input_fields);
319  return this->r_value_;
320  }
321 
322  /// Implementation of virtual method
323  void value_list(const Armor::array &point_list, const ElementAccessor<spacedim> &elm,
325  ASSERT_EQ(point_list.size(), value_list.size()).error("Different size of point list and value list.\n");
326 
327  for (uint i=0; i<point_list.size(); ++i)
328  value_list[i] = this->value(point_list.template mat<Value::NRows_, Value::NCols_>(i), elm);
329  }
330 
331 };
332 
333 
334 /**
335  * Auxiliary class to avoid explicit specification of constructor template parameters.
336  */
337 template<int spacedim, class Value>
338 class Model {
339 public:
341  typedef std::shared_ptr< FieldBaseType > FieldBasePtr;
342 
343  /**
344  * Fn is a functor class and fn its instance.
345  */
346  template<typename Fn, class ... InputFields>
347  //static auto create(Fn *fn, InputFields&&... inputs) -> decltype(auto)
348  static auto create(Fn fn, InputFields&&... inputs) -> decltype(auto)
349  {
350  return std::make_shared<FieldModel<spacedim, Value, Fn, InputFields...>>(fn, std::forward<InputFields>(inputs)...);
351  }
352 
353 
354 
355  template<typename Function, typename Tuple, size_t ... I>
356  static auto call_create(Function f, Tuple t, std::index_sequence<I ...>)
357  {
358  return create(f, std::get<I>(t) ...);
359  }
360 
361  /**
362  * Fn is a functor class and fn its instance.
363  */
364  template<typename Fn, class ... InputFields>
365  //static auto create_multi(Fn *fn, InputFields&&... inputs) -> decltype(auto)
366  static auto create_multi(Fn fn, InputFields&&... inputs) -> decltype(auto)
367  {
368  typedef std::tuple<InputFields...> FieldTuple;
369  FieldTuple field_tuple = std::forward_as_tuple((inputs)...);
370  constexpr uint n_inputs = sizeof...(InputFields);
372  ASSERT(n_comp > 0);
373  std::vector<FieldBasePtr> result_components;
374  for(uint i=0; i<n_comp; i++) {
375  const auto & component_of_inputs = detail::get_components< FieldTuple, n_inputs>::eval(field_tuple, i);
376  //const auto & all_args = std::tuple_cat(std::make_tuple(fn), component_of_inputs);
377  //FieldBasePtr component_field = detail::call(create<Fn, InputFields&&...>, all_args);
378 
379  FieldBasePtr component_field = call_create(fn, component_of_inputs, std::make_index_sequence<n_inputs>{});
380  result_components.push_back(component_field);
381  }
382 
383  return result_components;
384  }
385 };
386 
387 
388 
389 
390 
391 
392 
393 
394 
395 
396 #endif /* FIELD_MODEL_HH_ */
FieldModel::fn
Fn fn
Definition: field_model.hh:280
detail::model_cache_item
base case for building up arguments for the function call
Definition: field.hh:63
fmt::internal::get
T & get()
detail::model_cache_item< CALLABLE, FIELD_TUPLE, 0 >::eval
static auto eval(FMT_UNUSED int i_cache, CALLABLE f, FMT_UNUSED FIELD_TUPLE fields, Vs &&... args) -> decltype(auto)
Definition: field_model.hh:80
Armor::vec
ArmaVec< double, N > vec
Definition: armor.hh:885
detail::field_component
auto field_component(const MultiField< spacedim, Value > &f, uint i_comp) -> decltype(auto)
Definition: field_model.hh:132
field_algo_base.hh
ASSERT
#define ASSERT(expr)
Definition: asserts.hh:351
ElementCacheMap
Directing class of FieldValueCache.
Definition: field_value_cache.hh:151
detail::call
auto call(Function f, Tuple t)
Definition: field_model.hh:230
value
static constexpr bool value
Definition: json.hpp:87
detail
Definition: field.hh:60
std::vector< const FieldCommon * >
ElementAccessor
Definition: dh_cell_accessor.hh:32
FieldModel::value
const Value::return_type & value(const Point &p, const ElementAccessor< spacedim > &elm) override
Implementation of virtual method.
Definition: field_model.hh:315
FieldModel::FieldsTuple
std::tuple< InputFields... > FieldsTuple
Definition: field_model.hh:281
FieldModel::input_fields
FieldsTuple input_fields
Definition: field_model.hh:282
uint
unsigned int uint
Definition: mh_dofhandler.hh:101
FieldAlgorithmBase::Point
Space< spacedim >::Point Point
Definition: field_algo_base.hh:115
detail::n_components< FIELD_TUPLE, 0 >::eval
static uint eval(FMT_UNUSED FIELD_TUPLE fields, uint n_comp)
Definition: field_model.hh:108
FieldModel::Point
FieldAlgorithmBase< spacedim, Value >::Point Point
Definition: field_model.hh:285
Model::create_multi
static auto create_multi(Fn fn, InputFields &&... inputs) -> decltype(auto)
Definition: field_model.hh:366
ElementCacheMap::region_chunk_end
unsigned int region_chunk_end(unsigned int region_patch_idx) const
Return end position of region chunk in FieldValueCache.
Definition: field_value_cache.hh:257
detail::field_value::Point
FieldAlgorithmBase< spacedim, Value >::Point Point
Definition: field_model.hh:202
detail::get_dependency
Definition: field_model.hh:180
ASSERT_PERMANENT
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:348
FieldModel::value_list
void value_list(const Armor::array &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list) override
Implementation of virtual method.
Definition: field_model.hh:323
field_values.hh
detail::get_components
Definition: field_model.hh:153
detail::field_value< spacedim, Value, CALLABLE, FIELD_TUPLE, 0 >::eval
static auto eval(FMT_UNUSED const Point &p, FMT_UNUSED const ElementAccessor< spacedim > &elm, CALLABLE f, FMT_UNUSED FIELD_TUPLE fields, Vs &&... args) -> decltype(auto)
Definition: field_model.hh:221
ASSERT_EQ
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
detail::field_value::eval
static auto eval(const Point &p, const ElementAccessor< spacedim > &elm, CALLABLE f, FIELD_TUPLE fields, Vs &&... args) -> decltype(auto)
Definition: field_model.hh:205
FieldSet
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:159
Armor::Array::set
ArrayMatSet set(uint index)
Definition: armor.hh:838
Model::FieldBasePtr
std::shared_ptr< FieldBaseType > FieldBasePtr
Definition: field_model.hh:341
Armor::Array::size
unsigned int size() const
Definition: armor.hh:728
detail::field_value
Definition: field_model.hh:200
Value
@ Value
Definition: finite_element.hh:43
FieldModel::cache_update
void cache_update(FieldValueCache< typename Value::element_type > &data_cache, ElementCacheMap &cache_map, unsigned int region_patch_idx) override
Implements FieldAlgoBase::cache_update.
Definition: field_model.hh:300
ElementCacheMap::region_chunk_begin
unsigned int region_chunk_begin(unsigned int region_patch_idx) const
Return begin position of region chunk in FieldValueCache.
Definition: field_value_cache.hh:251
detail::get_dependency::eval
static std::vector< const FieldCommon * > eval(FIELD_TUPLE fields)
Definition: field_model.hh:181
multi_field.hh
FieldAlgorithmBase
Definition: field_algo_base.hh:112
Model
Definition: field_model.hh:338
detail::field_value< spacedim, Value, CALLABLE, FIELD_TUPLE, 0 >::Point
FieldAlgorithmBase< spacedim, Value >::Point Point
Definition: field_model.hh:218
std
Definition: doxy_dummy_defs.hh:5
MultiField
Class for representation of a vector of fields of the same physical quantity.
Definition: multi_field.hh:87
detail::get_dependency< FIELD_TUPLE, 0 >::eval
static std::vector< const FieldCommon * > eval(FMT_UNUSED FIELD_TUPLE fields)
Definition: field_model.hh:191
FieldModel::FieldModel
FieldModel(Fn func, InputFields... args)
Definition: field_model.hh:287
field_value_cache.hh
detail::get_components< FIELD_TUPLE, 0 >::eval
static auto eval(FMT_UNUSED FIELD_TUPLE fields, FMT_UNUSED uint n_comp) -> decltype(auto)
Definition: field_model.hh:167
detail::n_components::eval
static uint eval(FIELD_TUPLE fields, uint n_comp)
Definition: field_model.hh:94
Model::call_create
static auto call_create(Function f, Tuple t, std::index_sequence< I ... >)
Definition: field_model.hh:356
Armor::Array
Definition: armor.hh:597
FieldAlgorithmBase::r_value_
Value::return_type r_value_
Definition: field_algo_base.hh:281
Model::create
static auto create(Fn fn, InputFields &&... inputs) -> decltype(auto)
Definition: field_model.hh:348
FieldModel
Definition: field_model.hh:277
detail::get_components::eval
static auto eval(FIELD_TUPLE fields, uint i_comp) -> decltype(auto)
Definition: field_model.hh:154
Field
Class template representing a field with values dependent on: point, element, and region.
Definition: field.hh:91
FieldModel::set_dependency
std::vector< const FieldCommon * > set_dependency(FMT_UNUSED FieldSet &field_set)
Implements FieldAlgoBase::set_dependency.
Definition: field_model.hh:292
Model::FieldBaseType
FieldAlgorithmBase< spacedim, Value > FieldBaseType
Definition: field_model.hh:340
detail::n_components
Definition: field_model.hh:93
posix.h
detail::model_cache_item::eval
static auto eval(int i_cache, CALLABLE f, FIELD_TUPLE fields, Vs &&... args) -> decltype(auto)
Definition: field_model.hh:66
field.hh
field_common.hh
FMT_UNUSED
#define FMT_UNUSED
Definition: posix.h:75