Flow123d  release_1.8.2-1603-g0109a2b
interpolant_impl.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file interpolant_impl.hh
15  * @brief
16  */
17 
18 #ifndef INTERPOLANT_IMPL_H
19 #define INTERPOLANT_IMPL_H
20 
21 #include <cmath>
22 
23 #include "interpolant.hh"
24 #include "system/xio.h"
25 
26 /********************************** InterpolantBase ********************************/
27 
28 inline double InterpolantBase::error()
29 {
30  return error_;
31 }
32 
34 {
35  return stats;
36 }
37 
38 inline double InterpolantBase::bound_a() const
39 {
40  return bound_a_;
41 }
42 
43 inline double InterpolantBase::bound_b() const
44 {
45  return bound_b_;
46 }
47 
48 inline unsigned int InterpolantBase::size() const
49 {
50  return size_;
51 }
52 
53 
54 /********************************** Interpolant ********************************/
55 
56 template<template<class> class Func, class Type >
57 Interpolant::Interpolant(Func<Type>* func, bool interpolate_derivative)
58  : func(func),
59  interpolate_derivative(interpolate_derivative)
60 {
61  func_diff = new Func<B<Type> >();
62  func_diffn = new Func<T<Type> >();
63 
65  func_diffn->set_param_from_func(func);
66 
67  checks[Check::functor] = true;
68 }
69 
70 
71 template<template<class> class Func, class Type >
73 {
74  this->interpolate_derivative = interpolate_derivative;
75  this->func = func;
76  func_diff = new Func<B<Type> >();
77  func_diffn = new Func<T<Type> >();
79  func_diffn->set_param_from_func(func);
80 
81  checks[Check::functor] = true;
82 }
83 
84 
85 inline double Interpolant::val(double x)
86 {
87  //increase calls
89 
90  //uncomment if we want to do the check automatically
91  //every STATISTIC_CHECK calls check the statistics
92  //if((stats.total_calls % STATISTIC_CHECK == 0) && use_statistics)
93  // this->check_and_reinterpolate();
94 
95  //return value
96  if(x < bound_a_) //left miss
97  {
98  //DBGMSG("test\n");
99  //std::cout << "test a" << std::endl;
101  stats.min = std::min(stats.min, x);
102 
103  switch(extrapolation)
104  {
106  return f_vec[0];
108  return (f_vec[1] - f_vec[0])*(x/step-a_div_step) + f_vec[0]; //f_vec[0] + p1_vec[0]*(x-x_vec[0]);
110  default:
111  return f_val(x); //otherwise compute original functor
112  }
113  }
114  else if(x > bound_b_) //right miss
115  {
116  //DBGMSG("test\n");
117  //std::cout << "test b" << std::endl;
119  stats.max = std::max(stats.max, x);
120 
121  switch(extrapolation)
122  {
124  return f_vec[size_];
126  return (f_vec[size_] - f_vec[size_-1])*(x-bound_b_+step)/step + f_vec[size_-1];//f_vec[size_-1] + p1_vec[size_-1]*(x-x_vec[size_-1]);
128  default:
129  return f_val(x); //otherwise compute original functor
130  }
131  }
132  else //hit the interval
133  {
134  return val_p1(x);
135  }
136 }
137 
138 inline double Interpolant::val_test(double x)
139 {
140  /*
141  //increase calls
142  stats.total_calls++;
143 
144  if(x < bound_a_)
145  {
146  //std::cout << "test a" << std::endl;
147  return 0;
148  }
149  else if(x > bound_b_) //right miss
150  {
151  //std::cout << "test b" << std::endl;
152  return 0;
153  }
154  else //*/
155  return val_p1(x);
156 }
157 
158 inline DiffValue Interpolant::diff(double x)
159 {
160  OLD_ASSERT(interpolate_derivative, "Derivative is not interpolated. Flag must be switched true in constructor (or set_functor).");
161  //increase calls
162  stats.total_calls++;
163 
164  //uncomment if we want to do the check automatically
165  //every STATISTIC_CHECK calls check the statistics
166  //if((stats.total_calls % STATISTIC_CHECK == 0) && use_statistics)
167  // this->check_and_reinterpolate();
168 
169  if(x < bound_a_) //left miss
170  {
172  stats.min = std::min(stats.min, x);
173  switch(extrapolation)
174  {
176  return DiffValue(f_vec[0],
177  df_vec[0]);
179  return DiffValue((f_vec[1] - f_vec[0])*(x/step-a_div_step) + f_vec[0], //f_vec[0] + p1_vec[0]*(x-x_vec[0]),
180  (df_vec[1] - df_vec[0])*(x/step-a_div_step) + df_vec[0]);//df_vec[0] + p1d_vec[0]*(x-x_vec[0]));
182  default:
183  return f_diff(x); //otherwise compute original functor
184  }
185  }
186  else if(x > bound_b_) //right miss
187  {
189  stats.max = std::max(stats.max, x);
190  switch(extrapolation)
191  {
193  return DiffValue(f_vec[size_],
194  df_vec[size_]);
196  return DiffValue((f_vec[size_] - f_vec[size_-1])*(x-bound_b_+step)/step + f_vec[size_-1], //f_vec[size_-1] + p1_vec[size_-1]*(x-x_vec[size_-1]),
197  (df_vec[size_] - df_vec[size_-1])*(x-bound_b_+step)/step + df_vec[size_-1]);//df_vec[size_-1] + p1d_vec[size_-1]*(x-x_vec[size_-1]) );
199  default:
200  return f_diff(x); //otherwise compute original functor
201  }
202  }
203  else //hit the interval
204  {
205  return diff_p1(x);
206  }
207 }
208 
209 inline double Interpolant::f_val(double x)
210 {
211  return func->operator()(x);
212 }
213 
215 {
216  B<double> xx(x); // Initialize arguments
217  //Func func; // Instantiate functor
218  B<double> f(func_diff->operator()(xx)); // Evaluate function and record DAG
219  f.diff(0,1); // Differentiate
220 
221  DiffValue d;
222  d.first = f.x(); // Value of function
223  d.second = xx.d(0); // Value of df/dx
224  return d; // Return function value
225 }
226 
227 /*
228 inline unsigned int Interpolant::find_interval(double x)
229 {
230  //counts in which interval x is (the last node before x)
231  return floor((x - bound_a_) / step);
232 }
233 */
234 
235 /* //CONSTANT INTERPOLATION
236 inline double Interpolant::val_p0(double x)
237 {
238  return f_vec[find_interval(x)];
239 }
240 
241 inline DiffValue Interpolant::diff_p0(double x)
242 {
243  DiffValue result;
244  unsigned int i = find_interval(x);
245  result.f = f_vec[i];
246  result.dfdx = df_vec[i];
247  return result;
248 }
249 */
250 
251 inline double Interpolant::val_p1(double x)
252 {
253  /*
254 [ OK ] InterpolantTest.InterpolantEval_val (184 ms)
255 [ OK ] InterpolantTest.InterpolantEval_val_p1 (192 ms)
256 [ OK ] InterpolantTest.InterpolantEval_val_test (190 ms)
257 
258  When we used precomputed coeficients of P1 interpolation.
259  */
260  //unsigned int i = floor(x / step - a_div_step);
261  //return p1_vec[i]*(x-x_vec[i]) + f_vec[i];
262 
263  /*
264 [ OK ] InterpolantTest.InterpolantEval_val (162 ms)
265 [ OK ] InterpolantTest.InterpolantEval_val_p1 (163 ms)
266 [ OK ] InterpolantTest.InterpolantEval_val_test (162 ms)
267 
268 These results are satisfying:
269  + the function val_p1 itself is by 14% faster than before
270  + we use only one array to keep the function values
271  + all three functions take the same time which means
272  that the collecting statistics and going through several IF commands
273  does not affect the evaluation time
274  */
275  double x_step = x / step;
276  unsigned int i = floor(x_step - a_div_step);
277 
278  return (f_vec[i+1] - f_vec[i])*(x_step-i-a_div_step) + f_vec[i];
279 }
280 
281 
283 {
284  DiffValue result;
285  //unsigned int i = find_interval(x);
286  //result.first = p1_vec[i]*(x-x_vec[i]) + f_vec[i];
287  //result.second = p1d_vec[i]*(x-x_vec[i]) + df_vec[i];
288 
289  double x_step = x / step;
290  unsigned int i = floor(x_step - a_div_step);
291 
292  result.first = (f_vec[i+1] - f_vec[i])*(x_step-i-a_div_step) + f_vec[i];
293  result.second = (df_vec[i+1] - df_vec[i])*(x_step-i-a_div_step) + df_vec[i];
294 
295  return result;
296 }
297 
298 
299 /** Functor class that computes the argument of the integral \f$ (f(x)-i(x))^p + (f'(x)-i'(x))^p \f$ in the norm \f$ \|f-i\|_{W^1_p} \f$.
300  * It is used as input functor to integration.
301  */
303 {
304 public:
306  : interpolant(interpolant), p_(p), tol_(tol) {}
307 
308  inline double p() {return p_;}
309  inline double tol() {return tol_;}
310 
311  virtual double operator()(double x)
312  {
313  double f_val = interpolant->f_val(x);
314  double a = std::abs(f_val - interpolant->val(x)) / (std::abs(f_val) + tol_);
315 
316  return std::pow(a, p_);
317  }
318 
319 private:
321  double p_;
322  double tol_;
323 };
324 
325  /** Functor class that computes the argument of the integral \f$ (f(x)-i(x))^p + (f'(x)-i'(x))^p \f$ in the norm \f$ \|f-i\|_{W^1_p} \f$.
326  * It is used as input functor to integration.
327  */
329 {
330 public:
332  : interpolant(interpolant), p_(p), tol_(tol) {}
333 
334  inline double p() {return p_;}
335  inline double tol() {return tol_;}
336 
337  virtual double operator()(double x)
338  {
339  DiffValue f = interpolant->f_diff(x);
340  DiffValue g = interpolant->diff(x);
341  double a = std::abs(f.first - g.first) / (std::abs(f.first) + tol_)
342  + std::abs(f.second - g.second) / (std::abs(f.second) + tol_);
343 
344  return std::pow(a, p_);
345  }
346 
347 private:
349  double p_;
350  double tol_;
351 };
352 
353 
354 
355 /********************************** InterpolantImplicit ********************************/
356 
357 template<template<class> class Func, class Type >
359 {
360  this->func = func;
361  func_diff = new Func<B<Type> >();
362  func_diffn = new Func<T<Type> >();
363 
365  func_diffn->set_param_from_func(func);
366 
367  this->interpolate_derivative = interpolate_derivative;
368 
369  checks[Check::functor] = true;
370 }
371 
372 template<template<class> class Func, class Type >
374  : func(func),
375  interpolate_derivative(interpolate_derivative),
376  explicit_interpolant(NULL),
377  fix_(IFixVariable::no_fix)
378 {
379  func_diff = new Func<B<Type> >();
380  func_diffn = new Func<T<Type> >();
381 
383  func_diffn->set_param_from_func(func);
384 
385  checks[Check::functor] = true;
386 }
387 
388  ///class FuncExplicit.
389  /** This functor transforms implicit functor with two variables into
390  * an explicit functor with only one variable and the other one fixed.
391  */
392  template<class Type>
394  {
395  public:
396  ///Constructor.
398 
399  //constructor from templated implicit functor
400  template<class TType>
402  : func_impl(&func_impl), fix_(fix), fix_val(fix_val) {}
403 
404  Type operator()(Type u)
405  {
406  Type ret;
408  ret = func_impl->operator()(fix_val,u);
410  ret = func_impl->operator()(u,fix_val);
411 
412  return ret;
413  }
414 
415  private:
418  double fix_val;
419  };
420 
421 
422 inline double InterpolantImplicit::val(double u)
423 {
424  return explicit_interpolant->val(u);
425 }
426 
428 {
429  return explicit_interpolant->diff(u);
430 }
431 
432 #endif //INTERPOLATION_IMPL_H
FunctorBase< B< double > > * func_diff
Pointer to original functor with FADBAD B type.
Definition: interpolant.hh:378
double bound_b() const
Returns right boundary of the interval.
double a_div_step
bound_ divided by step - precomputed value for evaluation
Definition: interpolant.hh:162
unsigned int interval_miss_b
counts right misses of the interval
Definition: interpolant.hh:140
FuncError_wp1(Interpolant *interpolant, double p, double tol)
InterpolantImplicit()
constructor
Definition: interpolant.cc:547
Type operator()(Type u)
Virtual operator () with type Type.
Abstract templated implicit functor class.
Definition: functors.hh:131
void set_functor(Func< Type > *func, bool interpolate_derivative=false)
Sets the implicit functor.
unsigned int total_calls
counts total calls of evaluation
Definition: interpolant.hh:140
virtual double operator()(double x)
Virtual operator () with type Type.
double error()
Returns error of the interpolation.
double val_test(double x)
Do NOT use, only for testing purpose.
std::vector< double > df_vec
Vector of function derivatives values at nodes.
Definition: interpolant.hh:385
FunctorBase< T< double > > * func_diffn
Pointer to original functor with FADBAD T type.
Definition: interpolant.hh:379
std::pair< double, double > DiffValue
Definition: interpolant.hh:30
FuncError_lp(Interpolant *interpolant, double p, double tol)
I/O functions with filename storing, able to track current line in opened file. All standard stdio fu...
double f_val(double x)
Returns value of the original functor.
std::vector< double > f_vec
Vector of function values at nodes.
Definition: interpolant.hh:384
void set_functor(Func< Type > *func, bool interpolate_derivative=false)
Sets the functor.
double error_
Error of the interpolation.
Definition: interpolant.hh:176
unsigned int size() const
Returns the size of the interpolation table.
IFunctorBase< B< double > > * func_diff
Definition: interpolant.hh:521
Interpolant * explicit_interpolant
Definition: interpolant.hh:526
double max
maximal x for which the evaluation was called outside the interval ((initially is equal the right bou...
Definition: interpolant.hh:144
DiffValue diff(double x)
Returns interpolated value of the derivation.
DiffValue diff_p1(double x)
Finds interval on which x lies.
#define OLD_ASSERT(...)
Definition: global_defs.h:128
FuncExplicit(IFunctorBase< TType > &func_impl, IFixVariable::Type fix, double fix_val)
double val_p1(double x)
Do NOT use, unless you are 100% sure.
means that the linear approximation on the first and last subintervals will be used outside the inter...
Definition: interpolant.hh:38
Structure that keeps statistics of evaluation.
Definition: interpolant.hh:139
x variable will be fixed with given value
Definition: interpolant.hh:59
Abstract templated explicit functor class.
Definition: functors.hh:110
FunctorBase< double > * func
Pointer to original functor with double type.
Definition: interpolant.hh:375
DiffValue diff(double u)
Returns interpolated value of the derivation.
means that the values at the boundary points will be used outside the interval_miss_a ...
Definition: interpolant.hh:37
double val(double x)
Returns interpolated value.
double step
Chosen interpolation step.
Definition: interpolant.hh:162
means that the original functor will be called outside interpolation interval
Definition: interpolant.hh:39
std::vector< bool > checks
Vector of boolean values telling us which parameters are set or not.
Definition: interpolant.hh:201
EvalStatistics stats
Structure which keeps evaluation statistics. See InterpolantBase::eval_statistics.
Definition: interpolant.hh:209
Extrapolation::Type extrapolation
Definition: interpolant.hh:181
The main class for interpolation of functors.
Definition: interpolant.hh:286
IFunctorBase< T< double > > * func_diffn
Definition: interpolant.hh:522
virtual double operator()(double x)
Virtual operator () with type Type.
double bound_a() const
Returns left boundary of the interval.
void set_param_from_func(FunctorCommon< TType > *func)
Sets a functor&#39;s parameters from another functor.
double bound_a_
Left interval boundary.
Definition: interpolant.hh:162
unsigned int interval_miss_a
counts left misses of the interval
Definition: interpolant.hh:140
double val(double u)
Returns interpolated value.
bool interpolate_derivative
Is true if we want to interpolate the derivative too.
Definition: interpolant.hh:381
DiffValue f_diff(double x)
Returns 1st derivative of original functor using FADBAD.
double bound_b_
Right interval boundary.
Definition: interpolant.hh:162
Interpolant()
Default constructor.
Definition: interpolant.cc:159
y variable will be fixed with given value
Definition: interpolant.hh:60
double min
minimal x for which the evaluation was called outside the interval (initially is equal the left bound...
Definition: interpolant.hh:144
EvalStatistics statistics() const
Returns structure with evaluation statistics.
unsigned int size_
Number of dividing intervals.
Definition: interpolant.hh:167