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#include "Unit/Unit.H"
48
49namespace Numeric
50{
51namespace Interpolator
52{
53template <class T>
54class Linear : public Interpolator<T>
55{
56public:
57 Linear() {};
58 ~Linear() {};
59 Linear(const Set::Scalar &a_val)
60 {
61 interval_points.push_back(0.0);
62 data_points.push_back(a_val);
63 }
64 Linear(const std::string a_str, Unit unit_time = Unit::Less(), Unit unit_data = Unit::Less())
65 {
66 define(a_str, unit_time, unit_data);
67 }
68 Linear(const std::vector<T> _data_points, const std::vector<Set::Scalar> _interval_points)
69 {
70 define(_data_points,_interval_points);
71 };
72
73 void define(const std::string a_str, Unit a_unit_time, Unit a_unit_val)
74 {
75 std::string str = a_str;
76
78 {
79 if (!Util::String::Contains(str,"(")) Util::Abort(INFO,"Mismatched parentheses while trying to parse ",str);
80 if (!Util::String::Contains(str,")")) Util::Abort(INFO,"Mismatched parentheses while trying to parse ",str);
81 if (!Util::String::Contains(str,":")) Util::Abort(INFO,"Missing : in interpolator while trying to parse ",str);
82 Util::String::ReplaceAll(str,"(","");
83 Util::String::ReplaceAll(str,")","");
84
85 std::vector<std::string> splitstr = Util::String::Split(str,':');
86 std::string str_time = splitstr[0];
87 std::string str_val = splitstr[1];
88
89 std::vector<std::string> str_time_arr = Util::String::Split(str_time,',');
90 std::vector<std::string> str_val_arr = Util::String::Split(str_val,',');
91
92 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);
93
94 for (unsigned int i = 0; i < str_time_arr.size(); i++)
95 {
96 Unit unit_time = Unit::Parse(str_time_arr[i]);
97 if (!unit_time.isType(a_unit_time) && !unit_time.isType(Unit::Less()))
98 Util::Exception(INFO,"Invalid unit, ", str_time_arr[i]);
99 Unit unit_val = Unit::Parse(str_val_arr[i]);
100 if (!unit_val.isType(a_unit_val) && !unit_val.isType(Unit::Less()))
101 Util::Exception(INFO,"Invalid unit, ", str_val_arr[i]);
102 interval_points.push_back(unit_time.normalized_value());
103 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);
104 data_points.push_back(unit_val.normalized_value());
105 }
106 }
107 else
108 {
109 interval_points.push_back(0.0);
110 data_points.push_back(std::stod(a_str));
111 }
112 }
113
114 void define(const std::vector<T> _data_points, const std::vector<Set::Scalar> _interval_points)
115 {
116 data_points = _data_points;
117 interval_points = _interval_points;
118 if(data_points.size() != interval_points.size())
119 Util::Abort(INFO,"Data points and interval points have different sizes");
120 };
121
122 T operator() (const Set::Scalar point) const
123 {
124 // If there is only one point stored, return it.
125 if (data_points.size() == 1) return data_points[0];
126
127 // Do this if point is below interpolation range
128 if(point < interval_points[0])
129 {
130 return data_points[0];
131 }
132
134 int start = 0;
135 if (uniform)
136 {
137 start = (int)( (point - interval_points[0]) / interval);
138 start -= 1;
139 start = std::max(start,0);
140 start = std::min(start,(int)(interval_points.size()-2));
141 }
142
143 // Do this if point is within interpolation range
144 for (unsigned int i = start; i<interval_points.size()-1; i++)
145 {
146 if (interval_points[i] <= point && point <= interval_points[i+1])
147 {
148 return data_points[i] +
149 (point - interval_points[i]) * (data_points[i+1] - data_points[i]) /
151
152 }
153 }
154
155 // Otherwise point must be outside interpolation range, so
156 // return the value for the highest point
157 return data_points[interval_points.size()-1];
158 }
159
160 static void Parse(Linear<T> & value, IO::ParmParse & pp, Unit unit_time = Unit::Less(), Unit unit_value = Unit::Less())
161 {
162 std::string in;
163 pp_query("str",in); // Interpolator string used when Parsed from queryclass.
164 value.define(in, unit_time, unit_value);
165 }
166
167
168 static Linear<T> Read(std::string filename, int derivative = 0);
169
170protected:
171 std::vector<T> data_points;
172 std::vector<Set::Scalar> interval_points;
173 bool uniform = true;
174
175public:
176 template<class U> friend Linear<U> operator * (const Set::Scalar alpha, const Linear<U> &b);
177};
178
179template<class T>
180AMREX_FORCE_INLINE
182{
183 Linear<T> ret;
184 for (unsigned int i = 0; i < b.data_points.size(); i++)
185 ret.data_points.push_back(alpha * b.data_points[i]);
187 ret.uniform = b.uniform;
188 return ret;
189}
190
191template<>
193Linear<Set::Scalar> Linear<Set::Scalar>::Read(std::string filename, int derivative)
194{
195 std::ifstream input;
196 input.open(filename);
197 std::string line;
198 std::vector<Set::Scalar> theta, w;
199 // parse input
200 while (std::getline(input, line))
201 { std::vector<std::string> dat = Util::String::Split(line);
202 theta.push_back(std::stof(dat[0]));
203 w.push_back(std::stof(dat[1]));
204 }
205 if (derivative == 0)
206 {
207 return Linear<Set::Scalar>(w,theta);
208 }
209 else if (derivative == 1)
210 {
211 std::vector<Set::Scalar> thetasmall, dw;
212 for (unsigned int i = 1; i < theta.size() - 1; i++)
213 {
214 thetasmall.push_back(theta[i]);
215 dw.push_back((w[i + 1] - w[i - 1]) / (theta[i + 1] - theta[i - 1]));
216 }
217 return Linear<Set::Scalar>(dw,thetasmall);
218 }
219 else if (derivative == 2)
220 {
221 std::vector<Set::Scalar> thetasmall, ddw;
222 for (unsigned int i = 1; i < theta.size() - 1; i++)
223 {
224 thetasmall.push_back(theta[i]);
225 ddw.push_back((w[i + 1] - 2.0 * w[i] + w[i - 1]) / ((theta[i + 1] - theta[i]) * (theta[i] - theta[i - 1])));
226 }
227 return Linear<Set::Scalar>(ddw,thetasmall);
228 }
229 else Util::Abort(INFO,"derivative must be 0,1,2 but got ",derivative);
230 exit(-1);
231}
232
233
234}
235}
236
237#endif
#define pp_query(...)
Definition ParmParse.H:108
#define ALAMO_SINGLE_DEFINITION
Definition Util.H:26
#define INFO
Definition Util.H:21
T operator()(const Set::Scalar point) const
Definition Linear.H:122
std::vector< T > data_points
Definition Linear.H:171
friend Linear< U > operator*(const Set::Scalar alpha, const Linear< U > &b)
static void Parse(Linear< T > &value, IO::ParmParse &pp, Unit unit_time=Unit::Less(), Unit unit_value=Unit::Less())
Definition Linear.H:160
void define(const std::vector< T > _data_points, const std::vector< Set::Scalar > _interval_points)
Definition Linear.H:114
static Linear< T > Read(std::string filename, int derivative=0)
void define(const std::string a_str, Unit a_unit_time, Unit a_unit_val)
Definition Linear.H:73
Linear(const std::vector< T > _data_points, const std::vector< Set::Scalar > _interval_points)
Definition Linear.H:68
std::vector< Set::Scalar > interval_points
Definition Linear.H:172
Linear(const std::string a_str, Unit unit_time=Unit::Less(), Unit unit_data=Unit::Less())
Definition Linear.H:64
Linear(const Set::Scalar &a_val)
Definition Linear.H:59
AMREX_FORCE_INLINE Linear< T > operator*(const Set::Scalar alpha, const Linear< T > &b)
Definition Linear.H:181
This namespace contains some numerical tools.
Definition Function.H:6
amrex::Real Scalar
Definition Base.H:18
AMREX_FORCE_INLINE int ReplaceAll(std::string &str, const std::string before, const std::string after)
Definition String.H:23
AMREX_FORCE_INLINE bool Contains(std::string &str, const std::string find)
Definition String.H:150
AMREX_FORCE_INLINE std::vector< std::string > Split(std::string &str, const char delim=' ')
Definition String.H:138
void Abort(const char *msg)
Definition Util.cpp:225
void Exception(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:223
Definition Unit.H:20
bool isType(const Unit &test) const
Definition Unit.H:353
double normalized_value() const
Definition Unit.H:401
static Unit Less()
Definition Unit.H:187
static Unit Parse(double val, std::string unitstring)
Definition Unit.H:257