QMCPACK
BsplineOneDimSolvers.h
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
9 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
10 //
11 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
12 //////////////////////////////////////////////////////////////////////////////////////
13 
14 
15 #ifndef BSPLINE_ONEDIM_SOLVERS
16 #define BSPLINE_ONEDIM_SOLVERS
17 #include <vector>
18 #include <complex>
19 /** dummy declaration to be specialized
20  *
21  * Specializations for double and std::complex<double>
22  */
23 template<typename T>
25 {};
26 
27 template<typename T>
28 inline void FuncSolvePeriodicInterp1D(const std::vector<T>& data, std::vector<T>& p)
29 {
30  const T ratio = 0.25;
31  int N = data.size();
32  std::vector<T> d(N), gamma(N), mu(N);
33  //d = 1.5*data;
34  for (int i = 0; i < N; i++)
35  d[i] = 1.5 * data[i];
36  // First, eliminate leading coefficients
37  gamma[0] = ratio;
38  mu[0] = ratio;
39  mu[N - 1] = ratio;
40  gamma[N - 1] = 1.0;
41  for (int row = 1; row < (N - 1); row++)
42  {
43  double diag = 1.0 - mu[row - 1] * ratio;
44  double diagInv = 1.0 / diag;
45  gamma[row] = -ratio * gamma[row - 1] * diagInv;
46  mu[row] = diagInv * ratio;
47  d[row] = diagInv * (d[row] - ratio * d[row - 1]);
48  // Last row
49  d[N - 1] -= mu[N - 1] * d[row - 1];
50  gamma[N - 1] -= mu[N - 1] * gamma[row - 1];
51  mu[N - 1] = -mu[N - 1] * mu[row - 1];
52  }
53  // Last row: gamma(N-1) hold diagonal element
54  mu[N - 1] += ratio;
55  gamma[N - 1] -= mu[N - 1] * (mu[N - 2] + gamma[N - 2]);
56  d[N - 1] -= mu[N - 1] * d[N - 2];
57  p[N - 1] = d[N - 1] / gamma[N - 1];
58  // Now go back upward, back substituting
59  for (int row = N - 2; row >= 0; row--)
60  p[row] = d[row] - mu[row] * p[row + 1] - gamma[row] * p[N - 1];
61 }
62 
63 template<>
64 struct SolvePeriodicInterp1D<double>
65 {
66  static inline void apply(const std::vector<double>& data, std::vector<double>& p)
67  {
69  }
70 
71  template<typename CT>
72  static inline void apply(const CT& data, CT& p, int N)
73  {
74  const double ratio = 0.25;
75  CT d(N), gamma(N), mu(N);
76  for (int i = 0; i < N; i++)
77  d[i] = 1.5 * data[i];
78  // First, eliminate leading coefficients
79  gamma[0] = ratio;
80  mu[0] = ratio;
81  mu[N - 1] = ratio;
82  gamma[N - 1] = 1.0;
83  for (int row = 1; row < (N - 1); row++)
84  {
85  double diag = 1.0 - mu[row - 1] * ratio;
86  double diagInv = 1.0 / diag;
87  gamma[row] = -ratio * gamma[row - 1] * diagInv;
88  mu[row] = diagInv * ratio;
89  d[row] = diagInv * (d[row] - ratio * d[row - 1]);
90  // Last row
91  d[N - 1] -= mu[N - 1] * d[row - 1];
92  gamma[N - 1] -= mu[N - 1] * gamma[row - 1];
93  mu[N - 1] = -mu[N - 1] * mu[row - 1];
94  }
95  // Last row: gamma(N-1) hold diagonal element
96  mu[N - 1] += ratio;
97  gamma[N - 1] -= mu[N - 1] * (mu[N - 2] + gamma[N - 2]);
98  d[N - 1] -= mu[N - 1] * d[N - 2];
99  p[N] = d[N - 1] / gamma[N - 1];
100  // Now go back upward, back substituting
101  for (int row = N - 2; row >= 0; row--)
102  p[row + 1] = d[row] - mu[row] * p[row + 2] - gamma[row] * p[N];
103  }
104 };
105 
106 template<>
107 struct SolvePeriodicInterp1D<std::complex<double>>
108 {
109  using value_type = std::complex<double>;
110  using real_type = double;
111 
112  static inline void apply(const std::vector<value_type>& data, std::vector<value_type>& p)
113  {
114  int N = data.size();
115  std::vector<real_type> dataReal(N), dataImag(N), pReal(N), pImag(N);
116  for (int i = 0; i < N; i++)
117  {
118  dataReal[i] = data[i].real();
119  dataImag[i] = data[i].imag();
120  }
121  SolvePeriodicInterp1D<double>::apply(dataReal, pReal);
122  SolvePeriodicInterp1D<double>::apply(dataImag, pImag);
123  for (int i = 0; i < N; i++)
124  p[i] = value_type(pReal[i], pImag[i]);
125  }
126 };
127 
128 
129 template<typename T>
131 {};
132 
133 template<>
135 {
136  template<class CT>
137  static inline void apply(const CT& data, CT& p, int N, double* bcLower, double* bcUpper)
138  {
139  const double ratio = 0.25;
140  CT d(N + 2), mu(N + 2, ratio);
141  for (int i = 1; i <= N; i++)
142  d[i] = 1.5 * data[i - 1];
143  double al = 0.25 * bcLower[0];
144  double bl = 0.25 * bcLower[1];
145  double cl = 0.25 * bcLower[2];
146  double dl = 1.5 * bcLower[3];
147  double ar = 0.25 * bcUpper[0];
148  double br = 0.25 * bcUpper[1];
149  double cr = 0.25 * bcUpper[2];
150  double dr = 1.5 * bcUpper[3];
151  // First, eliminate leading coefficients
152  double alInv = 1.0 / al;
153  bl *= alInv;
154  cl *= alInv;
155  dl *= alInv;
156  d[0] = dl;
157  mu[0] = bl;
158  mu[1] = ratio - ratio * cl;
159  for (int row = 1; row <= N; row++)
160  {
161  double diag = 1.0 - mu[row - 1] * ratio;
162  double diagInv = 1.0 / diag;
163  mu[row] *= diagInv;
164  d[row] = diagInv * (d[row] - ratio * d[row - 1]);
165  }
166  br -= ar * mu[N - 1];
167  dr -= ar * d[N - 1];
168  cr -= br * mu[N];
169  dr -= br * d[N];
170  p[N + 1] = dr / cr;
171  // Now go back upward, back substituting
172  for (int row = N; row >= 1; row--)
173  p[row] = d[row] - mu[row] * p[row + 1];
174  // And do 0th row
175  p[0] = dl - bl * p[1] - cl * p[2];
176  }
177 };
178 
179 template<>
180 struct SolveFirstDerivInterp1D<std::complex<double>>
181 {
182  using value_type = std::complex<double>;
183  using real_type = double;
184 
185  template<class CT>
186  static inline void apply(const CT& data, CT& p, int N, double* bcLower, double* bcUpper)
187  {
188  std::vector<real_type> dataReal(N), dataImag(N), pReal(N), pImag(N);
189  for (int i = 0; i < N; i++)
190  {
191  dataReal[i] = data[i].real();
192  dataImag[i] = data[i].imag();
193  }
194  SolveFirstDerivInterp1D<double>::apply(dataReal, pReal, N, bcLower, bcUpper);
195  SolveFirstDerivInterp1D<double>::apply(dataImag, pImag, N, bcLower, bcUpper);
196  for (int i = 0; i < N; i++)
197  p[i] = value_type(pReal[i], pImag[i]);
198  }
199 };
200 
201 template<>
203 {
204  template<class CT>
205  static inline void apply(const CT& data, CT& p, int N, float* bcLower, float* bcUpper)
206  {
207  std::vector<double> data_d(N), p_d(N);
208  std::copy(data.begin(), data.end(), data_d.begin());
209  double bcLower_d[4];
210  double bcUpper_d[4];
211  std::copy(bcLower, bcLower + 4, bcLower_d);
212  std::copy(bcUpper, bcUpper + 4, bcUpper_d);
213 
214  SolveFirstDerivInterp1D<double>::apply(data_d, p_d, N, bcLower_d, bcUpper_d);
215 
216  std::copy(p_d.begin(), p_d.end(), p.begin());
217  }
218 };
219 
220 template<>
221 struct SolveFirstDerivInterp1D<std::complex<float>>
222 {
223  using value_type = std::complex<float>;
224  using real_type = float;
225 
226  template<class CT>
227  static inline void apply(const CT& data, CT& p, int N, float* bcLower, float* bcUpper)
228  {
229  std::vector<double> dataReal(N), dataImag(N), pReal(N), pImag(N);
230  for (int i = 0; i < N; i++)
231  {
232  dataReal[i] = data[i].real();
233  dataImag[i] = data[i].imag();
234  }
235 
236  double bcLower_d[4];
237  double bcUpper_d[4];
238  std::copy(bcLower, bcLower + 4, bcLower_d);
239  std::copy(bcUpper, bcUpper + 4, bcUpper_d);
240  SolveFirstDerivInterp1D<double>::apply(dataReal, pReal, N, bcLower_d, bcUpper_d);
241  SolveFirstDerivInterp1D<double>::apply(dataImag, pImag, N, bcLower_d, bcUpper_d);
242 
243  for (int i = 0; i < N; i++)
244  p[i] = value_type(static_cast<float>(pReal[i]), static_cast<float>(pImag[i]));
245  }
246 };
247 #endif
void FuncSolvePeriodicInterp1D(const std::vector< T > &data, std::vector< T > &p)
static void apply(const std::vector< double > &data, std::vector< double > &p)
dummy declaration to be specialized
void copy(const Array< T1, 3 > &src, Array< T2, 3 > &dest)
Definition: Blitz.h:639
static void apply(const CT &data, CT &p, int N, double *bcLower, double *bcUpper)
static void apply(const std::vector< value_type > &data, std::vector< value_type > &p)
static void apply(const CT &data, CT &p, int N, double *bcLower, double *bcUpper)
static void apply(const CT &data, CT &p, int N)
static void apply(const CT &data, CT &p, int N, float *bcLower, float *bcUpper)
static void apply(const CT &data, CT &p, int N, float *bcLower, float *bcUpper)
QMCTraits::FullPrecRealType value_type