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: Bryan Clark, bclark@Princeton.edu, Princeton University
8 //                    Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
9 //                    Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
10 //                    Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
11 //
12 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
13 //////////////////////////////////////////////////////////////////////////////////////
14 
15 
16 #include "StructFact.h"
17 #include "config/stdlib/math.hpp"
18 #include "CPU/e2iphi.h"
19 #include "CPU/SIMD/vmath.hpp"
20 #include "CPU/BLAS.hpp"
21 #include "Utilities/qmc_common.h"
22 
23 namespace qmcplusplus
24 {
25 //Constructor - pass arguments to KLists' constructor
StructFact(ParticleSet & P,RealType kc)26 StructFact::StructFact(ParticleSet& P, RealType kc)
27     : DoUpdate(false), StorePerParticle(false), SuperCellEnum(SUPERCELL_BULK)
28 {
29   if (qmc_common.use_ewald && P.LRBox.SuperCellEnum == SUPERCELL_SLAB)
30   {
31     app_log() << "  Setting StructFact::SuperCellEnum=SUPERCELL_SLAB " << std::endl;
32     SuperCellEnum = SUPERCELL_SLAB;
33   }
34 
35   UpdateNewCell(P, kc);
36 }
37 
38 //Destructor
~StructFact()39 StructFact::~StructFact() {}
40 
UpdateNewCell(ParticleSet & P,RealType kc)41 void StructFact::UpdateNewCell(ParticleSet& P, RealType kc)
42 {
43   //Generate the lists of k-vectors
44   KLists.UpdateKLists(P.LRBox, kc);
45   //resize any array
46   resize(P.getSpeciesSet().size(), P.getTotalNum(), KLists.numk);
47   //Compute the entire Rhok
48   FillRhok(P);
49 }
50 
resize(int ns,int nptcl,int nkpts)51 void StructFact::resize(int ns, int nptcl, int nkpts)
52 {
53   phiV.resize(nkpts);
54 #if defined(USE_REAL_STRUCT_FACTOR)
55   rhok_r.resize(ns, nkpts);
56   rhok_i.resize(ns, nkpts);
57   if (StorePerParticle)
58   {
59     eikr_r.resize(nptcl, nkpts);
60     eikr_i.resize(nptcl, nkpts);
61   }
62   eikr_r_temp.resize(nkpts);
63   eikr_i_temp.resize(nkpts);
64 #else
65   rhok.resize(ns, nkpts);
66   eikr.resize(nptcl, nkpts);
67   eikr_temp.resize(nkpts);
68 #endif
69 }
70 
71 
UpdateAllPart(ParticleSet & P)72 void StructFact::UpdateAllPart(ParticleSet& P) { FillRhok(P); }
73 
74 
75 /** evaluate rok per species, eikr  per particle
76  */
FillRhok(ParticleSet & P)77 void StructFact::FillRhok(ParticleSet& P)
78 {
79   int npart = P.getTotalNum();
80 #if defined(USE_REAL_STRUCT_FACTOR)
81   rhok_r = 0.0;
82   rhok_i = 0.0;
83   //algorithmA
84   const int nk = KLists.numk;
85   if (StorePerParticle)
86   {
87     // save per particle and species value
88     for (int i = 0; i < npart; ++i)
89     {
90       const auto& pos           = P.R[i];
91       auto* restrict eikr_r_ptr = eikr_r[i];
92       auto* restrict eikr_i_ptr = eikr_i[i];
93       auto* restrict rhok_r_ptr = rhok_r[P.GroupID[i]];
94       auto* restrict rhok_i_ptr = rhok_i[P.GroupID[i]];
95 #pragma omp simd
96       for (int ki = 0; ki < nk; ki++)
97       {
98         qmcplusplus::sincos(dot(KLists.kpts_cart[ki], pos), &eikr_i_ptr[ki], &eikr_r_ptr[ki]);
99         rhok_r_ptr[ki] += eikr_r_ptr[ki];
100         rhok_i_ptr[ki] += eikr_i_ptr[ki];
101       }
102     }
103   }
104   else
105   {
106     // save per species value
107     for (int i = 0; i < npart; ++i)
108     {
109       const auto& pos           = P.R[i];
110       auto* restrict rhok_r_ptr = rhok_r[P.GroupID[i]];
111       auto* restrict rhok_i_ptr = rhok_i[P.GroupID[i]];
112 #ifdef __INTEL_COMPILER
113 #pragma omp simd
114       for (int ki = 0; ki < nk; ki++)
115       {
116         RealType s, c;
117         qmcplusplus::sincos(dot(KLists.kpts_cart[ki], pos), &s, &c);
118         rhok_r_ptr[ki] += c;
119         rhok_i_ptr[ki] += s;
120       }
121 #else
122       for (int ki = 0; ki < nk; ki++)
123         phiV[ki] = dot(KLists.kpts_cart[ki], pos);
124       eval_e2iphi(nk, phiV.data(), eikr_r_temp.data(), eikr_i_temp.data());
125       for (int ki = 0; ki < nk; ki++)
126       {
127         rhok_r_ptr[ki] += eikr_r_temp[ki];
128         rhok_i_ptr[ki] += eikr_i_temp[ki];
129       }
130 #endif
131     }
132   }
133 #else
134   rhok = 0.0;
135   for (int i = 0; i < npart; i++)
136   {
137     PosType pos(P.R[i]);
138     RealType s, c; //get sin and cos
139     ComplexType* restrict eikr_ref = eikr[i];
140     ComplexType* restrict rhok_ref = rhok[P.GroupID[i]];
141     for (int ki = 0; ki < KLists.numk; ki++)
142     {
143       qmcplusplus::sincos(dot(KLists.kpts_cart[ki], pos), &s, &c);
144       eikr_ref[ki] = ComplexType(c, s);
145       rhok_ref[ki] += eikr_ref[ki];
146     }
147   }
148 #endif
149 }
150 
151 
makeMove(int active,const PosType & pos)152 void StructFact::makeMove(int active, const PosType& pos)
153 {
154 #if defined(USE_REAL_STRUCT_FACTOR)
155 #pragma omp simd
156   for (int ki = 0; ki < KLists.numk; ki++)
157     qmcplusplus::sincos(dot(KLists.kpts_cart[ki], pos), &eikr_i_temp[ki], &eikr_r_temp[ki]);
158 #else
159   RealType s, c; //get sin and cos
160   for (int ki = 0; ki < KLists.numk; ++ki)
161   {
162     qmcplusplus::sincos(dot(KLists.kpts_cart[ki], pos), &s, &c);
163     eikr_temp[ki] = ComplexType(c, s);
164   }
165 #endif
166 }
167 
acceptMove(int active,int gid,const PosType & rold)168 void StructFact::acceptMove(int active, int gid, const PosType& rold)
169 {
170 #if defined(USE_REAL_STRUCT_FACTOR)
171   if (StorePerParticle)
172   {
173     RealType* restrict eikr_ptr_r = eikr_r[active];
174     RealType* restrict eikr_ptr_i = eikr_i[active];
175     RealType* restrict rhok_ptr_r(rhok_r[gid]);
176     RealType* restrict rhok_ptr_i(rhok_i[gid]);
177     for (int ki = 0; ki < KLists.numk; ++ki)
178     {
179       rhok_ptr_r[ki] += (eikr_r_temp[ki] - eikr_ptr_r[ki]);
180       rhok_ptr_i[ki] += (eikr_i_temp[ki] - eikr_ptr_i[ki]);
181       eikr_ptr_r[ki] = eikr_r_temp[ki];
182       eikr_ptr_i[ki] = eikr_i_temp[ki];
183     }
184   }
185   else
186   {
187     RealType* restrict rhok_ptr_r(rhok_r[gid]);
188     RealType* restrict rhok_ptr_i(rhok_i[gid]);
189 
190 // add the new value and subtract the old value
191 #pragma omp simd
192     for (int ki = 0; ki < KLists.numk; ++ki)
193     {
194       RealType s, c;
195       qmcplusplus::sincos(dot(KLists.kpts_cart[ki], rold), &s, &c);
196       rhok_ptr_r[ki] += eikr_r_temp[ki] - c;
197       rhok_ptr_i[ki] += eikr_i_temp[ki] - s;
198     }
199   }
200 #else
201   ComplexType* restrict eikr_ptr = eikr[active];
202   ComplexType* restrict rhok_ptr(rhok[gid]);
203   for (int ki = 0; ki < KLists.numk; ++ki)
204   {
205     rhok_ptr[ki] += (eikr_temp[ki] - eikr_ptr[ki]);
206     eikr_ptr[ki] = eikr_temp[ki];
207   }
208 #endif
209 }
210 
rejectMove(int active,int gid)211 void StructFact::rejectMove(int active, int gid)
212 {
213   //do nothing
214 }
215 
turnOnStorePerParticle(ParticleSet & P)216 void StructFact::turnOnStorePerParticle(ParticleSet& P)
217 {
218 #if defined(USE_REAL_STRUCT_FACTOR)
219   if (!StorePerParticle)
220   {
221     StorePerParticle = true;
222     const int nptcl  = P.getTotalNum();
223     eikr_r.resize(nptcl, KLists.numk);
224     eikr_i.resize(nptcl, KLists.numk);
225     FillRhok(P);
226   }
227 #endif
228 }
229 
230 } // namespace qmcplusplus
231