Flow123d  JS_before_hm-1576-g4d0b70e
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_DBG(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(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(!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 
200  template<typename Function, typename Tuple>
201  auto call(Function f, Tuple t)
202  {
203  }
204 }
205 
206 
207 /**
208  * Class representing field computing form results of other fields.
209  *
210  * Example of usage:
211  @code
212  // Functor class with defined operator ()
213  class FnProduct {
214  public:
215  Vector operator() (Scalar a, Vector v) {
216  return a(0) * v;
217  }
218  };
219 
220  ...
221 
222  // Create ElementCacheMap
223  std::shared_ptr<EvalPoints> eval_points = std::make_shared<EvalPoints>();
224  eval_poinzs->add_bulk<3>( quad ); // initialize EvalPoints
225  ElementCacheMap elm_cache_map;
226  elm_cache_map.init(eval_points);
227 
228  // Definition of fields
229  Field<3, FieldValue<3>::Scalar > f_scal;
230  Field<3, FieldValue<3>::VectorFixed > f_vec;
231  Field<3, FieldValue<3>::VectorFixed > result;
232  ... // fill data to fields f_scal, f_vec
233 
234  // create instance FieldModel class, use helper method Model::create to simply passsing of parameters
235  auto f_product = Model<3, FieldValue<3>::VectorFixed>::create(FnProduct(), f_scal, f_vec);
236  // set field on all regions
237  result.set_mesh( *mesh );
238  result.set(f_product, time);
239  result.cache_reallocate(elm_cache_map);
240  result.set_time(tg.step(), LimitSide::right);
241 
242  // cache_update
243  result.cache_update(elm_cache_map);
244  @endcode
245  *
246  */
247 template<int spacedim, class Value, typename Fn, class ... InputFields>
248 class FieldModel : public FieldAlgorithmBase<spacedim, Value>
249 {
250 private:
251  Fn fn;
252  typedef std::tuple<InputFields...> FieldsTuple;
254 
255 public:
257 
258  FieldModel(Fn func, InputFields... args)
259  : fn(func), input_fields( std::forward_as_tuple((args)...) )
260  {}
261 
262  /// Implements FieldAlgoBase::set_dependency
264  return detail::get_dependency<
265  decltype(input_fields),
267  >::eval(input_fields);
268  }
269 
270  /// Implements FieldAlgoBase::cache_update
272  ElementCacheMap &cache_map, unsigned int region_patch_idx) override {
273  unsigned int reg_chunk_begin = cache_map.region_chunk_begin(region_patch_idx);
274  unsigned int reg_chunk_end = cache_map.region_chunk_end(region_patch_idx);
275  for(unsigned int i_cache=reg_chunk_begin; i_cache<reg_chunk_end; ++i_cache) {
276  data_cache.set(i_cache) =
278  Fn,
279  decltype(input_fields),
281  >::eval(i_cache, fn, input_fields);
282  }
283  }
284 
285  /// Implementation of virtual method
286  typename Value::return_type const &value(FMT_UNUSED const Point &p, FMT_UNUSED const ElementAccessor<spacedim> &elm) override {
287  ASSERT(false).error("Forbidden method!\n");
288  return this->r_value_;
289  }
290 
291  /// Implementation of virtual method
294  ASSERT(false).error("Forbidden method!\n");
295  }
296 
297 };
298 
299 
300 /**
301  * Auxiliary class to avoid explicit specification of constructor template parameters.
302  */
303 template<int spacedim, class Value>
304 class Model {
305 public:
307  typedef std::shared_ptr< FieldBaseType > FieldBasePtr;
308 
309  /**
310  * Fn is a functor class and fn its instance.
311  */
312  template<typename Fn, class ... InputFields>
313  //static auto create(Fn *fn, InputFields&&... inputs) -> decltype(auto)
314  static auto create(Fn fn, InputFields&&... inputs) -> decltype(auto)
315  {
316  return std::make_shared<FieldModel<spacedim, Value, Fn, InputFields...>>(fn, std::forward<InputFields>(inputs)...);
317  }
318 
319 
320 
321  template<typename Function, typename Tuple, size_t ... I>
322  static auto call_create(Function f, Tuple t, std::index_sequence<I ...>)
323  {
324  return create(f, std::get<I>(t) ...);
325  }
326 
327  /**
328  * Fn is a functor class and fn its instance.
329  */
330  template<typename Fn, class ... InputFields>
331  //static auto create_multi(Fn *fn, InputFields&&... inputs) -> decltype(auto)
332  static auto create_multi(Fn fn, InputFields&&... inputs) -> decltype(auto)
333  {
334  typedef std::tuple<InputFields...> FieldTuple;
335  FieldTuple field_tuple = std::forward_as_tuple((inputs)...);
336  constexpr uint n_inputs = sizeof...(InputFields);
338  ASSERT_DBG(n_comp > 0);
339  std::vector<FieldBasePtr> result_components;
340  for(uint i=0; i<n_comp; i++) {
341  const auto & component_of_inputs = detail::get_components< FieldTuple, n_inputs>::eval(field_tuple, i);
342  //const auto & all_args = std::tuple_cat(std::make_tuple(fn), component_of_inputs);
343  //FieldBasePtr component_field = detail::call(create<Fn, InputFields&&...>, all_args);
344 
345  FieldBasePtr component_field = call_create(fn, component_of_inputs, std::make_index_sequence<n_inputs>{});
346  result_components.push_back(component_field);
347  }
348 
349  return result_components;
350  }
351 };
352 
353 
354 
355 
356 
357 
358 
359 
360 
361 
362 #endif /* FIELD_MODEL_HH_ */
static auto eval(FMT_UNUSED int i_cache, CALLABLE f, FMT_UNUSED FIELD_TUPLE fields, Vs &&...args) -> decltype(auto)
Definition: field_model.hh:80
static auto eval(int i_cache, CALLABLE f, FIELD_TUPLE fields, Vs &&...args) -> decltype(auto)
Definition: field_model.hh:66
unsigned int region_chunk_begin(unsigned int region_patch_idx) const
Return begin position of region chunk in FieldValueCache.
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:159
static auto create_multi(Fn fn, InputFields &&...inputs) -> decltype(auto)
Definition: field_model.hh:332
ArmaVec< double, N > vec
Definition: armor.hh:885
auto field_component(const MultiField< spacedim, Value > &f, uint i_comp) -> decltype(auto)
Definition: field_model.hh:132
unsigned int uint
static uint eval(FIELD_TUPLE fields, uint n_comp)
Definition: field_model.hh:94
Class template representing a field with values dependent on: point, element, and region...
Definition: field.hh:94
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:271
Directing class of FieldValueCache.
static auto call_create(Function f, Tuple t, std::index_sequence< I... >)
Definition: field_model.hh:322
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
void value_list(FMT_UNUSED const Armor::array &point_list, FMT_UNUSED const ElementAccessor< spacedim > &elm, FMT_UNUSED std::vector< typename Value::return_type > &value_list) override
Implementation of virtual method.
Definition: field_model.hh:292
static uint eval(FMT_UNUSED FIELD_TUPLE fields, uint n_comp)
Definition: field_model.hh:108
static auto create(Fn fn, InputFields &&...inputs) -> decltype(auto)
Definition: field_model.hh:314
std::shared_ptr< FieldBaseType > FieldBasePtr
Definition: field_model.hh:307
static constexpr bool value
Definition: json.hpp:87
std::vector< const FieldCommon * > set_dependency(FMT_UNUSED FieldSet &field_set)
Implements FieldAlgoBase::set_dependency.
Definition: field_model.hh:263
static std::vector< const FieldCommon * > eval(FMT_UNUSED FIELD_TUPLE fields)
Definition: field_model.hh:191
Value::return_type const & value(FMT_UNUSED const Point &p, FMT_UNUSED const ElementAccessor< spacedim > &elm) override
Implementation of virtual method.
Definition: field_model.hh:286
Definition: field.hh:63
#define FMT_UNUSED
Definition: posix.h:75
FieldModel(Fn func, InputFields...args)
Definition: field_model.hh:258
unsigned int region_chunk_end(unsigned int region_patch_idx) const
Return end position of region chunk in FieldValueCache.
ArrayMatSet set(uint index)
Definition: armor.hh:838
Space< spacedim >::Point Point
base case for building up arguments for the function call
Definition: field.hh:66
static auto eval(FMT_UNUSED FIELD_TUPLE fields, FMT_UNUSED uint n_comp) -> decltype(auto)
Definition: field_model.hh:167
FieldAlgorithmBase< spacedim, Value > FieldBaseType
Definition: field_model.hh:306
FieldsTuple input_fields
Definition: field_model.hh:253
#define ASSERT_DBG(expr)
static auto eval(FIELD_TUPLE fields, uint i_comp) -> decltype(auto)
Definition: field_model.hh:154
std::tuple< InputFields... > FieldsTuple
Definition: field_model.hh:252
static std::vector< const FieldCommon * > eval(FIELD_TUPLE fields)
Definition: field_model.hh:181
auto call(Function f, Tuple t)
Definition: field_model.hh:201
Class for representation of a vector of fields of the same physical quantity.
Definition: multi_field.hh:87
FieldAlgorithmBase< spacedim, Value >::Point Point
Definition: field_model.hh:256