Example #1
0
 explicit mdarray(const mdarray<MDARGS...> &array):
     _imap(map_utils<map_type>::create(array.template shape<shape_t>())),
     _data(container_utils<storage_type>::create(array.size()))
 {
     //copy data
     for(size_t i=0;i<array.size();++i) (*this)[i] = array[i];
     //std::copy(array.begin(),array.end(),this->begin());
 }
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
double Potential::calc_PAW_hartree_potential(Atom& atom, const Radial_grid& grid,
                                             mdarray<double, 2> &full_density,
                                             mdarray<double, 3> &out_atom_pot)
{
    //---------------------
    //-- calc potential --
    //---------------------
    int lmsize_rho = out_atom_pot.size(0);

    Spheric_function<function_domain_t::spectral,double> dens_sf(&full_density(0,0), lmsize_rho, grid);

    // array passed to poisson solver
    Spheric_function<spectral,double> atom_pot_sf(lmsize_rho, grid);
    atom_pot_sf.zero();

    // create qmt to store multipoles
    mdarray<double_complex,1> qmt(lmsize_rho);

    // solve poisson eq and fill 0th spin component of hartree array (in nonmagnetic we have only this)
    qmt.zero();
    poisson_atom_vmt(dens_sf, atom_pot_sf, qmt, atom);

    // make spher funcs from arrays
    Spheric_function<spectral,double> out_atom_pot_sf(&out_atom_pot(0,0,0), lmsize_rho, grid);
    out_atom_pot_sf += atom_pot_sf;


    //---------------------
    //--- calc energy ---
    //---------------------
    std::vector<int> l_by_lm = Utils::l_by_lm( Utils::lmax_by_lmmax(lmsize_rho) );

    // create array for integration
    std::vector<double> intdata(grid.num_points(),0);

    double hartree_energy=0.0;

    for(int lm=0; lm < lmsize_rho; lm++)
    {
        // fill data to integrate
        for(int irad = 0; irad < grid.num_points(); irad++)
        {
            intdata[irad] = full_density(lm,irad) * out_atom_pot(lm, irad, 0) * grid[irad] * grid[irad];
        }

        // create spline from the data
        Spline<double> h_spl(grid,intdata);

        hartree_energy += 0.5 * h_spl.integrate(0);
    }

    return hartree_energy;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
double Potential::xc_mt_PAW_nonmagnetic(const Radial_grid& rgrid,
                                      mdarray<double, 3> &out_atom_pot,
                                      mdarray<double, 2> &full_rho_lm,
                                      const std::vector<double> &rho_core)
{
    Spheric_function<spectral,double> out_atom_pot_sf(&out_atom_pot(0,0,0), full_rho_lm.size(0), rgrid);

    Spheric_function<spectral,double> full_rho_lm_sf(&full_rho_lm(0,0), full_rho_lm.size(0), rgrid);

    Spheric_function<spectral,double> full_rho_lm_sf_new(full_rho_lm.size(0), rgrid);

    full_rho_lm_sf_new.zero();
    full_rho_lm_sf_new += full_rho_lm_sf;

    double invY00 = 1. / y00 ;

    for(int ir = 0; ir < rgrid.num_points(); ir++ )
    {
        full_rho_lm_sf_new(0,ir) += invY00 * rho_core[ir];
    }

    Spheric_function<spatial,double> full_rho_tp_sf = transform(sht_.get(), full_rho_lm_sf_new);

    // create potential in theta phi
    Spheric_function<spatial,double> vxc_tp_sf(sht_->num_points(), rgrid);

    // create energy in theta phi
    Spheric_function<spatial,double> exc_tp_sf(sht_->num_points(), rgrid);

    xc_mt_nonmagnetic(rgrid, xc_func_, full_rho_lm_sf_new, full_rho_tp_sf, vxc_tp_sf, exc_tp_sf);

    out_atom_pot_sf += transform(sht_.get(), vxc_tp_sf);

    //------------------------
    //--- calculate energy ---
    //------------------------
    Spheric_function<spectral,double> exc_lm_sf = transform(sht_.get(), exc_tp_sf );

    return inner(exc_lm_sf, full_rho_lm_sf_new);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
double Potential::xc_mt_PAW_collinear(const Radial_grid& rgrid,
                                    mdarray<double,3> &out_atom_pot,
                                    mdarray<double,2> &full_rho_lm,
                                    mdarray<double,3> &magnetization_lm,
                                    const std::vector<double> &rho_core)
{
    assert(out_atom_pot.size(2)==2);

    int lmsize_rho = full_rho_lm.size(0);

    // make spherical functions for input density
    Spheric_function<spectral,double> full_rho_lm_sf(&full_rho_lm(0,0),lmsize_rho,rgrid);

    Spheric_function<spectral,double> full_rho_lm_sf_new(full_rho_lm.size(0), rgrid);

    full_rho_lm_sf_new.zero();
    full_rho_lm_sf_new += full_rho_lm_sf;

    double invY00 = 1. / y00 ;

    for(int ir = 0; ir < rgrid.num_points(); ir++ )
    {
        full_rho_lm_sf_new(0,ir) += invY00 * rho_core[ir];
    }

    // make spherical functions for output potential
    Spheric_function<spectral,double> out_atom_effective_pot_sf(&out_atom_pot(0,0,0),lmsize_rho,rgrid);
    Spheric_function<spectral,double> out_atom_effective_field_sf(&out_atom_pot(0,0,1),lmsize_rho,rgrid);

    // make magnetization from z component in lm components
    Spheric_function<spectral,double> magnetization_Z_lm(&magnetization_lm(0,0,0), lmsize_rho, rgrid );

    // calculate spin up spin down density components in lm components
    // up = 1/2 ( rho + magn );  down = 1/2 ( rho - magn )
    Spheric_function<spectral,double> rho_u_lm_sf =  0.5 * (full_rho_lm_sf_new + magnetization_Z_lm);
    Spheric_function<spectral,double> rho_d_lm_sf =  0.5 * (full_rho_lm_sf_new - magnetization_Z_lm);

    // transform density to theta phi components
    Spheric_function<spatial,double> rho_u_tp_sf = transform(sht_.get(), rho_u_lm_sf );
    Spheric_function<spatial,double> rho_d_tp_sf = transform(sht_.get(), rho_d_lm_sf );

    // create potential in theta phi
    Spheric_function<spatial,double> vxc_u_tp_sf(sht_->num_points(), rgrid);
    Spheric_function<spatial,double> vxc_d_tp_sf(sht_->num_points(), rgrid);

    // create energy in theta phi
    Spheric_function<spatial,double> exc_tp_sf(sht_->num_points(), rgrid);

    // calculate XC
    xc_mt_magnetic(rgrid, xc_func_,
                   rho_u_lm_sf, rho_u_tp_sf,
                   rho_d_lm_sf, rho_d_tp_sf,
                   vxc_u_tp_sf, vxc_d_tp_sf,
                   exc_tp_sf);

    // transform back in lm
    out_atom_effective_pot_sf += transform(sht_.get(), 0.5 * (vxc_u_tp_sf + vxc_u_tp_sf) );
    out_atom_effective_field_sf += transform(sht_.get(), 0.5 * (vxc_u_tp_sf - vxc_u_tp_sf));
//////////////////////////////////////////////////////////////
//  std::cout<<"\n UP "<<std::endl;
//  for(int lm=0; lm<out_atom_pot_up_sf.angular_domain_size(); lm++)
//  {
//      for(int ir = 0; ir < rgrid.num_points(); ir++ )
//      {
//          if(full_rho_lm_sf(lm,ir) > 50)
//          std::cout<<full_rho_lm_sf(lm,ir)<<" ";
//      }
//  }
//  std::cout<<"\n POT "<<std::endl;
//  for(int lm=0; lm<out_atom_pot_up_sf.angular_domain_size(); lm++)
//  {
//      for(int ir = 0; ir < rgrid.num_points(); ir++ )
//      {
//          if(out_atom_pot_dn_sf(lm,ir) > 50)
//          std::cout<<out_atom_pot_dn_sf(lm,ir)<<" ";
//      }
//  }
//////////////////////////////////////////////////////////////

    //------------------------
    //--- calculate energy ---
    //------------------------
    Spheric_function<spectral,double> exc_lm_sf = transform(sht_.get(), exc_tp_sf );

    return inner(exc_lm_sf, full_rho_lm_sf_new);
}