MADNESS  version 0.9
interp.h
Go to the documentation of this file.
1 /*
2  This file is part of MADNESS.
3 
4  Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20  For more information please contact:
21 
22  Robert J. Harrison
23  Oak Ridge National Laboratory
24  One Bethel Valley Road
25  P.O. Box 2008, MS-6367
26 
27  email: harrisonrj@ornl.gov
28  tel: 865-241-3937
29  fax: 865-572-0680
30 
31  $Id$
32 */
33 #ifndef INTERP_H
34 #define INTERP_H
35 #include "wavef.h"
36 //#include <madness/world/world.h>
37 #include <cmath>
38 using std::max;
39 #include <vector>
40 
41 
42 template <typename T>
44  double lo; //< Interpolation is in range [lo,hi]
45  double hi; //< Interpolation is in range [lo,hi]
46  double h; //< Grid spacing
47  double rh; //< 1/h
48  int npt; //< No. of grid points
49  std::vector<T> a; //< (1+4)*npt vector of x and polynomial coefficients
50  // Cubic interp thru 4 points ... not good for noisy data
51  void cubic_fit(const double* x, const T* f, T* a) {
52  double x0_2 = x[0] * x[0], x1_2 = x[1] * x[1], x2_2 = x[2] * x[2], x3_2 = x[3] * x[3];
53  double x0_3 = x[0] * x[0] * x[0], x1_3 = x[1] * x[1] * x[1], x2_3 = x[2] * x[2] * x[2], x3_3 = x[3] * x[3] * x[3];
54 
55  a[0] = -(-x0_3 * x2_2 * x[3] * f[1] + x0_3 * x[2] * x3_2 * f[1] - x0_3 * f[3] * x[2] * x1_2 + x0_3 * x[3] * f[2] * x1_2 + x0_3 * f[3] * x2_2 * x[1] - x0_3 * x3_2 * f[2] * x[1] + x0_2 * x1_3 * f[3] * x[2] - x0_2 * x1_3 * f[2] * x[3] + x0_2 * x3_3 * f[2] * x[1] + x0_2 * f[1] * x2_3 * x[3] - x0_2 * f[1] * x3_3 * x[2] - x0_2 * f[3] * x2_3 * x[1] + x[0] * x3_2 * f[2] * x1_3 - x[0] * f[3] * x2_2 * x1_3 + x[0] * x1_2 * f[3] * x2_3 - x[0] * x1_2 * f[2] * x3_3 - x[0] * f[1] * x3_2 * x2_3 + x[0] * f[1] * x2_2 * x3_3 - f[0] * x2_3 * x1_2 * x[3] + f[0] * x2_2 * x1_3 * x[3] + f[0] * x3_2 * x2_3 * x[1] - f[0] * x3_3 * x2_2 * x[1] + f[0] * x3_3 * x1_2 * x[2] - f[0] * x3_2 * x1_3 * x[2]) / (-x2_2 * x[0] * x3_3 + x2_2 * x[0] * x1_3 - x0_2 * x[3] * x2_3 + x0_2 * x3_3 * x[2] - x0_2 * x[1] * x3_3 + x0_2 * x[1] * x2_3 + x0_2 * x1_3 * x[3] - x0_2 * x1_3 * x[2] + x3_2 * x[0] * x2_3 - x3_2 * x[0] * x1_3 + x[3] * x2_3 * x1_2 - x3_2 * x2_3 * x[1] + x3_3 * x2_2 * x[1] - x3_3 * x[2] * x1_2 + x[0] * x3_3 * x1_2 - x[0] * x2_3 * x1_2 - x0_3 * x3_2 * x[2] - x0_3 * x[3] * x1_2 + x0_3 * x3_2 * x[1] + x[2] * x3_2 * x1_3 - x2_2 * x[3] * x1_3 + x0_3 * x2_2 * x[3] - x0_3 * x2_2 * x[1] + x0_3 * x[2] * x1_2);
56  a[1] = (-x2_3 * x1_2 * f[0] + x3_2 * x2_3 * f[0] + x2_3 * x0_2 * f[1] + x1_2 * f[3] * x2_3 - x2_3 * x0_2 * f[3] - f[1] * x3_2 * x2_3 - f[3] * x2_2 * x1_3 - x3_3 * x2_2 * f[0] + f[1] * x2_2 * x3_3 + x2_2 * x1_3 * f[0] - f[1] * x2_2 * x0_3 + f[3] * x2_2 * x0_3 - x1_3 * x3_2 * f[0] - x0_2 * x1_3 * f[2] - f[3] * x0_3 * x1_2 + f[1] * x3_2 * x0_3 + x1_2 * f[2] * x0_3 + x3_3 * f[0] * x1_2 - x3_2 * f[2] * x0_3 - f[1] * x3_3 * x0_2 + x0_2 * x3_3 * f[2] - x1_2 * f[2] * x3_3 + x3_2 * f[2] * x1_3 + x0_2 * x1_3 * f[3]) / (-x[3] + x[2]) / (-x2_2 * x0_2 * x[3] - x2_2 * x[1] * x3_2 + x2_2 * x1_2 * x[3] + x2_2 * x[0] * x3_2 - x2_2 * x[0] * x1_2 + x2_2 * x0_2 * x[1] + x[2] * x[0] * x1_3 + x[2] * x0_3 * x[3] - x[2] * x0_3 * x[1] - x[2] * x1_3 * x[3] - x[2] * x0_2 * x3_2 + x[2] * x1_2 * x3_2 - x[2] * x[3] * x[0] * x1_2 + x[2] * x[3] * x0_2 * x[1] + x0_3 * x1_2 - x0_2 * x1_3 + x[3] * x[0] * x1_3 - x[3] * x0_3 * x[1] - x3_2 * x[0] * x1_2 + x3_2 * x0_2 * x[1]);
57  a[2] = -(-x1_3 * f[3] * x[2] + x1_3 * f[2] * x[3] + x1_3 * x[0] * f[3] + x1_3 * f[0] * x[2] - x1_3 * x[0] * f[2] - x1_3 * f[0] * x[3] + f[3] * x2_3 * x[1] - f[3] * x0_3 * x[1] - x[1] * x2_3 * f[0] + x[1] * f[2] * x0_3 + x3_3 * f[0] * x[1] - x3_3 * f[2] * x[1] + f[1] * x[3] * x0_3 - f[1] * x[0] * x3_3 - x3_3 * f[0] * x[2] + x3_3 * x[0] * f[2] - f[2] * x0_3 * x[3] + x2_3 * f[0] * x[3] + f[1] * x3_3 * x[2] - f[1] * x2_3 * x[3] + x2_3 * x[0] * f[1] - x2_3 * x[0] * f[3] + f[3] * x0_3 * x[2] - x[2] * f[1] * x0_3) / (x[3] * x2_2 - x3_2 * x[2] + x[1] * x3_2 - x[1] * x2_2 - x1_2 * x[3] + x1_2 * x[2]) / (-x[2] * x[1] * x[3] + x[1] * x[2] * x[0] - x0_2 * x[1] + x[1] * x[3] * x[0] + x[2] * x[3] * x[0] + x0_3 - x0_2 * x[2] - x0_2 * x[3]);
58  a[3] = (x[0] * f[3] * x1_2 - x0_2 * x[3] * f[2] + x2_2 * x[0] * f[1] + x0_2 * f[3] * x[2] - x3_2 * f[2] * x[1] - f[0] * x3_2 * x[2] - f[3] * x[2] * x1_2 - x2_2 * x[0] * f[3] - f[0] * x2_2 * x[1] + f[3] * x2_2 * x[1] + x0_2 * f[1] * x[3] + x[2] * x3_2 * f[1] - x0_2 * f[1] * x[2] + f[0] * x[2] * x1_2 + x[3] * f[2] * x1_2 + f[0] * x3_2 * x[1] + x3_2 * x[0] * f[2] - x[0] * f[2] * x1_2 - f[0] * x[3] * x1_2 - x0_2 * x[1] * f[3] + x0_2 * x[1] * f[2] + f[0] * x2_2 * x[3] - x2_2 * x[3] * f[1] - x3_2 * x[0] * f[1]) / (-x2_2 * x[0] * x3_3 + x2_2 * x[0] * x1_3 - x0_2 * x[3] * x2_3 + x0_2 * x3_3 * x[2] - x0_2 * x[1] * x3_3 + x0_2 * x[1] * x2_3 + x0_2 * x1_3 * x[3] - x0_2 * x1_3 * x[2] + x3_2 * x[0] * x2_3 - x3_2 * x[0] * x1_3 + x[3] * x2_3 * x1_2 - x3_2 * x2_3 * x[1] + x3_3 * x2_2 * x[1] - x3_3 * x[2] * x1_2 + x[0] * x3_3 * x1_2 - x[0] * x2_3 * x1_2 - x0_3 * x3_2 * x[2] - x0_3 * x[3] * x1_2 + x0_3 * x3_2 * x[1] + x[2] * x3_2 * x1_3 - x2_2 * x[3] * x1_3 + x0_3 * x2_2 * x[3] - x0_3 * x2_2 * x[1] + x0_3 * x[2] * x1_2);
59  }
60 
61 public:
62  template <typename functionT>
63  CubicInterpolationTable(double lo, double hi, int npt, functionT& f)
64  : lo(lo)
65  , hi(hi)
66  , h((hi-lo)/(npt-1))
67  , rh(1.0/h)
68  , npt(npt)
69  , a(npt*5)
70  {
71  // Evaluate the function to be interpolated
72  std::vector<T> p(npt);
73  std::vector<double> x(npt);
74  for (int i=0; i<npt; i++) p[i] = 0.0;
75  for (int i=0; i<npt; i++) {
76  x[i] = lo + i*h;
77  p[i] = f(x[i]);
78  }
79  // Generate interior polynomial coeffs
80  for (int i=1; i<=npt-3; i++) {
81  double mid = (x[i] + x[i+1])*0.5;
82  double y[4] = {x[i-1]-mid,x[i]-mid,x[i+1]-mid,x[i+2]-mid};
83  a[i*5] = mid;
84  cubic_fit(y, &p[i-1], &a[i*5+1]);
85  }
86  // Fixup end points
87  for (int j=0; j<5; j++) {
88  a[j] = a[5+j];
89  a[5*npt-5+j] = a[5*npt-10+j] = a[5*npt-15+j];
90  }
91  }
92 
93 
94  template <typename functionT>
95  CubicInterpolationTable(madness::World& world, double lo, double hi, int npt, functionT& f)
96  : lo(lo)
97  , hi(hi)
98  , h((hi-lo)/(npt-1))
99  , rh(1.0/h)
100  , npt(npt)
101  , a(npt*5)
102  {
103  // Evaluate the function to be interpolated
104  std::vector<T> p(npt);
105  std::vector<double> x(npt);
106  for (int i=0; i<npt; i++) {
107  x[i] = 0.0;
108  p[i] = 0.0;
109  }
110  for (int i=world.rank(); i<npt; i+=world.size()) {
111  x[i] = lo + i*h;
112  p[i] = f(x[i]);
113  }
114  // Gather / Broadcast elements of x and v
115  world.gop.sum(&p[0], npt);
116  world.gop.sum(&x[0], npt);
117  // Generate interior polynomial coeffs
118  for(int i=0; i<5*npt; i++) {
119  a[i] = 0.0;
120  }
121  for (int i=1+world.rank(); i<=npt-3; i+=world.size()) {
122  double mid = (x[i] + x[i+1])*0.5;
123  double y[4] = {x[i-1]-mid,x[i]-mid,x[i+1]-mid,x[i+2]-mid};
124  a[i*5] = mid;
125  cubic_fit(y, &p[i-1], &a[i*5+1]);
126  }
127  world.gop.sum(&a[0], 5*npt);
128  // Fixup end points
129  for (int j=0; j<5; j++) {
130  a[j] = a[5+j];
131  a[5*npt-5+j] = a[5*npt-10+j] = a[5*npt-15+j];
132  }
133  }
134 
136 
137  double myreal(const std::complex<double>& z) const {return z.real();}
138 
139  double myreal(double x) {return x;}
140 
141  T operator()(double y) const {
142  int i = (y-lo)*rh;
143  if (i<0 || i>=npt) throw "Out of range point";
144  i *= 5;
145  y -= myreal(a[i]);
146  double yy = y*y;
147  return (a[i+1] + y*a[i+2]) + yy*(a[i+3] + y*a[i+4]);
148  }
149 
150 // struct MemFuncPtr {
151 // ScatteringWF* obj;
152 // MemFuncPtr(CubicInterpolationTable* obj) : thisObj(obj) {}
153 // T operator()() { return thisObj->err }
154 // };
155 
156  template <typename fredT>
157  double err(fredT f) const {
158  double maxabserr = 0.0;
159  double h7 = h/7.0;
160  for (int i=0; i<7*npt; i++) {
161  double x = lo + h7*i;
162  T fit = (*this)(x);
163  T exact = f(x);
164  maxabserr = max(std::abs(fit-exact),maxabserr);
165  }
166  return maxabserr;
167  }
168 };
169 #endif
WorldGopInterface & gop
Global operations.
Definition: worldfwd.h:462
double myreal(double x)
Definition: interp.h:139
T operator()(double y) const
Definition: interp.h:141
NDIM & f
Definition: mra.h:2179
ProcessID size() const
Returns the number of processes in this world (same as MPI_Comm_size())
Definition: worldfwd.h:533
double err(fredT f) const
Definition: interp.h:157
FLOAT fit(const FLOAT &x, const vector< FLOAT > &p)
Definition: y.cc:326
CubicInterpolationTable()
Definition: interp.h:135
const T1 &f1 return GTEST_2_TUPLE_() T(f0, f1)
#define max(a, b)
Definition: lda.h:53
CubicInterpolationTable(madness::World &world, double lo, double hi, int npt, functionT &f)
Definition: interp.h:95
CubicInterpolationTable(double lo, double hi, int npt, functionT &f)
Definition: interp.h:63
void sum(T *buf, size_t nelem)
Inplace global sum while still processing AM & tasks.
Definition: worldgop.h:767
A parallel world with full functionality wrapping an MPI communicator.
Definition: worldfwd.h:416
ProcessID rank() const
Returns the process rank in this world (same as MPI_Comm_rank()))
Definition: worldfwd.h:526
double myreal(const std::complex< double > &z) const
Definition: interp.h:137
An class for 1-D data interpolation based on cubic polynomials.
Definition: interp.h:43