flow.hpp
Go to the documentation of this file.
1 
7 #pragma once
8 
9 #include "field.hpp"
10 #include "basic.hpp"
11 
12 namespace LCS {
13 
14 template <typename T, unsigned Dim>
15 class FlowField;
16 
17 template <typename T, typename Func, unsigned Dim>
19 
20 
25 {
28 };
29 
36 template <typename T, unsigned Dim = 2>
37 class FlowField
38 {
39  public:
44  FlowField(unsigned nx, unsigned ny):
45  nx_(nx), ny_(ny), delta_(), initial_time_(), current_time_(), step_(),
46  initial_pos_(new Position<T,Dim>(nx,ny)),
47  current_pos_(new Position<T,Dim>(nx,ny)) {}
48 
52  inline auto& InitialPosition()
53  {
54  return *initial_pos_;
55  }
56 
60  inline auto& CurrentPosition()
61  {
62  return *current_pos_;
63  }
64 
69  {
70  if (current_vel_ == nullptr)
71  throw std::invalid_argument("current velocity not set!");
72 
73  return *current_vel_;
74  }
75 
79  inline auto GetTime()
80  {
81  return current_time_;
82  }
83 
87  inline auto GetDirection()
88  {
89  return direction_;
90  }
91 
95 
99  inline void SetDelta(const T delta)
100  {
101  assert(delta > 0);
102  delta_ = delta;
103  }
104 
108  inline void SetStep(const unsigned step)
109  {
110  step_ = step;
111  }
112 
115  virtual void SetCurrentVelocity()
116  {}
117 
121  virtual void SetDirection(const Direction direction)
122  {}
123 
127  inline void SetInitialTime(const T time)
128  {
129  initial_time_ = time;
130  initial_pos_->UpdateTime(time);
131  UpdateTime(time);
132  }
133 
136  inline void UpdateTime()
137  {
138  switch(direction_)
139  {
140  case Forward: current_time_ += delta_; break;
141  case Backward: current_time_ -= delta_; break;
142  default: break;
143  }
144  current_pos_->UpdateTime(current_time_);
145  current_vel_->UpdateTime(current_time_);
146  }
147 
151  inline void UpdateTime(const T time)
152  {
153  current_time_ = time;
154  current_pos_->UpdateTime(current_time_);
155  if (current_vel_ != nullptr) current_vel_->UpdateTime(current_time_);
156  }
157 
159  void Run()
160  {
161  switch(direction_)
162  {
163  case Forward:
164  std::cout << "Particle forward advection begins" << std::endl;
165  break;
166  case Backward:
167  std::cout << "Particle backward advection begins" << std::endl;
168  break;
169  default: break;
170  }
172 
173  Clock clock;
174  for (unsigned i = 0; i < step_; ++i)
175  {
176  clock.Begin();
177  std::stringstream ss;
178  ss << "[" << std::setw(std::to_string(step_).length()) << (i+1)
179  << "/" << step_ << "]" <<
180  " Simulation time: " << current_time_;
181 
183 
184  switch(direction_)
185  {
186  case Forward: current_pos_->Update(*current_vel_, delta_); break;
187  case Backward: current_pos_->Update(*current_vel_, -delta_); break;
188  default: break;
189  }
190 
191  UpdateTime();
192 
193  ss << " - " << current_time_;
194  clock.End();
195  ss << " (Execution time: " <<
196  std::setprecision(4) << clock.GetTotalElapsedTime() <<
197  "s)" << std::endl;
198  std::cout << ss.str();
199  }
200  switch(direction_)
201  {
202  case Forward:
203  std::cout << "Particle forward advection ends" << std::endl;
204  break;
205  case Backward:
206  std::cout << "Particle backward advection ends" << std::endl;
207  break;
208  default: break;
209  }
210  }
211 
212  protected:
213  const unsigned nx_;
214  const unsigned ny_;
215  T delta_;
218  unsigned step_;
220  std::unique_ptr<Position<T, Dim>> initial_pos_;
221  std::unique_ptr<Position<T, Dim>> current_pos_;
222  std::shared_ptr<Velocity<T, Dim>> current_vel_;
223 };
224 
231 template <typename T, unsigned Dim = 2>
232 class DiscreteFlowField : public FlowField<T, Dim>
233 {
234  public:
241  DiscreteFlowField(unsigned nx, unsigned ny, unsigned data_nx, unsigned data_ny):
242  FlowField<T, Dim>(nx, ny), data_nx_(data_nx), data_ny_(data_ny),
243  data_delta_(), current_data_time_(), begin_data_time_(), end_data_time_(),
244  vel_file_name_prefix_(""), vel_file_name_suffix_(".txt"),
245  data_pos_(new Position<T,Dim>(data_nx, data_ny)),
246  previous_data_vel_(new Velocity<T,Dim>(data_nx, data_ny, *data_pos_)),
247  next_data_vel_(new Velocity<T,Dim>(data_nx, data_ny, *data_pos_)),
248  current_data_vel_(new Velocity<T,Dim>(data_nx, data_ny, *data_pos_)) {}
249 
254  DiscreteFlowField(unsigned nx, unsigned ny):
255  DiscreteFlowField(nx, ny, nx, ny) {}
256 
260  inline void SetVelocityFileNamePrefix(const std::string prefix)
261  {
262  vel_file_name_prefix_ = prefix;
263  }
264 
268  inline void SetVelocityFileNameSuffix(const std::string suffix)
269  {
270  vel_file_name_suffix_ = suffix;
271  }
272 
277  {
278  std::string file_name = vel_file_name_prefix_ +
279  std::to_string(static_cast<int>(data_vel.GetTime())) +
280  vel_file_name_suffix_;
281 
282  data_vel.ReadFromFile(file_name);
283 
284  std::cout << "Read velocity data at time = " <<
285  data_vel.GetTime() << " from " << file_name << std::endl;
286  }
287 
290  inline void SetCurrentVelocity()
291  {
292  T signed_data_delta = (this->direction_ == Forward) ? data_delta_ : (-data_delta_);
293 
294  // initialize data velocities
295  if (this->current_time_ == this->initial_time_)
296  {
297  current_data_time_ = begin_data_time_;
298 
299  // find the data velocity field that is temporally closest to the initial time
300  switch(this->direction_)
301  {
302  case Forward:
303  while (current_data_time_ < this->initial_time_)
304  current_data_time_ += signed_data_delta;
305  break;
306  case Backward:
307  while (current_data_time_ > this->initial_time_)
308  current_data_time_ -= signed_data_delta;
309  break;
310  default: break;
311  }
312 
313  // read two temporally adjacent data field (for later interpolation)
314  #pragma omp parallel
315  #pragma omp single nowait
316  {
317  #pragma omp task
318  {
319  previous_data_vel_->UpdateTime(current_data_time_);
320  ReadDataVelocityFromFile(*previous_data_vel_);
321  }
322  #pragma omp task
323  {
324  next_data_vel_->UpdateTime(current_data_time_ + signed_data_delta);
325  ReadDataVelocityFromFile(*next_data_vel_);
326  }
327  }
328 
329  // check if the current time is outside the time
330  // range of two temporally adjacent data field
331  } else if (((this->current_time_ >= current_data_time_ + signed_data_delta) &&
332  (end_data_time_ > current_data_time_ + signed_data_delta) &&
333  this->direction_ == Forward) ||
334  ((this->current_time_ <= current_data_time_ + signed_data_delta) &&
335  (end_data_time_ < current_data_time_ + signed_data_delta) &&
336  this->direction_ == Backward))
337  {
338  // update data velocities
339 
340  current_data_time_ += signed_data_delta;
341 
342  // read the next two temporally adjacent data velocity field so that
343  // the current time could be within the time range of the two data field
344  #pragma omp parallel
345  #pragma omp single nowait
346  {
347  #pragma omp task
348  {
349  previous_data_vel_->UpdateTime(current_data_time_);
350  ReadDataVelocityFromFile(*previous_data_vel_);
351  }
352  #pragma omp task
353  {
354  next_data_vel_->UpdateTime(current_data_time_ + signed_data_delta);
355  ReadDataVelocityFromFile(*next_data_vel_);
356  }
357  }
358  }
359 
360  // temporal interpolation
361  interpolate(previous_data_vel_->GetTime(),
362  next_data_vel_->GetTime(),
363  *previous_data_vel_, *next_data_vel_,
364  this->current_time_, *current_data_vel_);
365 
366  // spatial interpolation
367  this->current_vel_->InterpolateFrom(*current_data_vel_);
368 
369  }
370 
374  inline void SetDirection(const Direction direction)
375  {
376  this->direction_ = direction;
377  SetDataTimeRange(begin_data_time_, end_data_time_);
378  }
379 
383  {
384  auto initial_pos_data = this->initial_pos_->GetAll();
385  this->current_pos_->SetAll(initial_pos_data);
386  this->current_pos_->GetRange(0) = this->initial_pos_->GetRange(0);
387  this->current_pos_->GetRange(1) = this->initial_pos_->GetRange(1);
388  this->current_pos_->UpdateTime(this->initial_pos_->GetTime());
389  this->current_pos_->InitializeOutOfBoundTensor();
390 
391 
392  // set out boundary
393  T xmin, xmax, ymin, ymax;
394  std::tie(xmin, ymin) = data_pos_->Get(0,0);
395  std::tie(xmax, ymax) = data_pos_->Get(data_nx_-1,data_ny_-1);
396  this->current_pos_->SetBound(xmin, xmax, ymin, ymax);
397 
398  // set corresponding velocity tensor
399  this->current_vel_.reset(new Velocity<T, Dim>
400  (this->nx_, this->ny_, *(this->current_pos_)));
401  }
402 
405  inline auto& DataPosition()
406  {
407  return *data_pos_;
408  }
409 
412  inline auto& CurrentDataVelocity()
413  {
414  return *previous_data_vel_;
415  }
416 
420  inline void SetDataDelta(const T delta)
421  {
422  data_delta_ = delta;
423  }
424 
429  inline void SetDataTimeRange(const T t1, const T t2)
430  {
431  T begin_time = (t2 >= t1) ? t1 : t2;
432  T end_time = (t2 >= t1) ? t2 : t2;
433 
434  switch(this->direction_)
435  {
436  case Forward:
437  begin_data_time_ = begin_time;
438  end_data_time_ = end_time;
439  break;
440  case Backward:
441  begin_data_time_ = end_time;
442  end_data_time_ = begin_time;
443  break;
444  default: break;
445  }
446  }
447 
448  private:
449  const unsigned data_nx_;
450  const unsigned data_ny_;
451  T data_delta_;
452  T current_data_time_;
453  T begin_data_time_;
454  T end_data_time_;
455  std::string vel_file_name_prefix_;
456  std::string vel_file_name_suffix_;
457  std::unique_ptr<Position<T, Dim>> data_pos_;
458  std::unique_ptr<Velocity<T, Dim>> previous_data_vel_;
459  std::unique_ptr<Velocity<T, Dim>> next_data_vel_;
460  std::unique_ptr<Velocity<T, Dim>> current_data_vel_;
461 };
462 
463 
471 template <typename T, typename Func, unsigned Dim = 2>
472 class ContinuousFlowField : public FlowField<T, Dim>
473 {
474  public:
479  ContinuousFlowField(unsigned nx, unsigned ny):
480  FlowField<T, Dim>(nx, ny), parameters_() {}
481 
487  ContinuousFlowField(unsigned nx, unsigned ny, std::vector<T>& parameters):
488  FlowField<T, Dim>(nx, ny), parameters_(parameters) {}
489 
492  inline void SetCurrentVelocity()
493  {
494  // no parameters
495  if (parameters_.size() == 0)
496  current_continuous_vel_.reset(new ContinuousVelocity<T, Func, Dim>
497  (this->nx_, this->ny_, *(this->current_pos_),this->current_time_));
498  else
499  // there are parameters for continuous function
500  current_continuous_vel_.reset(new ContinuousVelocity<T, Func, Dim>
501  (this->nx_, this->ny_, *(this->current_pos_),
502  parameters_, this->current_time_));
503 
504  current_continuous_vel_->UpdateTime(this->current_time_);
505  this->current_vel_ = current_continuous_vel_;
506  }
507 
512  {
513  if (current_continuous_vel_ == nullptr)
514  throw std::invalid_argument("current velocity not set!");
515 
516  return *current_continuous_vel_;
517  }
518 
522  {
523  auto initial_pos_data = this->initial_pos_->GetAll();
524  this->current_pos_->SetAll(initial_pos_data);
525  this->current_pos_->GetRange(0) = this->initial_pos_->GetRange(0);
526  this->current_pos_->GetRange(1) = this->initial_pos_->GetRange(1);
527  this->current_pos_->UpdateTime(this->initial_pos_->GetTime());
528  }
529 
533  inline void SetDirection(const Direction direction)
534  {
535  this->direction_ = direction;
536  }
537 
538  private:
539  std::shared_ptr<ContinuousVelocity<T, Func, Dim>> current_continuous_vel_;
540  std::vector<T> parameters_;
541 };
542 
543 }
ContinuousFlowField(unsigned nx, unsigned ny, std::vector< T > &parameters)
Definition: flow.hpp:487
Direction
Definition: flow.hpp:24
Class for flow fields with a continous velocity function.
Definition: flow.hpp:18
auto & CurrentPosition()
Definition: flow.hpp:60
void ReadFromFile(const std::string &file_name)
Definition: field.hpp:63
auto & CurrentDataVelocity()
Definition: flow.hpp:412
void SetDelta(const T delta)
Definition: flow.hpp:99
void UpdateTime()
Definition: flow.hpp:136
Class for flow field.
Definition: flow.hpp:15
Field of particle velocities.
Definition: field.hpp:21
void End()
Definition: basic.hpp:374
void CopyInitialPositionToCurrentPosition()
Definition: flow.hpp:382
void CopyInitialPositionToCurrentPosition()
Definition: flow.hpp:521
FlowField(unsigned nx, unsigned ny)
Definition: flow.hpp:44
auto & DataPosition()
Definition: flow.hpp:405
Classes of physical fields.
Field of particle positions.
Definition: field.hpp:18
void SetStep(const unsigned step)
Definition: flow.hpp:108
auto GetDirection()
Definition: flow.hpp:87
const unsigned ny_
Definition: flow.hpp:214
void Run()
Definition: flow.hpp:159
T interpolate(T x1, T x2, T y1, T y2, T xm)
Definition: basic.hpp:321
T delta_
Definition: flow.hpp:215
virtual void SetCurrentVelocity()
Definition: flow.hpp:115
Velocity field with continuous velocity function.
Definition: field.hpp:24
void SetVelocityFileNameSuffix(const std::string suffix)
Definition: flow.hpp:268
void SetVelocityFileNamePrefix(const std::string prefix)
Definition: flow.hpp:260
ContinuousFlowField(unsigned nx, unsigned ny)
Definition: flow.hpp:479
Class for time recording.
Definition: basic.hpp:354
std::shared_ptr< Velocity< T, Dim > > current_vel_
Definition: flow.hpp:222
void SetDirection(const Direction direction)
Definition: flow.hpp:533
void SetDataDelta(const T delta)
Definition: flow.hpp:420
Definition: flow.hpp:27
void SetDataTimeRange(const T t1, const T t2)
Definition: flow.hpp:429
const unsigned nx_
Definition: flow.hpp:213
auto & InitialPosition()
Definition: flow.hpp:52
virtual void CopyInitialPositionToCurrentPosition()
Definition: flow.hpp:94
virtual Velocity< T, Dim > & CurrentVelocity()
Definition: flow.hpp:68
T current_time_
Definition: flow.hpp:217
std::unique_ptr< Position< T, Dim > > current_pos_
Definition: flow.hpp:221
void UpdateTime(const T time)
Definition: flow.hpp:151
std::unique_ptr< Position< T, Dim > > initial_pos_
Definition: flow.hpp:220
unsigned step_
Definition: flow.hpp:218
void SetCurrentVelocity()
Definition: flow.hpp:290
void ReadDataVelocityFromFile(Velocity< T, Dim > &data_vel)
Definition: flow.hpp:276
auto GetTime()
Definition: flow.hpp:79
void SetInitialTime(const T time)
Definition: flow.hpp:127
Basic classes needed such as Vector and Tensor.
DiscreteFlowField(unsigned nx, unsigned ny, unsigned data_nx, unsigned data_ny)
Definition: flow.hpp:241
ContinuousVelocity< T, Func, Dim > & CurrentVelocity()
Definition: flow.hpp:511
DiscreteFlowField(unsigned nx, unsigned ny)
Definition: flow.hpp:254
auto GetTime() const
Definition: field.hpp:55
void SetDirection(const Direction direction)
Definition: flow.hpp:374
Direction direction_
Definition: flow.hpp:219
void SetCurrentVelocity()
Definition: flow.hpp:492
T initial_time_
Definition: flow.hpp:216
double GetTotalElapsedTime() const
Definition: basic.hpp:400
void Begin()
Definition: basic.hpp:363
Class for flow fields with discrete data.
Definition: flow.hpp:232
Definition: flow.hpp:26
virtual void SetDirection(const Direction direction)
Definition: flow.hpp:121