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