00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "QMCMikesBetterWalkerInitialization.h"
00014
00015 #define PI 3.14159265359
00016 #define a0 0.529177257507
00017
00018 QMCMikesBetterWalkerInitialization::
00019 QMCMikesBetterWalkerInitialization( QMCInput *INPUT )
00020 {
00021 Input = INPUT;
00022 }
00023
00024 Array2D<double> QMCMikesBetterWalkerInitialization::initializeWalkerPosition()
00025 {
00026 int nelectrons = Input->WF.getNumberElectrons();
00027 Array2D<double> R(nelectrons,3);
00028
00029
00030 int nTestWalkers = Input->flags.walker_initialization_combinations;
00031 Array3D<double> severalRs(nelectrons,3,nTestWalkers);
00032 severalRs = initializeBunchOfWalkersPosition();
00033
00034
00035 R = FindBestWalker(severalRs);
00036
00037
00038 return R;
00039 }
00040
00041
00042 Array3D<double> QMCMikesBetterWalkerInitialization::initializeBunchOfWalkersPosition()
00043 {
00044 int nelectrons = Input->WF.getNumberElectrons();
00045 int nTestWalkers = Input->flags.walker_initialization_combinations;
00046 int natoms = Input->flags.Natoms;
00047 Array2D<double> atom_centers(natoms,3);
00048 atom_centers = Input->Molecule.Atom_Positions;
00049 Array3D<double> severalRs(nelectrons,3,nTestWalkers);
00050 double x0 = 0.0;
00051 double y0 = 0.0;
00052 double z0 = 0.0;
00053 double x = 0.0;
00054 double y = 0.0;
00055 double z = 0.0;
00056 int which_atom = 0;
00057
00058
00059 for(int i=0;i<nelectrons;i++)
00060 {
00061
00062 for(int j=0;j<nTestWalkers;j++)
00063 {
00064
00065
00066 which_atom=0;
00067
00068 x0=atom_centers(which_atom,0);
00069 y0=atom_centers(which_atom,1);
00070 z0=atom_centers(which_atom,2);
00071
00072
00073
00074
00075 x=x+x0;
00076 y=y+y0;
00077 z=z+z0;
00078
00079
00080
00081
00082 severalRs(i,0,j)=x;
00083 severalRs(i,1,j)=y;
00084 severalRs(i,2,j)=z;
00085 }
00086 }
00087
00088 return severalRs;
00089 }
00090
00091 Array2D<double> QMCMikesBetterWalkerInitialization::
00092 FindBestWalker(Array3D<double> &severalRs)
00093 {
00094
00095 int nelectrons = severalRs.dim1();
00096 int nTestWalkers = severalRs.dim3();
00097
00098 Array2D<double> Occupations(nelectrons,nTestWalkers);
00099 Array2D<double> GradOccupations(nelectrons,nTestWalkers);
00100
00101 for(int i=0;i<nelectrons;i++)
00102 {
00103 for(int j=0;j<nTestWalkers;i++)
00104 {
00105 Occupations(i,j) = 1.0/nTestWalkers;
00106 }
00107 }
00108
00109
00110
00111
00112
00113 double grad_bound=1.0;
00114 double step_size=0.1;
00115 int number_of_steps=4;
00116
00117
00118 for(int i=0;i<number_of_steps;i++)
00119 {
00120
00121 GradObjectiveFunctionForWalkers(severalRs,Occupations,GradOccupations);
00122
00123
00124 BoundGradOccupations(GradOccupations,grad_bound);
00125
00126
00127 MoveOccupations(Occupations,GradOccupations,step_size);
00128 }
00129
00130
00131
00132
00133 Array2D<double> R(nelectrons,3);
00134
00135
00136 for(int i=0;i<nelectrons;i++)
00137 {
00138
00139 double max_occ=0.0;
00140 int max_occ_index=-99999;
00141
00142
00143 for(int j=0;j<nTestWalkers;j++)
00144 {
00145 if(max_occ<Occupations(i,j))
00146 {
00147 max_occ=Occupations(i,j);
00148 max_occ_index=j;
00149 }
00150 }
00151
00152
00153 R(i,0)=severalRs(i,0,max_occ_index);
00154 R(i,1)=severalRs(i,1,max_occ_index);
00155 R(i,2)=severalRs(i,2,max_occ_index);
00156 }
00157 return R;
00158 }
00159
00160 void QMCMikesBetterWalkerInitialization::
00161 FixConstraints(Array2D<double> &Occupations)
00162 {
00163 double sum;
00164 for(int i=0;i<Occupations.dim1();i++)
00165 {
00166 sum=0.0;
00167 for(int j=0;j<(Occupations.dim2()-1);j++)
00168 {
00169
00170 if(Occupations(i,j)>1.0)
00171 {
00172 Occupations(i,j)=1.0;
00173 }
00174
00175 if(Occupations(i,j)<0.0)
00176 {
00177 Occupations(i,j)=0.0;
00178 }
00179 sum = sum + Occupations(i,j);
00180 }
00181 if(sum>1.0)
00182 {
00183
00184 for(int j=0;j<(Occupations.dim2()-1);j++)
00185 {
00186 Occupations(i,j)=Occupations(i,j)/sum;
00187 }
00188 sum=1.0;
00189 }
00190
00191 Occupations(i,Occupations.dim2()-1) = 1.0-sum;
00192 }
00193 }
00194
00195 double QMCMikesBetterWalkerInitialization::
00196 ObjectiveFunctionForWalkers(Array3D<double> &severalRs,Array2D<double> &Occupations)
00197 {
00198 double ee_energy = 0.0;
00199 double en_energy = 0.0;
00200 double temp=0.0;
00201 double x1,y1,z1,x2,y2,z2;
00202 double occ1,occ2;
00203 double r;
00204
00205
00206 int nalpha = Input->WF.getNumberElectrons(true);
00207
00208
00209
00210 for(int i=0;i<severalRs.dim1();i++)
00211 {
00212
00213 for(int j=0;j<severalRs.dim3();j++)
00214 {
00215
00216 for(int m=(i+1);m<severalRs.dim1();m++)
00217 {
00218
00219 for(int n=0;n<severalRs.dim3();n++)
00220 {
00221 x1=severalRs(i,0,j);
00222 y1=severalRs(i,1,j);
00223 z1=severalRs(i,2,j);
00224 x2=severalRs(m,0,n);
00225 y2=severalRs(m,1,n);
00226 z2=severalRs(m,2,n);
00227 occ1=Occupations(i,j);
00228 occ2=Occupations(m,n);
00229
00230 r=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
00231
00232
00233
00234
00235 if((i<nalpha && m<nalpha) || (i>=nalpha && m>=nalpha))
00236 {
00237 temp=Energy_parallel(r);
00238 }
00239 else
00240 {
00241 temp=Energy_opposite(r);
00242 }
00243
00244 ee_energy=ee_energy+temp*occ1*occ2;
00245 }
00246 }
00247 }
00248 }
00249
00250
00251 int natoms = Input->flags.Natoms;
00252 Array2D<double> atom_centers(natoms,3);
00253 Array1D<int> atom_charges(natoms);
00254 atom_centers = Input->Molecule.Atom_Positions;
00255 atom_charges = Input->Molecule.Z;
00256 int charge;
00257
00258
00259 for(int i=0;i<severalRs.dim1();i++)
00260 {
00261
00262 for(int j=0;j<severalRs.dim3();j++)
00263 {
00264
00265 for(int k=0;k<natoms;k++)
00266 {
00267 x1=severalRs(i,0,j);
00268 y1=severalRs(i,1,j);
00269 z1=severalRs(i,2,j);
00270 x2=atom_centers(k,0);
00271 y2=atom_centers(k,1);
00272 z2=atom_centers(k,2);
00273 occ1=Occupations(i,j);
00274
00275 r=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
00276
00277 charge=atom_charges(k);
00278
00279 temp=Energy_el_nuclr(r,charge);
00280
00281 en_energy=en_energy+temp*occ1;
00282 }
00283 }
00284 }
00285
00286 return (ee_energy+en_energy);
00287 }
00288
00289 void QMCMikesBetterWalkerInitialization::
00290 GradObjectiveFunctionForWalkers(Array3D<double> &severalRs,
00291 Array2D<double> &Occupations,
00292 Array2D<double> &GradOccupations)
00293 {
00294 double initial_energy = ObjectiveFunctionForWalkers(severalRs,Occupations);
00295 double dr = 0.1;
00296 double perturb_energy;
00297 double r_orig;
00298
00299
00300 for(int i=0;i<severalRs.dim1();i++)
00301 {
00302
00303 for(int j=0;j<severalRs.dim3();j++)
00304 {
00305 r_orig = Occupations(i,j);
00306
00307 Occupations(i,j) = Occupations(i,j)+dr;
00308 FixConstraints(Occupations);
00309
00310 perturb_energy = ObjectiveFunctionForWalkers(severalRs,Occupations);
00311
00312 GradOccupations(i,j) = (perturb_energy-initial_energy)/dr;
00313
00314 Occupations(i,j) = r_orig;
00315 FixConstraints(Occupations);
00316 }
00317 }
00318 }
00319
00320 void QMCMikesBetterWalkerInitialization::
00321 BoundGradOccupations(Array2D<double> &GradOccupations,double bound)
00322 {
00323 double mag,temp;
00324
00325 for(int i=0;i<GradOccupations.dim1();i++)
00326 {
00327 mag = 0.0;
00328
00329 for(int j=0;j<GradOccupations.dim2();j++)
00330 {
00331 temp = GradOccupations(i,j);
00332 mag = mag+temp*temp;
00333 }
00334
00335 mag = sqrt(mag);
00336
00337 for(int j=0;j<GradOccupations.dim2();j++)
00338 {
00339 GradOccupations(i,j) = GradOccupations(i,j)/mag*bound;
00340 }
00341 }
00342 }
00343
00344 void QMCMikesBetterWalkerInitialization::
00345 MoveOccupations(Array2D<double> &Occupations,
00346 Array2D<double> &GradOccupations,
00347 double dr)
00348 {
00349
00350 for(int i=0;i<GradOccupations.dim1();i++)
00351 {
00352
00353 for(int j=0;j<(GradOccupations.dim2()-1);j++)
00354 {
00355 Occupations(i,j)=Occupations(i,j)
00356 +dr*GradOccupations(i,j);
00357 }
00358 FixConstraints(Occupations);
00359 }
00360 }
00361
00362 double QMCMikesBetterWalkerInitialization::Energy_parallel(double r)
00363 {
00364
00365 return 2.0/r;
00366 }
00367
00368 double QMCMikesBetterWalkerInitialization::Energy_opposite(double r)
00369 {
00370 return 1.0/r;
00371 }
00372
00373 double QMCMikesBetterWalkerInitialization::Energy_el_nuclr(double r,
00374 int charge)
00375 {
00376 return -1.0*charge/r;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387