void Dmc_method::doTmove(Properties_point & pt,Pseudopotential * pseudo, System * sys, Wavefunction_data * wfdata, Wavefunction * wf, Sample_point * sample, Guiding_function * guideingwf) { vector <Tmove> tmov; pt.setSize(nwf); wf->getVal(wfdata,0,pt.wf_val); sys->calcKinetic(wfdata,sample,wf,pt.kinetic); pt.potential=sys->calcLoc(sample); pt.weight=1.0; //this gets set later anyway pt.count=1; pseudo->calcNonlocTmove(wfdata,sys,sample,wf,pt.nonlocal,tmov); doublevar sum=1; for(vector<Tmove>::iterator mov=tmov.begin(); mov!=tmov.end(); mov++) { assert(mov->vxx < 0); sum-=timestep*mov->vxx; } pt.nonlocal(0)-=(sum-1)/timestep; //subtract_out_enwt=-(sum-1)/timestep; assert(sum >= 0); if(tmoves) { ///Non-size consistent doublevar rand=rng.ulec()*sum; sum=1; //reset to choose the move if(rand > sum) { for(vector<Tmove>::iterator mov=tmov.begin(); mov!=tmov.end(); mov++) { sum-=timestep*mov->vxx; if(rand < sum) { sample->translateElectron(mov->e,mov->pos); break; } } } } else { // Size-consistent vector < vector<Tmove> > tmv_by_e(nelectrons); for(vector<Tmove>::iterator mov=tmov.begin(); mov!=tmov.end(); mov++) { tmv_by_e[mov->e].push_back(*mov); } for(int e=0; e< nelectrons; e++) { doublevar sum_e=1.0; for(vector<Tmove>::iterator mov=tmv_by_e[e].begin(); mov!=tmv_by_e[e].end(); mov++) { sum_e-=timestep*mov->vxx; } doublevar rand=rng.ulec()*sum_e; doublevar sel_sum=1; if(rand > sel_sum) { for(vector<Tmove>::iterator mov=tmv_by_e[e].begin(); mov!=tmv_by_e[e].end(); mov++) { sel_sum-=timestep*mov->vxx; if(rand < sel_sum) { sample->translateElectron(e,mov->pos); break; } } } } } }
void Maximize_method::run(Program_options & options, ostream & output) { Wavefunction * wf=NULL; Sample_point * sample=NULL; sys->generateSample(sample); wfdata->generateWavefunction(wf); sample->attachObserver(wf); int nconfig=100; Array1 <Config_save_point> config_pos(nconfig); Array1 <doublevar> epos(3); Primary guidewf; generate_sample(sample,wf,wfdata,&guidewf,nconfig,config_pos); int nelectrons=sample->electronSize(); Properties_gather mygather; string tablename=options.runid+".table"; ofstream tableout(tablename.c_str()); for(int e=0; e< nelectrons; e++) { sample->getElectronPos(e,epos); for(int d=0; d< 3; d++) { tableout << "e" << e << "_"<< d << " "; } } tableout << "elocal" << endl; for(int i=0; i < nconfig; i++) { maximize(sample,wf,config_pos(i)); for(int e=0; e< nelectrons; e++) { sample->getElectronPos(e,epos); for(int d=0; d< 3; d++) { tableout << epos(d) << " "; } } Properties_point pt; mygather.gatherData(pt, pseudo, sys, wfdata, wf, sample, &guidewf); tableout << pt.energy(0) << endl; config_pos(i).write(cout); } delete wf; delete sample; }
//---------------------------------------------------------------------- int Postprocess_method::gen_point(Wavefunction * wf, Sample_point * sample, Config_save_point & configpos, doublevar weight, Properties_point & pt) { Primary guide; Properties_gather gather; configpos.restorePos(sample); pseudo->randomize(); if(evaluate_energy) gather.gatherData(pt,pseudo,sys,wfdata,wf,sample,&guide); pt.avgrets.Resize(1,average_var.GetDim(0)); //cout << mpi_info.node << " generating a point with " << average_var.GetDim(0) << " avgrets " << endl; for(int i=0; i< average_var.GetDim(0); i++) { average_var(i)->randomize(wfdata,wf,sys,sample); average_var(i)->evaluate(wfdata, wf, sys, pseudo,sample,pt, pt.avgrets(0,i)); } for(int i=0; i< densplt.GetDim(0); i++) densplt(i)->accumulate(sample,weight); pt.weight(0)=weight; }
void Reptation_method::get_center_avg(deque <Reptile_point> & reptile, Properties_point & pt) { int nwf=reptile[0].prop.kinetic.GetDim(0); int size=reptile.size(); if(nwf >1) error("nwf > 0 not supported yet"); pt.setSize(nwf); int num=size/2+1; pt=reptile[num].prop; pt.count=1; pt.weight=1; }
//---------------------------------------------------------------------- int Postprocess_method::worker(Wavefunction * wf, Sample_point * sample) { #ifdef USE_MPI Config_save_point tmpconfig; doublevar weight; Properties_point pt; pt.setSize(1); tmpconfig.mpiReceive(0); MPI_Recv(weight,0); MPI_Status status; while(true) { gen_point(wf,sample,tmpconfig,weight,pt); int done=1; MPI_Send(done,0); pt.mpiSend(0); MPI_Recv(done,0); if(done==0) break; tmpconfig.mpiReceive(0); MPI_Recv(weight,0); } cout << mpi_info.node << " : done " << endl; #endif //USE_MPI }
void Reptation_method::get_avg(deque <Reptile_point> & reptile, Properties_point & pt) { int size=reptile.size(); int nwf=reptile[0].prop.kinetic.GetDim(0); if(nwf >1) error("nwf > 0 not supported yet"); pt.setSize(nwf); Reptile_point & last(reptile[size-1]); //How to do averaging at either end. Not doing this right //now because of correlated sampling..if we really want energies, //usually DMC is a better choice. pt=last.prop; //Reptile_point & first(reptile[0]); //pt.kinetic(0)=.5*(first.prop.kinetic(0)+last.prop.kinetic(0)); //pt.nonlocal(0)=.5*(first.prop.nonlocal(0)+last.prop.nonlocal(0)); //pt.potential(0)=.5*(first.prop.potential(0) + last.prop.potential(0)); pt.count=1; pt.weight=1; }
/*! */ void Reptation_method::runWithVariables(Properties_manager & prop, System * sys, Wavefunction_data * wfdata, Pseudopotential * psp, ostream & output) { allocateIntermediateVariables(sys, wfdata); prop.setSize(wf->nfunc(), nblock, nstep, 1, sys, wfdata); prop.initializeLog(average_var); Properties_manager prop_center; string logfile, label_temp; prop.getLog(logfile, label_temp); label_temp+="_cen"; prop_center.setLog(logfile, label_temp); prop_center.setSize(wf->nfunc(), nblock, nstep, 1, sys, wfdata); prop_center.initializeLog(average_var); cout.precision(10); output.precision(10); Sample_point * center_samp(NULL); sys->generateSample(center_samp); Reptile_point pt; Array1 <Reptile> reptiles; int nreptile=1; if(!readcheck(readconfig,reptiles)) { Array1 <Config_save_point> configs; generate_sample(sample,wf,wfdata,guidewf,nreptile,configs); reptiles.Resize(nreptile); for(int r=0; r< nreptile; r++) { reptiles[r].direction=1; configs(r).restorePos(sample); wf->notify(all_electrons_move,0); wf->updateLap(wfdata,sample); for(int i=0; i< reptile_length; i++) { doublevar main_diffusion; slither(1,reptiles[r].reptile, mygather,pt,main_diffusion); reptiles[r].reptile.push_back(pt); } } } nreptile=reptiles.GetDim(0); //assert(reptile.size()==reptile_length); //Branch limiting variables //we start off with no limiting, and establish the parameters after the //first block. This seems to be reasonably stable, since it's mostly //to keep the reptile from getting stuck. eref=0; energy_cutoff=1e16; //--------begin averaging.. Array3 <doublevar> derivatives_block(nblock, sys->nIons(), 3); for(int block=0; block< nblock; block++) { //clock_t block_start_time=clock(); doublevar avg_age=0; doublevar max_age=0; doublevar main_diff=0; double ntry=0, naccept=0; double nbounce=0; for(int r=0; r< nreptile; r++) { Reptile & curr_reptile=reptiles[r]; //Control variable that will be set to one when //we change direction, which signals to recalculate //the wave function int recalc=1; for(int step=0; step< nstep; step++) { psp->randomize(); if(recalc) { if(curr_reptile.direction==1) curr_reptile.reptile[reptile_length-1].restorePos(sample); else curr_reptile.reptile[0].restorePos(sample); } doublevar main_diffusion; doublevar accept=slither(curr_reptile.direction, curr_reptile.reptile,mygather, pt, main_diffusion); ntry++; if(accept+rng.ulec() > 1.0) { recalc=0; naccept++; main_diff+=main_diffusion; if(curr_reptile.direction==1) { curr_reptile.reptile.pop_front(); curr_reptile.reptile.push_back(pt); } else { curr_reptile.reptile.pop_back(); curr_reptile.reptile[0].branching=pt.branching; curr_reptile.reptile.push_front(pt); } } else { recalc=1; curr_reptile.direction*=-1; nbounce++; } for(deque<Reptile_point>::iterator i=curr_reptile.reptile.begin(); i!=curr_reptile.reptile.end(); i++) { i->age++; avg_age+=i->age/reptile_length; if(i->age > max_age) max_age=i->age; } Properties_point avgpt; get_avg(curr_reptile.reptile, avgpt); avgpt.parent=0; avgpt.nchildren=1; //just one walker avgpt.children(0)=0; prop.insertPoint(step, 0, avgpt); int cpt=reptile_length/2+1; Properties_point centpt; get_center_avg(curr_reptile.reptile, centpt); centpt.parent=0; centpt.nchildren=1; centpt.children(0)=0; prop_center.insertPoint(step, 0, centpt); curr_reptile.reptile[cpt].restorePos(center_samp); for(int i=0; i< densplt.GetDim(0); i++) densplt(i)->accumulate(center_samp,1.0); if(center_trace != "" && (block*nstep+step)%trace_wait==0) { ofstream checkfile(center_trace.c_str(), ios::app); if(!checkfile)error("Couldn't open ", center_trace); checkfile << "SAMPLE_POINT { \n"; write_config(checkfile, sample); checkfile << "}\n\n"; } } //step } //reptile prop.endBlock(); prop_center.endBlock(); double ntot=parallel_sum(nstep); Properties_block lastblock; prop.getLastBlock(lastblock); eref=lastblock.avg(Properties_types::total_energy,0); energy_cutoff=10*sqrt(lastblock.var(Properties_types::total_energy,0)); nbounce=parallel_sum(nbounce); naccept=parallel_sum(naccept); ntry=parallel_sum(ntry); avg_age=parallel_sum(avg_age); for(int i=0; i< densplt.GetDim(0); i++) densplt(i)->write(); storecheck(reptiles, storeconfig); main_diff=parallel_sum(main_diff); if(output) { output << "****Block " << block << " acceptance " << naccept/ntry << " average steps before bounce " << ntot/nbounce << endl; output << "average age " << avg_age/ntot << " max age " << max_age << endl; output << "eref " << eref << " cutoff " << energy_cutoff << endl; output << "Green's function sampler:" << endl; sampler->showStats(output); prop.printBlockSummary(output); output << "Center averaging: " << endl; prop_center.printBlockSummary(output); } sampler->resetStats(); //clock_t block_end_time=clock(); //cout << mpi_info.node << ":CPU block time " //// << double(block_end_time-block_start_time)/double(CLOCKS_PER_SEC) // << endl; } //block if(output) { output << "############## Reptation Done ################\n"; output << "End averages " << endl; prop.printSummary(output,average_var); output << "Center averages " << endl; prop_center.printSummary(output,average_var); //Print out a PDB file with one of the reptiles, for visualization purposes if(print_pdb) { ofstream pdbout("rmc.pdb"); pdbout.precision(3); pdbout << "REMARK 4 Mode COMPLIES WITH FORMAT V. 2.0\n"; int nelectrons=sample->electronSize(); int counter=1; string name="H"; for(int e=0; e<nelectrons; e++) { for(deque<Reptile_point>::iterator i=reptiles[0].reptile.begin(); i!=reptiles[0].reptile.end(); i++) { pdbout<<"ATOM"<<setw(7)<< counter <<" " <<name<<" UNK 1" <<setw(12)<< i->electronpos[e][0] <<setw(8)<< i->electronpos[e][1] <<setw(8)<< i->electronpos[e][2] << " 1.00 0.00\n"; counter++; } } int nions=sys->nIons(); Array1 <doublevar> ionpos(3); vector <string> atomnames; sys->getAtomicLabels(atomnames); for(int i=0; i< nions; i++) { sys->getIonPos(i,ionpos); pdbout<<"ATOM"<<setw(7)<< counter <<" " <<atomnames[i]<<" UNK 1" <<setw(12)<< ionpos[0] <<setw(8)<< ionpos[1] <<setw(8)<< ionpos[2] << " 1.00 0.00\n"; } counter=1; for(int e=0; e<nelectrons; e++) { for(deque<Reptile_point>::iterator i=reptiles[0].reptile.begin(); i!=reptiles[0].reptile.end(); i++) { if(i != reptiles[0].reptile.begin()) { pdbout << "CONECT" << setw(5) << counter << setw(5) << counter-1 << endl; } counter++; } } } //------------Done PDB file } delete center_samp; wfdata->clearObserver(); deallocateIntermediateVariables(); }
void Postprocess_method::run(Program_options & options, ostream & output) { Sample_point * sample=NULL; Wavefunction * wf=NULL; sys->generateSample(sample); wfdata->generateWavefunction(wf); sample->attachObserver(wf); Properties_gather gather; Primary guide; int nelec=sample->electronSize(); int ndim=3; int npoints_tot=0; FILE * f; if(mpi_info.node==0) { f=fopen(configfile.c_str(),"r"); if(ferror(f)) error("Could not open",configfile); fseek(f,0,SEEK_END); long int lSize=ftell(f); rewind(f); npoints_tot=lSize/(sizeof(doublevar)*(nelec*3+1+4)); output << "Estimated number of samples in this file: " << npoints_tot << endl; output << "We are skipping the first " << nskip << " of these " << endl; Config_save_point tmpconfig; for(int i=0; i< nskip; i++) { doublevar weight; tmpconfig.readBinary(f,nelec,ndim,weight); // doublevar weight; // if(!fread(&weight,sizeof(doublevar),1,f)) error("Misformatting in binary file",configfile, " perhaps nskip is too large?"); } } #ifdef USE_MPI if(mpi_info.nprocs<2) error("POSTPROCESS must be run with at least 2 processes if it is run in parallel."); if(mpi_info.node==0) { master(wf,sample,f,output); } else { worker(wf,sample); } #else Config_save_point tmpconfig; Properties_point pt; pt.setSize(1); int npoints=0; Postprocess_average postavg(average_var.GetDim(0)); doublevar weight; while(tmpconfig.readBinary(f,nelec,ndim,weight)) { tmpconfig.restorePos(sample); gen_point(wf,sample,tmpconfig,weight,pt); postavg.update_average(pt); npoints++; doublevar progress=doublevar(npoints)/doublevar(npoints_tot); if(fabs(progress*10-int(progress*10)) < 0.5/npoints_tot) { cout << "progress: " << progress*100 << "% done" << endl; } } postavg.print(average_var,output); #endif //USE_MPI for(int i=0; i< densplt.GetDim(0); i++) densplt(i)->write(); if(mpi_info.node==0) fclose(f); delete sample; delete wf; }
int Postprocess_method::master(Wavefunction * wf, Sample_point * sample,FILE * f, ostream & os) { #ifdef USE_MPI Config_save_point tmpconfig; doublevar weight; Properties_point pt; pt.setSize(1); int nelec=sample->electronSize(); int ndim=3; MPI_Status status; Postprocess_average postavg(average_var.GetDim(0)); //Get everyone started with data cout << "master: sending initial data" << endl; for(int r=1; r < mpi_info.nprocs; r++) { if(!tmpconfig.readBinary(f,nelec,ndim,weight)) { error("Binary file may not contain enough walkers; finished after ",r); } tmpconfig.mpiSend(r); MPI_Send(weight,r); } int totcount=0; cout << "master : going through file " << endl; while(tmpconfig.readBinary(f,nelec,ndim,weight)) { // doublevar weight; // if(!fread(&weight,sizeof(doublevar),1,f)) error("Misformatting in binary file",configfile); //Is anyone done? //When done, receive completed point and send out new point int done; MPI_Recv(&done,1,MPI_INT,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_Comm_grp,&status); //cout << "master: received " << done << " from " << status.MPI_SOURCE << endl; done=1; pt.mpiReceive(status.MPI_SOURCE); MPI_Send(done,status.MPI_SOURCE); tmpconfig.mpiSend(status.MPI_SOURCE); MPI_Send(weight,status.MPI_SOURCE); //introduce completed point into the average //cout << "master: updating average " << endl; postavg.update_average(pt); totcount++; if(totcount%1000==0) cout << "Completed " << totcount << " walkers " << endl; } cout << "master: collecting final averages " << endl; //Loop through all the nodes and collect their last points, adding them in //Write out the final averages. for(int r=1; r < mpi_info.nprocs; r++) { int done; MPI_Recv(done,r); done=0; pt.mpiReceive(r); MPI_Send(done,r); postavg.update_average(pt); } postavg.print(average_var,os); #endif //USE_MPI }