1 /*
2
3 Copyright (C) 2007 Lucas K. Wagner, Jindrich Kolorenc
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
19 */
20
21
22
23 #include "HEG_sample.h"
24 #include "ulec.h"
25 #include "Wavefunction.h"
26 #include "HEG_system.h"
27
28 //----------------------------------------------------------------------
29
generateStorage(Sample_storage * & store)30 void HEG_sample::generateStorage(Sample_storage * & store)
31 {
32 store=new Sample_storage;
33 store->pointdist_temp.Resize(nelectrons,5);
34 store->pos_temp.Resize(3);
35 }
36
saveUpdate(int e,Sample_storage * store)37 void HEG_sample::saveUpdate(int e, Sample_storage * store)
38 {
39 getElectronPos(e, store->pos_temp);
40 for(int d=0; d< 5; d++) {
41 for(int i=0; i<e; i++)
42 {
43 store->pointdist_temp(i,d)=pointdist(i,e,d);
44 }
45 for(int j=e; j < nelectrons; j++)
46 {
47 store->pointdist_temp(j,d)=pointdist(e,j,d);
48 }
49 }
50 }
51
restoreUpdate(int e,Sample_storage * store)52 void HEG_sample::restoreUpdate(int e, Sample_storage * store){
53 for(int i=0; i<3; i++) {
54 elecpos(e,i)=store->pos_temp(i);
55 }
56 for(int d=0; d< 5; d++) {
57
58 for(int i=0; i<e; i++)
59 pointdist(i,e,d)=store->pointdist_temp(i,d);
60
61 for(int j=e; j < nelectrons; j++)
62 pointdist(e,j,d)=store->pointdist_temp(j,d);
63 }
64 }
65
66
67
68 //----------------------------------------------------------------------
69
70 /*!
71
72 */
updateEEDist()73 void HEG_sample::updateEEDist() {
74
75 #define ORTHOGONAL_CELL 1
76
77 #ifdef ORTHOGONAL_CELL
78
79 // Fast evaluation of electron electron distances. Unfortunately,
80 // it REQUIRES simple ORTHOGONAL simulation cell and thus cannot
81 // be used in general crystalline environment (for homogeneous
82 // gas such a loss of generality does not matter, does it?). It
83 // is tempting to replace 1/latVec with recipLatVec and do proper
84 // matrix multiplications, but as noted above, it is flawed as
85 // a general concept.
86 Array1 <doublevar> dist_lc(3);
87 for(int e=0; e< nelectrons; e++) {
88 if(elecDistStale(e)==1) {
89 for (int d=0; d<3; d++)
90 elecpos_lc(e,d)=elecpos(e,d)/parent->latVec(d,d);
91 }
92 }
93
94 for(int e=0; e< nelectrons; e++) {
95 if(elecDistStale(e)==1) {
96
97 elecDistStale(e)=0;
98
99 for(int j=0; j< e; j++) {
100 for(int d=0; d< 3; d++) {
101 dist_lc(d)=elecpos_lc(j,d)-elecpos_lc(e,d);
102 dist_lc(d)-=floor(dist_lc(d)+0.5);
103 }
104 pointdist(j,e,1)=0.0;
105 for (int d=0; d<3; d++) {
106 pointdist(j,e,d+2)=parent->latVec(d,d)*dist_lc(d);
107 pointdist(j,e,1)+=pointdist(j,e,d+2)*pointdist(j,e,d+2);
108 }
109 pointdist(j,e,0)=sqrt(pointdist(j,e,1));
110 }
111
112 for(int k=e+1; k< nelectrons; k++) {
113 for(int d=0; d< 3; d++) {
114 dist_lc(d)=elecpos_lc(e,d)-elecpos_lc(k,d);
115 dist_lc(d)-=floor(dist_lc(d)+0.5);
116 }
117 pointdist(e,k,1)=0.0;
118 for (int d=0; d<3; d++) {
119 pointdist(e,k,d+2)=parent->latVec(d,d)*dist_lc(d);
120 pointdist(e,k,1)+=pointdist(e,k,d+2)*pointdist(e,k,d+2);
121 }
122 pointdist(e,k,0)=sqrt(pointdist(e,k,1));
123 }
124
125 } // if(elecDistStale(e)==1) {
126 } // loop over electrons
127
128 #else
129 // Original Lucas version from Periodic_sample
130 for(int e=0; e< nelectrons; e++) {
131 if(elecDistStale(e)==1) {
132
133 elecDistStale(e)=0;
134 for(int j=0; j<e; j++) {
135 pointdist(j, e,1)=0.0;
136 }
137 for(int k=e+1; k<nelectrons; k++) {
138 pointdist(e,k,1)=0.0;
139 }
140
141 //Find the closest image
142 Array1 <doublevar> tmpvec(3);
143 doublevar tmpdis;
144 doublevar height2=parent->smallestheight*parent->smallestheight*.25;
145
146 for(int j=0; j< e; j++) {
147 //first try within the primitive cell
148 for(int d=0; d< 3; d++)
149 pointdist(j,e,d+2)=elecpos(j,d)-elecpos(e,d);
150 for(int d=0; d< 3; d++)
151 pointdist(j,e,1)+=pointdist(j,e,d+2)*pointdist(j,e,d+2);
152
153 //then check outside if we haven't found the minimum image
154 if(pointdist(j,e,1) > height2) {
155 for(int a=0; a< 26; a++) {
156 for(int d=0; d< 3; d++)
157 tmpvec(d)=elecpos(j,d)-elecpos(e,d)+tmplat(a,d);
158
159 tmpdis=0;
160 for(int d=0; d<3; d++) tmpdis+=tmpvec(d)*tmpvec(d);
161
162 if(tmpdis < pointdist(j,e,1)) {
163 pointdist(j,e,1)=tmpdis;
164 for(int d=0; d< 3; d++) {
165 pointdist(j, e, d+2)=tmpvec(d);
166 }
167 }
168 if(tmpdis < height2)
169 break;
170 }
171 }
172 }
173
174 for(int k=e+1; k< nelectrons; k++) {
175 //first try within the primitive cell
176 for(int d=0; d< 3; d++)
177 pointdist(e,k,d+2)=elecpos(e,d)-elecpos(k,d);
178 for(int d=0; d< 3; d++)
179 pointdist(e,k,1)+=pointdist(e,k,d+2)*pointdist(e,k,d+2);
180
181 //then check outside if we haven't found the minimum image
182 if(pointdist(e,k,1) > height2) {
183 for(int a=0; a< 26; a++) {
184 for(int d=0; d< 3; d++)
185 tmpvec(d)=elecpos(e,d)-elecpos(k,d)+tmplat(a,d);
186
187 tmpdis=0;
188 for(int d=0; d<3; d++) tmpdis+=tmpvec(d)*tmpvec(d);
189
190 if(tmpdis < pointdist(e,k,1)) {
191 pointdist(e,k,1)=tmpdis;
192 for(int d=0; d< 3; d++) {
193 pointdist(e, k, d+2)=tmpvec(d);
194 }
195 }
196 if(tmpdis < height2)
197 break;
198 }
199 }
200 }
201
202 //---------------------------
203 for(int j=0; j<e; j++) {
204 pointdist(j, e,0)=sqrt(pointdist(j, e,1));
205 //cout << j << " " << e << " " << pointdist(j,e,2) << endl;
206 }
207 for(int k=e+1; k<nelectrons; k++) {
208 pointdist(e, k,0)=sqrt(pointdist(e, k,1));
209 //cout << e << " " << k << " " << pointdist(e,k,2) << endl;
210 }
211
212 } // if(elecDistStale(e)==1) {
213 } // loop over electrons
214
215 #endif
216
217 }
218
219
220 //----------------------------------------------------------------------
221
init(System * sys)222 void HEG_sample::init(System * sys) {
223 assert(sys != NULL);
224 recast(sys, parent); //assign sys to parent
225
226 nelectrons=parent->nelectrons(0)+parent->nelectrons(1);
227
228 elecpos.Resize(nelectrons, 3);
229 pointdist.Resize(nelectrons, nelectrons,5);
230 elecpos_lc.Resize(nelectrons, 3);
231
232 elecDistStale.Resize(nelectrons);
233 elecDistStale=1;
234
235 tmplat.Resize(26,3);
236 int counter=0;
237 for(int aa=-1; aa <= 1; aa++) {
238 for(int bb=-1; bb <= 1; bb++) {
239 for(int cc=-1; cc <= 1; cc++) {
240 if(aa!=0 || bb !=0 || cc!=0) {
241 for(int d=0; d< 3; d++) {
242 tmplat(counter,d)=aa*parent->latVec(0,d)
243 +bb*parent->latVec(1,d)
244 +cc*parent->latVec(2,d);
245 }
246 counter++;
247 }
248 }
249 }
250 }
251
252 // update_overall_sign is false for complex-valued wavefunctions,
253 // i.e., for non-integer k-points
254 update_overall_sign=true;
255 for (int d=0; d<3; d++) {
256 doublevar intpart;
257 modf(parent->kpt(d),&intpart);
258 if ( parent->kpt(d) != intpart ) update_overall_sign=false;
259 }
260
261 }
262
263
264 //----------------------------------------------------------------------
265
randomGuess()266 void HEG_sample::randomGuess()
267 {
268 Array1 <doublevar> trialPos(3);
269
270 // homogeneous distribution of electrons in the simulation cell
271 for(int e=0; e<nelectrons; e++)
272 {
273 doublevar rn0=rng.ulec();
274 doublevar rn1=rng.ulec();
275 doublevar rn2=rng.ulec();
276 for(int d=0; d< 3; d++)
277 {
278 trialPos(d)=rn0*parent->latVec(0,d) +
279 rn1*parent->latVec(1,d) + rn2*parent->latVec(2,d);
280 }
281 setElectronPos(e, trialPos);
282 }
283
284 elecDistStale=1;
285
286 if(wfObserver)
287 {
288 wfObserver->notify(all_electrons_move, 0);
289 }
290
291 }
292
293
294 //----------------------------------------------------------------------
295
setElectronPos(const int e,const Array1<doublevar> & position)296 void HEG_sample::setElectronPos(const int e,
297 const Array1 <doublevar> & position)
298 {
299
300 assert( position.GetDim(0) == 3 );
301 Array1 <doublevar> temp(position.GetDim(0));
302 temp=position;
303 Array1 <int> nshift;
304 parent->enforcePbc(temp, nshift);
305
306 for(int i=0; i<3; i++)
307 {
308 //points.r(i,e) = temp(i);
309 elecpos(e,i)=temp(i);
310 }
311 elecDistStale(e)=1;
312
313 if(wfObserver)
314 {
315 wfObserver->notify(electron_move, e);
316 }
317
318 }
319
320
translateElectron(const int e,const Array1<doublevar> & trans)321 void HEG_sample::translateElectron(const int e, const Array1 <doublevar> & trans) {
322 Array1 <doublevar> temp(trans.GetDim(0));
323
324 for(int d=0; d< 3; d++)
325 temp(d)=elecpos(e,d)+trans(d);
326 Array1<int> nshift;
327 parent->enforcePbc(temp, nshift);
328 doublevar kdotr=0;
329 for(int d=0; d< 3; d++)
330 kdotr+=parent->kpt(d)*nshift(d);
331 if ( update_overall_sign ) overall_sign*=cos(pi*kdotr);
332 // the sign of the phase here is critical for correct evaluation of
333 // density matrices
334 overall_phase-=pi*kdotr;
335 // I suppose the value of overall_phase averages around zero, no
336 // "modulo" operation should be needed
337 //overall_phase=overall_phase - 2*pi * (int) (overall_phase/pi/2);
338
339 //if(fabs(kdotr) > 1e-8)
340 // cout << "shift " << nshift(0) << " "
341 // << nshift(1) << " " << nshift(2) << endl;
342
343 for(int i=0; i<3; i++)
344 elecpos(e,i)=temp(i);
345
346 elecDistStale(e)=1;
347
348 if(wfObserver)
349 wfObserver->notify(electron_move, e);
350
351 }
352
353 //----------------------------------------------------------------------
354
355 #include <iomanip>
356
rawOutput(ostream & os)357 void HEG_sample::rawOutput(ostream & os)
358 {
359 os << "HEG_sample\n";
360 os << " numElectrons " << nelectrons << endl;
361 for(int e=0; e< nelectrons; e++)
362 {
363 for(int d=0; d< 3; d++)
364 {
365 os << setw(20) << setprecision(12) << elecpos(e,d);
366 }
367 os << "\n";
368 }
369 }
370
371
rawInput(istream & is)372 void HEG_sample::rawInput(istream & is)
373 {
374 string text;
375 is >> text;
376 if(text != "HEG_sample")
377 error("expected HEG_sample, got ", text);
378
379 is >> text;
380 if(text != "numElectrons")
381 error("expected numElectrons, got ", text);
382 //cout << "electrons " << endl;
383 is >> nelectrons;
384 for(int e=0; e< nelectrons; e++)
385 {
386 for(int d=0; d< 3; d++)
387 {
388 is >> elecpos(e,d);
389
390 }
391 }
392
393 elecDistStale=1;
394
395 }
396
397 //-------------------------------------------------------------------------
398