Alamo
Linear.H
Go to the documentation of this file.
1 //
2 // This is a general-purpose routine for specifying time-interpolated
3 // quantities in an input file.
4 // Interpolators obey the following syntax:
5 //
6 // .. code-block:: bash
7 //
8 // (t1,t2,..,tn;v1,v2,...,vn)
9 //
10 // where :code:`tn` are times and :code:`vn` are values at those times.
11 //
12 // :bdg-danger-line:`Note: do not include whitespace in an interpolator, this will mess with the parser.`
13 //
14 // Interpolators can usually be used in place of regular numbers, but only
15 // when supported by the calling parse function.
16 //
17 // For instance, the `BC::Operator::Elastic::TensionTest` allows the user to specify
18 // fixed displacement; for instance, to specify a value of 0.1:
19 //
20 // .. code-block:: bash
21 //
22 // bc.tenstion_test.disp = 0.1
23 //
24 // However, it may be desirable to change the value over time.
25 // In this case, one may specify an interpolator string instead:
26 //
27 // .. code-block:: bash
28 //
29 // bc.tenstion_test.disp = (1.0,1.5,2.0;0.0,0.1,0.0)
30 //
31 // This will cause the displacement value to be zero for :code:`t<1.0`;
32 // ramp to :code:`0.1` as :code:`1.0<t<2.0`;
33 // ramp back to :code:`0.0` as :code:`2.0<t<3.0`;
34 // and then remain at the constant value of :code:`3.0` for :code:`t>3.0`.
35 //
36 
37 #ifndef NUMERIC_INTERPOLATOR_LINEAR_H_
38 #define NUMERIC_INTERPOLATOR_LINEAR_H_
39 
40 #include <AMReX.H>
41 #include <AMReX_MultiFab.H>
42 #include "Set/Set.H"
43 #include "Util/Util.H"
45 #include "IO/ParmParse.H"
46 
47 namespace Numeric
48 {
49 namespace Interpolator
50 {
51 template <class T>
52 class Linear : public Interpolator<T>
53 {
54 public:
55  Linear() {};
56  ~Linear() {};
57  Linear(const Set::Scalar &a_val)
58  {
59  interval_points.push_back(0.0);
60  data_points.push_back(a_val);
61  }
62  Linear(const std::string a_str)
63  {
64  define(a_str);
65  }
66  Linear(const std::vector<T> _data_points, const std::vector<Set::Scalar> _interval_points)
67  {
68  define(_data_points,_interval_points);
69  };
70 
71  void define(const std::string a_str)
72  {
73  std::string str = a_str;
74 
75  if (Util::String::Contains(str,"(") || Util::String::Contains(str,":") || Util::String::Contains(str,")") || Util::String::Contains(str,","))
76  {
77  if (!Util::String::Contains(str,"(")) Util::Abort(INFO,"Mismatched parentheses while trying to parse ",str);
78  if (!Util::String::Contains(str,")")) Util::Abort(INFO,"Mismatched parentheses while trying to parse ",str);
79  if (!Util::String::Contains(str,":")) Util::Abort(INFO,"Missing : in interpolator while trying to parse ",str);
80  Util::String::ReplaceAll(str,"(","");
81  Util::String::ReplaceAll(str,")","");
82 
83  std::vector<std::string> splitstr = Util::String::Split(str,':');
84  std::string str_time = splitstr[0];
85  std::string str_val = splitstr[1];
86 
87  std::vector<std::string> str_time_arr = Util::String::Split(str_time,',');
88  std::vector<std::string> str_val_arr = Util::String::Split(str_val,',');
89 
90  if (str_time_arr.size() != str_val_arr.size()) Util::Abort(INFO,"Mismatched number of time values vs array values while trying to parse ", str);
91 
92  for (unsigned int i = 0; i < str_time_arr.size(); i++)
93  {
94  interval_points.push_back(std::stod(str_time_arr[i]));
95  if (i > 0) if (interval_points[i] < interval_points[i-1]) Util::Abort(INFO,"Time series must monotonically increase - error while trying to parse ", str);
96  data_points.push_back(std::stod(str_val_arr[i]));
97  }
98  }
99  else
100  {
101  interval_points.push_back(0.0);
102  data_points.push_back(std::stod(a_str));
103  }
104  }
105 
106  void define(const std::vector<T> _data_points, const std::vector<Set::Scalar> _interval_points)
107  {
108  data_points = _data_points;
109  interval_points = _interval_points;
110  if(data_points.size() != interval_points.size())
111  Util::Abort(INFO,"Data points and interval points have different sizes");
112  };
113 
114  T operator() (const Set::Scalar point) const
115  {
116  // If there is only one point stored, return it.
117  if (data_points.size() == 1) return data_points[0];
118 
119  // Do this if point is below interpolation range
120  if(point < interval_points[0])
121  {
122  return data_points[0];
123  }
124 
126  int start = 0;
127  if (uniform)
128  {
129  start = (int)( (point - interval_points[0]) / interval);
130  start -= 1;
131  start = std::max(start,0);
132  start = std::min(start,(int)(interval_points.size()-2));
133  }
134 
135  // Do this if point is within interpolation range
136  for (unsigned int i = start; i<interval_points.size(); i++)
137  {
138  if (interval_points[i] <= point && point <= interval_points[i+1])
139  {
140  return data_points[i] +
141  (point - interval_points[i]) * (data_points[i+1] - data_points[i]) /
142  (interval_points[i+1] - interval_points[i]);
143 
144  }
145  }
146 
147  // Otherwise point must be outside interpolation range, so
148  // return the value for the highest point
149  return data_points[interval_points.size()-1];
150  }
151 
152  static void Parse(Linear<T> & value, IO::ParmParse & pp)
153  {
154  std::string in;
155  pp_query("str",in); // Interpolator string used when Parsed from queryclass.
156  value.define(in);
157  }
158 
159 
160  static Linear<T> Read(std::string filename, int derivative = 0);
161 
162 protected:
163  std::vector<T> data_points;
164  std::vector<Set::Scalar> interval_points;
165  bool uniform = true;
166 
167 public:
168  template<class U> friend Linear<U> operator * (const Set::Scalar alpha, const Linear<U> &b);
169 };
170 
171 template<class T>
172 AMREX_FORCE_INLINE
174 {
175  Linear<T> ret;
176  for (unsigned int i = 0; i < b.data_points.size(); i++)
177  ret.data_points.push_back(alpha * b.data_points[i]);
179  ret.uniform = b.uniform;
180  return ret;
181 }
182 
183 template<>
186 {
187  std::ifstream input;
188  input.open(filename);
189  std::string line;
190  std::vector<Set::Scalar> theta, w;
191  // parse input
192  while (std::getline(input, line))
193  { std::vector<std::string> dat = Util::String::Split(line);
194  theta.push_back(std::stof(dat[0]));
195  w.push_back(std::stof(dat[1]));
196  }
197  if (derivative == 0)
198  {
199  return Linear<Set::Scalar>(w,theta);
200  }
201  else if (derivative == 1)
202  {
203  std::vector<Set::Scalar> thetasmall, dw;
204  for (unsigned int i = 1; i < theta.size() - 1; i++)
205  {
206  thetasmall.push_back(theta[i]);
207  dw.push_back((w[i + 1] - w[i - 1]) / (theta[i + 1] - theta[i - 1]));
208  }
209  return Linear<Set::Scalar>(dw,thetasmall);
210  }
211  else if (derivative == 2)
212  {
213  std::vector<Set::Scalar> thetasmall, ddw;
214  for (unsigned int i = 1; i < theta.size() - 1; i++)
215  {
216  thetasmall.push_back(theta[i]);
217  ddw.push_back((w[i + 1] - 2.0 * w[i] + w[i - 1]) / ((theta[i + 1] - theta[i]) * (theta[i] - theta[i - 1])));
218  }
219  return Linear<Set::Scalar>(ddw,thetasmall);
220  }
221  else Util::Abort(INFO,"derivative must be 0,1,2 but got ",derivative);
222  exit(-1);
223 }
224 
225 
226 }
227 }
228 
229 #endif
Util::filename
std::string filename
Definition: Util.cpp:19
Numeric::Interpolator::Linear::Parse
static void Parse(Linear< T > &value, IO::ParmParse &pp)
Definition: Linear.H:152
Util.H
Numeric::Interpolator::Linear::define
void define(const std::string a_str)
Definition: Linear.H:71
Util::String::Split
std::vector< std::string > Split(std::string &str, const char delim)
Definition: Util.cpp:291
Util::String::ReplaceAll
int ReplaceAll(std::string &str, const std::string before, const std::string after)
Definition: Util.cpp:224
ALAMO_SINGLE_DEFINITION
#define ALAMO_SINGLE_DEFINITION
Definition: Util.H:25
Numeric::Interpolator::Interpolator
Definition: Interpolator.H:21
Numeric::Interpolator::Linear::data_points
std::vector< T > data_points
Definition: Linear.H:163
Numeric::Interpolator::Linear::Linear
Linear(const std::vector< T > _data_points, const std::vector< Set::Scalar > _interval_points)
Definition: Linear.H:66
ParmParse.H
Numeric::Interpolator::Linear::Linear
Linear(const Set::Scalar &a_val)
Definition: Linear.H:57
pp_query
#define pp_query(...)
Definition: ParmParse.H:104
Numeric::Interpolator::Linear::interval_points
std::vector< Set::Scalar > interval_points
Definition: Linear.H:164
Set::Scalar
amrex::Real Scalar
Definition: Base.H:19
Numeric::Interpolator::Linear::~Linear
~Linear()
Definition: Linear.H:56
Numeric::Interpolator::Linear::operator*
friend Linear< U > operator*(const Set::Scalar alpha, const Linear< U > &b)
Numeric::Interpolator::Linear::operator()
T operator()(const Set::Scalar point) const
Definition: Linear.H:114
Interpolator.H
Numeric::Interpolator::operator*
AMREX_FORCE_INLINE Linear< T > operator*(const Set::Scalar alpha, const Linear< T > &b)
Definition: Linear.H:173
Numeric::Interpolator::Linear::Linear
Linear(const std::string a_str)
Definition: Linear.H:62
Numeric::Interpolator::Linear
Definition: Linear.H:52
Util::Abort
void Abort(const char *msg)
Definition: Util.cpp:165
Numeric::Interpolator::Linear::Read
static Linear< T > Read(std::string filename, int derivative=0)
Numeric::Interpolator::Linear::define
void define(const std::vector< T > _data_points, const std::vector< Set::Scalar > _interval_points)
Definition: Linear.H:106
Numeric::Interpolator::Linear::Linear
Linear()
Definition: Linear.H:55
Set.H
IO::ParmParse
Definition: ParmParse.H:110
Util::String::Contains
bool Contains(std::string &str, const std::string find)
Definition: Util.cpp:301
Numeric
This namespace contains some numerical tools.
Definition: Function.H:5
INFO
#define INFO
Definition: Util.H:20
Numeric::Interpolator::Linear::uniform
bool uniform
Definition: Linear.H:165