Flow123d  JS_before_hm-915-gc632be9
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 
37 template <int spacedim> class ElementAccessor;
38 
39 
40 /**
41  * Wrapper for resolution of the overloaded functions passed as a parameter to the FieldModel.
42  *
43  * Example:
44  @code
45  double product(double x, double y) {...}
46  Vec product(double x, Vec y) {...}
47  Model<3, FieldValue<3>::VectorFixed>::create(wrapper_overload(product), f_scal, f_vec);
48  @endcode
49  *
50  * Should automaticaly resolve the second model_cache_item::eval function.
51  */
52 #define wrap_overload(func) [](auto&&... ps){ return func( std::forward<decltype(ps)>(ps)... ); }
53 
54 namespace detail
55 {
56  /**
57  * Extract cached values on index i_cache from the input fields and call given function on these values.
58  */
59 
60  /// base case for building up arguments for the function call
61  template< typename CALLABLE, typename FIELD_TUPLE, int INDEX >
62  struct model_cache_item
63  {
64  template< typename... Vs >
65  static auto eval(int i_cache, CALLABLE f, FIELD_TUPLE fields, Vs&&... args) -> decltype(auto) {
66  const auto &single_field = std::get < INDEX - 1 > (std::forward<decltype(fields)>(fields));
68  i_cache, f, std::forward<decltype(fields)>(fields),
69  single_field[i_cache], std::forward<Vs>(args)...);
70 
71  }
72  };
73 
74  /// terminal case - do the actual function call
75  template< typename CALLABLE, typename FIELD_TUPLE >
76  struct model_cache_item< CALLABLE, FIELD_TUPLE, 0 >
77  {
78  template< typename... Vs >
79  static auto eval(int i_cache, CALLABLE f, FIELD_TUPLE fields, Vs&&... args) -> decltype(auto)
80  {
81  return f(std::forward<Vs>(args)...);
82  };
83  };
84 
85  /**
86  * Check common number of components of the input fields/multifields.
87  * Return number of components.
88  * Return 0 for no multifields.
89  * Throw for different number of components.
90  */
91  template<typename FIELD_TUPLE, int INDEX >
92  struct n_components {
93  static uint eval(FIELD_TUPLE fields, uint n_comp) {
94  const auto &single_field = std::get < INDEX - 1 > (std::forward<decltype(fields)>(fields));
95  uint n_comp_new = single_field.n_comp();
96  if (n_comp == 0) {
97  n_comp = n_comp_new;
98  } else {
99  ASSERT_DBG(n_comp == n_comp_new);
100  }
101  return n_components<FIELD_TUPLE, INDEX - 1>::eval(std::forward<decltype(fields)>(fields), n_comp);
102  };
103  };
104 
105  template<typename FIELD_TUPLE>
106  struct n_components<FIELD_TUPLE, 0> {
107  static uint eval(FIELD_TUPLE fields, uint n_comp)
108  {
109  return n_comp;
110  };
111  };
112 
113 
114  /**
115  * Return component 'i_comp' of the multifield 'f' or the field 'f'.
116  */
117  /*template<class FIELD>
118  auto field_component(FIELD f, uint i_comp) -> decltype(auto)
119  {
120  if (f.is_multifield()) {
121  return f[i_comp];
122  } else {
123  return f;
124  }
125  }*/
126 
127  /**
128  * Return component 'i_comp' of the multifield 'f'.
129  */
130  template<int spacedim, class Value>
131  auto field_component(const MultiField<spacedim, Value> &f, uint i_comp) -> decltype(auto)
132  {
133  ASSERT(f.is_multifield());
134  return f[i_comp];
135  }
136 
137  /**
138  * Return the field 'f'. Variant to previous method.
139  */
140  template<int spacedim, class Value>
141  auto field_component(const Field<spacedim, Value> &f, uint i_comp) -> decltype(auto)
142  {
143  ASSERT(!f.is_multifield());
144  return f;
145  }
146 
147  /**
148  * For given tuple of fields/multifields and given component index
149  * return the tuple of the selected components.
150  */
151  template<typename FIELD_TUPLE, int INDEX>
152  struct get_components {
153  static auto eval(FIELD_TUPLE fields, uint i_comp) -> decltype(auto)
154  {
155  const auto &single_field = std::get < INDEX - 1 > (std::forward<decltype(fields)>(fields));
156  return std::tuple_cat(
157  std::forward_as_tuple(field_component(single_field, i_comp)),
159  std::forward<decltype(fields)>(fields), i_comp)
160  );
161  };
162  };
163 
164  template<typename FIELD_TUPLE>
165  struct get_components<FIELD_TUPLE, 0> {
166  static auto eval(FIELD_TUPLE fields, uint n_comp) -> decltype(auto)
167  {
168  return std::forward_as_tuple<>();
169  };
170  };
171 
172 
173 
174 
175  template<typename Function, typename Tuple>
176  auto call(Function f, Tuple t)
177  {
178  }
179 }
180 
181 
182 /**
183  * Class representing field computing form results of other fields.
184  *
185  * Example of usage:
186  @code
187  // Functor class with defined operator ()
188  class FnProduct {
189  public:
190  Vector operator() (Scalar a, Vector v) {
191  return a(0) * v;
192  }
193  };
194 
195  ...
196 
197  // Create ElementCacheMap
198  std::shared_ptr<EvalPoints> eval_points = std::make_shared<EvalPoints>();
199  eval_poinzs->add_bulk<3>( quad ); // initialize EvalPoints
200  ElementCacheMap elm_cache_map;
201  elm_cache_map.init(eval_points);
202 
203  // Definition of fields
204  Field<3, FieldValue<3>::Scalar > f_scal;
205  Field<3, FieldValue<3>::VectorFixed > f_vec;
206  Field<3, FieldValue<3>::VectorFixed > result;
207  ... // fill data to fields f_scal, f_vec
208 
209  // create instance FieldModel class, use helper method Model::create to simply passsing of parameters
210  auto f_product = Model<3, FieldValue<3>::VectorFixed>::create(FnProduct(), f_scal, f_vec);
211  // set field on all regions
212  result.set_mesh( *mesh );
213  result.set_field(mesh->region_db().get_region_set("ALL"), f_product);
214  result.cache_allocate(eval_points);
215  result.set_time(tg.step(), LimitSide::right);
216 
217  // cache_update
218  result.cache_update(elm_cache_map);
219  @endcode
220  *
221  */
222 template<int spacedim, class Value, typename Fn, class ... InputFields>
223 class FieldModel : public FieldAlgorithmBase<spacedim, Value>
224 {
225 private:
226  Fn* fn;
227  typedef std::tuple<InputFields...> FieldsTuple;
229 
230 public:
232 
233  FieldModel(Fn* func, InputFields... args)
234  : fn(func), input_fields( std::forward_as_tuple((args)...) )
235  {}
236 
237 
238 
239 
241  ElementCacheMap &cache_map, unsigned int region_idx) override {
242  auto update_cache_data = cache_map.update_cache_data();
243  unsigned int region_in_cache = update_cache_data.region_cache_indices_range_.find(region_idx)->second;
244  unsigned int i_cache_el_begin = update_cache_data.region_value_cache_range_[region_in_cache];
245  unsigned int i_cache_el_end = update_cache_data.region_value_cache_range_[region_in_cache+1];
246  for(unsigned int i_cache=i_cache_el_begin; i_cache<i_cache_el_end; ++i_cache) {
247  data_cache.data().set(i_cache) =
249  Fn,
250  decltype(input_fields),
252  >::eval(i_cache, fn, input_fields);
253  }
254  }
255 
256  /// Implementation of virtual method
257  typename Value::return_type const &value(const Point &p, const ElementAccessor<spacedim> &elm) override {
258  ASSERT(false).error("Forbidden method!\n");
259  return this->r_value_;
260  }
261 
262  /// Implementation of virtual method
263  void value_list(const Armor::array &point_list, const ElementAccessor<spacedim> &elm,
264  std::vector<typename Value::return_type> &value_list) override {
265  ASSERT(false).error("Forbidden method!\n");
266  }
267 
268 };
269 
270 
271 /**
272  * Auxiliary class to avoid explicit specification of constructor template parameters.
273  */
274 template<int spacedim, class Value>
275 class Model {
276 public:
278  typedef std::shared_ptr< FieldBaseType > FieldBasePtr;
279 
280  template<typename Fn, class ... InputFields>
281  static auto create(Fn *fn, InputFields&&... inputs) -> decltype(auto)
282  {
283  return std::make_shared<FieldModel<spacedim, Value, Fn, InputFields...>>(fn, std::forward<InputFields>(inputs)...);
284  }
285 
286 
287 
288  template<typename Function, typename Tuple, size_t ... I>
289  static auto call_create(Function f, Tuple t, std::index_sequence<I ...>)
290  {
291  return create(f, std::get<I>(t) ...);
292  }
293 
294  template<typename Fn, class ... InputFields>
295  static auto create_multi(Fn *fn, InputFields&&... inputs) -> decltype(auto)
296  {
297  typedef std::tuple<InputFields...> FieldTuple;
298  FieldTuple field_tuple = std::forward_as_tuple((inputs)...);
299  constexpr uint n_inputs = sizeof...(InputFields);
301  ASSERT_DBG(n_comp > 0);
302  std::vector<FieldBasePtr> result_components;
303  for(uint i=0; i<n_comp; i++) {
304  const auto & component_of_inputs = detail::get_components< FieldTuple, n_inputs>::eval(field_tuple, i);
305  //const auto & all_args = std::tuple_cat(std::make_tuple(fn), component_of_inputs);
306  //FieldBasePtr component_field = detail::call(create<Fn, InputFields&&...>, all_args);
307 
308  FieldBasePtr component_field = call_create(fn, component_of_inputs, std::make_index_sequence<n_inputs>{});
309  result_components.push_back(component_field);
310  }
311 
312  return result_components;
313  }
314 };
315 
316 
317 
318 
319 
320 
321 
322 
323 
324 
325 #endif /* FIELD_MODEL_HH_ */
static auto eval(int i_cache, CALLABLE f, FIELD_TUPLE fields, Vs &&...args) -> decltype(auto)
Definition: field_model.hh:65
auto field_component(const MultiField< spacedim, Value > &f, uint i_comp) -> decltype(auto)
Definition: field_model.hh:131
unsigned int uint
static uint eval(FIELD_TUPLE fields, uint n_comp)
Definition: field_model.hh:93
const UpdateCacheHelper & update_cache_data() const
Return update cache data helper.
Class template representing a field with values dependent on: point, element, and region...
Definition: field.hh:92
void cache_update(FieldValueCache< typename Value::element_type > &data_cache, ElementCacheMap &cache_map, unsigned int region_idx) override
Definition: field_model.hh:240
FieldModel(Fn *func, InputFields...args)
Definition: field_model.hh:233
Directing class of FieldValueCache.
static auto eval(FIELD_TUPLE fields, uint n_comp) -> decltype(auto)
Definition: field_model.hh:166
static auto call_create(Function f, Tuple t, std::index_sequence< I... >)
Definition: field_model.hh:289
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
std::shared_ptr< FieldBaseType > FieldBasePtr
Definition: field_model.hh:278
static constexpr bool value
Definition: json.hpp:87
static uint eval(FIELD_TUPLE fields, uint n_comp)
Definition: field_model.hh:107
Definition: field.hh:61
const Armor::Array< elm_type > & data() const
Return data vector.
std::unordered_map< unsigned int, unsigned int > region_cache_indices_range_
Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) override
Implementation of virtual method.
Definition: field_model.hh:257
ArrayMatSet set(uint index)
Definition: armor.hh:821
Space< spacedim >::Point Point
base case for building up arguments for the function call
Definition: field.hh:64
FieldAlgorithmBase< spacedim, Value > FieldBaseType
Definition: field_model.hh:277
static auto create_multi(Fn *fn, InputFields &&...inputs) -> decltype(auto)
Definition: field_model.hh:295
FieldsTuple input_fields
Definition: field_model.hh:228
static auto eval(int i_cache, CALLABLE f, FIELD_TUPLE fields, Vs &&...args) -> decltype(auto)
Definition: field_model.hh:79
#define ASSERT_DBG(expr)
static auto eval(FIELD_TUPLE fields, uint i_comp) -> decltype(auto)
Definition: field_model.hh:153
std::tuple< InputFields... > FieldsTuple
Definition: field_model.hh:227
auto call(Function f, Tuple t)
Definition: field_model.hh:176
Class for representation of a vector of fields of the same physical quantity.
Definition: multi_field.hh:89
static auto create(Fn *fn, InputFields &&...inputs) -> decltype(auto)
Definition: field_model.hh:281
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:263
FieldAlgorithmBase< spacedim, Value >::Point Point
Definition: field_model.hh:231