void Backflow_pf_wf::calcVal(Sample_point * sample) { int tote=nelectrons(0)+nelectrons(1); for(int e=0; e< tote; e++) { //int s=spin(e); sample->updateEIDist(); parent->bfwrapper.updateVal(sample,jast, e, 0, updatedMoVal); for(int i=0; i< updatedMoVal.GetDim(0); i++) { for(int d=0; d< 1; d++) { moVal(d,e,i)=updatedMoVal(i,d); } } } //cout << "doing pfaffian " << endl; for (int pf=0;pf<npf;pf++){ FillPfaffianMatrix( mopfaff_tot(pf), moVal, parent->pfkeeper.occupation_pos, parent->pfkeeper.npairs, parent->pfkeeper.order_in_pfaffian(pf), parent->pfkeeper.tripletorbuu, parent->pfkeeper.tripletorbdd, parent->pfkeeper.singletorb, parent->pfkeeper.unpairedorb, parent->pfkeeper.normalization, coef_eps ); pfaffVal(pf) = PfaffianInverseMatrix(mopfaff_tot(pf), inverse(pf)); //cout << "Pfaffian value: "<< pfaffVal(pf) << endl; } }
void Backflow_pf_wf::init(Wavefunction_data * wfdata) { Backflow_pf_wf_data * dataptr; recast(wfdata, dataptr); recast(wfdata, parent); nmo=dataptr->bfwrapper.nmo(); npf=dataptr->pfkeeper.npf; coef_eps=dataptr->pfkeeper.coef_eps; //nsfunc=dataptr->pfkeeper.nsfunc; nelectrons.Resize(2); nelectrons=dataptr->pfkeeper.nelectrons; int tote=nelectrons(0)+nelectrons(1); ndim=3; int upuppairs=dataptr->pfkeeper.npairs(0); int downdownpairs=dataptr->pfkeeper.npairs(1); int nopairs=dataptr->pfkeeper.npairs(2); npairs=upuppairs+downdownpairs+nopairs; //Properties and intermediate calculation storage. moVal.Resize(10,tote, dataptr->pfkeeper.totoccupation(0).GetSize()); updatedMoVal.Resize(dataptr->pfkeeper.totoccupation(0).GetSize(),10); inverse.Resize(npf); pfaffVal.Resize(npf); mopfaff_tot.Resize(npf); for (int pf=0;pf<npf;pf++){ inverse(pf).Resize(npairs, npairs); inverse(pf)=0; for(int e=0; e< npairs; e++){ inverse(pf)(e,e)=1; } pfaffVal(pf)=1; mopfaff_tot(pf).Resize(npairs,npairs); } electronIsStaleVal.Resize(tote); electronIsStaleLap.Resize(tote); electronIsStaleVal=0; electronIsStaleLap=0; updateEverythingVal=1; updateEverythingLap=1; sampleAttached=0; dataAttached=0; coor_grad.Resize(tote,tote,ndim,ndim); coor_lap.Resize(tote,tote,ndim); gradlap.Resize(tote,5); jast.init(&parent->bfwrapper.jdata); jast.keep_ion_dep(); }
void Backflow_pf_wf::updateVal(Wavefunction_data * wfdata, Sample_point * sample) { assert(sampleAttached); assert(dataAttached); Backflow_pf_wf_data * pfaffdata; recast(wfdata, pfaffdata); if(updateEverythingVal){ calcVal(sample); updateEverythingVal=0; electronIsStaleVal=0; } else { for(int e=0; e< nelectrons(0)+nelectrons(1); e++) { if(electronIsStaleVal(e)) { calcVal(sample); //updateVal(e,sample); electronIsStaleVal=0; } } } assert(sampleAttached); assert(dataAttached); }
void Backflow_pf_wf::updateLap( Wavefunction_data * wfdata, Sample_point * sample) { assert(sampleAttached); assert(dataAttached); if(updateEverythingLap==1) { calcLap(sample); updateEverythingVal=0; updateEverythingLap=0; electronIsStaleLap=0; electronIsStaleVal=0; } else { for(int e=0; e< nelectrons(0)+nelectrons(1); e++) { if(electronIsStaleLap(e)) { calcLap(sample); electronIsStaleLap(e)=0; electronIsStaleVal(e)=0; } } } }
void BCS_wf::saveUpdate(Sample_point * sample, int e1, int e2, Wavefunction_storage * wfstore) { BCS_wf_storage * store; recast(wfstore, store); jast.saveUpdate(sample,e1,e2,store->jast_store); store->inverse=inverse; store->detVal=detVal; // // unpaired electrons go into extra one-body orbitals, this // functionality will be resurrected later // //int nmo=moVal.GetDim(1); //int nd=moVal.GetDim(2); //for(int m=0; m< nmo; m++) { // for(int d=0; d< nd; d++) { // store->moVal(m,d)=moVal(e,m,d); // } //} // We assume the two electrons have opposite spins assert( spin(e1) != spin(e2) ); int e_up, e_down; e_up = spin(e1) ? e2 : e1; e_down = spin(e1) ? e1 : e2; { int nj=derivatives.GetDim(1); assert(nj==nelectrons(0)); int nd=derivatives.GetDim(2); for(int j=0; j< nj; j++) { for(int d=0; d< nd; d++) { store->derivatives(j,d)=derivatives(e_up,j,d); } } int ep=e_up+nelectrons(0); for(int j=0; j< nj; j++) { for(int d=0; d< nd; d++) { store->derivatives(j+nelectrons(0),d)=derivatives(ep,j,d); } } } { int ni=derivatives.GetDim(0); assert(ni==2*nelectrons(0)); int nd=derivatives.GetDim(2); int rede=e_down-nelectrons(0); for(int i=0; i< ni; i++) { for(int d=0; d< nd; d++) { store->derivatives_2(i,d)=derivatives(i,rede,d); } } } }
void BCS_wf::restoreUpdate(Sample_point * sample, int e, Wavefunction_storage * wfstore) { BCS_wf_storage * store; recast(wfstore, store); jast.restoreUpdate(sample,e,store->jast_store); detVal=store->detVal; inverse=store->inverse; // // unpaired electrons go into extra one-body orbitals, this // functionality will be resurrected later // //int nmo=moVal.GetDim(1); //int nd=moVal.GetDim(2); //for(int m=0; m< nmo; m++) { // for(int d=0; d< nd; d++) { // moVal(e,m,d)=store->moVal(m,d); // } //} if(spin(e)==0) { int nj=derivatives.GetDim(1); assert(nj==nelectrons(0)); int nd=derivatives.GetDim(2); for(int j=0; j< nj; j++) { for(int d=0; d< nd; d++) { derivatives(e,j,d)=store->derivatives(j,d); } } int ep=e+nelectrons(0); for(int j=0; j< nj; j++) { for(int d=0; d< nd; d++) { derivatives(ep,j,d)=store->derivatives(j+nelectrons(0),d); } } } else { int ni=derivatives.GetDim(0); assert(ni==2*nelectrons(0)); int nd=derivatives.GetDim(2); int rede=e-nelectrons(0); for(int i=0; i< ni; i++) { for(int d=0; d< nd; d++) { derivatives(i,rede,d)=store->derivatives(i,d); } } } electronIsStaleLap=0; electronIsStaleVal=0; updateEverythingLap=0; updateEverythingVal=0; //calcLap(sample); }
void BCS_wf::init(Wavefunction_data * wfdata) { BCS_wf_data * dataptr; recast(wfdata, dataptr); recast(wfdata, parent); //nmo=dataptr->molecorb->getNmo(); ndet=1; nelectrons.Resize(2); nelectrons=dataptr->nelectrons; int tote=nelectrons(0)+nelectrons(1); ndim=3; if(nelectrons(0) != nelectrons(1)) { error("For BCS wave function, the number of spin up electrons must" " be equal to the number of spin down electrons."); } spin.Resize(tote); spin=dataptr->spin; //moVal.Resize(tote, nmo,5); //updatedMoVal.Resize(nmo,5); detVal.Resize (ndet); inverse.Resize(ndet); for(int det=0; det < ndet; det++) { inverse(det).Resize(nelectrons(0), nelectrons(0)); inverse(det)=0; for(int e=0; e< nelectrons(0); e++) { inverse(det)(e,e)=1; inverse(det)(e,e)=1; } detVal(det)=1; } electronIsStaleVal.Resize(tote); electronIsStaleLap.Resize(tote); electronIsStaleVal=0; electronIsStaleLap=0; updateEverythingVal=1; updateEverythingLap=1; sampleAttached=0; dataAttached=0; jast.init(&parent->jastdata); derivatives.Resize(2*nelectrons(0),nelectrons(1),4); assert(jastcof==NULL); jastcof=new BCS_jastrow_u; }
//Note that the matrix is almost symmetric-- //we can use that to halve the computational time void BCS_wf::calcLap(Sample_point * sample) { int tote=nelectrons(0)+nelectrons(1); Array3 <doublevar> temp_der; Array2 <doublevar> temp_lap; for(int e=0; e< tote; e++) { sample->updateEIDist(); // //parent->molecorb->updateLap(sample,e,0,updatedMoVal); //for(int i=0; i< updatedMoVal.GetDim(0); i++) { // for(int d=0; d< 5; d++) { // moVal(e,i,d)=updatedMoVal(i,d); // } //} } Array2 <doublevar> onebody; jast.updateLap(&parent->jastdata,sample); jast.get_twobody(twobody); jast.get_onebody_save(onebody); int maxmatsize=max(nelectrons(0),nelectrons(1)); Array2 <doublevar> modet(maxmatsize, maxmatsize); modet=0; for(int det=0; det < ndet; det++ ) { for(int i=0; i< nelectrons(0); i++) { for(int j=0; j< nelectrons(1); j++) { int jshift=nelectrons(0)+j; Array2 <doublevar> ugrad; jastcof->valGradLap(twobody,onebody,i,jshift,ugrad); modet(i,j)=parent->magnification_factor*ugrad(0,0); for(int d=0; d< 4; d++) { derivatives(i,j,d)=ugrad(0,d+1); derivatives(i+nelectrons(0),j,d)=ugrad(1,d+1); } } // // unpaired electrons go into extra one-body orbitals, this // functionality will be resurrected later // //for(int j=nelectrons(1); j< nelectrons(0); j++) { // modet(i,j)=moVal(i,parent->occupation(det,0)(j),0); //} } detVal(det)= TransposeInverseMatrix(modet,inverse(det), nelectrons(0)).val(); } }
void BCS_wf::getLap(Wavefunction_data * wfdata, int e, Wf_return & lap) { getVal(wfdata,e,lap); for(int d=1; d< 5; d++) { if(spin(e)==0) { for(int det=0; det < ndet; det++) { doublevar temp=0; for(int j=0; j< nelectrons(1); j++) { temp+=derivatives(e,j,d-1) *inverse(det)(e,j); } // // unpaired electrons go into extra one-body orbitals, this // functionality will be resurrected later // //for(int j=nelectrons(1); j < nelectrons(0); j++) { // //error("need to do spin-polarized derivatives"); // temp+=moVal(e,parent->occupation(det,0)(j),d) // *inverse(det)(e,j); //} if(ndet > 1) error("update BCS::getLap() for ndet > 1"); lap.amp(0,d)=parent->magnification_factor*temp; } } else { for(int det=0; det < ndet; det++) { doublevar temp=0; int red=parent->rede(e); for(int i=0; i< nelectrons(0); i++) { temp+=derivatives(i+nelectrons(0),red,d-1) *inverse(det)(i,red); } lap.amp(0,d)=parent->magnification_factor*temp; } } } for(int d=1; d< 5; d++) { lap.phase(0,d)=0.0; } }
//Watch out that some of the indices are reversed from Kwon-- //this is to make the updates a bit more convienent. void Backflow_pf_wf::calcLap(Sample_point * sample) { //cout <<"Start Backflow_pf_wf::calcLap"<<endl; int tote=nelectrons(0)+nelectrons(1); Array3 <doublevar> temp_der; Array2 <doublevar> temp_lap; Array3 <doublevar> moVal_gradonly; moVal_gradonly.Resize(3,tote,updatedMoVal.GetDim(0)); for(int e=0; e< tote; e++) { //int s=spin(e); sample->updateEIDist(); parent->bfwrapper.updateLap(sample,jast,e,0,updatedMoVal, temp_der, temp_lap); for(int i=0; i< updatedMoVal.GetDim(0); i++) { for(int d=0; d< 10; d++) { moVal(d,e,i)=updatedMoVal(i,d); if(d>0 && d<4) moVal_gradonly(d-1,e,i)=moVal(d,e,i); } } for(int i=0; i< tote; i++) { for(int a=0; a< 3; a++) { for(int b=0; b < 3; b++) { coor_grad(e,i,a,b)=temp_der(i,a,b); } coor_lap(e,i,a)=temp_lap(i,a); } } } //cout << "doing pfaffian " << endl; for (int pf=0;pf<npf;pf++){ FillPfaffianMatrix( mopfaff_tot(pf), moVal, parent->pfkeeper.occupation_pos, parent->pfkeeper.npairs, parent->pfkeeper.order_in_pfaffian(pf), parent->pfkeeper.tripletorbuu, parent->pfkeeper.tripletorbdd, parent->pfkeeper.singletorb, parent->pfkeeper.unpairedorb, parent->pfkeeper.normalization, coef_eps ); pfaffVal(pf) = PfaffianInverseMatrix(mopfaff_tot(pf), inverse(pf)); //cout << "Pfaffian value: "<< pfaffVal(pf) << endl; } //cout << "done pfaffian" << endl; gradlap=0; Array1 <doublevar> gradmod2(tote); Array1 <Array3 <doublevar> > F(npf); Array1 <Array4 <doublevar> > H(npf); doublevar funcval=0; gradmod2=0; Array2 <doublevar> grad(tote,ndim); Array1 < Array1 < Array1 < Array1 <doublevar> > > > mopfaff_row; Array1 < Array1 < Array1 < Array2 <doublevar> > > > mopfaff_row_hess; mopfaff_row.Resize(npf); mopfaff_row_hess.Resize(npf); //cout <<"Getting all pairing orbital derivatives"<<endl; for(int pf=0;pf<npf;pf++){ mopfaff_row(pf).Resize(tote); mopfaff_row_hess(pf).Resize(tote); for(int i=0; i<tote; i++) { UpdatePfaffianRowLap(mopfaff_row(pf)(i), i, moVal, parent->pfkeeper.occupation_pos, parent->pfkeeper.npairs, parent->pfkeeper.order_in_pfaffian(pf), parent->pfkeeper.tripletorbuu, parent->pfkeeper.tripletorbdd, parent->pfkeeper.singletorb, parent->pfkeeper.unpairedorb, parent->pfkeeper.normalization, coef_eps ); UpdatePfaffianRowHess(mopfaff_row_hess(pf)(i), i, moVal_gradonly, parent->pfkeeper.occupation_pos, parent->pfkeeper.npairs, parent->pfkeeper.order_in_pfaffian(pf), parent->pfkeeper.tripletorbuu, parent->pfkeeper.tripletorbdd, parent->pfkeeper.singletorb, parent->pfkeeper.unpairedorb, parent->pfkeeper.normalization, coef_eps ); // for(int k=0;k<mopfaff_row(pf)(i).GetSize();k++){ // cout<<"i and k "<<i<<" "<<k<<endl; // for(int a=0;a<mopfaff_row(pf)(i)(k).GetDim(0);a++){ // for(int b=0;b<mopfaff_row_hess(pf)(i)(k).GetDim(0);b++) // cout << mopfaff_row(pf)(i)(k)(a) <<" "; // cout <<endl; // } //} } } //cout <<"Done getting all pairing orbital derivatives"<<endl; for(int pf=0;pf<npf;pf++){ grad=0; //cout << "pfaffVal "<<pfaffVal(det,0)<<" "<<pfaffVal(det,1)<<endl; funcval+=parent->pfkeeper.pfwt(pf)*pfaffVal(pf); F(pf).Resize(tote,tote,ndim); F(pf)=0; H(pf).Resize(tote,tote,ndim,ndim); H(pf)=0; if(pfaffVal(pf)!=0){ Array3 <doublevar> & fref(F(pf)); Array4 <doublevar> & href(H(pf)); for(int i=0; i<tote; i++) for(int j=0; j< tote; j++) { for(int k=0; k< npairs; k++){ for(int a=0;a < ndim; a++) { fref(i,j,a)+=mopfaff_row(pf)(j)(k)(a+1)*inverse(pf)(k,i); for(int l=0; l< npairs; l++){ for(int b=0;b < ndim; b++) { href(i,j,a,b)+=mopfaff_row(pf)(i)(k)(a+1)*mopfaff_row(pf)(j)(l)(b+1)*inverse(pf)(k,l); } } } } } //for(int i=0; i<tote; i++) // for(int j=0; j< tote; j++) { // cout <<i<<" "<<j<<endl; // for(int a=0;a < ndim; a++) // for(int b=0;b < ndim; b++) // cout <<href(i,j,a,b)<<endl; //} for(int i=0; i< tote; i++) { for(int j=0; j< tote; j++) { for(int a=0; a< ndim; a++) { for(int b=0; b< ndim; b++) { grad(i,a)+=fref(j,j,b)*coor_grad(j,i,a,b); } } } for(int a=0; a< ndim; a++) { doublevar weight=1.0; if(npf >1) weight=parent->pfkeeper.pfwt(pf)*pfaffVal(pf); gradmod2(i)+=grad(i,a)*grad(i,a)*weight; gradlap(i,a)+=grad(i,a)*weight; } } } }//pf for(int i=0; i< tote; i++) { for(int a=0; a< ndim; a++) { if(funcval==0) gradlap(i,a)=0; else if(npf>1) gradlap(i,a)*=1/funcval; } if(funcval==0) gradmod2(i)=0; else if(npf>1) gradmod2(i)*=1/funcval; } //Hessian lookup for MO's Array2 <int> hess_lookup(3,3); hess_lookup(0,0)=4; hess_lookup(1,1)=5; hess_lookup(2,2)=6; hess_lookup(0,1)=hess_lookup(1,0)=7; hess_lookup(0,2)=hess_lookup(2,0)=8; hess_lookup(1,2)=hess_lookup(2,1)=9; //Laplacian for(int i=0; i< tote; i++) { //coordinate whose lap we're taking for(int pf=0;pf<npf;pf++){ Array3 <doublevar> & fref(F(pf)); Array4 <doublevar> & href(H(pf)); Array2 <doublevar> & invref(inverse(pf)); doublevar lap=0; if(pfaffVal(pf)!=0){ for(int j=0; j< tote; j++) { for(int a=0; a< ndim; a++) { lap+=fref(j,j,a)*coor_lap(j,i,a); } } //cout << "i= " << i << endl; //doublevar lap1=lap; //cout << "lap1 " << lap << endl; for(int j=0; j < tote; j++) { for(int k=0; k < npairs; k++) { for(int a=0; a< ndim; a++) { for(int b=0; b< ndim; b++) { for(int g=0; g< ndim; g++) { if(k<tote){ lap-=coor_grad(j,i,a,b)*coor_grad(k,i,a,g)* (fref(k,j,b)*fref(j,k,g)- (href(j,k,b,g)+mopfaff_row_hess(pf)(j)(k)(b,g))*invref(k,j)); } lap+=coor_grad(j,i,a,b)*coor_grad(j,i,a,g) *invref(k,j)*mopfaff_row(pf)(j)(k)(hess_lookup(b,g)); //if(fabs(coor_grad(i,j,a,b)) > 1e-16 // && fabs(coor_grad(i,k,a,g)) > 1e-16 ) //cout << "j " << j << " k " << k << " a " << a // << " b " << b << " g " << g << " cijab " << coor_grad(i,j,a,b) // << " cikag " << coor_grad(i,k,a,g) // << " fkjb " << fref(kr,jr,b) << " fjkg " << fref(jr,kr,g) // << endl; } } } } } } if(npf>1) lap*=parent->pfkeeper.pfwt(pf)*pfaffVal(pf); gradlap(i,3)+=lap; }//pf //cout <<"gradlap(i,3) "<<gradlap(i,3)<<endl; if(funcval==0) gradlap(i,3)=0; else if(npf>1) gradlap(i,3)*=1/funcval; gradlap(i,3)+=gradmod2(i); //cout <<"After grad correction: gradlap(i,3) "<<gradlap(i,3)<<endl; if(isnan(gradlap(i,3))) { cout << "NAN! " << "gradmod2 " << gradmod2(i) <<endl; //<< " lap1 " << lap1 << " lap2 " << lap2 //<< " lap3 " << lap3 << endl; } }//i-th electron //cout << "done " << endl; }
int BCS_wf::getParmDeriv(Wavefunction_data *wfdata , Sample_point * sample, Parm_deriv_return & parm_derivatives ) { // analytic expressions below are valid only if jastrow can provide // analytic derivatives (not sure if it is enough to test this) if ( !parent->jastdata.supports(parameter_derivatives) ) return 0; //cout << "BCS_wf: doing analytic derivatives with respect to parameters." // << endl ; int nparms_full=parent->nparms(); int nparms_start=parm_derivatives.nparms_start; int nparms_end=parm_derivatives.nparms_end; int nparms=nparms_end-nparms_start; parm_derivatives.gradient.Resize(nparms); parm_derivatives.hessian.Resize(nparms, nparms); // gradients of the two-body orbital Array3 <doublevar> twobody_parm_deriv; jast.updateLap(&parent->jastdata,sample); jast.get_twobody_ParmDeriv(sample,twobody_parm_deriv); // gradient parm_derivatives.gradient=0.0; for(int det=0; det < ndet; det++) { for (int alpha=0; alpha<nparms; alpha++) { for(int i=0; i< nelectrons(0); i++) { for (int j=0; j< nelectrons(1); j++) { parm_derivatives.gradient(alpha)+= twobody_parm_deriv(i,nelectrons(0)+j,alpha)*inverse(det)(i,j)* parent->magnification_factor; } } } } // hessian parm_derivatives.hessian=0.0; for(int det=0; det < ndet; det++) { for (int alpha=0; alpha<nparms; alpha++) { for (int beta=0; beta<nparms; beta++) { parm_derivatives.hessian(alpha,beta)+= parm_derivatives.gradient(alpha)*parm_derivatives.gradient(beta); for(int i=0; i< nelectrons(0); i++) { for (int j=0; j< nelectrons(1); j++) { for(int k=0; k< nelectrons(0); k++) { for (int l=0; l< nelectrons(1); l++) { parm_derivatives.hessian(alpha,beta)-= twobody_parm_deriv(i,nelectrons(0)+j,alpha)*inverse(det)(k,j)* twobody_parm_deriv(k,nelectrons(0)+l,beta)*inverse(det)(i,l)* parent->magnification_factor*parent->magnification_factor; } } } } } } } return 1; }
void BCS_wf::updateLap(int e, Sample_point * sample ) { int s=spin(e); sample->updateEIDist(); // //parent->molecorb->updateLap(sample,e,0,updatedMoVal); //for(int i=0; i< updatedMoVal.GetDim(0); i++) { // for(int d=0; d< 5; d++) { // moVal(e,i,d)=updatedMoVal(i,d); // } //} Array2 <doublevar> onebody; jast.updateLap(&parent->jastdata,sample); jast.get_twobody(twobody); jast.get_onebody_save(onebody); for(int det=0; det < ndet; det++ ) { Array1 <doublevar> detUpdate(nelectrons(0)); if(s==0) { //------------spin up electron for(int j=0; j< nelectrons(1); j++) { int jshift=nelectrons(0)+j; Array2 <doublevar> ugrad; jastcof->valGradLap(twobody,onebody,e,jshift,ugrad); detUpdate(j)=parent->magnification_factor*ugrad(0,0); for(int d=0; d< 4; d++) { derivatives(e,j,d)=ugrad(0,d+1); derivatives(e+nelectrons(0),j,d)=ugrad(1,d+1); } } // // unpaired electrons go into extra one-body orbitals, this // functionality will be resurrected later // //for(int j=nelectrons(1); j< nelectrons(0); j++) { // detUpdate(j)=moVal(e,parent->occupation(det,0)(j),0); //} detVal(det)/=InverseUpdateColumn(inverse(det),detUpdate,e,nelectrons(0)); } else { //--------------------spin down electrons int eshift=e; int edown=e-nelectrons(0); for(int i=0; i< nelectrons(0); i++) { Array2 <doublevar> ugrad; jastcof->valGradLap(twobody,onebody,i,eshift,ugrad); detUpdate(i)=parent->magnification_factor*ugrad(0,0); for(int d=0; d< 4; d++) { derivatives(i,edown,d)=ugrad(0,d+1); derivatives(i+nelectrons(0),edown,d)=ugrad(1,d+1); } } detVal(det)/=InverseUpdateRow(inverse(det),detUpdate, edown,nelectrons(0)); } } }