1 /*
2
3 Copyright (C) 2007 Lucas K. Wagner
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 #include "Split_sample.h"
22 #include "qmc_io.h"
23
allocate(vector<string> & words,Dynamics_generator * & sam)24 int allocate(vector <string> & words, Dynamics_generator *& sam) {
25 if(caseless_eq(words[0],"SPLIT"))
26 sam=new Split_sampler;
27 else if(caseless_eq(words[0],"RUNGE"))
28 sam=new SRK_dmc;
29 else if(caseless_eq(words[0],"UNR"))
30 sam=new UNR_sampler;
31 else
32 error("unknown type of sampler: ", words[0]);
33
34 sam->read(words);
35 return 1;
36 }
37
38 //----------------------------------------------------------------------
39
limDrift(Array1<doublevar> & drift,doublevar tau,drift_type dtype)40 void limDrift(Array1 <doublevar> & drift, doublevar tau, drift_type dtype)
41 {
42 doublevar drift2=0;
43 doublevar drifta=0;
44
45
46 if(dtype==drift_cutoff) {
47 const doublevar drmax=4;
48
49 for(int d=0; d<3; d++)
50 drift2+=drift(d)*drift(d);
51
52 drifta=drmax/max( (doublevar) sqrt(drift2), drmax);
53 //cout << "drifta " << drifta*tau << endl;
54 for(int d=0; d<3; d++) {
55 drift(d)*= tau*drifta;
56 }
57 }
58 else if(dtype==drift_cyrus) {
59
60 const doublevar acyrus=0.25;
61
62 doublevar tau2=tau*2.;
63
64 for(int d=0; d<3; d++)
65 {
66 drift2+=drift(d)*drift(d);
67 }
68
69 drift2*=acyrus;
70 if(drift2 > 1e-8)
71 drifta=(sqrt(1.+tau2*drift2)-1)/(drift2);
72 else drifta=tau;
73
74 //cout << "drifta " << drifta << endl;
75 for(int d=0; d<3; d++)
76 drift(d)*=drifta;
77
78 }
79 else {
80 error("Unknown drift_type in limDrift");
81 }
82
83 }
84
85 //-------------------------------------------------------------------
86
87 /*!
88 returns the exponent of the transition probability for
89 going from point1 to point2
90 */
transition_prob(int point1,int point2,doublevar timestep,drift_type dtype)91 doublevar Split_sampler::transition_prob(int point1, int point2,
92 doublevar timestep,
93 drift_type dtype) {
94 doublevar prob=0;
95 static Array1 <doublevar> drift(3);
96 //cout << "transition probability" << endl;
97
98 drift=trace(point1).drift;
99
100 limDrift(drift, timestep, dtype);
101
102 for(int d=0; d< 3; d++) {
103
104 prob-=(trace(point2).pos(d)-trace(point1).pos(d)-drift(d))
105 *(trace(point2).pos(d)-trace(point1).pos(d)-drift(d));
106 }
107 prob/=(2.0*timestep);
108
109 return prob;
110 }
111
transition_prob(Point & point1,Point & point2,doublevar timestep,drift_type dtype)112 doublevar transition_prob(Point & point1, Point & point2,
113 doublevar timestep, drift_type dtype) {
114 doublevar prob=0;
115 Array1 <doublevar> drift(3);
116 //cout << "transition probability" << endl;
117
118 drift=point1.drift;
119
120
121 limDrift(drift, timestep, dtype);
122
123 for(int d=0; d< 3; d++) {
124 prob-=(point2.pos(d)-point1.pos(d)-drift(d))
125 *(point2.pos(d)-point1.pos(d)-drift(d));
126 }
127 prob/=(2.0*timestep);
128 return prob;
129 }
130
131 //---------------------------------------------------------------------
132
133
runge_kutta_resamp(Point & p1,Point & p2,doublevar timestep,drift_type dtype,int ndim=3)134 doublevar runge_kutta_resamp(Point & p1, Point & p2,
135 doublevar timestep, drift_type dtype,
136 int ndim=3) {
137 Array1 <doublevar> dr1(3), dr2(3);
138 dr1=p1.drift; dr2=p2.drift;
139
140 limDrift(dr1, timestep, dtype);
141 limDrift(dr2, timestep, dtype);
142 Array1 <doublevar> avg(3);
143 for(int d=0; d< 3; d++) {
144 avg(d)=(dr1(d)+dr2(d))/2.0;
145 }
146 doublevar green_forward=0;
147 for(int d=0; d< ndim; d++) {
148 green_forward+=(p2.pos(d)-p1.pos(d)-avg(d))*(p2.pos(d)-p1.pos(d)-avg(d));
149 //green_forward+=(p2.pos(d)-p1.pos(d))*(p2.pos(d)-p1.pos(d))+avg(d)*avg(d);
150 }
151 return -green_forward/(2*timestep);
152 }
153
154
runge_kutta_symm(Point & p1,Point & p2,doublevar timestep,drift_type dtype,int ndim=3)155 doublevar runge_kutta_symm(Point & p1, Point & p2,
156 doublevar timestep, drift_type dtype,
157 int ndim=3) {
158 Array1 <doublevar> dr1(3), dr2(3);
159 dr1=p1.drift; dr2=p2.drift;
160
161 limDrift(dr1, timestep, dtype);
162 limDrift(dr2, timestep, dtype);
163 Array1 <doublevar> avg(3);
164 for(int d=0; d< 3; d++) {
165 avg(d)=(dr1(d)+dr2(d))/2.0;
166 }
167 //limDrift(avg,timestep, dtype);
168 doublevar green_forward=0;
169 for(int d=0; d< ndim; d++) {
170 //green_forward+=(p2.pos(d)-p1.pos(d)-avg(d))*(p2.pos(d)-p1.pos(d)-avg(d));
171 green_forward+=(p2.pos(d)-p1.pos(d))*(p2.pos(d)-p1.pos(d))+avg(d)*avg(d);
172 }
173 return -green_forward/(2*timestep);
174 }
175
176
linear_symm(Point & p1,Point & p2,doublevar timestep,drift_type dtype,int ndim=3)177 doublevar linear_symm(Point & p1, Point & p2,
178 doublevar timestep, drift_type dtype,
179 int ndim=3) {
180 Array1 <doublevar> dr1(3), dr2(3);
181 dr1=p1.drift; dr2=p2.drift;
182
183 limDrift(dr1, timestep,dtype);
184 limDrift(dr2, timestep, dtype);
185
186 doublevar green_forward=0;
187 for(int d=0; d< ndim; d++) {
188
189 green_forward+=(p2.pos(d)-p1.pos(d))*(p2.pos(d)-p1.pos(d))
190 +(p2.pos(d)-p1.pos(d))*(dr2(d)-dr1(d))
191 +.5*(dr2(d)*dr2(d)+dr1(d)*dr1(d));
192
193 // Runge-kutta move
194 //doublevar tmp=p2.pos(d)-p1.pos(d)-.5*(dr2(d)+dr1(d));
195 //green_forward+=tmp*tmp;
196 //green_forward+=(p2.pos(d)-p1.pos(d))*(p2.pos(d)-p1.pos(d))
197 // +.25*(dr2(d)+dr1(d))*(dr2(d)+dr1(d));
198 }
199 return -green_forward/(2*timestep);
200 }
201
202 //----------------------------------------------------------------------
203
read(vector<string> & words)204 void Split_sampler::read(vector <string> & words) {
205 unsigned int pos=0;
206
207 readvalue(words, pos=0, divide_, "DIVIDER");
208 if(haskeyword(words, pos=0, "RESTRICT_NODES"))
209 restrict_nodes=1;
210
211 int depth;
212 if(readvalue(words, pos=0, depth, "DEPTH"))
213 setRecursionDepth(depth);
214
215 string drifttype;
216 if(readvalue(words, pos=0, drifttype, "DRIFT_TYPE")) {
217 if(drifttype=="CYRUS")
218 setDriftType(drift_cyrus);
219 else if(drifttype=="CUTOFF")
220 setDriftType(drift_cutoff);
221 else error("Didn't understand DRIFT_TYPE ", drifttype);
222 }
223
224
225 }
226
227
greenFunction(Sample_point * sample,Wavefunction * wf,Wavefunction_data * wfdata,Guiding_function * guidingwf,int e,Array1<doublevar> & newpos,doublevar timestep,Dynamics_info & info,Dynamics_info & oldinfo)228 doublevar Dynamics_generator::greenFunction(Sample_point * sample, Wavefunction * wf,
229 Wavefunction_data * wfdata,
230 Guiding_function * guidingwf,
231 int e,
232 Array1 <doublevar> & newpos,
233 doublevar timestep,
234 Dynamics_info & info, Dynamics_info & oldinfo) {
235
236 //cout << "auxillary " << endl;
237 drift_type dtype=drift_cyrus;
238 assert(newpos.GetDim(0) >= 3);
239 wf->updateLap(wfdata, sample);
240 Point p1; p1.lap.Resize(wf->nfunc(), 5);
241 p1.sign=sample->overallSign();
242 int ndim=sample->ndim();
243
244 sample->getElectronPos(e,p1.pos);
245 wf->getLap(wfdata, e, p1.lap);
246 guidingwf->getLap(p1.lap, p1.drift);
247
248
249 for(int d=0; d< ndim; d++)
250 p1.translation(d)=newpos(d)-p1.pos(d);
251
252 sample->translateElectron(e,p1.translation);
253 wf->updateLap(wfdata, sample);
254 Point p2; p2.lap.Resize(wf->nfunc(), 5);
255 p2.sign=sample->overallSign();
256 p2.pos=newpos;
257 wf->getLap(wfdata, e, p2.lap);
258 guidingwf->getLap(p2.lap, p2.drift);
259
260
261 info.green_forward=exp(::transition_prob(p1, p2, timestep, dtype));
262 info.green_backward=::transition_prob(p2,p1, timestep, dtype);
263 info.symm_gf=exp(linear_symm(p1, p2, timestep, dtype));
264
265 //cout << "gf:elec " << e << " new wfval " << p2.lap.amp(0,0) << endl;
266 info.diffuse_start=p1.drift;
267 limDrift(info.diffuse_start, timestep, dtype);
268 for(int d=0; d< ndim; d++) {
269 //cout << "secondary drift " << info.drift_pos(d) << endl;
270 info.diffuse_start(d)+=p1.pos(d);
271 }
272 info.diffuse_end=newpos;
273 info.orig_pos=p1.pos;
274 info.new_pos=newpos;
275 info.diffusion_rate=0;
276 for(int d=0; d< ndim; d++)
277 info.diffusion_rate+=(info.diffuse_end(d)-info.diffuse_start(d))
278 *(info.diffuse_end(d)-info.diffuse_start(d));
279
280 info.acceptance=min(1.0, (exp(info.green_backward)/info.green_forward)
281 *guidingwf->getTrialRatio(p2.lap, p1.lap)
282 *guidingwf->getTrialRatio(p2.lap, p1.lap));
283
284
285 //trying a better gf
286 //info.green_forward*=info.acceptance;///oldinfo.acceptance;
287 //--------
288
289
290 info.accepted=0;
291 doublevar ratio=guidingwf->getTrialRatio(p1.lap,p2.lap)*p1.sign*p2.sign;
292 if(ratio < 0) cout << "crossed node " << endl;
293
294 return info.acceptance;
295 }
296
297
298 //----------------------------------------------------------------------
299 /*!
300 From x to y in the trace
301 */
get_acceptance(Guiding_function * guidingwf,int x,int y)302 doublevar Split_sampler::get_acceptance(Guiding_function * guidingwf,
303 int x, int y) {
304 //indent = indent + " ";
305
306 doublevar ratio=guidingwf->getTrialRatio(trace(y).lap,
307 trace(x).lap)*trace(x).sign
308 *trace(y).sign;
309
310 if(restrict_nodes && ratio < 0) return 0;
311
312 ratio=ratio*ratio;
313 //cout << indent << "*********" << endl;
314 //cout << indent << "ratio x " << x << " y " << y << " : " << ratio << endl;
315
316 int dir=1;
317 if(y-x < 0) {
318 dir=-1;
319 }
320
321
322 doublevar prob_transition=0; //exponent of transition probability
323 //We use the current move as well(thus y+1 or x-1)
324 for(int i=x+dir; i != y+dir; i+= dir ) {
325 int dist=abs(x-i);
326 //cout << indent << "transition from " << y << " to " << y-dir*dist
327 // << " and " << x << " to " << x+dir*dist << " using " << dist
328 // << " (timestep " << timesteps(dist)
329 // << endl;
330
331 doublevar num=transition_prob(y,y-dir*dist,timesteps(dist), dtype);
332 doublevar den=transition_prob(x,x+dir*dist,timesteps(dist), dtype);
333 prob_transition+=num-den;
334 //cout << indent << "num " << num << " den " << den << " num-den " << num-den << endl;
335 }
336
337 doublevar reject_prob_den=1; //denominator(forward rejections)
338 doublevar reject_prob_num=1; //numerator(backward rejection)
339 for(int i=x+dir; i != y; i+=dir) {
340 int dist=abs(x-i);
341 //cout << indent << "->acceptance from " << y << " to " << y-dir*dist
342 // << endl;
343 reject_prob_num*=1-get_acceptance(guidingwf, y, y-dir*dist);
344 //cout << indent << "->over " << x << " to " << x+dir*dist << endl;
345 reject_prob_den*=1-get_acceptance(guidingwf, x,x+dir*dist);
346 }
347
348 doublevar acc=0;
349
350 const doublevar tiny=1e-10;
351 if(fabs(reject_prob_den) < tiny) {
352 if(fabs(reject_prob_num) < tiny) acc=0;
353 else {
354 //If we have a zero on the denominator, we know that
355 //alpha(y->x)=1/alpha(x->y) must be zero, so therefore the acceptance is 1
356 acc=1;
357 //cout << indent << "warn:denominator zero : " << reject_prob_den << " num "
358 // << reject_prob_num << endl;
359 //error("problem in split_sample; denominator zero");
360 }
361 }
362 else {
363 //cout << indent << "prob_transition " << prob_transition
364 // << " " << reject_prob_num << " " << reject_prob_den << endl;
365 acc=ratio*exp(prob_transition)*reject_prob_num/reject_prob_den;
366 }
367 //cout << indent << "acceptance " << acc << endl;
368 //indent.erase(indent.end()-1);
369 //indent.erase(indent.end()-1);
370
371 return min(1.0,acc);
372
373 }
374
375 #include "ulec.h"
376 #include "Wavefunction_data.h"
377
378
379 //----------------------------------------------------------------------
split_driver(int e,Sample_point * sample,Wavefunction * wf,Wavefunction_data * wfdata,Guiding_function * guidingwf,int depth,Dynamics_info & info,doublevar & efftimestep)380 int Split_sampler::split_driver(int e,
381 Sample_point * sample,
382 Wavefunction * wf,
383 Wavefunction_data * wfdata,
384 Guiding_function * guidingwf,
385 int depth,
386 Dynamics_info & info,
387 doublevar & efftimestep) {
388
389 //cout << "primary " << endl;
390 assert(trace.GetDim(0) >= depth);
391 assert(recursion_depth_ <= timesteps.GetDim(0));
392
393 if(depth > recursion_depth_) return 0;
394
395 static Array1 <doublevar> c_olddrift(3);
396 static Array1 <doublevar> c_newdrift(3);
397
398 c_olddrift=trace(0).drift;
399 limDrift(c_olddrift, timesteps(depth), dtype);
400
401 int ndim=sample->ndim();
402
403 //cout << "drift " << c_olddrift(0) << " "
404 // << c_olddrift(1) << " " << c_olddrift(2) << endl;
405 //info.drift_pos.Resize(3);
406
407 for(int d=0; d< ndim; d++) {
408 trace(depth).gauss(d)=rng.gasdev();
409 trace(depth).translation(d)=trace(depth).gauss(d)*sqrt(timesteps(depth))
410 + c_olddrift(d);
411 trace(depth).pos(d)=trace(0).pos(d)
412 + trace(depth).translation(d);
413
414
415 }
416
417 doublevar diffusion_rate=0;
418 for(int d=0; d< ndim; d++)
419 diffusion_rate+=trace(depth).gauss(d)*timesteps(depth)*trace(depth).gauss(d);;
420
421
422 sample->translateElectron(e, trace(depth).translation);
423 trace(depth).sign=sample->overallSign();
424
425 if(wfdata->supports(laplacian_update) ) {
426 wf->updateLap(wfdata, sample);
427 wf->getLap(wfdata, e, trace(depth).lap);
428 }
429 else {
430 wf->updateForceBias(wfdata, sample);
431 wf->getForceBias(wfdata, e, trace(depth).lap);
432 }
433
434 guidingwf->getLap(trace(depth).lap, trace(depth).drift);
435
436 //indent="";
437 //cout << "#######################acceptance for " << depth << endl;
438 doublevar acc=get_acceptance(guidingwf, 0,depth);
439 //cout << "acceptance for " << depth << " : " << acc << endl;
440
441 info.green_forward=exp(transition_prob(0,depth,timesteps(depth), dtype));
442 //cout << "green_forward " << info.green_forward << endl;
443 info.green_backward=exp(transition_prob(depth,0,timesteps(depth),dtype));
444 info.diffusion_rate=diffusion_rate;
445 info.acceptance=acc;
446 info.orig_pos=trace(0).pos;
447 info.diffuse_start.Resize(3);
448 for(int d=0; d< ndim; d++)
449 info.diffuse_start(d)=trace(0).pos(d)+c_olddrift(d);
450 info.diffuse_end=trace(depth).pos;
451 info.new_pos=trace(depth).pos;
452 info.gauss=trace(depth).gauss;
453
454 info.symm_gf=exp(linear_symm(trace(0), trace(depth), timesteps(depth), dtype));
455 info.resample_gf=info.symm_gf;
456 //trying a better gf
457 //info.green_forward*=info.acceptance;
458 //--------
459
460
461 if (acc+rng.ulec() > 1.0) {
462 info.accepted=1;
463 return depth;
464 }
465 else {
466 info.accepted=0;
467
468 static Array1 <doublevar> rev(3,0.0);
469 for(int d=0; d< 3; d++) rev(d)=-trace(depth).translation(d);
470 sample->translateElectron(e,rev);
471
472 depth++;
473
474 return split_driver(e,sample, wf, wfdata, guidingwf,
475 depth, info, efftimestep);
476 }
477
478 }
479
480
481 //----------------------------------------------------------------------
482
sample(int e,Sample_point * sample,Wavefunction * wf,Wavefunction_data * wfdata,Guiding_function * guidingwf,Dynamics_info & info,doublevar & efftimestep)483 int Split_sampler::sample(int e,
484 Sample_point * sample,
485 Wavefunction * wf,
486 Wavefunction_data * wfdata,
487 Guiding_function * guidingwf,
488 Dynamics_info & info,
489 doublevar & efftimestep) {
490
491 if(! wfStore.isInitialized())
492 wfStore.initialize(sample, wf);
493
494 wf->updateLap(wfdata, sample);
495 wfStore.saveUpdate(sample, wf, e);
496 trace.Resize(recursion_depth_+1);
497
498 for(int i=0; i < recursion_depth_+1; i++) {
499 trace(i).lap.Resize(wf->nfunc(), 5);
500 }
501
502 timesteps.Resize(recursion_depth_+1);
503 timesteps=efftimestep;
504
505
506 for(int i=2; i< recursion_depth_+1; i++) {
507 timesteps(i)=efftimestep/pow(divide_,i-1);
508 }
509
510 int depth=0;
511
512 sample->getElectronPos(e,trace(depth).pos);
513 wf->getLap(wfdata, e, trace(depth).lap);
514 trace(depth).sign=sample->overallSign();
515
516 guidingwf->getLap(trace(depth).lap, trace(depth).drift);
517 depth++;
518
519
520 int acc=split_driver(e, sample, wf, wfdata, guidingwf, depth,
521 info, efftimestep);
522
523 if(acc > 0) {
524 acceptances(acc-1)++;
525 for(int i=0; i< acc; i++) {
526 tries(i)++;
527 }
528 }
529 else {
530 for(int i=0; i< recursion_depth_; i++) {
531 tries(i)++;
532 }
533 }
534
535 if(!acc) {
536 wfStore.restoreUpdate(sample, wf, e);
537 }
538 //cout << "-----------split done" << endl;
539 return acc;
540 }
541
542
543 //----------------------------------------------------------------------
544
545
showStats(ostream & os)546 void Split_sampler::showStats(ostream & os) {
547 doublevar totacc=0;
548 for(int i=0; i< recursion_depth_; i++) {
549 totacc+=acceptances(i);
550 }
551
552 os << "Total acceptance " << totacc/tries(0) << endl;
553 for(int i=0; i< recursion_depth_; i++) {
554 os << "accept_level" << i << " " << acceptances(i)/tries(i)
555 << " tries " << tries(i) << endl;
556 }
557 }
558
559 //----------------------------------------------------------------------
560
561
resetStats()562 void Split_sampler::resetStats() {
563 acceptances=0;
564 tries=0;
565 }
566 //----------------------------------------------------------------------
567 //######################################################################
568
showStats(ostream & os)569 void UNR_sampler::showStats(ostream & os) {
570 os << "acceptance " << acceptance/tries << endl;
571 }
572
resetStats()573 void UNR_sampler::resetStats() {
574 acceptance=0;
575 tries=0;
576 }
577
578
getDriftEtc(Point & pt,Sample_point * sample,doublevar tstep,int e,doublevar & exponent,doublevar & probability,Array1<doublevar> & rnuc)579 void UNR_sampler::getDriftEtc(Point & pt, Sample_point * sample,
580 doublevar tstep, int e,
581 doublevar & exponent,
582 //!< exponent at which to do an exponential move
583 doublevar & probability,
584 //!< probability to do an exponential move
585 Array1 <doublevar> & rnuc
586 //!< distance array for closest ion
587 ) {
588 Array1 <doublevar> z(5);
589 Array1 <doublevar> dist(5);
590 int closest_ion=-1;
591 z(0)=1e8;
592 int nions=sample->ionSize();
593 sample->updateEIDist();
594 for(int at=0; at< nions; at++) {
595 sample->getEIDist(e,at,dist);
596 //cout << "dist " << dist(0) << endl;
597 if(dist(0) < z(0)) {
598 z=dist;
599 closest_ion=at;
600 }
601 }
602
603 assert(closest_ion!=-1);
604 doublevar charge=sample->getIonCharge(closest_ion);
605 rnuc.Resize(3);
606 //Here we back out the nucleus position from the distance,
607 //which is the best way to do it for periodic systems.
608 //There may be a small bug here if the periodic cell is really
609 //small and we can traverse it in one step..there may be extra
610 //rejections. It shouldn't generally be a concern, though.
611 for(int d=0; d< 3; d++) {
612 rnuc(d)=pt.pos(d)-z(d+2);
613 }
614
615 //the exponent for the exponential moves
616 exponent=sqrt(charge*charge+1/tstep);
617
618 doublevar vhatdotzhat=0;
619 doublevar driftmag=0;
620 for(int d=0; d< 3; d++) driftmag+=pt.drift(d)*pt.drift(d);
621 driftmag=sqrt(driftmag);
622 if(fabs(driftmag) > 1e-16) {
623 for(int d=0;d < 3; d++) {
624 vhatdotzhat+=z(d+2)*pt.drift(d)/(driftmag*z(0));
625 //cout << "vhat " << vhatdotzhat << endl;
626 }
627
628 //cout << "driftmag " << driftmag << endl;
629 //magic numbers!! taken from UNR as usual
630 doublevar a=.5*(1+vhatdotzhat)
631 +charge*charge*z(0)*z(0)/(10*(4+charge*charge*z(0)*z(0)));
632
633 doublevar prefac=(-1+sqrt(1+2*a*driftmag*driftmag*tstep))
634 /(a*driftmag*driftmag*tstep);
635
636 driftmag=0;
637 for(int d=0;d < 3; d++) {
638 pt.drift(d)*=prefac;
639 driftmag+=pt.drift(d)*pt.drift(d);
640 }
641 driftmag=sqrt(driftmag);
642 //cout << "driftmag " << driftmag << endl;
643 }
644
645 doublevar vz=vhatdotzhat*driftmag;
646 Array1 <doublevar> rho(3);
647 rho=0;
648 doublevar rhomag=0;
649 for(int d=0; d< 3; d++) {
650 rho(d)=pt.drift(d)-vz*z(d+2)/z(0);
651 rhomag+=rho(d)*rho(d);
652 }
653 rhomag=sqrt(rhomag);
654 doublevar zpp=max(z(0)+vz*tstep,0.0);
655 doublevar rhoscale=2*tstep*zpp/(z(0)+zpp);
656 for(int d=0;d < 3; d++) {
657 pt.drift(d)=rnuc(d)+rhoscale*rho(d)+zpp*z(d+2)/z(0);
658 }
659
660
661 probability=0.5*erfc((z(0)+vz*tstep)/sqrt(2*tstep));
662
663 }
664
665 //----------------------------------------------------------------------
666
UNRgreenfunc(Point & pt1,Point & pt2,doublevar tstep,doublevar exponent,doublevar prob,Array1<doublevar> & rnuc)667 doublevar UNRgreenfunc(Point & pt1, Point & pt2,
668 doublevar tstep,
669 doublevar exponent, doublevar prob,
670 Array1 <doublevar> & rnuc) {
671 assert(rnuc.GetDim(0)==3);
672 doublevar gaussmov=0;
673 doublevar expmov=0;
674 for(int d=0; d< 3; d++) {
675 gaussmov+=(pt2.pos(d)-pt1.drift(d))*(pt2.pos(d)-pt1.drift(d));
676 expmov+=(pt2.pos(d)-rnuc(d))*(pt2.pos(d)-rnuc(d));
677 //cout << "rnuc " << rnuc(d) << " pt2 " << pt2.pos(d) << " pt1 " << pt1.drift(d) << endl;
678 }
679 doublevar gaussnorm=sqrt(8*pi*pi*pi*tstep*tstep*tstep);
680 gaussnorm=1/gaussnorm;
681
682
683 return prob*exponent*exponent*exponent*exp(-2*exponent*sqrt(expmov))/pi
684 + (1-prob)*exp(-gaussmov/(2*tstep))*gaussnorm;
685 }
686 //----------------------------------------------------------------------
687
sample(int e,Sample_point * sample,Wavefunction * wf,Wavefunction_data * wfdata,Guiding_function * guidewf,Dynamics_info & info,doublevar & tstep)688 int UNR_sampler::sample(int e, Sample_point * sample,
689 Wavefunction * wf, Wavefunction_data * wfdata,
690 Guiding_function * guidewf,
691 Dynamics_info & info,
692 doublevar & tstep) {
693
694 tries++;
695 Point p1; p1.lap.Resize(wf->nfunc(), 5);
696
697 wf->updateLap(wfdata, sample);
698 sample->getElectronPos(e,p1.pos);
699 wf->getLap(wfdata, e, p1.lap);
700 p1.sign=sample->overallSign();
701 guidewf->getLap(p1.lap, p1.drift);
702
703 //Starting determination of move..
704 //using (close to) the notation of UNR
705 Array1 <doublevar> rnuc(3);
706 doublevar prob,exponent;
707
708 //cout << "p1.drift "; write_array(cout,p1.drift); cout << endl;
709 getDriftEtc(p1,sample,tstep,e, exponent,prob,rnuc);
710
711 //cout << "p1.pos ";
712 //write_array(cout, p1.pos);
713 //cout << endl;
714 //cout << "p1.drift "; write_array(cout,p1.drift); cout << endl;
715
716
717 Point p2; p2.lap.Resize(wf->nfunc(),5);
718 //cout << "prob " << prob << endl;
719 if(prob+rng.ulec() > 1.0) {
720 //cout << "doing exponential move "<< endl;
721 doublevar r=ranr2exponential()/(2*exponent);
722 doublevar theta=rancos();
723 doublevar phi=2*pi*rng.ulec();
724 p2.pos=rnuc;
725 p2.pos(0)+=r*sin(theta)*cos(phi);
726 p2.pos(1)+=r*sin(theta)*sin(phi);
727 p2.pos(2)+=r*cos(theta);
728
729 }
730 else {
731 //cout << " do a gaussian move." << endl;
732 for(int d=0; d< 3; d++) {
733 p2.pos(d)=p1.drift(d)+sqrt(tstep)*rng.gasdev();
734 }
735 }
736
737 //cout << "p2.pos "; write_array(cout,p2.pos); cout << endl;
738
739 Array1 <doublevar> translate(3);
740 for(int d=0; d< 3; d++) translate(d)=p2.pos(d)-p1.pos(d);
741 sample->translateElectron(e,translate);
742 wf->updateLap(wfdata, sample);
743 wf->getLap(wfdata, e, p2.lap);
744 p2.sign=sample->overallSign();
745 guidewf->getLap(p2.lap, p2.drift);
746
747 Array1 <doublevar> rnucp(3);
748 doublevar probp,exponentp;
749 getDriftEtc(p2,sample,tstep,e,exponentp,probp,rnucp);
750
751 //cout << "p2.drift "; write_array(cout,p2.drift); cout << endl;
752
753
754 doublevar ratio=guidewf->getTrialRatio(p2.lap,p1.lap)
755 *p2.sign*p1.sign;
756
757 doublevar acc=ratio*ratio*UNRgreenfunc(p2,p1,tstep,exponentp,probp,rnucp)
758 /UNRgreenfunc(p1,p2,tstep,exponent,prob,rnuc);
759
760 //cout << "forward " << UNRgreenfunc(p2,p1,tstep,exponentp,probp,rnucp) << endl;
761 //cout << "acceptance " << acc << " ratio " << ratio
762 // << "forward " << UNRgreenfunc(p2,p1,tstep,exponentp,probp,rnucp)
763 // << " backward " << UNRgreenfunc(p1,p2,tstep,exponent,prob,rnuc) << endl;
764
765 if(restrict_nodes && ratio < 0) {
766 //cout << "stopping nodal crossing " << endl;
767 acc=0;
768 }
769
770 //cout << "acceptance " << acc << endl;
771 //cout <<"##############################\n";
772
773 info.diffusion_rate=0;
774 for(int d=0;d < 3; d++) {
775 info.diffusion_rate+=(p2.pos(d)-p1.drift(d))*(p2.pos(d)-p1.drift(d))*tstep;
776 }
777 info.acceptance=acc;
778 info.orig_pos=p1.pos;
779 info.diffuse_start=p1.drift;
780 info.diffuse_end=p2.pos;
781 info.new_pos=p2.pos;
782
783 if(acc+rng.ulec()>1.0) {
784 info.accepted=1;
785 acceptance++;
786 return 1;
787 }
788 else {
789 sample->setElectronPos(e,p1.pos);
790 info.accepted=0;
791 return 0;
792 }
793
794
795 }
796
797 //----------------------------------------------------------------------
798 //######################################################################
read(vector<string> & words)799 void SRK_dmc::read(vector <string> & words) {
800 unsigned int pos=0;
801 if(haskeyword(words, pos=0, "RESAMPLE"))
802 resample=1;
803 else resample=0;
804
805 readvalue(words, pos=0, resample_tol, "RESAMPLE_TOL");
806
807 string drifttype;
808 setDriftType(drift_cyrus);
809 if(readvalue(words, pos=0, drifttype, "DRIFT_TYPE")) {
810 if(drifttype=="CYRUS")
811 setDriftType(drift_cyrus);
812 else if(drifttype=="CUTOFF")
813 setDriftType(drift_cutoff);
814 else error("Didn't understand DRIFT_TYPE ", drifttype);
815 }
816
817 diagnostics=false;
818 if(haskeyword(words,pos=0,"DIAGNOSTICS")) diagnostics=true;
819 third_move=false;
820 if(haskeyword(words,pos=0, "THIRD_MOVE")) third_move=true;
821
822 if(diagnostics) {
823 string basename="srk_diagnostics";
824 canonical_filename(basename,mpi_info.node);
825 diagnostics_print.open(basename.c_str(), ios::app);
826 for(int i=0; i< 3; i++)
827 for(int j=0; j< 3; j++)
828 diagnostics_print << "r"<<i<<j << " ";
829 for(int i=0; i< 3; i++) diagnostics_print << "g"<<i <<" ";
830 for(int i=0; i< 3; i++) {
831 for(int j=0; j< 5; j++)
832 diagnostics_print << "p"<<i<<j << " ";
833 diagnostics_print << "p_phase" << i <<" ";
834 }
835
836 diagnostics_print << endl;
837
838 }
839
840 }
841
842
843
844
greenFunction(Sample_point * sample,Wavefunction * wf,Wavefunction_data * wfdata,Guiding_function * guidingwf,int e,Array1<doublevar> & newpos,doublevar timestep,Dynamics_info & info,Dynamics_info & oldinfo)845 doublevar SRK_dmc::greenFunction(Sample_point * sample, Wavefunction * wf,
846 Wavefunction_data * wfdata,
847 Guiding_function * guidingwf,
848 int e,
849 Array1 <doublevar> & newpos,
850 doublevar timestep,
851 Dynamics_info & info, Dynamics_info & oldinfo) {
852
853 //cout << "auxillary " << endl;
854 //drift_type dtype=drift_cyrus;
855 assert(newpos.GetDim(0) >= 3);
856 wf->updateLap(wfdata, sample);
857 Point p1; p1.lap.Resize(wf->nfunc(), 5);
858 p1.sign=sample->overallSign();
859 int ndim=sample->ndim();
860
861 sample->getElectronPos(e,p1.pos);
862 wf->getLap(wfdata, e, p1.lap);
863 guidingwf->getLap(p1.lap, p1.drift);
864
865
866 for(int d=0; d< ndim; d++)
867 p1.translation(d)=newpos(d)-p1.pos(d);
868
869 sample->translateElectron(e,p1.translation);
870 wf->updateLap(wfdata, sample);
871 Point p2; p2.lap.Resize(wf->nfunc(), 5);
872 p2.sign=sample->overallSign();
873 p2.pos=newpos;
874 wf->getLap(wfdata, e, p2.lap);
875 guidingwf->getLap(p2.lap, p2.drift);
876
877
878 info.green_forward=exp(runge_kutta_resamp(p1, p2, timestep, dtype));
879
880 info.symm_gf=exp(runge_kutta_symm(p1, p2, timestep, dtype));
881 info.green_backward=exp(transition_prob(p2,p1, timestep, dtype));
882
883 //cout << "gf:elec " << e << " new wfval " << p2.lap.amp(0,0) << endl;
884 info.diffuse_start=p1.drift;
885 limDrift(info.diffuse_start, timestep, dtype);
886 for(int d=0; d< ndim; d++) {
887 //cout << "secondary drift " << info.drift_pos(d) << endl;
888 info.diffuse_start(d)+=p1.pos(d);
889 }
890 info.diffuse_end=newpos;
891 info.orig_pos=p1.pos;
892 info.new_pos=newpos;
893 info.diffusion_rate=0;
894 for(int d=0; d< ndim; d++)
895 info.diffusion_rate+=(info.diffuse_end(d)-info.diffuse_start(d))
896 *(info.diffuse_end(d)-info.diffuse_start(d));
897
898 info.acceptance=min(1.0, (exp(info.green_backward)/info.green_forward)
899 *guidingwf->getTrialRatio(p2.lap, p1.lap)
900 *guidingwf->getTrialRatio(p2.lap, p1.lap));
901 info.accepted=0;
902 doublevar ratio=guidingwf->getTrialRatio(p1.lap,p2.lap)*p1.sign*p2.sign;
903 if(ratio < 0) cout << "crossed node " << endl;
904
905 return info.acceptance;
906 }
907
908 //----------------------------------------------------------
909
rk_step(int e,Sample_point * sample,Wavefunction * wf,Wavefunction_data * wfdata,Guiding_function * guidingwf,Dynamics_info & info,doublevar & timestep,Array1<Point> & trace)910 int SRK_dmc::rk_step(int e,
911 Sample_point * sample,
912 Wavefunction * wf,
913 Wavefunction_data * wfdata,
914 Guiding_function * guidingwf,
915 Dynamics_info & info,
916 doublevar & timestep, Array1 <Point> & trace
917 ) {
918
919
920 //drift_type dtype=drift_cyrus;
921 assert(trace.GetDim(0)==3);
922
923 Array1 <doublevar> c_olddrift=trace(0).drift;
924 limDrift(c_olddrift,timestep, dtype);
925 int ndim=sample->ndim();
926 //Calculate first move
927 for(int d=0; d< ndim; d++) {
928 trace(1).translation(d)=trace(0).gauss(d)*sqrt(timestep)
929 + c_olddrift(d);
930 trace(1).pos(d)=trace(0).pos(d)
931 + trace(1).translation(d);
932 }
933
934 info.diffusion_rate=0;
935 for(int d=0; d< ndim; d++)
936 info.diffusion_rate+=trace(0).gauss(d)*timestep*trace(0).gauss(d);;
937
938 sample->translateElectron(e, trace(1).translation);
939 trace(1).sign=sample->overallSign();
940
941 wf->updateLap(wfdata, sample);
942 wf->getLap(wfdata, e, trace(1).lap);
943 guidingwf->getLap(trace(1).lap, trace(1).drift);
944
945 //Calculate second move
946 Array1 <doublevar> c_newdrift=trace(1).drift;
947 limDrift(c_newdrift,timestep, dtype);
948
949 for(int d=0; d< 3; d++) {
950 trace(2).gauss(d)=trace(0).gauss(d);
951 trace(2).translation(d)=.5*(c_newdrift(d)+c_olddrift(d))
952 +trace(0).gauss(d)*sqrt(timestep)-trace(1).translation(d);
953 trace(2).pos(d)=trace(1).pos(d)+trace(2).translation(d);
954 }
955
956 sample->translateElectron(e,trace(2).translation);
957 trace(2).sign=sample->overallSign();
958 wf->updateLap(wfdata, sample);
959 wf->getLap(wfdata, e, trace(2).lap);
960 guidingwf->getLap(trace(2).lap, trace(2).drift);
961
962 int last_point=2;
963 if(third_move) {
964 last_point=3;
965 Array1 <doublevar> c_newnewdrift=trace(2).drift;
966 limDrift(c_newnewdrift,timestep,dtype);
967 for(int d=0; d< 3; d++) {
968 trace(3).gauss(d)=trace(0).gauss(d);
969 trace(3).translation(d)=.5*(c_newnewdrift(d)+c_olddrift(d))
970 +trace(0).gauss(d)*sqrt(timestep)
971 -trace(1).translation(d)-trace(2).translation(d);
972 trace(3).pos(d)=trace(1).pos(d)+trace(3).translation(d);
973 }
974
975 sample->translateElectron(e,trace(3).translation);
976 trace(3).sign=sample->overallSign();
977 wf->updateLap(wfdata, sample);
978 wf->getLap(wfdata, e, trace(3).lap);
979 guidingwf->getLap(trace(3).lap, trace(3).drift);
980
981
982 }
983
984 info.symm_gf=exp(runge_kutta_symm(trace(0), trace(last_point), timestep, dtype));
985 info.resample_gf=exp(runge_kutta_resamp(trace(0), trace(last_point), timestep, dtype));
986 info.green_forward=exp(-info.diffusion_rate/(2*timestep));
987 //cout << "symm " << info.symm_gf << " forward " << info.green_forward
988 // << " ratio " << info.symm_gf/info.green_forward << endl;
989 info.green_backward=transition_prob(trace(last_point),trace(0),timestep,dtype);
990 info.acceptance=1.0;
991 info.orig_pos=trace(0).pos;
992 info.new_pos=trace(last_point).pos;
993
994 if(diagnostics) {
995 for(int i=0; i< 3; i++)
996 for(int j=0; j< 3; j++)
997 diagnostics_print << trace(i).pos(j) << " ";
998 for(int i=0; i< 3; i++) diagnostics_print << trace(0).gauss(i) << " ";
999 for(int i=0; i< 3; i++) {
1000 for(int j=0; j< 5; j++)
1001 diagnostics_print << trace(i).lap.amp(0,j) << " ";
1002 diagnostics_print << trace(i).lap.phase(0,0) << " ";
1003 }
1004
1005 diagnostics_print << endl;
1006 }
1007
1008 return 1;
1009
1010 }
1011
1012
1013 //----------------------------------------------------------------------
1014
sample(int e,Sample_point * sample,Wavefunction * wf,Wavefunction_data * wfdata,Guiding_function * guidingwf,Dynamics_info & info,doublevar & timestep)1015 int SRK_dmc::sample(int e,
1016 Sample_point * sample,
1017 Wavefunction * wf,
1018 Wavefunction_data * wfdata,
1019 Guiding_function * guidingwf,
1020 Dynamics_info & info,
1021 doublevar & timestep
1022 ) {
1023
1024 //drift_type dtype=drift_cyrus;
1025 tries++;
1026 int ntrace=40;
1027 Array1 <Point> trace(ntrace);
1028 for(int i=0; i < ntrace; i++) {
1029 trace(i).lap.Resize(wf->nfunc(), 5);
1030 }
1031 for(int d=0; d< 3; d++) {
1032 trace(0).gauss(d)=rng.gasdev();
1033 }
1034
1035
1036 wf->updateLap(wfdata, sample);
1037 sample->getElectronPos(e,trace(0).pos);
1038 wf->getLap(wfdata, e, trace(0).lap);
1039 trace(0).sign=sample->overallSign();
1040 guidingwf->getLap(trace(0).lap, trace(0).drift);
1041
1042 //cout << "initial rk step " << endl;
1043 rk_step(e,sample, wf, wfdata, guidingwf, info, timestep, trace);
1044
1045 /*
1046 int pos=3;
1047 Array1 <doublevar> err(ntrace,0.0);
1048 err(2)=fabs(info.resample_gf/info.green_forward -1);
1049 while(resample &&
1050 fabs(info.resample_gf/info.green_forward-1) > resample_tol &&
1051 pos < ntrace) {
1052 //cout << "big error " << info.symm_gf/info.green_forward << endl;
1053 Array1 <doublevar> newdrift(3), orig_drift(3);
1054 orig_drift=trace(0).drift;
1055 newdrift=trace(pos-1).drift;
1056 limDrift(orig_drift, timestep, dtype);
1057 limDrift(newdrift, timestep, dtype);
1058 for(int d=0; d< 3; d++) {
1059 trace(pos).gauss(d)=trace(0).gauss(d);
1060 trace(pos).translation(d)=.5*(newdrift(d)+orig_drift(d))
1061 +trace(0).gauss(d)*sqrt(timestep);//-trace(pos-1).translation(d);
1062 trace(pos).pos(d)=trace(0).pos(d)+trace(pos).translation(d);
1063 }
1064
1065 sample->setElectronPos(e,trace(pos).pos);
1066 trace(pos).sign=sample->overallSign();
1067 wf->updateLap(wfdata, sample);
1068 wf->getLap(wfdata, e, trace(pos).lap);
1069 guidingwf->getLap(trace(pos).lap, trace(pos).drift);
1070
1071 info.symm_gf=exp(runge_kutta_symm(trace(0), trace(pos), timestep, dtype));
1072 info.resample_gf=exp(runge_kutta_resamp(trace(0), trace(pos),
1073 timestep, dtype));
1074 info.new_pos=trace(pos).pos;
1075
1076 err(pos)=fabs(info.resample_gf/info.green_forward-1);
1077 pos++;
1078 }
1079
1080 if(pos==ntrace) {
1081 nbottom++;
1082 int bestindex=2; doublevar bestratio=err(bestindex);
1083 for(int i=2; i < ntrace; i++) {
1084 if(err(i) < bestratio) { bestindex=i; bestratio=err(i); }
1085 }
1086 if(bestindex!=pos-1) {
1087 //cout << " large remaining error "; write_array(cout, err); cout << endl;
1088 //cout << "best index " << bestindex << endl;
1089
1090
1091 info.symm_gf=exp(runge_kutta_symm(trace(0), trace(bestindex),
1092 timestep, dtype));
1093 info.resample_gf=exp(runge_kutta_resamp(trace(0), trace(bestindex),
1094 timestep, dtype));
1095 info.new_pos=trace(bestindex).pos;
1096 sample->setElectronPos(e,trace(bestindex).pos);
1097 pos=bestindex+1;
1098 }
1099 }
1100 */
1101 //if(pos > 3) cout << "final ratio " << info.symm_gf/info.green_forward << endl;
1102
1103 doublevar ratio=guidingwf->getTrialRatio(trace(2).lap,
1104 trace(0).lap)
1105 *trace(0).sign*trace(2).sign;
1106
1107
1108 info.diffuse_start.Resize(3);
1109 for(int d=0; d< 3; d++)
1110 info.diffuse_start(d)=trace(2).pos(d)-sqrt(timestep)*trace(0).gauss(d);
1111
1112 info.diffuse_end=trace(2).pos;
1113
1114 //retries+=pos-3;
1115 if(ratio < 0) {
1116 //cout << "rejecting node crossing " << endl;
1117 info.accepted=0;
1118 sample->setElectronPos(e, trace(0).pos);
1119 wf->updateLap(wfdata, sample);
1120 return 0;
1121 }
1122 acceptances++;
1123 info.accepted=1;
1124 return 1;
1125 }
1126
1127
1128