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