QMCPACK
OptimizedBreakup.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: Paul R. C. Kent, kentpr@ornl.gov, Oak Ridge National Laboratory
8 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
9 //
10 // File created by: Paul R. C. Kent, kentpr@ornl.gov, Oak Ridge National Laboratory
11 //////////////////////////////////////////////////////////////////////////////////////
12 
13 
14 // http://pathintegrals.info //
15 /////////////////////////////////////////////////////////////
16 
17 #ifndef OPTIMIZED_BREAKUP_H
18 #define OPTIMIZED_BREAKUP_H
19 
20 #include "blitz/array.h"
21 
23 {
24 public:
25  //protected:
26  double r_c;
28  double Omega;
29 
30 public:
31  /// Set the cutoff radius
32  virtual void Set_rc(double rc) = 0;
33  inline double Get_rc() { return r_c; }
34  inline void SetBox(TinyVector<double, 3> box);
36  /// Returns the number of basis elements
37  virtual int NumElements() = 0;
38  /// Returns the basis element n evaluated in real space at r
39  virtual double h(int n, double r) = 0;
40  /// Returns the basis element n evaluated in k space at k
41  virtual double c(int n, double k) = 0;
42  virtual double dc_dk(int n, double k) = 0;
43  double c_numerical(int n, double k);
44  /// This returns the coefficient of the nth basis function
45  //virtual double Get_t(int n) const = 0;
46  /// This sets the coefficient of the nth basis function
47  //virtual void Set_t(int n, double t) = 0;
48  /// This returns the linear combination of the basis functions with
49  /// coefficients t_n
50  //virtual double f (double r) = 0;
51  BasisClass() : r_c(0.0)
52  { /* do nothing */
53  }
54 };
55 
56 
58 {
59 private:
61  void Addk(double k, double degeneracy = 1.0);
62 
63 public:
64  // First element is |k|, second is degeneracy of the point.
66  void SetkVecs(double kc, double kcont, double kMax);
67  /// kc is the k-space cutoff for the Ewald sum.
68  /// kMax is largest k we use in determining the error in the breakup.
69  /// t is the set of coefficients of the breakup.
70  /// inFit is a boolean array telling whether t_n should be optimized
71  /// or left at its initial value. Returns chi-squared for the breakup.
72  double DoBreakup(const Array<double, 1>& Vk, Array<double, 1>& t, const Array<bool, 1>& adjust);
73  /// Same as above, but we assume that all t's are adjusted.
74  double DoBreakup(const Array<double, 1>& Vk, Array<double, 1>& t);
76  { /* Do nothing */
77  }
78 };
79 
80 
82 {
83  Box = box;
84  Omega = box[0] * box[1] * box[2];
85 }
86 
88 
89 
90 /// Locally Piecewise Quintic Hermite Interpolant
92 {
93  /// public is HACK
94  //private:
95 public:
96  int NumKnots;
97  double delta, deltaInv;
99  /// The following are helpers to calculate the Fourier transform of
100  /// the basis functions
101  inline std::complex<double> Eplus(int i, double k, int n);
102  inline std::complex<double> Eminus(int i, double k, int n);
103  inline double Dplus(int i, double k, int n);
104  inline double Dminus(int i, double k, int n);
105  inline std::complex<double> dEplus_dk(int i, double k, int n);
106  inline std::complex<double> dEminus_dk(int i, double k, int n);
107  inline double dDplus_dk(int i, double k, int n);
108  inline double dDminus_dk(int i, double k, int n);
110 
111 public:
112  inline double GetDelta() { return delta; }
113  // n must be at least 2;
114  void SetNumKnots(int n);
115  void Set_rc(double rc);
116  int NumElements();
117  double h(int n, double r);
118  double c(int n, double k);
119  double dc_dk(int n, double k);
121  {
122  S = 1.0, 0.0, 0.0, -10.0, 15.0, -6.0, 0.0, 1.0, 0.0, -6.0, 8.0, -3.0, 0.0, 0.0, 0.5, -1.5, 1.5, -0.5;
123  }
124 };
125 
126 inline std::complex<double> LPQHI_BasisClass::Eplus(int i, double k, int n)
127 {
128  std::complex<double> eye(0.0, 1.0);
129 
130  if (n == 0)
131  {
132  std::complex<double> e1(cos(k * delta) - 1.0, sin(k * delta));
133  std::complex<double> e2(cos(k * delta * i), sin(k * delta * i));
134  return (-(eye / k) * e1 * e2);
135  }
136  else
137  {
138  std::complex<double> t1, t2;
139  double sign = 1.0;
140  t1 = std::complex<double>(cos(k * delta * (i + 1)), sin(k * delta * (i + 1)));
141  t2 = -(double)n / delta * Eplus(i, k, n - 1);
142  ;
143  return (-(eye / k) * (t1 + t2));
144  }
145 }
146 
147 inline std::complex<double> LPQHI_BasisClass::dEplus_dk(int i, double k, int n)
148 {
149  std::complex<double> eye(0.0, 1.0);
150 
151  if (n == 0)
152  {
153  std::complex<double> e1(cos(k * delta) - 1.0, sin(k * delta));
154  std::complex<double> de1(-delta * sin(k * delta), delta * cos(k * delta));
155  std::complex<double> e2(cos(k * delta * i), sin(k * delta * i));
156  std::complex<double> de2(-delta * i * sin(k * delta * i), delta * i * cos(k * delta * i));
157  return ((eye / (k * k)) * e1 * e2 - (eye / k) * (de1 * e2 + e1 * de2));
158  }
159  else
160  {
161  std::complex<double> t1, t2, dt1, dt2;
162  double sign = 1.0;
163  t1 = std::complex<double>(cos(k * delta * (i + 1)), sin(k * delta * (i + 1)));
164  dt1 = std::complex<double>(-delta * (i + 1) * sin(k * delta * (i + 1)), delta * (i + 1) * cos(k * delta * (i + 1)));
165  t2 = -(double)n / delta * Eplus(i, k, n - 1);
166  dt2 = -(double)n / delta * dEplus_dk(i, k, n - 1);
167  return ((eye / (k * k)) * (t1 + t2) - (eye / k) * (dt1 + dt2));
168  }
169 }
170 
171 inline std::complex<double> LPQHI_BasisClass::Eminus(int i, double k, int n)
172 {
173  std::complex<double> eye(0.0, 1.0);
174 
175  if (n == 0)
176  {
177  std::complex<double> e1(cos(k * delta) - 1.0, -sin(k * delta));
178  std::complex<double> e2(cos(k * delta * i), sin(k * delta * i));
179  return (-(eye / k) * e1 * e2);
180  }
181  else
182  {
183  std::complex<double> t1, t2;
184  double sign = (n & 1) ? -1.0 : 1.0;
185  t1 = sign * std::complex<double>(cos(k * delta * (i - 1)), sin(k * delta * (i - 1)));
186  t2 = -(double)n / delta * Eminus(i, k, n - 1);
187  return (-(eye / k) * (t1 + t2));
188  }
189 }
190 
191 inline std::complex<double> LPQHI_BasisClass::dEminus_dk(int i, double k, int n)
192 {
193  std::complex<double> eye(0.0, 1.0);
194 
195  if (n == 0)
196  {
197  std::complex<double> e1(cos(k * delta) - 1.0, -sin(k * delta));
198  std::complex<double> de1(-delta * sin(k * delta), -delta * cos(k * delta));
199  std::complex<double> e2(cos(k * delta * i), sin(k * delta * i));
200  std::complex<double> de2(-delta * i * sin(k * delta * i), delta * i * cos(k * delta * i));
201  return ((eye / (k * k)) * e1 * e2 - (eye / k) * (de1 * e2 + e1 * de2));
202  }
203  else
204  {
205  std::complex<double> t1, t2, dt1, dt2;
206  double sign = (n & 1) ? -1.0 : 1.0;
207  t1 = sign * std::complex<double>(cos(k * delta * (i - 1)), sin(k * delta * (i - 1)));
208  dt1 = sign *
209  std::complex<double>(-delta * (i - 1) * sin(k * delta * (i - 1)), delta * (i - 1) * cos(k * delta * (i - 1)));
210  t2 = -(double)n / delta * Eminus(i, k, n - 1);
211  dt2 = -(double)n / delta * dEminus_dk(i, k, n - 1);
212  return ((eye / (k * k)) * (t1 + t2) - (eye / k) * (dt1 + dt2));
213  }
214 }
215 
216 
217 inline double LPQHI_BasisClass::Dplus(int i, double k, int n)
218 {
219  std::complex<double> eye(0.0, 1.0);
220  std::complex<double> Z1 = Eplus(i, k, n + 1);
221  std::complex<double> Z2 = Eplus(i, k, n);
222  return 4.0 * M_PI / (k * Omega) * (delta * Z1.imag() + i * delta * Z2.imag());
223 }
224 
225 inline double LPQHI_BasisClass::dDplus_dk(int i, double k, int n)
226 {
227  std::complex<double> eye(0.0, 1.0);
228  std::complex<double> Z1 = Eplus(i, k, n + 1);
229  std::complex<double> Z2 = Eplus(i, k, n);
230  std::complex<double> dZ1 = dEplus_dk(i, k, n + 1);
231  std::complex<double> dZ2 = dEplus_dk(i, k, n);
232  return -4.0 * M_PI / (k * k * Omega) * (delta * Z1.imag() + i * delta * Z2.imag()) +
233  4.0 * M_PI / (k * Omega) * (delta * dZ1.imag() + i * delta * dZ2.imag());
234 }
235 
236 inline double LPQHI_BasisClass::Dminus(int i, double k, int n)
237 {
238  std::complex<double> eye(0.0, 1.0);
239  std::complex<double> Z1 = Eminus(i, k, n + 1);
240  std::complex<double> Z2 = Eminus(i, k, n);
241  return -4.0 * M_PI / (k * Omega) * (delta * Z1.imag() + i * delta * Z2.imag());
242 }
243 
244 inline double LPQHI_BasisClass::dDminus_dk(int i, double k, int n)
245 {
246  std::complex<double> eye(0.0, 1.0);
247  std::complex<double> Z1 = Eminus(i, k, n + 1);
248  std::complex<double> dZ1 = dEminus_dk(i, k, n + 1);
249  std::complex<double> Z2 = Eminus(i, k, n);
250  std::complex<double> dZ2 = dEminus_dk(i, k, n);
251  return 4.0 * M_PI / (k * k * Omega) * (delta * Z1.imag() + i * delta * Z2.imag()) -
252  4.0 * M_PI / (k * Omega) * (delta * dZ1.imag() + i * delta * dZ2.imag());
253 }
254 
255 
256 #endif
BasisClass()
This returns the coefficient of the nth basis function.
virtual int NumElements()=0
Returns the number of basis elements.
virtual double h(int n, double r)=0
Returns the basis element n evaluated in real space at r.
double dDplus_dk(int i, double k, int n)
void Addk(double k, double degeneracy=1.0)
MakeReturn< UnaryNode< FnSin, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sin(const Vector< T1, C1 > &l)
virtual void Set_rc(double rc)=0
Set the cutoff radius.
std::complex< double > dEplus_dk(int i, double k, int n)
int NumElements()
Returns the number of basis elements.
void SetkVecs(double kc, double kcont, double kMax)
double h(int n, double r)
Returns the basis element n evaluated in real space at r.
TinyMatrix< double, 3, 6 > S
std::complex< double > Eminus(int i, double k, int n)
MakeReturn< UnaryNode< FnCos, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t cos(const Vector< T1, C1 > &l)
double c(int n, double k)
Returns the basis element n evaluated in k space at k.
double c_numerical(int n, double k)
double DoBreakup(const Array< double, 1 > &Vk, Array< double, 1 > &t, const Array< bool, 1 > &adjust)
kc is the k-space cutoff for the Ewald sum.
void Set_rc(double rc)
Set the cutoff radius.
virtual double dc_dk(int n, double k)=0
void SetNumKnots(int n)
TinyVector< double, 3 > Box
double Dplus(int i, double k, int n)
double sign(double x)
Definition: Standard.h:73
OptimizedBreakupClass(BasisClass &basis)
double Get_rc()
Locally Piecewise Quintic Hermite Interpolant.
double dc_dk(int n, double k)
double dDminus_dk(int i, double k, int n)
Array< TinyVector< double, 2 >, 1 > kpoints
double Dminus(int i, double k, int n)
std::complex< double > dEminus_dk(int i, double k, int n)
void SetBox(TinyVector< double, 3 > box)
Array< double, 1 > tvec
virtual double c(int n, double k)=0
Returns the basis element n evaluated in k space at k.
A D-dimensional Array class based on PETE.
Definition: OhmmsArray.h:25
TinyVector< double, 3 > GetBox()
int NumKnots
public is HACK
std::complex< double > Eplus(int i, double k, int n)
The following are helpers to calculate the Fourier transform of the basis functions.