QMCPACK
PWBasis.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 /** @file PWBasis.h
16  * @brief Declaration of Plane-wave basis set
17  */
18 #ifndef QMCPLUSPLUS_PLANEWAVEBASIS_BLAS_H
19 #define QMCPLUSPLUS_PLANEWAVEBASIS_BLAS_H
20 
21 #include "Configuration.h"
22 #include "Particle/ParticleSet.h"
23 #include "Message/Communicate.h"
24 #include "CPU/e2iphi.h"
25 #include "hdf/hdf_archive.h"
26 
27 /** If defined, use recursive method to build the basis set for each position
28  *
29  * performance improvement is questionable: load vs sin/cos
30  */
31 //#define PWBASIS_USE_RECURSIVE
32 
33 namespace qmcplusplus
34 {
35 /** Plane-wave basis set
36  *
37  * Rewrite of PlaneWaveBasis to utilize blas II or III
38  * Support more general input tags
39  */
40 class PWBasis : public QMCTraits
41 {
42 public:
45 
46 private:
47  ///max of maxg[i]
48  int maxmaxg;
49  //Need to store the maximum translation in each dimension to use recursive PW generation.
51  //The PlaneWave data - keep all of these strictly private to prevent inconsistencies.
53  ///twist angle in reduced
55  ///twist angle in cartesian
56  PosType twist_cart; //Twist angle in reduced and Cartesian.
57 
58  ///gvecs in reduced coordiates
59  std::vector<GIndex_t> gvecs;
60  ///Reduced coordinates with offset gvecs_shifted[][idim]=gvecs[][idim]+maxg[idim]
61  std::vector<GIndex_t> gvecs_shifted;
62 
63  std::vector<RealType> minusModKplusG2;
64  std::vector<PosType> kplusgvecs_cart; //Cartesian.
65 
67  //Real wavefunctions here. Now the basis states are cos(Gr) or sin(Gr), not exp(iGr)
68  //We need a way of switching between them for G -> -G, otherwise the
69  //determinant will have multiple rows that are equal (to within a constant factor)
70  //of others, giving a zero determinant. For this, we build a vector (negative) which
71  //stores whether a vector is "+" or "-" (with some criterion, to be defined). We
72  //the switch from cos() to sin() based on the value of this input.
73  std::vector<int> negative;
74 
75 public:
76  //enumeration for the value, laplacian, gradients and size
77  enum
78  {
85  };
86 
88 
90  /* inputmap is used for a memory efficient way of
91  *
92  * importing the basis-set and coefficients when the desired energy cutoff may be
93  * lower than that represented by all data in the wavefunction input file.
94  * The steps taken are:
95  * - Read all basis data.
96  * - Create map. inputmap[i] = j; j is correct PW index, i is input coef index.
97  * For basis elements outside cutoff, inputmap[i] = gvecs.size();
98  * - Coefficients are in same order as PWs in inputfile => simply file into
99  * storage matrix using the map as the input. All excess coefficients are
100  * put into [gvecs.size()] and not used. i.e. coefs need to be allocated 1 higher.
101  * Such an approach is not needed for Gamma-point only calculations because the
102  * basis is spherically ordered. However, when a twist-angle is used, the "sphere"
103  * of allowed planewaves is shifted.
104  */
105 
107 
108  std::vector<int> inputmap;
109 
110  ///total number of basis functions
112 
113  ///local copy of Lattice
115 
116  ///default constructor
118 
119  ///constructor
120  PWBasis(const PosType& twistangle) : maxmaxg(0), twist(twistangle), NumPlaneWaves(0) {}
121 
122  ~PWBasis() {}
123 
124  ///set the twist angle
125  void setTwistAngle(const PosType& tang);
126 
127  ///reset
128  void reset();
129 
130  /** Read basisset from hdf5 file. Apply ecut.
131  * @param h5basisgroup h5 node where basis is located
132  * @param ecutoff cutoff energy
133  * @param lat CrystalLattice
134  * @param resizeContainer if true, resize internal storage.
135  * @return the number of plane waves
136  */
137  int readbasis(hdf_archive& h5basisgroup,
138  RealType ecutoff,
139  const ParticleLayout& lat,
140  const std::string& pwname = "planewaves",
141  const std::string& pwmultname = "multipliers",
142  bool resizeContainer = true);
143 
144  /** Remove basis elements if kinetic energy > ecut.
145  *
146  * Keep and indexmap so we know how to match coefficients on read.
147  */
148  void trimforecut();
149 
150 #if defined(PWBASIS_USE_RECURSIVE)
151  /** Fill the recursion coefficients matrix.
152  *
153  * @todo Generalize to non-orthorohmbic cells
154  */
155  inline void BuildRecursionCoefs(const PosType& pos)
156  {
157  PosType tau_red(Lattice.toUnit(pos));
158 // RealType phi=TWOPI*tau_red[0];
159 // RealType nphi=maxg0*phi;
160 // ComplexType ct0(std::cos(phi),std::sin(phi));
161 // ComplexType t(std::cos(nphi),-std::sin(nphi));
162 // C0[0]=t;
163 // for(int n=1; n<=2*maxg0; n++) C0[n] = (t *= ct0);
164 //
165 // phi=TWOPI*tau_red[1];
166 // nphi=maxg1*phi;
167 // ct0=ComplexType(std::cos(phi),std::sin(phi));
168 // t=ComplexType(std::cos(nphi),-std::sin(nphi));
169 // C1[0]=t;
170 // for(int n=1; n<=2*maxg1; n++) C1[n] = (t *= ct0);
171 //
172 // phi=TWOPI*tau_red[2];
173 // nphi=maxg2*phi;
174 // ct0=ComplexType(std::cos(phi),std::sin(phi));
175 // t=ComplexType(std::cos(nphi),-std::sin(nphi));
176 // C2[0]=t;
177 // for(int n=1; n<=2*maxg2; n++) C2[n] = (t *= ct0);
178 #pragma ivdep
179  for (int idim = 0; idim < 3; idim++)
180  {
181  int ng = maxg[idim];
182  RealType phi = TWOPI * tau_red[idim];
183  RealType nphi = ng * phi;
184  ComplexType Ctemp(std::cos(phi), std::sin(phi));
185  ComplexType t(std::cos(nphi), -std::sin(nphi));
186  ComplexType* restrict cp_ptr = C[idim];
187  *cp_ptr++ = t;
188  for (int n = 1; n <= 2 * ng; n++)
189  {
190  *cp_ptr++ = (t *= Ctemp);
191  }
192  }
193  //Base version
194  //#pragma ivdep
195  // for(int idim=0; idim<3; idim++){
196  // RealType phi=TWOPI*tau_red[idim];
197  // ComplexType Ctemp(std::cos(phi),std::sin(phi));
198  // int ng=maxg[idim];
199  // ComplexType* restrict cp_ptr=C[idim]+ng;
200  // ComplexType* restrict cn_ptr=C[idim]+ng-1;
201  // *cp_ptr=1.0;
202  // for(int n=1; n<=ng; n++,cn_ptr--){
203  // ComplexType t(Ctemp*(*cp_ptr++));
204  // *cp_ptr = t;
205  // *cn_ptr = conj(t);
206  // }
207  // }
208  //Not valid for general supercell
209  // // Cartesian of twist for 1,1,1 (reduced coordinates)
210  // PosType G111(1.0,1.0,1.0);
211  // G111 = Lattice.k_cart(G111);
212  //
213  // //Precompute a small number of complex factors (PWs along b1,b2,b3 lines)
214  // //using a fast recursion algorithm
215  //#pragma ivdep
216  // for(int idim=0; idim<3; idim++){
217  // //start the recursion with the 111 vector.
218  // RealType phi = pos[idim] * G111[idim];
219  // register ComplexType Ctemp(std::cos(phi), std::sin(phi));
220  // int ng=maxg[idim];
221  // ComplexType* restrict cp_ptr=C[idim]+ng;
222  // ComplexType* restrict cn_ptr=C[idim]+ng-1;
223  // *cp_ptr=1.0;
224  // for(int n=1; n<=ng; n++,cn_ptr--){
225  // ComplexType t(Ctemp*(*cp_ptr++));
226  // *cp_ptr = t;
227  // *cn_ptr = conj(t);
228  // }
229  // }
230  }
231 
232  inline void evaluate(const PosType& pos)
233  {
234  BuildRecursionCoefs(pos);
235  RealType twistdotr = dot(twist_cart, pos);
236  ComplexType pw0(std::cos(twistdotr), std::sin(twistdotr));
237  //Evaluate the planewaves for particle iat.
238  for (int ig = 0; ig < NumPlaneWaves; ig++)
239  {
240  //PW is initialized as exp(i*twist.r) so that the final basis evaluations are for (twist+G).r
241  ComplexType pw(pw0); //std::cos(twistdotr),std::sin(twistdotr));
242  for (int idim = 0; idim < 3; idim++)
243  pw *= C(idim, gvecs_shifted[ig][idim]);
244  //pw *= C0[gvecs_shifted[ig][0]];
245  //pw *= C1[gvecs_shifted[ig][1]];
246  //pw *= C2[gvecs_shifted[ig][2]];
247  Zv[ig] = pw;
248  }
249  }
250  /** Evaluate all planewaves and derivatives for the iat-th particle
251  *
252  * The basis functions are evaluated for particles iat: first <= iat < last
253  * Evaluate the plane-waves at current particle coordinates using a fast
254  * recursion algorithm. Order of Y,dY and d2Y is kept correct.
255  * These can be "dotted" with coefficients later to complete orbital evaluations.
256  */
257  inline void evaluateAll(const ParticleSet& P, int iat)
258  {
259  const PosType& r(P.activeR(iat));
260  BuildRecursionCoefs(r);
261  RealType twistdotr = dot(twist_cart, r);
262  ComplexType pw0(std::cos(twistdotr), std::sin(twistdotr));
263  //Evaluate the planewaves and derivatives.
264  ComplexType* restrict zptr = Z.data();
265  for (int ig = 0; ig < NumPlaneWaves; ig++, zptr += 5)
266  {
267  //PW is initialized as exp(i*twist.r) so that the final basis evaluations
268  //are for (twist+G).r
269  ComplexType pw(pw0);
270  // THE INDEX ORDER OF C DOESN'T LOOK TOO GOOD: this could be fixed
271  for (int idim = 0; idim < 3; idim++)
272  pw *= C(idim, gvecs_shifted[ig][idim]);
273  //pw *= C0[gvecs_shifted[ig][0]];
274  //pw *= C1[gvecs_shifted[ig][1]];
275  //pw *= C2[gvecs_shifted[ig][2]];
276  zptr[0] = pw;
277  zptr[1] = minusModKplusG2[ig] * pw;
278  zptr[2] = kplusgvecs_cart[ig][0] * ComplexType(-pw.imag(), pw.real());
279  zptr[3] = kplusgvecs_cart[ig][1] * ComplexType(-pw.imag(), pw.real());
280  zptr[4] = kplusgvecs_cart[ig][2] * ComplexType(-pw.imag(), pw.real());
281  }
282  }
283 #else
284  inline void evaluate(const PosType& pos)
285  {
286  //Evaluate the planewaves for particle iat.
287  for (int ig = 0; ig < NumPlaneWaves; ig++)
288  phi[ig] = dot(kplusgvecs_cart[ig], pos);
290  }
291  inline void evaluateAll(const ParticleSet& P, int iat)
292  {
293  const PosType& r(P.activeR(iat));
294  evaluate(r);
295  ComplexType* restrict zptr = Z.data();
296  for (int ig = 0; ig < NumPlaneWaves; ig++, zptr += 5)
297  {
298  //PW is initialized as exp(i*twist.r) so that the final basis evaluations
299  //are for (twist+G).r
300  ComplexType& pw = Zv[ig];
301  zptr[0] = pw;
302  zptr[1] = minusModKplusG2[ig] * pw;
303  zptr[2] = kplusgvecs_cart[ig][0] * ComplexType(-pw.imag(), pw.real());
304  zptr[3] = kplusgvecs_cart[ig][1] * ComplexType(-pw.imag(), pw.real());
305  zptr[4] = kplusgvecs_cart[ig][2] * ComplexType(-pw.imag(), pw.real());
306  }
307  }
308 #endif
309  // /** Fill the recursion coefficients matrix.
310  // *
311  // * @todo Generalize to non-orthorohmbic cells
312  // */
313  // void BuildRecursionCoefsByAdd(const PosType& pos)
314  // {
315  // // Cartesian of twist for 1,1,1 (reduced coordinates)
316  // PosType G111(1.0,1.0,1.0);
317  // G111 = Lattice.k_cart(G111);
318  // //PosType redP=P.Lattice.toUnit(P.R[iat]);
319  // //Precompute a small number of complex factors (PWs along b1,b2,b3 lines)
320  // for(int idim=0; idim<3; idim++){
321  // //start the recursion with the 111 vector.
322  // RealType phi = pos[idim] * G111[idim];
323  // int ng(maxg[idim]);
324  // RealType* restrict cp_ptr=logC[idim]+ng;
325  // RealType* restrict cn_ptr=logC[idim]+ng-1;
326  // *cp_ptr=0.0;
327  // //add INTEL vectorization
328  // for(int n=1; n<=ng; n++,cn_ptr--){
329  // RealType t(phi+*cp_ptr++);
330  // *cp_ptr = t;
331  // *cn_ptr = -t;
332  // }
333  // }
334  // }
335 };
336 } // namespace qmcplusplus
337 #endif
void evaluateAll(const ParticleSet &P, int iat)
Definition: PWBasis.h:291
a class that defines a supercell in D-dimensional Euclean space.
PosType twist
twist angle in reduced
Definition: PWBasis.h:54
Vector< RealType > phi
Definition: PWBasis.h:106
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
void evaluate(const PosType &pos)
Definition: PWBasis.h:284
PWBasis(const PosType &twistangle)
constructor
Definition: PWBasis.h:120
CrystalLattice< OHMMS_PRECISION, OHMMS_DIM > ParticleLayout
Definition: Configuration.h:79
MakeReturn< UnaryNode< FnSin, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sin(const Vector< T1, C1 > &l)
void setTwistAngle(const PosType &tang)
set the twist angle
Definition: PWBasis.cpp:60
std::vector< GIndex_t > gvecs_shifted
Reduced coordinates with offset gvecs_shifted[][idim]=gvecs[][idim]+maxg[idim].
Definition: PWBasis.h:61
class to handle hdf file
Definition: hdf_archive.h:51
QTBase::ComplexType ComplexType
Definition: Configuration.h:59
int maxmaxg
max of maxg[i]
Definition: PWBasis.h:48
Matrix< ComplexType > C
Definition: PWBasis.h:66
Vector< ComplexType > Zv
Definition: PWBasis.h:89
ParticleSet::ParticleLayout ParticleLayout
Definition: PWBasis.h:43
QMCTraits::PosType PosType
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
MakeReturn< UnaryNode< FnCos, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t cos(const Vector< T1, C1 > &l)
Matrix< ComplexType > Z
Definition: PWBasis.h:87
void trimforecut()
Remove basis elements if kinetic energy > ecut.
Definition: PWBasis.cpp:83
void reset()
reset
Definition: PWBasis.cpp:70
PWBasis()
default constructor
Definition: PWBasis.h:117
SingleParticlePos toUnit(const TinyVector< T1, D > &r) const
Convert a cartesian vector to a unit vector.
const PosType & activeR(int iat) const
return the active position if the particle is active or the return current position if not ...
Definition: ParticleSet.h:265
std::vector< GIndex_t > gvecs
gvecs in reduced coordiates
Definition: PWBasis.h:59
std::vector< int > negative
Definition: PWBasis.h:73
QMCTraits::RealType RealType
int readbasis(hdf_archive &h5basisgroup, RealType ecutoff, const ParticleLayout &lat, const std::string &pwname="planewaves", const std::string &pwmultname="multipliers", bool resizeContainer=true)
Read basisset from hdf5 file.
Definition: PWBasis.cpp:23
int NumPlaneWaves
total number of basis functions
Definition: PWBasis.h:111
ParticleLayout Lattice
local copy of Lattice
Definition: PWBasis.h:114
QMCTraits::ComplexType ComplexType
Tensor< typename BinaryReturn< T1, T2, OpMultiply >::Type_t, D > dot(const AntiSymTensor< T1, D > &lhs, const AntiSymTensor< T2, D > &rhs)
std::vector< RealType > minusModKplusG2
Definition: PWBasis.h:63
Plane-wave basis set.
Definition: PWBasis.h:40
traits for QMC variables
Definition: Configuration.h:49
void eval_e2iphi(int n, const T *restrict phi, T *restrict phase_r, T *restrict phase_i)
Definition: e2iphi.h:61
PosType twist_cart
twist angle in cartesian
Definition: PWBasis.h:56
std::vector< PosType > kplusgvecs_cart
Definition: PWBasis.h:64
std::vector< int > inputmap
Definition: PWBasis.h:108