LCOV - code coverage report
Current view: top level - src/Numeric/Interpolator - Linear.H (source / functions) Hit Total Coverage
Test: coverage_merged.info Lines: 63 89 70.8 %
Date: 2024-11-18 05:28:54 Functions: 9 10 90.0 %

          Line data    Source code
       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"
      44             : #include "Numeric/Interpolator/Interpolator.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         482 :     Linear() {};
      56         694 :     ~Linear() {};
      57         496 :     Linear(const Set::Scalar &a_val)
      58         496 :     {
      59         496 :         interval_points.push_back(0.0);
      60         496 :         data_points.push_back(a_val);
      61         496 :     }
      62         104 :     Linear(const std::string a_str)
      63         104 :     {
      64         104 :         define(a_str);
      65         104 :     }
      66           2 :     Linear(const std::vector<T> _data_points, const std::vector<Set::Scalar> _interval_points)
      67           2 :     {
      68           2 :         define(_data_points,_interval_points);
      69           2 :     };
      70             :     
      71         106 :     void define(const std::string a_str)
      72             :     {
      73         212 :         std::string str = a_str;
      74             :         
      75         106 :         if (Util::String::Contains(str,"(") || Util::String::Contains(str,":") || Util::String::Contains(str,")") || Util::String::Contains(str,","))
      76             :         {
      77          36 :             if (!Util::String::Contains(str,"(")) Util::Abort(INFO,"Mismatched parentheses while trying to parse ",str);
      78          36 :             if (!Util::String::Contains(str,")")) Util::Abort(INFO,"Mismatched parentheses while trying to parse ",str);
      79          36 :             if (!Util::String::Contains(str,":")) Util::Abort(INFO,"Missing : in interpolator while trying to parse ",str);
      80          36 :             Util::String::ReplaceAll(str,"(","");
      81          36 :             Util::String::ReplaceAll(str,")","");
      82             : 
      83          72 :             std::vector<std::string> splitstr = Util::String::Split(str,':');
      84          72 :             std::string str_time = splitstr[0];
      85          72 :             std::string str_val  = splitstr[1];
      86             :             
      87          72 :             std::vector<std::string> str_time_arr = Util::String::Split(str_time,',');
      88          72 :             std::vector<std::string> str_val_arr  = Util::String::Split(str_val,',');
      89             : 
      90          36 :             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         108 :             for (unsigned int i = 0; i < str_time_arr.size(); i++)
      93             :             {
      94          72 :                 interval_points.push_back(std::stod(str_time_arr[i]));
      95          72 :                 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          72 :                 data_points.push_back(std::stod(str_val_arr[i]));
      97             :             }
      98             :         }
      99             :         else
     100             :         {
     101          70 :             interval_points.push_back(0.0);
     102          70 :             data_points.push_back(std::stod(a_str));
     103             :         }
     104         106 :     }
     105             : 
     106           2 :     void define(const std::vector<T> _data_points, const std::vector<Set::Scalar> _interval_points) 
     107             :     {
     108           2 :         data_points = _data_points;
     109           2 :         interval_points = _interval_points;
     110           2 :         if(data_points.size() != interval_points.size())
     111           0 :             Util::Abort(INFO,"Data points and interval points have different sizes");
     112           2 :     };
     113             : 
     114    77639820 :     T operator() (const Set::Scalar point) const
     115             :     {
     116             :         // If there is only one point stored, return it.
     117    77639820 :         if (data_points.size() == 1) return data_points[0];
     118             : 
     119             :         // Do this if point is below interpolation range
     120        9348 :         if(point < interval_points[0])
     121             :         {
     122         200 :             return data_points[0];
     123             :         }
     124             : 
     125        9148 :         Set::Scalar interval = interval_points[1]-interval_points[0];
     126        9148 :         int start = 0;
     127        9148 :         if (uniform)
     128             :         {
     129        9148 :             start = (int)( (point - interval_points[0]) / interval);
     130        9148 :             start -= 1;
     131        9148 :             start = std::max(start,0);
     132        9148 :             start = std::min(start,(int)(interval_points.size()-2));
     133             :         }
     134             : 
     135             :         // Do this if point is within interpolation range
     136        9742 :         for (unsigned int i = start; i<interval_points.size(); i++)
     137             :         {
     138        9544 :             if (interval_points[i] <= point && point <= interval_points[i+1])
     139             :             {
     140        8950 :                 return data_points[i] +
     141        8950 :                         (point - interval_points[i]) * (data_points[i+1] - data_points[i]) /
     142        8950 :                         (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         198 :         return  data_points[interval_points.size()-1];
     150             :     }
     151             : 
     152           2 :     static void Parse(Linear<T> & value, IO::ParmParse & pp)
     153             :     {
     154           2 :         std::string in;
     155           2 :         pp_query("str",in); // Interpolator string used when Parsed from queryclass.
     156           2 :         value.define(in);
     157           2 :     }
     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
     173             : Linear<T> operator * (const Set::Scalar alpha, const Linear<T> &b)
     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]);
     178             :     ret.interval_points = b.interval_points;
     179             :     ret.uniform = b.uniform;
     180             :     return ret;
     181             : }
     182             : 
     183             : template<>
     184             : ALAMO_SINGLE_DEFINITION
     185           0 : Linear<Set::Scalar> Linear<Set::Scalar>::Read(std::string filename, int derivative)
     186             : {
     187           0 :     std::ifstream input;
     188           0 :     input.open(filename);
     189           0 :     std::string line;
     190           0 :     std::vector<Set::Scalar> theta, w;
     191             :     // parse input 
     192           0 :     while (std::getline(input, line))
     193           0 :     {        std::vector<std::string> dat = Util::String::Split(line);
     194           0 :         theta.push_back(std::stof(dat[0]));
     195           0 :         w.push_back(std::stof(dat[1]));
     196             :     }
     197           0 :     if (derivative == 0)
     198             :     {
     199           0 :         return Linear<Set::Scalar>(w,theta);
     200             :     }
     201           0 :     else if (derivative == 1)
     202             :     {
     203           0 :         std::vector<Set::Scalar> thetasmall, dw;
     204           0 :         for (unsigned int i = 1; i < theta.size() - 1; i++)
     205             :         {
     206           0 :             thetasmall.push_back(theta[i]);
     207           0 :             dw.push_back((w[i + 1] - w[i - 1]) / (theta[i + 1] - theta[i - 1]));
     208             :         }
     209           0 :         return Linear<Set::Scalar>(dw,thetasmall);
     210             :     }
     211           0 :     else if (derivative == 2)
     212             :     {
     213           0 :         std::vector<Set::Scalar> thetasmall, ddw;
     214           0 :         for (unsigned int i = 1; i < theta.size() - 1; i++)
     215             :         {
     216           0 :             thetasmall.push_back(theta[i]);
     217           0 :             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           0 :         return Linear<Set::Scalar>(ddw,thetasmall);
     220             :     }
     221           0 :     else Util::Abort(INFO,"derivative must be 0,1,2 but got ",derivative);
     222           0 :     exit(-1);
     223             : }
     224             : 
     225             : 
     226             : }
     227             : }
     228             : 
     229             : #endif

Generated by: LCOV version 1.14