Flow123d  release_3.0.0-695-g67d21c4
element_data_cache.cc
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 element_data_cache.cc
15  * @brief
16  */
17 
18 
19 #include <limits>
20 #include <ostream>
21 #include "io/element_data_cache.hh"
22 #include "io/msh_basereader.hh"
24 #include "system/system.hh"
25 #include "system/tokenizer.hh"
26 #include "boost/lexical_cast.hpp"
27 
28 
29 
30 template <typename T>
33  check_scale_data_(CheckScaleData::none) {}
34 
35 
36 template <typename T>
37 ElementDataCache<T>::ElementDataCache(std::string field_name, double time, unsigned int size_of_cache, unsigned int row_vec_size)
39 {
40  this->time_ = time;
41  this->field_input_name_ = field_name;
42  this->data_ = create_data_cache(size_of_cache, row_vec_size);
43 }
44 
45 
46 template <typename T>
47 ElementDataCache<T>::ElementDataCache(std::string field_name, unsigned int n_rows, unsigned int n_cols, unsigned int size)
49 {
50  this->set_vtk_type<T>();
51  this->field_name_ = field_name;
52  this->field_input_name_ = this->field_name_;
53 
54  this->n_values_ = size;
55 
56  if (n_cols == 1) {
57  if (n_rows == 1) {
58  this->n_elem_ = N_SCALAR;
59  } else {
60  if (n_rows > 1) {
61  if (n_rows > 3) {
63  "Do not support output of vectors with fixed size >3. Field: %s\n",
64  this->field_input_name_.c_str());
65  } else {
66  this->n_elem_ = N_VECTOR;
67  }
68  } else {
69  THROW(ExcOutputVariableVector() << EI_FieldName(this->field_input_name_));
70  }
71  }
72  } else {
73  this->n_elem_ = N_TENSOR;
74  }
75 
77 }
78 
79 
80 template <typename T>
82 
83 
84 template <typename T>
86  ASSERT_LT(component_idx, data_.size()).error("Index of component is out of range.\n");
87  return data_[component_idx];
88 }
89 
90 
91 template <typename T>
92 typename ElementDataCache<T>::CacheData ElementDataCache<T>::create_data_cache(unsigned int size_of_cache, unsigned int row_vec_size) {
93  typename ElementDataCache<T>::CacheData data_cache(size_of_cache);
94  for (unsigned int i=0; i<size_of_cache; ++i) {
95  typename ElementDataCache<T>::ComponentDataPtr row_vec = std::make_shared<std::vector<T>>();
96  row_vec->resize(row_vec_size, numeric_limits<T>::signaling_NaN());
97  data_cache[i] = row_vec;
98  }
99 
100  return data_cache;
101 }
102 
103 
104 template <typename T>
105 void ElementDataCache<T>::read_ascii_data(Tokenizer &tok, unsigned int n_components, unsigned int i_row) {
106  unsigned int idx;
107  for (unsigned int i_vec=0; i_vec<data_.size(); ++i_vec) {
108  idx = i_row * n_components;
109  std::vector<T> &vec = *( data_[i_vec].get() );
110  for (unsigned int i_col=0; i_col < n_components; ++i_col, ++idx) {
111  vec[idx] = boost::lexical_cast<T>(*tok);
112  ++tok;
113  }
114  }
115 }
116 
117 
118 template <typename T>
119 void ElementDataCache<T>::read_binary_data(std::istream &data_stream, unsigned int n_components, unsigned int i_row) {
120  unsigned int idx;
121  for (unsigned int i_vec=0; i_vec<data_.size(); ++i_vec) {
122  idx = i_row * n_components;
123  std::vector<T> &vec = *( data_[i_vec].get() );
124  for (unsigned int i_col=0; i_col < n_components; ++i_col, ++idx) {
125  data_stream.read(reinterpret_cast<char *>(&vec[idx]), sizeof(T));
126  }
127  }
128 }
129 
130 
131 /**
132  * Output data element on given index @p idx. Method for writing data
133  * to output stream.
134  *
135  * \note This method is used only by MSH file format.
136  */
137 template <typename T>
138 void ElementDataCache<T>::print_ascii(ostream &out_stream, unsigned int idx)
139 {
140  ASSERT_LT(idx, this->n_values_).error();
141  std::vector<T> &vec = *( this->data_[0].get() );
142  for(unsigned int i = n_elem_*idx; i < n_elem_*(idx+1); ++i )
143  out_stream << vec[i] << " ";
144 }
145 
146 /**
147  * \brief Print all data stored in output data
148  *
149  * TODO: indicate if the tensor data are output in column-first or raw-first order
150  * and possibly implement transposition. Set such property for individual file formats.
151  * Class OutputData stores always in raw-first order.
152  */
153 template <typename T>
154 void ElementDataCache<T>::print_ascii_all(ostream &out_stream)
155 {
156  std::vector<T> &vec = *( this->data_[0].get() );
157  for(unsigned int idx = 0; idx < this->n_values_; idx++) {
158  for(unsigned int i = n_elem_*idx; i < n_elem_*(idx+1); ++i )
159  out_stream << vec[i] << " ";
160  }
161 }
162 
163 
164 /// Prints the whole data vector into stream.
165 template <typename T>
166 void ElementDataCache<T>::print_binary_all(ostream &out_stream, bool print_data_size)
167 {
168  if (print_data_size) {
169  // write size of data
170  unsigned long long int data_byte_size = this->n_values_ * n_elem_ * sizeof(T);
171  out_stream.write(reinterpret_cast<const char*>(&data_byte_size), sizeof(unsigned long long int));
172  }
173  // write data
174  std::vector<T> &vec = *( this->data_[0].get() );
175  for(unsigned int idx = 0; idx < this->n_values_; idx++) {
176  for(unsigned int i = n_elem_*idx; i < n_elem_*(idx+1); ++i )
177  out_stream.write(reinterpret_cast<const char*>(&(vec[i])), sizeof(T));
178  }
179 }
180 
181 
182 template <typename T>
183 void ElementDataCache<T>::print_all_yaml(ostream &out_stream, unsigned int precision)
184 {
185  out_stream << "[ ";
186  std::vector<T> &vec = *( this->data_[0].get() );
187  for(unsigned int idx = 0; idx < this->n_values_; idx++) {
188  if (idx != 0) out_stream << " , ";
189  unsigned int vec_pos = n_elem_ * idx; // position of element value in data cache
190  switch (this->n_elem_) {
191  case NumCompValueType::N_SCALAR: {
192  out_stream << field_value_to_yaml( vec[vec_pos], precision );
193  break;
194  }
195  case NumCompValueType::N_VECTOR: {
196  typename arma::Col<T>::template fixed<3> vec_val;
197  for (unsigned int i=0; i<3; ++i, ++vec_pos)
198  vec_val(i) = vec[vec_pos];
199  out_stream << field_value_to_yaml( vec_val, precision );
200  break;
201  }
202  case NumCompValueType::N_TENSOR: {
203  typename arma::Mat<T>::template fixed<3,3> mat_val;
204  for (unsigned int i=0; i<3; ++i)
205  for (unsigned int j=0; j<3; ++j, ++vec_pos)
206  mat_val(i,j) = vec[vec_pos];
207  out_stream << field_value_to_yaml( mat_val, precision );
208  break;
209  }
210  }
211  }
212  out_stream << " ]";
213 }
214 
215 
216 template <typename T>
217 void ElementDataCache<T>::get_min_max_range(double &min, double &max)
218 {
219  min = std::numeric_limits<double>::max();
220  max = std::numeric_limits<double>::min();
221  std::vector<T> &vec = *( this->data_[0].get() );
222  for(unsigned int idx = 0; idx < this->n_values_; idx++) {
223  for(unsigned int i = n_elem_*idx; i < n_elem_*(idx+1); ++i ) {
224  if (vec[i] < min) min = vec[i];
225  if (vec[i] > max) max = vec[i];
226  }
227  }
228 }
229 
230 
231 /**
232  * Store data element of given data value under given index.
233  */
234 template <typename T>
235 void ElementDataCache<T>::store_value(unsigned int idx, const T * value) {
236  ASSERT_LT_DBG(idx, this->n_values_);
237  std::vector<T> &vec = *( this->data_[0].get() );
238  unsigned int vec_idx = idx*this->n_elem_;
239  for(unsigned int i = 0; i < this->n_elem_; i++, vec_idx++) {
240  vec[vec_idx] = value[i];
241  }
242 };
243 
244 /**
245  * Add value to given index
246  */
247 template <typename T>
248 void ElementDataCache<T>::add(unsigned int idx, const T * value) {
249  ASSERT_LT_DBG(idx, this->n_values_);
250  std::vector<T> &vec = *( this->data_[0].get() );
251  unsigned int vec_idx = idx*this->n_elem_;
252  for(unsigned int i = 0; i < this->n_elem_; i++, vec_idx++) {
253  vec[vec_idx] += value[i];
254  }
255 };
256 
257 /**
258  * Reset values at given index
259  */
260 template <typename T>
261 void ElementDataCache<T>::zero(unsigned int idx) {
262  ASSERT_LT_DBG(idx, this->n_values_);
263  std::vector<T> &vec = *( this->data_[0].get() );
264  unsigned int vec_idx = idx*this->n_elem_;
265  for(unsigned int i = 0; i < this->n_elem_; i++, vec_idx++) {
266  vec[vec_idx] = 0;
267  }
268 };
269 
270 /**
271  * Normalize values at given index
272  */
273 template <typename T>
274 void ElementDataCache<T>::normalize(unsigned int idx, unsigned int divisor) {
275  ASSERT_LT_DBG(idx, this->n_values_);
276  std::vector<T> &vec = *( this->data_[0].get() );
277  unsigned int vec_idx = idx*this->n_elem_;
278  for(unsigned int i = 0; i < this->n_elem_; i++, vec_idx++) {
279  vec[vec_idx] /= divisor;
280  }
281 };
282 
283 template <typename T>
284 CheckResult ElementDataCache<T>::check_values(double default_val, double lower_bound, double upper_bound) {
285  if (check_scale_data_ != CheckScaleData::none) return CheckResult::ok; // method is executed only once
287 
288  bool is_nan = false, out_of_limit = false;
289  for (unsigned int j=0; j<data_.size(); ++j) {
290  std::vector<T> &vec = *( this->data_[j].get() );
291  for(unsigned int i=0; i<vec.size(); ++i) {
292  if ( std::isnan(vec[i]) ) {
293  if ( std::isnan(default_val) ) is_nan = true;
294  else vec[i] = default_val;
295  }
296  if ( (vec[i] < lower_bound) || (vec[i] > upper_bound) ) out_of_limit = true;
297  }
298  }
299 
300  if (is_nan) return CheckResult::not_a_number;
301  else if (out_of_limit) return CheckResult::out_of_limits;
302  else return CheckResult::ok;
303 };
304 
305 template <typename T>
307  if (check_scale_data_ == CheckScaleData::scale) return; // method is executed only once
308  ASSERT_DBG(check_scale_data_ == CheckScaleData::check).warning("Data should be checked before scaling. Rather call 'check_values'!\n");
309 
310  for (unsigned int j=0; j<data_.size(); ++j) {
311  std::vector<T> &vec = *( this->data_[j].get() );
312  for(unsigned int i=0; i<vec.size(); ++i) {
313  vec[i] *= coef;
314  }
315  }
316 
317  check_scale_data_ = CheckScaleData::scale;
318 };
319 
320 /// Access i-th element in the data vector.
321 template <class T>
323 {
324  std::vector<T> &vec = *( this->data_[0].get() );
325  ASSERT_DBG(i < vec.size());
326  return vec[i];
327 }
328 
329 
330 
331 // explicit instantiation of template class
332 template class ElementDataCache<unsigned int>;
333 template class ElementDataCache<int>;
334 template class ElementDataCache<double>;
double time_
time step stored in cache
void read_binary_data(std::istream &data_stream, unsigned int n_components, unsigned int i_row) override
Implements ElementDataCacheBase::read_binary_data.
std::shared_ptr< std::vector< T > > ComponentDataPtr
CheckScaleData
Allow to hold sign, if data in cache is checked and scale (both can be executed only once) ...
void print_ascii(ostream &out_stream, unsigned int idx) override
string field_value_to_yaml(const T &mat, unsigned int prec)
CheckScaleData check_scale_data_
Sign, if data in cache is checked and scale.
Some value(s) is set to NaN.
void store_value(unsigned int idx, const T *value)
T & operator[](unsigned int i)
Access i-th element in the data vector of 0th component.
void read_ascii_data(Tokenizer &tok, unsigned int n_components, unsigned int i_row) override
Implements ElementDataCacheBase::read_ascii_data.
Some value(s) is out of limits.
static constexpr bool value
Definition: json.hpp:87
ElementDataCache()
Default constructor.
void get_min_max_range(double &min, double &max) override
void add(unsigned int idx, const T *value)
DummyInt isnan(...)
Definition: format.h:306
virtual ~ElementDataCache() override
Destructor of ElementDataCache.
static CacheData create_data_cache(unsigned int size_of_cache, unsigned int row_vec_size)
void zero(unsigned int idx)
#define xprintf(...)
Definition: system.hh:92
void scale_data(double coef)
void print_all_yaml(ostream &out_stream, unsigned int precision) override
Data is neither checked nor scaled.
CheckResult
Return type of method that checked data stored in ElementDataCache (NaN values, limits) ...
CheckResult check_values(double default_val, double lower_bound, double upper_bound)
void normalize(unsigned int idx, unsigned int divisor)
void print_binary_all(ostream &out_stream, bool print_data_size=true) override
Print all data stored in output data to appended binary format.
std::string field_input_name_
name of field stored in cache
Definition: system.hh:64
#define ASSERT_LT(a, b)
Definition of comparative assert macro (Less Than)
Definition: asserts.hh:295
ComponentDataPtr get_component_data(unsigned int component_idx)
Return vector of element data for get component.
#define ASSERT_DBG(expr)
Definition: asserts.hh:349
void print_ascii_all(ostream &out_stream) override
Print all data stored in output data ro ascii format.
All values are not NaN and are in limits.
T check(T value)
Definition: format.h:312
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
#define ASSERT_LT_DBG(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
Definition: asserts.hh:299