//----------------------------------------------------------------------
//
//
//
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);

}
Beispiel #2
0
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;
    }


}