//---------------------------------------------------------------------- // // // doublevar Wannier_method::evaluate_local(const Array3 <dcomplex> & eikr, Array2 <doublevar> & Rgen, Array2 <doublevar> & R) { int norb=Rgen.GetDim(0); Array2 <doublevar> gvec(3,3); sys->getPrimRecipLattice(gvec); Array1 <doublevar> gnorm(3); gnorm=0; for(int d=0; d < 3; d++) { for(int d1=0; d1 < 3; d1++) { gnorm(d)+=gvec(d,d1)*gvec(d,d1); } gnorm(d)=sqrt(gnorm(d)); } Array2 <dcomplex> tmp(norb,norb),tmp2(norb,norb); make_rotation_matrix(Rgen,R); doublevar func=0; for(int d=0; d< 3; d++) { tmp=0.0; for(int i=0; i< norb; i++) { for(int j=0; j< norb; j++) { for(int k=0; k< norb; k++) { tmp(i,k)+=eikr(d,i,j)*R(k,j); } } } tmp2=0; for(int i=0; i< norb; i++) { for(int j=0; j< norb; j++) { for(int k=0; k< norb; k++) { tmp2(i,k)+=R(i,j)*tmp(j,k); } } } //cout << "========for d=" << d << endl; for(int i=0; i< norb; i++) { doublevar f= -log(norm(tmp2(i,i)))/(gnorm(d)*gnorm(d)); func+=f; // cout << setw(9) << f; } } //cout << endl; return func/(3*norb); }
TEST(gsl_vector, sum_std_vector) { std::vector<double> vec = {5.0, 2.0, 10.0}; std::vector<double> vec1 = {1.0, 2.0, 9.0}; optimize::GSLVector gvec(vec); std::vector<double> res = optimize::GSLVector::sum(gvec.get(), &vec1); ASSERT_NEAR(6.0, res[0], 1E-6); ASSERT_NEAR(4.0, res[1], 1E-6); ASSERT_NEAR(19.0, res[2], 1E-6); }
//---------------------------------------------------------------------- void Wannier_method::optimize_rotation(Array3 <dcomplex> & eikr, Array2 <doublevar> & R ) { int norb=eikr.GetDim(1); Array2 <doublevar> gvec(3,3); sys->getPrimRecipLattice(gvec); Array1 <doublevar> gnorm(3); gnorm=0; for(int d=0; d < 3; d++) { for(int d1=0; d1 < 3; d1++) { gnorm(d)+=gvec(d,d1)*gvec(d,d1); } gnorm(d)=sqrt(gnorm(d)); } for(int i=0; i< norb; i++) { cout << "rloc2 " << i << " "; for(int d=0; d< 3; d++) { cout << -log(norm(eikr(d,i,i)))/(gnorm(d)*gnorm(d)) << " "; } cout << endl; } Array2 <doublevar> Rgen(norb,norb),Rgen_save(norb,norb); //R(norb,norb); R.Resize(norb,norb); //Array2 <dcomplex> tmp(norb,norb),tmp2(norb,norb); //Shake up the angles, since often the original orbitals //are at a maximum and derivatives are zero. Array2 <doublevar> deriv(norb,norb); Rgen=0.0; for(int ii=0; ii< norb; ii++) { for(int jj=ii+1; jj< norb; jj++) { Rgen(ii,jj)=rng.gasdev()*pi*shake; } } for(int step=0; step < max_opt_steps; step++) { doublevar fbase=evaluate_local(eikr,Rgen,R); for(int ii=0; ii <norb; ii++) { cout << "deriv "; for(int jj=ii+1; jj < norb; jj++) { doublevar save_rgeniijj=Rgen(ii,jj); doublevar h=1e-6; Rgen(ii,jj)+=h; doublevar func=evaluate_local(eikr,Rgen,R); deriv(ii,jj)=(func-fbase)/h; Rgen(ii,jj)=save_rgeniijj; cout << deriv(ii,jj) << " "; } cout << endl; } doublevar rloc_thresh=0.0001; Rgen_save=Rgen; doublevar best_func=1e99, best_tstep=0.0; doublevar bracket_tstep=0.0; doublevar last_func=fbase; for(doublevar tstep=0.01; tstep < 20.0; tstep*=2.0) { doublevar func=eval_tstep(eikr,Rgen,Rgen_save,deriv,tstep,R); cout << "tstep " << tstep << " func " << func << endl; if(func > fbase or func > last_func) { bracket_tstep=tstep; break; } else last_func=func; } cout << "bracket_tstep " << bracket_tstep << endl; doublevar resphi=2.-(1.+sqrt(5.))/2.; doublevar a=0, b=resphi*bracket_tstep, c=bracket_tstep; doublevar af=fbase, bf=eval_tstep(eikr,Rgen,Rgen_save,deriv,b,R), cf=eval_tstep(eikr,Rgen,Rgen_save,deriv,bracket_tstep,R); cout << "first step a,b,c " << a << " " << b << " " << c << " funcs " << af << " " << bf << " " << cf << endl; for(int it=0; it < 20; it++) { doublevar d,df; if( (c-b) > (b-a)) d=b+resphi*(c-b); else d=b-resphi*(b-a); df=eval_tstep(eikr,Rgen,Rgen_save,deriv,d,R); if(df < bf) { if( (c-b) > (b-a) ) { a=b; af=bf; b=d; bf=df; } else { c=b; cf=bf; b=d; bf=df; } } else { if( (c-b) > (b-a) ) { c=d; cf=df; } else { a=d; af=df; } } cout << "step " << it << " a,b,c " << a << " " << b << " " << c << " funcs " << af << " " << bf << " " << cf << endl; } best_tstep=b; /* bool made_move=false; while (!made_move) { for(doublevar tstep=0.00; tstep < max_tstep; tstep+=0.1*max_tstep) { for(int ii=0; ii< norb;ii++) { for(int jj=ii+1; jj < norb; jj++) { Rgen(ii,jj)=Rgen_save(ii,jj)-tstep*deriv(ii,jj); } } doublevar func=evaluate_local(eikr,Rgen,R); if(func < best_func) { best_func=func; best_tstep=tstep; } cout << " tstep " << tstep << " " << func << endl; } if(abs(best_tstep) < 0.2*max_tstep) max_tstep*=0.5; else if(abs(best_tstep-max_tstep) < 1e-14) max_tstep*=2.0; else made_move=true; } */ for(int ii=0; ii< norb; ii++) { for(int jj=ii+1; jj < norb; jj++) { Rgen(ii,jj)=Rgen_save(ii,jj)-best_tstep*deriv(ii,jj); } } doublevar func2=evaluate_local(eikr,Rgen,R); doublevar max_change=0; for(int ii=0; ii < norb; ii++) { for(int jj=ii+1; jj< norb; jj++) { doublevar change=abs(Rgen(ii,jj)-Rgen_save(ii,jj)); if(change > max_change) max_change=change; } } cout << "tstep " << best_tstep << " rms " << sqrt(func2) << " bohr max change " << max_change <<endl; doublevar threshold=0.0001; if(max_change < threshold) break; if(abs(best_func-fbase) < rloc_thresh) break; /* bool moved=false; for(int ii=0; ii< norb; ii++) { for(int jj=ii+1; jj< norb; jj++) { doublevar save_rgeniijj=Rgen(ii,jj); doublevar best_del=0; doublevar best_f=1e99; for(doublevar del=-0.5; del < 0.5; del+=0.05) { cout << "############ for del = " << del << endl; Rgen(ii,jj)=save_rgeniijj+del; doublevar func=evaluate_local(eikr,Rgen,R); if(func < best_f) { best_f=func; best_del=del; } cout << "func " << func << endl; } Rgen(ii,jj)=save_rgeniijj+best_del; if(abs(best_del) > 1e-12) moved=true; } } if(!moved) break; */ } make_rotation_matrix(Rgen,R); }
//---------------------------------------------------------------------- void Wannier_method::calculate_overlap(Array1 <int> & orb_list, Array3 <dcomplex> & eikr, Array2 <doublevar> & phi2phi2) { Array1 <Array1 <int> > tmp_list(1); tmp_list(0)=orb_list; mymomat->buildLists(tmp_list); int list=0; Array2 <doublevar> gvec(3,3); if(!sys->getPrimRecipLattice(gvec) ) error("Need getPrimRecipLattice"); int norb=orb_list.GetDim(0); eikr.Resize(3,norb,norb); phi2phi2.Resize(norb,norb); eikr=0.0; phi2phi2=0.0; Array1 <doublevar> prop(3); Array1 <doublevar> n_lat(3); n_lat=0.0; for(int d=0; d < 3; d++) { for(int d1=0; d1 < 3; d1++) n_lat(d)+=LatticeVec(d,d1)*LatticeVec(d,d1); n_lat(d)=sqrt(n_lat(d)); prop(d)=resolution/double(n_lat(d)); //cout << "prop " << prop(d) << " res " << resolution << " norm " << n_lat(d) << endl; } cout << "calculating...." << endl; mymovals.Resize(norb,1); Array1 <doublevar> r(3),x(3); Array1 <doublevar> norm_orb(norb); norm_orb=0.0; int totpts=0; for(r(0)=origin(0); r(0) < 1.0; r(0)+=prop(0)) { cout << "percent done: " << r(0)*100 << endl; for(r(1)=origin(1); r(1) < 1.0; r(1)+=prop(1)) { for(r(2)=origin(2); r(2) < 1.0; r(2)+=prop(2)) { totpts++; for(int d=0; d< 3; d++) { x(d)=0.0; for(int d1=0; d1 < 3; d1++) { x(d)+=r(d1)*LatticeVec(d1,d); } } mywalker->setElectronPos(0,x); mymomat->updateVal(mywalker,0,list,mymovals); for(int i=0; i < norb; i++) norm_orb(i)+=mymovals(i,0)*mymovals(i,0); for(int d=0; d< 3; d++) { doublevar gdotr=0; for(int d1=0; d1 < 3; d1++) { gdotr+=gvec(d,d1)*x(d1); } dcomplex exp_tmp=exp(dcomplex(0,-1)*2.*pi*gdotr); for(int i=0; i< norb; i++) { for(int j=0; j< norb; j++) { eikr(d,i,j)+=exp_tmp*mymovals(i,0)*mymovals(j,0); } } } for(int i=0; i< norb; i++) { for(int j=0; j< norb; j++) { phi2phi2(i,j)+=mymovals(i,0)*mymovals(i,0)*mymovals(j,0)*mymovals(j,0); } } } } } for(int i=0; i< norb; i++) norm_orb(i)=sqrt(norm_orb(i)); for(int d=0; d< 3; d++) { for(int i=0; i < norb; i++) { for(int j=0; j< norb; j++) { eikr(d,i,j)/=norm_orb(i)*norm_orb(j); //cout << d << " " << i << " " << j << " " << eikr(d,i,j) << endl; } } } cout << "square overlap " << endl; for(int i=0; i < norb; i++) { for(int j=0; j< norb; j++) { phi2phi2(i,j)/=(norm_orb(i)*norm_orb(i)*norm_orb(j)*norm_orb(j)); cout << sqrt(phi2phi2(i,j)) << " "; } cout << endl; } }