1 //////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source
3 // License. See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by:
8 // Miguel A. Morales, moralessilva2@llnl.gov
9 // Lawrence Livermore National Laboratory
10 //
11 // File created by:
12 // Miguel A. Morales, moralessilva2@llnl.gov
13 // Lawrence Livermore National Laboratory
14 ////////////////////////////////////////////////////////////////////////////////
15
16 #ifndef QMCPLUSPLUS_AFQMC_WALKERSETUPDATES_HPP
17 #define QMCPLUSPLUS_AFQMC_WALKERSETUPDATES_HPP
18
19 #include <algorithm>
20
21 #include "Configuration.h"
22 #include "AFQMC/config.h"
23 #include "AFQMC/Numerics/ma_blas.hpp"
24 #include "AFQMC/Walkers/WalkerConfig.hpp"
25
26 namespace qmcplusplus
27 {
28 namespace afqmc
29 {
30 template<class Wlk, class OMat, class Mat, class WMat>
free_projection_walker_update(Wlk && w,RealType dt,OMat && overlap,Mat && MFfactor,RealType Eshift,Mat && hybrid_weight,WMat & work)31 void free_projection_walker_update(Wlk&& w,
32 RealType dt,
33 OMat&& overlap,
34 Mat&& MFfactor,
35 RealType Eshift,
36 Mat&& hybrid_weight,
37 WMat& work)
38 {
39 int nwalk = w.size();
40 // constexpr if can be used to avoid the memory copy, by comparing the pointer types
41 // between WMat and Mat/OMat
42 if (work.size(0) < 7 || work.size(1) < nwalk)
43 work.reextent({7, nwalk});
44
45 w.getProperty(WEIGHT, work[0]);
46 w.getProperty(PHASE, work[1]);
47 w.getProperty(PSEUDO_ELOC_, work[2]);
48 w.getProperty(OVLP, work[3]);
49 using std::copy_n;
50 copy_n(overlap.origin(), nwalk, work[4].origin());
51 copy_n(MFfactor.origin(), nwalk, work[5].origin());
52 copy_n(hybrid_weight.origin(), nwalk, work[6].origin());
53
54 for (int i = 0; i < nwalk; i++)
55 {
56 ComplexType old_ovlp = work[3][i];
57 ComplexType old_eloc = work[2][i];
58 ComplexType eloc;
59 ComplexType ratioOverlaps = ComplexType(1.0, 0.0);
60 eloc = work[5][i] / dt;
61 ComplexType factor = std::exp(-dt * (0.5 * (eloc + old_eloc) - Eshift));
62 work[0][i] *= std::abs(factor);
63 work[1][i] *= factor / std::abs(factor);
64 work[2][i] = eloc;
65 work[3][i] = work[4][i];
66 }
67
68 w.setProperty(WEIGHT, work[0]);
69 w.setProperty(PHASE, work[1]);
70 w.setProperty(PSEUDO_ELOC_, work[2]);
71 w.setProperty(OVLP, work[3]);
72 }
73
74 template<class Wlk, class OMat, class Mat, class WMat>
hybrid_walker_update(Wlk && w,RealType dt,bool apply_constrain,bool imp_sampl,RealType Eshift,OMat && overlap,Mat && MFfactor,Mat && hybrid_weight,WMat & work)75 void hybrid_walker_update(Wlk&& w,
76 RealType dt,
77 bool apply_constrain,
78 bool imp_sampl,
79 RealType Eshift,
80 OMat&& overlap,
81 Mat&& MFfactor,
82 Mat&& hybrid_weight,
83 WMat& work)
84 {
85 int nwalk = w.size();
86 // constexpr if can be used to avoid the memory copy, by comparing the pointer types
87 // between WMat and Mat/OMat
88 if (work.size(0) < 7 || work.size(1) < nwalk)
89 work.reextent({7, nwalk});
90
91 bool BackProp = (w.getBPPos() >= 0 && w.getBPPos() < w.NumBackProp());
92
93 w.getProperty(WEIGHT, work[0]);
94 w.getProperty(PSEUDO_ELOC_, work[1]);
95 w.getProperty(OVLP, work[2]);
96 using std::copy_n;
97 copy_n(overlap.origin(), nwalk, work[4].origin());
98 copy_n(MFfactor.origin(), nwalk, work[5].origin());
99 copy_n(hybrid_weight.origin(), nwalk, work[6].origin());
100
101 for (int i = 0; i < nwalk; i++)
102 {
103 ComplexType old_ovlp = work[2][i];
104 ComplexType old_eloc = work[1][i];
105 ComplexType eloc;
106 RealType scale = 1.0;
107 ComplexType ratioOverlaps = ComplexType(1.0, 0.0);
108
109 if (imp_sampl)
110 ratioOverlaps = work[4][i] / old_ovlp;
111 if (!std::isfinite(ratioOverlaps.real()) && apply_constrain && imp_sampl)
112 {
113 scale = 0.0;
114 eloc = old_eloc;
115 }
116 else
117 {
118 scale = (apply_constrain ? (std::max(0.0, std::cos(std::arg(ratioOverlaps) - work[5][i].imag()))) : 1.0);
119 if (imp_sampl)
120 eloc = (work[5][i] - work[6][i] - std::log(ratioOverlaps)) / dt;
121 else
122 eloc = work[5][i] / dt;
123 }
124 ComplexType eloc_ = eloc;
125
126 if ((!std::isfinite(eloc.real())) || (std::abs(eloc.real()) < std::numeric_limits<RealType>::min()))
127 {
128 scale = 0.0;
129 eloc = old_eloc;
130 }
131 else
132 {
133 eloc = ComplexType(std::max(std::min(eloc.real(), Eshift + std::sqrt(2.0 / dt)), Eshift - std::sqrt(2.0 / dt)),
134 eloc.imag());
135 }
136 //#define __AFQMC_DEBUG_VERBOSE__
137 #if defined(__AFQMC_DEBUG_VERBOSE__)
138 std::cout << " update: "
139 << " eloc: " << eloc << "\n"
140 << " eloc_: " << eloc_ << "\n"
141 << " ov: " << work[4][i] << "\n"
142 << " old_ov: " << old_ovlp << "\n"
143 << " ratio: " << ratioOverlaps << "\n"
144 << " MFfactor: " << work[5][i] << "\n"
145 << " hybrid_weight: " << work[6][i] << "\n"
146 << " scale: " << scale << "\n"
147 << std::endl;
148 #endif
149
150 work[0][i] *= ComplexType(scale * std::exp(-dt * (0.5 * (eloc.real() + old_eloc.real()) - Eshift)), 0.0);
151 work[1][i] = eloc;
152 work[2][i] = work[4][i];
153 work[3][i] = std::exp(-ComplexType(0.0, dt) * (0.5 * (eloc.imag() + old_eloc.imag()))) / scale;
154 }
155 w.setProperty(WEIGHT, work[0]);
156 w.setProperty(PSEUDO_ELOC_, work[1]);
157 w.setProperty(OVLP, work[2]);
158 if (BackProp)
159 {
160 auto&& WFac((*w.getWeightFactors())[w.getHistoryPos()]);
161 using std::copy_n;
162 copy_n(work[3].origin(), nwalk, WFac.origin());
163 auto&& WHis((*w.getWeightHistory())[w.getHistoryPos()]);
164 copy_n(work[0].origin(), nwalk, WHis.origin());
165 }
166 }
167
168 template<class Wlk, class EMat, class OMat, class Mat, class WMat>
local_energy_walker_update(Wlk && w,RealType dt,bool apply_constrain,RealType Eshift,OMat && overlap,EMat && energies,Mat && MFfactor,Mat && hybrid_weight,WMat & work)169 void local_energy_walker_update(Wlk&& w,
170 RealType dt,
171 bool apply_constrain,
172 RealType Eshift,
173 OMat&& overlap,
174 EMat&& energies,
175 Mat&& MFfactor,
176 Mat&& hybrid_weight,
177 WMat& work)
178 {
179 int nwalk = w.size();
180 // constexpr if can be used to avoid the memory copy, by comparing the pointer types
181 // between WMat and Mat/OMat
182 if (work.size(0) < 12 || work.size(1) < nwalk)
183 work.reextent({12, nwalk});
184
185 bool BackProp = (w.getBPPos() >= 0 && w.getBPPos() < w.NumBackProp());
186
187 w.getProperty(WEIGHT, work[0]);
188 w.getProperty(PSEUDO_ELOC_, work[1]);
189 w.getProperty(OVLP, work[2]);
190 w.getProperty(E1_, work[3]);
191 w.getProperty(EXX_, work[4]);
192 w.getProperty(EJ_, work[5]);
193 using std::copy_n;
194 copy_n(overlap.origin(), nwalk, work[7].origin());
195 copy_n(MFfactor.origin(), nwalk, work[8].origin());
196 ma::copy(energies({0, nwalk}, 0), work[9]);
197 ma::copy(energies({0, nwalk}, 1), work[10]);
198 ma::copy(energies({0, nwalk}, 2), work[11]);
199
200 for (int i = 0; i < nwalk; i++)
201 {
202 ComplexType old_ovlp = work[2][i];
203 ComplexType old_eloc = work[1][i];
204 ComplexType eloc = work[9][i] + work[10][i] + work[11][i];
205 RealType scale = 1.0;
206 ComplexType ratioOverlaps = work[7][i] / old_ovlp;
207
208 if (!std::isfinite((ratioOverlaps * work[8][i]).real()) && apply_constrain)
209 {
210 scale = 0.0;
211 eloc = old_eloc;
212 }
213 else
214 scale = (apply_constrain ? (std::max(0.0, std::cos(std::arg(ratioOverlaps) - work[8][i].imag()))) : 1.0);
215
216 if ((!std::isfinite(eloc.real())) || (std::abs(eloc.real()) < std::numeric_limits<RealType>::min()))
217 {
218 scale = 0.0;
219 eloc = old_eloc;
220 }
221 else
222 {
223 eloc = ComplexType(std::max(std::min(eloc.real(), Eshift + std::sqrt(2.0 / dt)), Eshift - std::sqrt(2.0 / dt)),
224 eloc.imag());
225 }
226
227 work[0][i] *= ComplexType(scale * std::exp(-dt * (0.5 * (eloc.real() + old_eloc.real()) - Eshift)), 0.0);
228 work[6][i] = std::exp(-ComplexType(0.0, dt) * (0.5 * (eloc.imag() + old_eloc.imag()))) / scale;
229 work[1][i] = eloc;
230 work[2][i] = work[7][i];
231 work[3][i] = work[9][i];
232 work[4][i] = work[10][i];
233 work[5][i] = work[11][i];
234 }
235
236 w.setProperty(WEIGHT, work[0]);
237 w.setProperty(PSEUDO_ELOC_, work[1]);
238 w.setProperty(OVLP, work[2]);
239 w.setProperty(E1_, work[3]);
240 w.setProperty(EXX_, work[4]);
241 w.setProperty(EJ_, work[5]);
242 if (BackProp)
243 {
244 auto&& WFac((*w.getWeightFactors())[w.getHistoryPos()]);
245 using std::copy_n;
246 copy_n(work[6].origin(), nwalk, WFac.origin());
247 auto&& WHis((*w.getWeightHistory())[w.getHistoryPos()]);
248 copy_n(work[0].origin(), nwalk, WHis.origin());
249 }
250 }
251
252 } // namespace afqmc
253
254 } // namespace qmcplusplus
255
256 #endif
257