@@ -88,7 +88,6 @@ OperatorEXXPW<T, Device>::OperatorEXXPW(const int* isk_in,
8888 tpiba = ucell->tpiba ;
8989 Real tpiba2 = tpiba * tpiba;
9090 // calculate the exx_divergence
91- exx_divergence ();
9291
9392}
9493
@@ -617,101 +616,156 @@ void OperatorEXXPW<T, Device>::get_potential() const
617616 Real nqs_half2 = 0.5 * kv->nmp [1 ];
618617 Real nqs_half3 = 0.5 * kv->nmp [2 ];
619618
619+ setmem_real_op ()(pot, 0 , rhopw->npw * wfcpw->nks * wfcpw->nks );
620620 int nks = wfcpw->nks , npw = rhopw->npw ;
621621 double tpiba2 = tpiba * tpiba;
622- // calculate the pot
623- for (int ik = 0 ; ik < nks; ik++)
622+ // calculate Fock pot
623+ auto param_fock = GlobalC::exx_info.info_global .coulomb_param [Conv_Coulomb_Pot_K::Coulomb_Type::Fock];
624+ for (auto param : param_fock)
624625 {
625- for (int iq = 0 ; iq < nks; iq++)
626+ double exx_div = exx_divergence (Conv_Coulomb_Pot_K::Coulomb_Type::Fock);
627+ double alpha = std::stod (param[" alpha" ]);
628+ for (int ik = 0 ; ik < nks; ik++)
626629 {
627- const ModuleBase::Vector3<double > k_c = wfcpw->kvec_c [ik];
628- const ModuleBase::Vector3<double > k_d = wfcpw->kvec_d [ik];
629- const ModuleBase::Vector3<double > q_c = wfcpw->kvec_c [iq];
630- const ModuleBase::Vector3<double > q_d = wfcpw->kvec_d [iq];
631-
632- #ifdef _OPENMP
633- #pragma omp parallel for schedule(static)
634- #endif
635- for (int ig = 0 ; ig < rhopw->npw ; ig++)
630+ for (int iq = 0 ; iq < nks; iq++)
636631 {
637- const ModuleBase::Vector3<double > g_d = rhopw->gdirect [ig];
638- const ModuleBase::Vector3<double > kqg_d = k_d - q_d + g_d;
639- // For gamma_extrapolation (https://doi.org/10.1103/PhysRevB.79.205114)
640- // 7/8 of the points in the grid are "activated" and 1/8 are disabled.
641- // grid_factor is designed for the 7/8 of the grid to function like all of the points
642- Real grid_factor = 1 ;
643- double extrapolate_grid = 8.0 /7.0 ;
644- if (gamma_extrapolation)
632+ const ModuleBase::Vector3<double > k_c = wfcpw->kvec_c [ik];
633+ const ModuleBase::Vector3<double > k_d = wfcpw->kvec_d [ik];
634+ const ModuleBase::Vector3<double > q_c = wfcpw->kvec_c [iq];
635+ const ModuleBase::Vector3<double > q_d = wfcpw->kvec_d [iq];
636+
637+ #ifdef _OPENMP
638+ #pragma omp parallel for schedule(static)
639+ #endif
640+ for (int ig = 0 ; ig < rhopw->npw ; ig++)
645641 {
646- // if isint(kqg_d[0] * nqs_half1) && isint(kqg_d[1] * nqs_half2) && isint(kqg_d[2] * nqs_half3)
647- auto isint = [](double x)
642+ const ModuleBase::Vector3<double > g_d = rhopw->gdirect [ig];
643+ const ModuleBase::Vector3<double > kqg_d = k_d - q_d + g_d;
644+ // For gamma_extrapolation (https://doi.org/10.1103/PhysRevB.79.205114)
645+ // 7/8 of the points in the grid are "activated" and 1/8 are disabled.
646+ // grid_factor is designed for the 7/8 of the grid to function like all of the points
647+ Real grid_factor = 1 ;
648+ double extrapolate_grid = 8.0 / 7.0 ;
649+ if (gamma_extrapolation)
648650 {
649- double epsilon = 1e-6 ; // this follows the isint judgement in q-e
650- return std::abs (x - std::round (x)) < epsilon;
651- };
652- if (isint (kqg_d[0 ] * nqs_half1) &&
653- isint (kqg_d[1 ] * nqs_half2) &&
654- isint (kqg_d[2 ] * nqs_half3))
651+ // if isint(kqg_d[0] * nqs_half1) && isint(kqg_d[1] * nqs_half2) && isint(kqg_d[2] * nqs_half3)
652+ auto isint = [](double x) {
653+ double epsilon = 1e-6 ; // this follows the isint judgement in q-e
654+ return std::abs (x - std::round (x)) < epsilon;
655+ };
656+ if (isint (kqg_d[0 ] * nqs_half1) && isint (kqg_d[1 ] * nqs_half2) && isint (kqg_d[2 ] * nqs_half3))
657+ {
658+ grid_factor = 0 ;
659+ }
660+ else
661+ {
662+ grid_factor = extrapolate_grid;
663+ }
664+ }
665+
666+ const int nk_fac = PARAM.inp .nspin == 2 ? 2 : 1 ;
667+ const int nk = nks / nk_fac;
668+ const int ig_kq = ik * nks * npw + iq * npw + ig;
669+
670+ Real gg = (k_c - q_c + rhopw->gcar [ig]).norm2 () * tpiba2;
671+ // if (kqgcar2 > 1e-12) // vasp uses 1/40 of the smallest (k spacing)**2
672+ if (gg >= 1e-8 )
655673 {
656- grid_factor = 0 ;
674+ Real fac = -ModuleBase::FOUR_PI * ModuleBase::e2 / gg;
675+ pot[ig_kq] += fac * grid_factor * alpha;
657676 }
677+ // }
658678 else
659679 {
660- grid_factor = extrapolate_grid ;
680+ pot[ig_kq] += exx_div * alpha ;
661681 }
682+ // assert(is_finite(density_recip[ig]));
662683 }
684+ }
685+ }
686+ }
663687
664- const int nk_fac = PARAM.inp .nspin == 2 ? 2 : 1 ;
665- const int nk = nks / nk_fac;
666- const int ig_kq = ik * nks * npw + iq * npw + ig;
688+ // calculate erfc pot
689+ auto param_erfc = GlobalC::exx_info.info_global .coulomb_param [Conv_Coulomb_Pot_K::Coulomb_Type::Erfc];
690+ for (auto param : param_erfc)
691+ {
692+ double erfc_omega = std::stod (param[" omega" ]);
693+ double erfc_omega2 = erfc_omega * erfc_omega;
694+ double alpha = std::stod (param[" alpha" ]);
695+ double exx_div = exx_divergence (Conv_Coulomb_Pot_K::Coulomb_Type::Erfc, erfc_omega);
696+ for (int ik = 0 ; ik < nks; ik++)
697+ {
698+ for (int iq = 0 ; iq < nks; iq++)
699+ {
700+ const ModuleBase::Vector3<double > k_c = wfcpw->kvec_c [ik];
701+ const ModuleBase::Vector3<double > k_d = wfcpw->kvec_d [ik];
702+ const ModuleBase::Vector3<double > q_c = wfcpw->kvec_c [iq];
703+ const ModuleBase::Vector3<double > q_d = wfcpw->kvec_d [iq];
667704
668- Real gg = (k_c - q_c + rhopw-> gcar [ig]). norm2 () * tpiba2;
669- Real hse_omega2 = GlobalC::exx_info. info_global . hse_omega * GlobalC::exx_info. info_global . hse_omega ;
670- // if (kqgcar2 > 1e-12) // vasp uses 1/40 of the smallest (k spacing)**2
671- if (gg >= 1e-8 )
705+ # ifdef _OPENMP
706+ # pragma omp parallel for schedule(static)
707+ # endif
708+ for ( int ig = 0 ; ig < rhopw-> npw ; ig++ )
672709 {
673- Real fac = -ModuleBase::FOUR_PI * ModuleBase::e2 / gg;
674- // if (PARAM.inp.dft_functional == "hse")
675- if (GlobalC::exx_info.info_global .ccp_type == Conv_Coulomb_Pot_K::Ccp_Type::Erfc)
710+ const ModuleBase::Vector3<double > g_d = rhopw->gdirect [ig];
711+ const ModuleBase::Vector3<double > kqg_d = k_d - q_d + g_d;
712+ // For gamma_extrapolation (https://doi.org/10.1103/PhysRevB.79.205114)
713+ // 7/8 of the points in the grid are "activated" and 1/8 are disabled.
714+ // grid_factor is designed for the 7/8 of the grid to function like all of the points
715+ Real grid_factor = 1 ;
716+ double extrapolate_grid = 8.0 / 7.0 ;
717+ if (gamma_extrapolation)
676718 {
677- pot[ig_kq] = fac * (1.0 - std::exp (-gg / 4.0 / hse_omega2)) * grid_factor;
719+ // if isint(kqg_d[0] * nqs_half1) && isint(kqg_d[1] * nqs_half2) && isint(kqg_d[2] * nqs_half3)
720+ auto isint = [](double x) {
721+ double epsilon = 1e-6 ; // this follows the isint judgement in q-e
722+ return std::abs (x - std::round (x)) < epsilon;
723+ };
724+ if (isint (kqg_d[0 ] * nqs_half1) && isint (kqg_d[1 ] * nqs_half2) && isint (kqg_d[2 ] * nqs_half3))
725+ {
726+ grid_factor = 0 ;
727+ }
728+ else
729+ {
730+ grid_factor = extrapolate_grid;
731+ }
678732 }
679- else if (GlobalC::exx_info.info_global .ccp_type == Conv_Coulomb_Pot_K::Ccp_Type::Erf)
680- {
681- pot[ig_kq] = fac * (std::exp (-gg / 4.0 / hse_omega2)) * grid_factor;
682- }
683- else
684- {
685- pot[ig_kq] = fac * grid_factor;
686- }
687- }
688- // }
689- else
690- {
691- // if (PARAM.inp.dft_functional == "hse")
692- if (GlobalC::exx_info.info_global .ccp_type == Conv_Coulomb_Pot_K::Ccp_Type::Erfc &&
693- !gamma_extrapolation)
733+
734+ const int nk_fac = PARAM.inp .nspin == 2 ? 2 : 1 ;
735+ const int nk = nks / nk_fac;
736+ const int ig_kq = ik * nks * npw + iq * npw + ig;
737+
738+ Real gg = (k_c - q_c + rhopw->gcar [ig]).norm2 () * tpiba2;
739+ // if (kqgcar2 > 1e-12) // vasp uses 1/40 of the smallest (k spacing)**2
740+ if (gg >= 1e-8 )
694741 {
695- pot[ig_kq] = exx_div - ModuleBase::PI * ModuleBase::e2 / hse_omega2;
742+ Real fac = -ModuleBase::FOUR_PI * ModuleBase::e2 / gg;
743+ pot[ig_kq] += fac * (1.0 - std::exp (-gg / 4.0 / erfc_omega2)) * grid_factor * alpha;
696744 }
745+ // }
697746 else
698747 {
699- pot[ig_kq] = exx_div;
748+ // if (PARAM.inp.dft_functional == "hse")
749+ if (!gamma_extrapolation)
750+ {
751+ pot[ig_kq] += (exx_div - ModuleBase::PI * ModuleBase::e2 / erfc_omega2) * alpha;
752+ }
753+ else
754+ {
755+ pot[ig_kq] += exx_div * alpha;
756+ }
700757 }
758+ // assert(is_finite(density_recip[ig]));
701759 }
702- // assert(is_finite(density_recip[ig]));
703760 }
704761 }
705762 }
706763}
707764
708765template <typename T, typename Device>
709- void OperatorEXXPW<T, Device>::exx_divergence()
766+ double OperatorEXXPW<T, Device>::exx_divergence(Conv_Coulomb_Pot_K::Coulomb_Type coulomb_type, double erfc_omega) const
710767{
711- if (GlobalC::exx_info.info_lip .lambda == 0.0 )
712- {
713- return ;
714- }
768+ double exx_div = 0 ;
715769
716770 Real nqs_half1 = 0.5 * kv->nmp [0 ];
717771 Real nqs_half2 = 0.5 * kv->nmp [1 ];
@@ -764,9 +818,9 @@ void OperatorEXXPW<T, Device>::exx_divergence()
764818
765819 if (qq <= 1e-8 ) continue ;
766820 // else if (PARAM.inp.dft_functional == "hse")
767- else if (GlobalC::exx_info. info_global . ccp_type == Conv_Coulomb_Pot_K::Ccp_Type ::Erfc)
821+ else if (coulomb_type == Conv_Coulomb_Pot_K::Coulomb_Type ::Erfc)
768822 {
769- double omega = GlobalC::exx_info. info_global . hse_omega ;
823+ double omega = erfc_omega ;
770824 double omega2 = omega * omega;
771825 div += std::exp (-alpha * qq) / qq * (1.0 - std::exp (-qq*tpiba2 / 4.0 / omega2)) * grid_factor;
772826 }
@@ -783,9 +837,9 @@ void OperatorEXXPW<T, Device>::exx_divergence()
783837 // if (PARAM.inp.dft_functional == "hse")
784838 if (!gamma_extrapolation)
785839 {
786- if (GlobalC::exx_info. info_global . ccp_type == Conv_Coulomb_Pot_K::Ccp_Type ::Erfc)
840+ if (coulomb_type == Conv_Coulomb_Pot_K::Coulomb_Type ::Erfc)
787841 {
788- double omega = GlobalC::exx_info. info_global . hse_omega ;
842+ double omega = erfc_omega ;
789843 div += tpiba2 / 4.0 / omega / omega; // compensate for the finite value when qq = 0
790844 }
791845 else
@@ -805,9 +859,9 @@ void OperatorEXXPW<T, Device>::exx_divergence()
805859 double dq = 5.0 / std::sqrt (alpha) / nqq;
806860 double aa = 0.0 ;
807861 // if (PARAM.inp.dft_functional == "hse")
808- if (GlobalC::exx_info. info_global . ccp_type == Conv_Coulomb_Pot_K::Ccp_Type ::Erfc)
862+ if (coulomb_type == Conv_Coulomb_Pot_K::Coulomb_Type ::Erfc)
809863 {
810- double omega = GlobalC::exx_info. info_global . hse_omega ;
864+ double omega = erfc_omega ;
811865 double omega2 = omega * omega;
812866#ifdef _OPENMP
813867#pragma omp parallel for reduction(+:aa)
@@ -828,7 +882,7 @@ void OperatorEXXPW<T, Device>::exx_divergence()
828882// exx_div = 0;
829883// std::cout << "EXX divergence: " << exx_div << std::endl;
830884
831- return ;
885+ return exx_div ;
832886}
833887
834888template <typename T, typename Device>
0 commit comments