field.hpp
Go to the documentation of this file.
1 
7 #pragma once
8 
9 #include "basic.hpp"
10 #include <omp.h>
11 
12 namespace LCS {
13 
14 template <typename T, unsigned Dim, unsigned Size>
15 struct FieldPolicy;
16 
17 template <typename T, unsigned Dim>
18 class Position;
19 
20 template <typename T, unsigned Dim>
21 class Velocity;
22 
23 template <typename T, typename Func, unsigned Dim>
25 
26 
34 template <typename T, unsigned Dim = 2, unsigned Size = 2>
35 class Field
36 {
37  public:
42  Field(unsigned nx, unsigned ny): nx_(nx), ny_(ny), data_(nx, ny), time_() {}
43 
47  inline auto& GetAll() const
48  {
49  return data_;
50  }
51 
55  inline auto GetTime() const
56  {
57  return time_;
58  }
59 
63  inline void ReadFromFile(const std::string& file_name)
64  {
66  }
67 
71  inline void SetAll(Tensor<Vector<T, Size>, Dim>& data)
72  {
73  data_ = data;
74  }
75 
79  inline void UpdateTime(const T time)
80  {
81  time_ = time;
82  }
83 
87  inline void WriteToFile(const std::string& file_name) const
88  {
90  }
91 
92  friend struct FieldPolicy<T, Dim, Size>;
93 
94  protected:
95  const unsigned nx_;
96  const unsigned ny_;
98  T time_;
99 };
100 
103 template <typename T, unsigned Dim, unsigned Size>
104 struct FieldPolicy {};
105 
110 template <typename T, unsigned Size>
111 struct FieldPolicy<T, 2, Size>
112 {
117  static inline void WriteToFile(const Field<T, 2, Size>& field, const std::string& file_name)
118  {
119  std::ofstream file;
120  file.open(file_name);
121  if (!file.is_open())
122  throw std::runtime_error("file does not open correctly!");
123 
124  file.clear();
125  file << field.nx_ << std::endl;
126  file << field.ny_ << std::endl;
127  file << field.time_ << std::endl;
128  file << field.data_;
129  file.close();
130  }
131 
136  static inline void ReadFromFile(Field<T, 2, Size>& field, const std::string& file_name)
137  {
138  std::ifstream file;
139  file.open(file_name, std::ios::in);
140  if (!file.is_open())
141  throw std::runtime_error("file does not open correctly!");
142 
143  // check if sizes match
144  unsigned nx, ny;
145  file >> nx; file >> ny;
146  if (field.nx_!=nx || field.ny_!=ny)
147  throw std::domain_error("sizes do not match!");
148 
149  // read in time stamp
150  file >> field.time_;
151 
152  // read in data
153  file >> field.data_;
154 
155  file.close();
156  }
157 
158 };
159 
166 template <typename T, unsigned Dim = 2>
167 class Position : public Field<T, Dim, Dim>
168 {
169  public:
170  using vec = LCS::Vector<T, Dim>;
171 
176  Position(unsigned nx, unsigned ny): Field<T, Dim, Dim>(nx, ny) {}
177 
182  void SetAll(const std::vector<T>& xrange, const std::vector<T>& yrange)
183  {
184  // make sure sizes match
185  if (xrange.size()!=this->nx_||yrange.size()!=this->ny_)
186  throw std::domain_error("sizes do not match!");
187 
188  // fill in the values
189  #pragma omp parallel for
190  for (unsigned i = 0; i < this->nx_; ++i)
191  for (unsigned j = 0; j < this->ny_; ++j)
192  this->data_(i,j) = vec(xrange[i], yrange[j]);
193 
194  pos_xrange_ = xrange;
195  pos_yrange_ = yrange;
196  }
197 
204  void SetAll(const T& xmin, const T& xmax, const T& ymin, const T& ymax)
205  {
206  std::vector<T> xrange(this->nx_, 0), yrange(this->ny_, 0);
207  int i = 0, j = 0;
208  // fill in the values with uniform step
209  std::generate(xrange.begin(), xrange.end(),
210  [&]{ return xmin + (i++) * (xmax-xmin)/(this->nx_-1);});
211  std::generate(yrange.begin(), yrange.end(),
212  [&]{ return ymin + (j++) * (ymax-ymin)/(this->ny_-1);});
213  SetAll(xrange, yrange);
214  }
215 
219  {
221  }
222 
228  inline auto Get(const unsigned i, const unsigned j) const
229  {
230  return std::make_tuple(this->data_(i,j).x, this->data_(i,j).y);
231  }
232 
236  inline auto& GetRange(const unsigned axis)
237  {
238  // need to check the input and if ranges exist
239  if (axis == 0)
240  return pos_xrange_;
241  else
242  return pos_yrange_;
243  }
244 
249  void Update(Velocity<T, Dim>& vel, T delta)
250  {
251  #pragma omp parallel for
252  for (unsigned i = 0; i < this->nx_; ++i)
253  {
254  for (unsigned j = 0; j < this->ny_; ++j)
255  {
256  T vx, vy;
257  std::tie(vx, vy) = vel.Get(i,j);
258  this->data_(i,j).x += vx * delta;
259  this->data_(i,j).y += vy * delta;
260 
261  // check if the position is out of bound
262  // need to deal with NAN values
263  if (out_of_bound_ != nullptr)
264  if (this->data_(i,j).x < bound_xmin_ ||
265  this->data_(i,j).x > bound_xmax_ ||
266  this->data_(i,j).y < bound_ymin_ ||
267  this->data_(i,j).y > bound_ymax_)
268  out_of_bound_->SetValue(i, j, true);
269  }
270  }
271  }
272 
276  {
277  // default value is false
278  out_of_bound_.reset(new Tensor<bool, Dim>(this->nx_, this->ny_));
279  }
280 
286  inline bool IsOutOfBound(const unsigned i, const unsigned j)
287  {
288  if (out_of_bound_ != nullptr)
289  return out_of_bound_->GetValue(i,j);
290  else
291  return false; // default value
292  }
293 
300  inline void SetBound(const T& xmin, const T& xmax, const T& ymin, const T& ymax)
301  {
302  bound_xmin_ = xmin;
303  bound_xmax_ = xmax;
304  bound_ymin_ = ymin;
305  bound_ymax_ = ymax;
306  }
307 
308  private:
309  std::unique_ptr<Tensor<bool, Dim>> out_of_bound_;
310  std::vector<T> pos_xrange_;
311  std::vector<T> pos_yrange_;
313  T bound_xmin_;
314  T bound_xmax_;
315  T bound_ymin_;
316  T bound_ymax_;
317 };
318 
326 template <typename T, unsigned Dim = 2>
327 class Velocity : public Field<T, Dim, Dim>
328 {
329  public:
330  using vec = LCS::Vector<T, Dim>;
331 
337  Velocity(unsigned nx, unsigned ny, Position<T, Dim>& pos):
338  Field<T, Dim, Dim>(nx, ny), pos_(pos) {}
339 
345  inline auto Get(const unsigned i, const unsigned j) const
346  {
347  return std::make_tuple(this->data_(i,j).x, this->data_(i,j).y);
348  }
349 
353  inline auto& GetPosition()
354  {
355  return pos_;
356  }
357 
362  {
363  // interpolation only works for orthogonal coordinates
364  auto const ref_pos_x = ref_vel.GetPosition().GetRange(0);
365  auto const ref_pos_y = ref_vel.GetPosition().GetRange(1);
366 
367  #pragma omp parallel for
368  for (unsigned i = 0; i < this->nx_; ++i)
369  {
370  T pos_x, pos_y;
371  Tensor<Vector<T, 2>, 2> ref_v(2,2);
372 
373  for (unsigned j = 0; j < this->ny_; ++j)
374  {
375  // skip if the current position is out of bound
376  if (pos_.IsOutOfBound(i,j)) continue;
377 
378  std::tie(pos_x, pos_y) = pos_.Get(i, j);
379 
380  auto iter_x = std::upper_bound(ref_pos_x.begin(), ref_pos_x.end(), pos_x);
381  if (iter_x == ref_pos_x.end()) --iter_x;
382  if (iter_x == ref_pos_x.begin()) ++iter_x;
383  int i_next = std::distance(ref_pos_x.begin(), iter_x);
384  int i_pre = i_next - 1;
385 
386  auto iter_y = std::upper_bound(ref_pos_y.begin(), ref_pos_y.end(), pos_y);
387  if (iter_y == ref_pos_y.end()) --iter_y;
388  if (iter_y == ref_pos_y.begin()) ++iter_y;
389  int j_next = std::distance(ref_pos_y.begin(), iter_y);
390  int j_pre = j_next - 1;
391 
392  // add another getter for Tensor class?
393  std::tie(ref_v(0,0).x, ref_v(0,0).y) = ref_vel.Get(i_pre, j_pre);
394  std::tie(ref_v(0,1).x, ref_v(0,1).y) = ref_vel.Get(i_pre, j_next);
395  std::tie(ref_v(1,0).x, ref_v(1,0).y) = ref_vel.Get(i_next, j_pre);
396  std::tie(ref_v(1,1).x, ref_v(1,1).y) = ref_vel.Get(i_next, j_next);
397 
398  auto vx1 = interpolate(ref_pos_x[i_pre], ref_pos_x[i_next],
399  ref_v(0,0).x, ref_v(1,0).x, pos_x);
400  auto vx2 = interpolate(ref_pos_x[i_pre], ref_pos_x[i_next],
401  ref_v(0,1).x, ref_v(1,1).x, pos_x);
402  auto vxm = interpolate(ref_pos_y[j_pre], ref_pos_y[j_next],
403  vx1, vx2, pos_y);
404 
405  auto vy1 = interpolate(ref_pos_x[i_pre], ref_pos_x[i_next],
406  ref_v(0,0).y, ref_v(1,0).y, pos_x);
407  auto vy2 = interpolate(ref_pos_x[i_pre], ref_pos_x[i_next],
408  ref_v(0,1).y, ref_v(1,1).y, pos_x);
409  auto vym = interpolate(ref_pos_y[j_pre], ref_pos_y[j_next],
410  vy1, vy2, pos_y);
411 
412  this->data_(i,j).x = vxm;
413  this->data_(i,j).y = vym;
414  }
415  }
416  }
417 
418  protected:
420 };
421 
429 template <typename T, typename Func, unsigned Dim>
430 class ContinuousVelocity : public Velocity<T, Dim>
431 {
432  public:
433  using vec = LCS::Vector<T, Dim>;
434 
441  ContinuousVelocity(unsigned nx, unsigned ny, Position<T, Dim>& pos, T time=0):
442  Velocity<T, Dim>(nx, ny, pos), f_()
443  {
444  this->time_ = time;
445  SetAll();
446  }
447 
455  ContinuousVelocity(unsigned nx, unsigned ny, Position<T, Dim>& pos,
456  std::vector<T>& parameters, T time=0): Velocity<T, Dim>(nx, ny, pos), f_(parameters)
457  {
458  this->time_ = time;
459  SetAll();
460  }
461 
464  void SetAll()
465  {
466  #pragma omp parallel for
467  for (unsigned i = 0; i < this->nx_; ++i)
468  {
469  for (unsigned j = 0; j < this->ny_; ++j)
470  {
471  T x, y, vx, vy;
472  std::tie(x, y) = this->pos_.Get(i, j);
473  std::tie(vx, vy) = f_(x, y, this->time_);
474  this->data_(i,j) = vec(vx, vy);
475  }
476  }
477  }
478 
482  inline Func& Function()
483  {
484  return f_;
485  }
486 
487  private:
488  Func f_;
489 };
490 
491 }
void ReadFromFile(const std::string &file_name)
Definition: field.hpp:63
Field(unsigned nx, unsigned ny)
Definition: field.hpp:42
Field of particle velocities.
Definition: field.hpp:21
Position< T, Dim > & pos_
Definition: field.hpp:419
const unsigned nx_
Definition: field.hpp:95
Position(unsigned nx, unsigned ny)
Definition: field.hpp:176
void SetAll(Tensor< vec, Dim > &data)
Definition: field.hpp:218
bool IsOutOfBound(const unsigned i, const unsigned j)
Definition: field.hpp:286
Field of particle positions.
Definition: field.hpp:18
void InterpolateFrom(Velocity< T, Dim > &ref_vel)
Definition: field.hpp:361
Class for tensors.
Definition: basic.hpp:183
auto Get(const unsigned i, const unsigned j) const
Definition: field.hpp:345
T interpolate(T x1, T x2, T y1, T y2, T xm)
Definition: basic.hpp:321
Velocity field with continuous velocity function.
Definition: field.hpp:24
auto & GetAll() const
Definition: field.hpp:47
void SetBound(const T &xmin, const T &xmax, const T &ymin, const T &ymax)
Definition: field.hpp:300
static void WriteToFile(const Field< T, 2, Size > &field, const std::string &file_name)
Definition: field.hpp:117
const unsigned ny_
Definition: field.hpp:96
void Update(Velocity< T, Dim > &vel, T delta)
Definition: field.hpp:249
void SetAll(Tensor< Vector< T, Size >, Dim > &data)
Definition: field.hpp:71
Class for general physical fields.
Definition: field.hpp:35
ContinuousVelocity(unsigned nx, unsigned ny, Position< T, Dim > &pos, T time=0)
Definition: field.hpp:441
void UpdateTime(const T time)
Definition: field.hpp:79
Dimension-dependent implementations of Field class.
Definition: field.hpp:15
Basic classes needed such as Vector and Tensor.
Tensor< Vector< T, Size >, Dim > data_
Definition: field.hpp:97
ContinuousVelocity(unsigned nx, unsigned ny, Position< T, Dim > &pos, std::vector< T > &parameters, T time=0)
Definition: field.hpp:455
void SetAll()
Definition: field.hpp:464
void WriteToFile(const std::string &file_name) const
Definition: field.hpp:87
Struct for vectors.
Definition: basic.hpp:92
Velocity(unsigned nx, unsigned ny, Position< T, Dim > &pos)
Definition: field.hpp:337
auto & GetPosition()
Definition: field.hpp:353
void SetAll(const T &xmin, const T &xmax, const T &ymin, const T &ymax)
Definition: field.hpp:204
void SetAll(const std::vector< T > &xrange, const std::vector< T > &yrange)
Definition: field.hpp:182
auto GetTime() const
Definition: field.hpp:55
void InitializeOutOfBoundTensor()
Definition: field.hpp:275
auto Get(const unsigned i, const unsigned j) const
Definition: field.hpp:228
auto & GetRange(const unsigned axis)
Definition: field.hpp:236
Func & Function()
Definition: field.hpp:482
static void ReadFromFile(Field< T, 2, Size > &field, const std::string &file_name)
Definition: field.hpp:136
T time_
Definition: field.hpp:98