[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/pplab/abacus-develop/develop/source/source_io/cal_ldos.cpp [Back]  [Original]

#include "cal_ldos.h"

#include "cal_dos.h"
#include "cube_io.h"
#include "source_estate/module_dm/cal_dm_psi.h"
#include "source_lcao/module_gint/temp_gint/gint_interface.h"

#include 

namespace ModuleIO
{

#ifdef __LCAO
template 
void Cal_ldos::cal_ldos_lcao(const elecstate::ElecStateLCAO* pelec,
                                const psi::Psi& psi,
                                const Parallel_Grid& pgrid,
                                const UnitCell& ucell)
{
    for (int ie = 0; ie < PARAM.inp.stm_bias[2]; ie++)
    {
        // energy range for ldos (efermi as reference)
        const double en = PARAM.inp.stm_bias[0] + ie * PARAM.inp.stm_bias[1];
        const double emin = en < 0 ? en : 0;
        const double emax = en > 0 ? en : 0;

        // calculate weight (for bands not in the range, weight is zero)
        ModuleBase::matrix weight(pelec->ekb.nr, pelec->ekb.nc);
        for (int ik = 0; ik < pelec->ekb.nr; ++ik)
        {
            const double efermi = pelec->eferm.get_efval(pelec->klist->isk[ik]);

            for (int ib = 0; ib < pelec->ekb.nc; ib++)
            {
                const double eigenval = (pelec->ekb(ik, ib) - efermi) * ModuleBase::Ry_to_eV;
                if (eigenval >= emin && eigenval  0 ? pelec->klist->wk[ik] - pelec->wg(ik, ib) : pelec->wg(ik, ib);
                }
            }
        }

        // calculate dm-like for ldos
        const int nspin_dm = PARAM.inp.nspin == 2 ? 2 : 1;
        elecstate::DensityMatrix dm_ldos(pelec->DM->get_paraV_pointer(),
                                                    nspin_dm,
                                                    pelec->klist->kvec_d,
                                                    pelec->klist->get_nks() / nspin_dm);

        elecstate::cal_dm_psi(pelec->DM->get_paraV_pointer(), weight, psi, dm_ldos);
        dm_ldos.init_DMR(*(pelec->DM->get_DMR_pointer(1)));
        dm_ldos.cal_DMR();

        // allocate ldos space
        std::vector ldos_space(PARAM.inp.nspin * pelec->charge->nrxx);
        double** ldos = new double*[PARAM.inp.nspin];
        for (int is = 0; is < PARAM.inp.nspin; ++is)
        {
            ldos[is] = &ldos_space[is * pelec->charge->nrxx];
        }

    // calculate ldos
#ifdef __OLD_GINT
        ModuleBase::WARNING_QUIT("Cal_ldos::dm2ldos",
                                 "do not support old grid integral, please recompile with __NEW_GINT");
#else
        ModuleGint::cal_gint_rho(dm_ldos.get_DMR_vector(), PARAM.inp.nspin, ldos);
#endif

        // I'm not sure whether ldos should be output for each spin or not
        // ldos[0] += ldos[1] for nspin_dm == 2
        if (nspin_dm == 2)
        {
            BlasConnector::axpy(pelec->charge->nrxx, 1.0, ldos[1], 1, ldos[0], 1);
        }

        // write ldos to cube file
        std::stringstream fn;
        fn nrxx);

        for (int ik = 0; ik < pelec->klist->get_nks(); ++ik)
        {
            psi.fix_k(ik);
            const double efermi = pelec->eferm.get_efval(pelec->klist->isk[ik]);
            const int nbands = psi.get_nbands();

            for (int ib = 0; ib < nbands; ib++)
            {
                pelec->basis->recip2real(&psi(ib, 0), wfcr.data(), ik);

                const double eigenval = (pelec->ekb(ik, ib) - efermi) * ModuleBase::Ry_to_eV;
                double weight = en > 0 ? pelec->klist->wk[ik] - pelec->wg(ik, ib) : pelec->wg(ik, ib);
                weight /= ucell.omega;

                if (eigenval >= emin && eigenval basis->nrxx; ir++)
                    {
                        ldos[ir] += weight * norm(wfcr[ir]);
                    }
                }
            }
        }

        std::stringstream fn;
        fn charge->nrxx);
    std::vector wfcr(pelec->basis->nrxx);
    for (int ik = 0; ik < pelec->klist->get_nks(); ++ik)
    {
        psi.fix_k(ik);
        const double efermi = pelec->eferm.get_efval(pelec->klist->isk[ik]);
        const int nbands = psi.get_nbands();

        for (int ib = 0; ib < nbands; ib++)
        {
            pelec->basis->recip2real(&psi(ib, 0), wfcr.data(), ik);
            const double weight = pelec->klist->wk[ik] / ucell.omega;

            for (int ir = 0; ir < pelec->basis->nrxx; ir++)
            {
                tmp[ir] += weight * norm(wfcr[ir]);
            }

            std::vector results(npoints, 0);
            trilinear_interpolate(points, shifts, pgrid, tmp, results);

            const double eigenval = pelec->ekb(ik, ib) * ModuleBase::Ry_to_eV;

            for (int ie = 0; ie < ndata; ++ie)
            {
                const double en = emin + ie * PARAM.inp.dos_edelta_ev;
                const double de = en - eigenval;
                const double de2 = de * de;
                const double gauss = exp(-de2 / sigma2) / sigma_PI;
                for (int ip = 0; ip < npoints; ++ip)
                {
                    ldos[ip][ie] += results[ip] * gauss;
                }
            }
        }
    }

    std::ofstream ofs_ldos;
    std::stringstream fn;
    fn 

Web Proxy Viewer  |  New URL  |  Original Page