138 const std::vector<std::vector<std::vector<Numerical_Orbital_Lm>>>& abfs_in)
143 this->mpi_comm = mpi_comm_in;
145 this->orb_cutoff_ = orb.
cutoffs();
150 this->abfs = abfs_in;
154 for(
size_t T=0;
T!=this->abfs.size(); ++
T )
157 this->exx_objs.clear();
160 this->MGT = std::make_shared<ORB_gaunt_table>();
161 for(
const auto &settings_list : this->coulomb_settings)
164 this->exx_objs[settings_list.first].cv.set_orbitals(ucell, orb,
165 this->lcaos, this->abfs, this->exx_objs[settings_list.first].abfs_ccp,
166 this->info.kmesh_times, this->MGT, settings_list.second.first );
169 this->exx_objs[settings_list.first].evq.init(ucell, orb,
170 this->mpi_comm, this->p_kv, this->lcaos, this->abfs,
171 settings_list.second.second, this->MGT, this->info.ccp_rmesh_times, this->info.kmesh_times);
178template <
typename Tdata>
187 this->mpi_comm = mpi_comm_in;
189 this->orb_cutoff_ = orb.
cutoffs();
194 const std::vector<std::vector<std::vector<Numerical_Orbital_Lm>>> abfs_same_atom
198 this->info.kmesh_times,
199 this->info.pca_threshold);
200 if (this->info.files_abfs.empty())
202 this->abfs = abfs_same_atom;
211 for (
size_t T = 0;
T != this->abfs.size(); ++
T)
214 = std::max(
GlobalC::exx_info.info_ri.abfs_Lmax,
static_cast<int>(this->abfs[
T].size()) - 1);
217 this->exx_objs.clear();
218 this->coulomb_settings.clear();
220 = std::make_pair(
true,
222 this->info.coulomb_param, ucell, kv_in));
224 this->MGT = std::make_shared<ORB_gaunt_table>();
226 if (center2_settings == this->coulomb_settings.end())
228 throw std::invalid_argument(
"Exx_LRI::init_spencer failed to prepare Center2 settings.");
233 center2_settings->second.second,
234 this->info.ccp_rmesh_times);
241 this->info.kmesh_times,
243 center2_settings->second.first);
248template <
typename Tdata>
253 const std::vector<std::vector<std::vector<Numerical_Orbital_Lm>>>& abfs_in)
258 this->mpi_comm = mpi_comm_in;
260 this->orb_cutoff_ = orb.
cutoffs();
265 this->abfs = abfs_in;
269 for (
size_t T = 0;
T != this->abfs.size(); ++
T)
272 = std::max(
GlobalC::exx_info.info_ri.abfs_Lmax,
static_cast<int>(this->abfs[
T].size()) - 1);
275 this->exx_objs.clear();
276 this->coulomb_settings.clear();
278 = std::make_pair(
true,
280 this->info.coulomb_param, ucell, kv_in));
282 this->MGT = std::make_shared<ORB_gaunt_table>();
284 if (center2_settings == this->coulomb_settings.end())
286 throw std::invalid_argument(
"Exx_LRI::init_spencer failed to prepare Center2 settings.");
290 center2_settings->second.second,
291 this->info.ccp_rmesh_times);
298 this->info.kmesh_times,
300 center2_settings->second.first);
305template<
typename Tdata>
317 std::vector<TA> atoms(ucell.
nat);
318 for(
int iat=0; iat<ucell.
nat; ++iat)
319 { atoms[iat] = iat; }
320 std::map<TA,TatomR> atoms_pos;
321 for(
int iat=0; iat<ucell.
nat; ++iat)
323 const std::array<TatomR,Ndim> latvec
327 const std::array<Tcell,Ndim> period = {this->p_kv->nmp[0], this->p_kv->nmp[1], this->p_kv->nmp[2]};
329 this->exx_lri.set_parallel(this->mpi_comm, atoms_pos, latvec, period);
332 const std::array<Tcell,Ndim> period_Vs = LRI_CV_Tools::cal_latvec_range<Tcell>(1+this->info.ccp_rmesh_times, ucell, orb_cutoff_);
333 const std::pair<std::vector<TA>, std::vector<std::vector<std::pair<TA,std::array<Tcell,Ndim>>>>>
334 list_As_Vs = RI::Distribute_Equally::distribute_atoms_periods(this->mpi_comm, atoms, period_Vs, 2,
false);
336 std::map<TA,std::map<TAC,RI::Tensor<Tdata>>> Vs;
337 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, Ndim>>> dVs;
338 for(
const auto &settings_list : this->coulomb_settings)
340 std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>
341 Vs_temp = this->exx_objs[settings_list.first].cv.cal_Vs(ucell,
342 list_As_Vs.first, list_As_Vs.second[0],
343 {{
"writable_Vws",
true}});
347 this->exx_objs[settings_list.first].evq.init_ions(ucell, period_Vs);
348 const auto &coulomb_param = settings_list.second.second;
349 std::map<TA, std::map<TAC, RI::Tensor<Tdata>>> Vs_ewald;
350 for(
const auto ¶m_list : coulomb_param)
352 std::map<TA, std::map<TAC, RI::Tensor<Tdata>>> Vs_ewald_temp;
353 switch(param_list.first)
357 double chi = this->exx_objs[settings_list.first].evq.get_singular_chi(ucell, param_list.second, 2.0);
358 Vs_ewald_temp = this->exx_objs[settings_list.first].evq.cal_Vs(ucell, chi, Vs_temp);
363 throw std::invalid_argument( std::string(__FILE__) +
" line " + std::to_string(__LINE__) );
367 Vs_ewald = Vs_ewald.empty() ? Vs_ewald_temp :
LRI_CV_Tools::add(Vs_ewald, Vs_ewald_temp);
375 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, Ndim>>>
376 dVs_temp = this->exx_objs[settings_list.first].cv.cal_dVs(ucell,
377 list_As_Vs.first, list_As_Vs.second[0],
378 {{
"writable_dVws",true}});
385 this->exx_lri.set_Vs(std::move(Vs), this->info.V_threshold);
389 std::array<std::map<TA, std::map<TAC, RI::Tensor<Tdata>>>, Ndim>
391 this->exx_lri.set_dVs(std::move(dVs_order), this->info.V_grad_threshold);
394 std::array<std::array<std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>,3>,3> dVRs =
LRI_CV_Tools::cal_dMRs(ucell,dVs_order);
395 this->exx_lri.set_dVRs(std::move(dVRs), this->info.V_grad_R_threshold);
399 const std::array<Tcell,Ndim> period_Cs = LRI_CV_Tools::cal_latvec_range<Tcell>(2, ucell,orb_cutoff_);
400 const std::pair<std::vector<TA>, std::vector<std::vector<std::pair<TA,std::array<Tcell,Ndim>>>>>
401 list_As_Cs = RI::Distribute_Equally::distribute_atoms_periods(this->mpi_comm, atoms, period_Cs, 2,
false);
403 std::map<TA,std::map<TAC,RI::Tensor<Tdata>>> Cs;
404 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, 3>>> dCs;
405 for(
const auto &settings_list : this->coulomb_settings)
407 if(settings_list.second.first)
409 std::pair<std::map<TA, std::map<TAC, RI::Tensor<Tdata>>>,
410 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, 3>>>>
411 Cs_dCs = this->exx_objs[settings_list.first].cv.cal_Cs_dCs(
413 list_As_Cs.first, list_As_Cs.second[0],
414 {{
"cal_dC",PARAM.inp.cal_force||PARAM.inp.cal_stress},
415 {
"writable_Cws",true}, {
"writable_dCws",true}, {
"writable_Vws",false}, {
"writable_dVws",false}});
416 std::map<TA,std::map<TAC,RI::Tensor<Tdata>>> &Cs_temp = std::get<0>(Cs_dCs);
422 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, 3>>> &dCs_temp = std::get<1>(Cs_dCs);
430 this->exx_lri.set_Cs(std::move(Cs), this->info.C_threshold);
434 std::array<std::map<TA, std::map<TAC, RI::Tensor<Tdata>>>, Ndim>
436 this->exx_lri.set_dCs(std::move(dCs_order), this->info.C_grad_threshold);
439 std::array<std::array<std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>,3>,3> dCRs =
LRI_CV_Tools::cal_dMRs(ucell,dCs_order);
440 this->exx_lri.set_dCRs(std::move(dCRs), this->info.C_grad_R_threshold);
447 template <
typename Tdata>
449 std::map<TA, std::map<
TAC, RI::Tensor<Tdata>>>& Cs,
456 std::vector<TA> atoms(ucell.
nat);
457 for(
int iat=0; iat<ucell.
nat; ++iat)
459 std::map<TA,TatomR> atoms_pos;
460 for(
int iat=0; iat<ucell.
nat; ++iat)
462 const std::array<TatomR,Ndim> latvec
466 const std::array<Tcell,Ndim> period = {this->p_kv->nmp[0], this->p_kv->nmp[1], this->p_kv->nmp[2]};
468 this->exx_lri.set_parallel(this->mpi_comm, atoms_pos, latvec, period);
471 const std::array<Tcell, Ndim> period_Vs
472 = LRI_CV_Tools::cal_latvec_range<Tcell>(1 + this->info.ccp_rmesh_times, ucell, orb_cutoff_);
473 const std::pair<std::vector<TA>, std::vector<std::vector<std::pair<TA,std::array<Tcell,Ndim>>>>>
474 list_As_Vs = RI::Distribute_Equally::distribute_atoms_periods(this->mpi_comm, atoms, period_Vs, 2,
false);
476 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, Ndim>>> dVs;
477 for(
const auto &settings_list : this->coulomb_settings)
479 if(!settings_list.second.first)
continue;
480 std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>
481 Vs_temp = this->exx_objs[settings_list.first].cv.cal_Vs(ucell,
482 list_As_Vs.first, list_As_Vs.second[0],
483 {{
"writable_Vws",true}});
488 for (
const auto& IJRc: this->exx_objs[settings_list.first].cv.Vws)
490 const TA& I = IJRc.first;
491 const auto& JRc = IJRc.second;
492 for (
const auto& JRc_tensor: JRc)
494 const TA& J = JRc_tensor.first;
495 const auto Rc = JRc_tensor.second;
496 for (
const auto& Rc_tensor: Rc)
498 const auto& R = Rc_tensor.first;
503 std::cout <<
"Coulomb: number of atom-pairs inside atomic overlap is " << flag <<
". " << std::endl;
504 if (this->info.coul_moment ==
true)
506 double hf_Rcut = std::pow(0.75 * this->p_kv->get_nkstot_full() * ucell.
omega / (
ModuleBase::PI), 1.0 / 3.0);
516 moment_abfs =
nullptr;
521 for (
const auto& IJRc: this->exx_objs[settings_list.first].cv.Vws)
523 const auto& JRc = IJRc.second;
524 for (
const auto& JRc_tensor: JRc)
526 const auto Rc = JRc_tensor.second;
527 for (
const auto& Rc_tensor: Rc)
533 std::cout <<
"Coulomb: number of all atom-pairs is " << flag <<
". " << std::endl;
540 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, Ndim>>>
541 dVs_temp = this->exx_objs[settings_list.first].cv.cal_dVs(ucell,
542 list_As_Vs.first, list_As_Vs.second[0],
543 {{
"writable_dVws",true}});
553 this->exx_lri.set_Vs(std::move(Vs_cut), this->info.V_threshold);
557 std::map<TA,std::map<TAC,std::array<RI::Tensor<Tdata>,Ndim>>> dVs
558 = this->exx_objs[coulomb_method].cv.cal_dVs(ucell,
559 list_As_Vs.first, list_As_Vs.second[0],
560 {{
"writable_dVws",true}});
563 std::array<std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>,Ndim> dVs_order
565 this->exx_lri.set_dVs(std::move(dVs_order), this->info.V_grad_threshold);
568 std::array<std::array<std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>,3>,3> dVRs
570 this->exx_lri.set_dVRs(std::move(dVRs), this->info.V_grad_R_threshold);
574 const std::array<Tcell,Ndim> period_Cs = LRI_CV_Tools::cal_latvec_range<Tcell>(2, ucell,orb_cutoff_);
575 const std::pair<std::vector<TA>, std::vector<std::vector<std::pair<TA,std::array<Tcell,Ndim>>>>>
576 list_As_Cs = RI::Distribute_Equally::distribute_atoms_periods(this->mpi_comm, atoms, period_Cs, 2,
false);
577 std::pair<std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>,
578 std::map<TA,std::map<TAC,std::array<RI::Tensor<Tdata>,3>>>>
579 Cs_dCs = this->exx_objs[coulomb_method].cv.cal_Cs_dCs(ucell,
580 list_As_Cs.first, list_As_Cs.second[0],
581 {{
"cal_dC",PARAM.inp.cal_force||PARAM.inp.cal_stress},
582 {
"writable_Cws",true},
583 {
"writable_dCws",true},
584 {
"writable_Vws",false},
585 {
"writable_dVws",false}});
586 Cs = std::get<0>(Cs_dCs);
592 this->exx_lri.set_Cs(Cs, this->info.C_threshold);
596 std::map<TA,std::map<TAC,std::array<RI::Tensor<Tdata>,3>>>& dCs = std::get<1>(Cs_dCs);
598 std::array<std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>,Ndim> dCs_order
600 this->exx_lri.set_dCs(std::move(dCs_order), this->info.C_grad_threshold);
603 std::array<std::array<std::map<TA,std::map<TAC,RI::Tensor<Tdata>>>,3>,3> dCRs
605 this->exx_lri.set_dCRs(std::move(dCRs), this->info.C_grad_R_threshold);
611template <
typename Tdata>
613 std::map<TA, std::map<
TAC, RI::Tensor<Tdata>>>& Cs,
620 std::vector<TA> atoms(ucell.
nat);
621 for (
int iat = 0; iat < ucell.
nat; ++iat)
623 std::map<TA, TatomR> atoms_pos;
624 for (
int iat = 0; iat < ucell.
nat; ++iat)
629 const std::array<Tcell, Ndim> period = {this->p_kv->nmp[0], this->p_kv->nmp[1], this->p_kv->nmp[2]};
631 this->exx_lri.set_parallel(this->mpi_comm, atoms_pos, latvec, period);
634 const std::array<Tcell, Ndim> period_Vs
635 = LRI_CV_Tools::cal_latvec_range<Tcell>(1 + this->info.ccp_rmesh_times, ucell, orb_cutoff_);
636 const std::pair<std::vector<TA>, std::vector<std::vector<std::pair<TA, std::array<Tcell, Ndim>>>>> list_As_Vs
637 = RI::Distribute_Equally::distribute_atoms_periods(this->mpi_comm, atoms, period_Vs, 2,
false);
639 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, Ndim>>> dVs;
640 for (
const auto& settings_list: this->coulomb_settings)
642 if (!settings_list.second.first)
644 std::map<TA, std::map<TAC, RI::Tensor<Tdata>>> Vs_temp
645 = this->exx_objs[settings_list.first].cv.cal_Vs(ucell,
647 list_As_Vs.second[0],
648 {{
"writable_Vws", true}});
653 for (
const auto& IJRc: this->exx_objs[settings_list.first].cv.Vws)
655 const TA& I = IJRc.first;
656 const auto& JRc = IJRc.second;
657 for (
const auto& JRc_tensor: JRc)
659 const TA& J = JRc_tensor.first;
660 const auto Rc = JRc_tensor.second;
661 for (
const auto& Rc_tensor: Rc)
663 const auto& R = Rc_tensor.first;
668 std::cout <<
"Coulomb: number of atom-pairs inside atomic overlap is " << flag <<
". " << std::endl;
669 if (this->info.coul_moment ==
true)
671 double hf_Rcut = std::pow(0.75 * this->p_kv->get_nkstot_full() * ucell.
omega / (
ModuleBase::PI), 1.0 / 3.0);
681 moment_abfs =
nullptr;
686 for (
const auto& IJRc: this->exx_objs[settings_list.first].cv.Vws)
688 const auto& JRc = IJRc.second;
689 for (
const auto& JRc_tensor: JRc)
691 const auto Rc = JRc_tensor.second;
692 for (
const auto& Rc_tensor: Rc)
698 std::cout <<
"Coulomb: number of all atom-pairs is " << flag <<
". " << std::endl;
703 this->exx_objs[settings_list.first].evq.init_ions(ucell, period_Vs);
704 const auto& coulomb_param = settings_list.second.second;
705 std::map<TA, std::map<TAC, RI::Tensor<Tdata>>> Vs_ewald;
706 for (
const auto& param_list: coulomb_param)
708 std::map<TA, std::map<TAC, RI::Tensor<Tdata>>> Vs_ewald_temp;
709 switch (param_list.first)
713 = this->exx_objs[settings_list.first].evq.get_singular_chi(ucell, param_list.second, 2.0);
714 Vs_ewald_temp = this->exx_objs[settings_list.first].evq.cal_Vs(ucell, chi, Vs_temp);
718 throw std::invalid_argument(std::string(__FILE__) +
" line " + std::to_string(__LINE__));
722 Vs_ewald = Vs_ewald.empty() ? Vs_ewald_temp :
LRI_CV_Tools::add(Vs_ewald, Vs_ewald_temp);
759template <
typename Tdata>
761 std::map<
TA, std::map<
TAC, RI::Tensor<Tdata>>>& Cs,
768 std::vector<TA> atoms(ucell.
nat);
769 for (
int iat = 0; iat < ucell.
nat; ++iat)
773 std::map<TA, TatomR> atoms_pos;
774 for (
int iat = 0; iat < ucell.
nat; ++iat)
781 const std::array<Tcell, Ndim> period = {this->p_kv->nmp[0], this->p_kv->nmp[1], this->p_kv->nmp[2]};
783 this->exx_lri.set_parallel(this->mpi_comm, atoms_pos, latvec, period);
786 auto center2_obj_it = this->exx_objs.find(center2_method);
787 if (center2_obj_it == this->exx_objs.end())
789 throw std::invalid_argument(std::string(__FILE__) +
" line " + std::to_string(__LINE__));
792 const std::array<Tcell, Ndim> period_Vs
793 = LRI_CV_Tools::cal_latvec_range<Tcell>(1 + this->info.ccp_rmesh_times, ucell, orb_cutoff_);
794 const std::pair<std::vector<TA>, std::vector<std::vector<std::pair<TA, std::array<Tcell, Ndim>>>>> list_As_Vs
795 = RI::Distribute_Equally::distribute_atoms_periods(this->mpi_comm, atoms, period_Vs, 2,
false);
797 Vs_cut = center2_obj_it->second.cv.cal_Vs(
800 list_As_Vs.second[0],
801 {{
"writable_Vws", true}});
807 this->exx_lri.set_Vs(Vs_cut, this->info.V_threshold);
809 const std::array<Tcell, Ndim> period_Cs = LRI_CV_Tools::cal_latvec_range<Tcell>(2, ucell, orb_cutoff_);
810 const std::pair<std::vector<TA>, std::vector<std::vector<std::pair<TA, std::array<Tcell, Ndim>>>>> list_As_Cs
811 = RI::Distribute_Equally::distribute_atoms_periods(this->mpi_comm, atoms, period_Cs, 2,
false);
812 std::pair<std::map<TA, std::map<TAC, RI::Tensor<Tdata>>>,
813 std::map<TA, std::map<TAC, std::array<RI::Tensor<Tdata>, 3>>>>
814 Cs_dCs = center2_obj_it->second.cv.cal_Cs_dCs(
817 list_As_Cs.second[0],
819 {
"writable_Cws", true},
820 {
"writable_dCws", true},
821 {
"writable_Vws", false},
822 {
"writable_dVws", false}});
823 Cs = std::get<0>(Cs_dCs);
829 this->exx_lri.set_Cs(Cs, this->info.C_threshold);
834template <
typename Tdata>
836 std::map<
TA, std::map<
TAC, RI::Tensor<Tdata>>>& Cs,
843 std::vector<TA> atoms(ucell.
nat);
844 for (
int iat = 0; iat < ucell.
nat; ++iat)
848 std::map<TA, TatomR> atoms_pos;
849 for (
int iat = 0; iat < ucell.
nat; ++iat)
856 const std::array<Tcell, Ndim> period = {this->p_kv->nmp[0], this->p_kv->nmp[1], this->p_kv->nmp[2]};
858 this->exx_lri.set_parallel(this->mpi_comm, atoms_pos, latvec, period);
860 const std::array<Tcell, Ndim> period_Vs
861 = LRI_CV_Tools::cal_latvec_range<Tcell>(1 + this->info.ccp_rmesh_times, ucell, orb_cutoff_);
862 const std::pair<std::vector<TA>, std::vector<std::vector<std::pair<TA, std::array<Tcell, Ndim>>>>> list_As_Vs
863 = RI::Distribute_Equally::distribute_atoms_periods(this->mpi_comm, atoms, period_Vs, 2,
false);
865 for (
const auto& settings_list : this->coulomb_settings)
867 std::map<TA, std::map<TAC, RI::Tensor<Tdata>>> Vs_temp
868 = this->exx_objs[settings_list.first].cv.cal_Vs(
871 list_As_Vs.second[0],
872 {{
"writable_Vws",
true}});
877 this->exx_objs[settings_list.first].evq.init_ions(ucell, period_Vs);
878 std::map<TA, std::map<TAC, RI::Tensor<Tdata>>> Vs_ewald;
879 for (
const auto& param_list : settings_list.second.second)
881 std::map<TA, std::map<TAC, RI::Tensor<Tdata>>> Vs_ewald_temp;
882 switch (param_list.first)
886 double chi = this->exx_objs[settings_list.first].evq.get_singular_chi(ucell, param_list.second, 2.0);
887 Vs_ewald_temp = this->exx_objs[settings_list.first].evq.cal_Vs(ucell, chi, Vs_temp);
892 throw std::invalid_argument(std::string(__FILE__) +
" line " + std::to_string(__LINE__));
895 Vs_ewald = Vs_ewald.empty() ? Vs_ewald_temp :
LRI_CV_Tools::add(Vs_ewald, Vs_ewald_temp);
912template<
typename Tdata>
926 { this->exx_lri.set_symmetry(
false, {}); }
934 this->exx_lri.set_Ds(Ds[is], this->info.dm_threshold, suffix);
935 this->exx_lri.cal_Hs({
"",
"",suffix });
939 this->Hexxs[is] = RI::Communicate_Tensors_Map_Judge::comm_map2_first(
940 this->mpi_comm, std::move(this->exx_lri.Hs), std::get<0>(judge[is]), std::get<1>(judge[is]));
945 auto Hs_a2D = this->exx_lri.post_2D.set_tensors_map2(this->exx_lri.Hs);
949 this->exx_lri.energy = this->exx_lri.post_2D.cal_energy(
950 this->exx_lri.post_2D.saves[
"Ds_" + suffix],
951 this->exx_lri.post_2D.set_tensors_map2(Hs_a2D));
953 this->Hexxs[is] = RI::Communicate_Tensors_Map_Judge::comm_map2_first(
954 this->mpi_comm, std::move(Hs_a2D), std::get<0>(judge[is]), std::get<1>(judge[is]));
956 this->Eexx += std::real(this->exx_lri.energy);
957 post_process_Hexx(this->Hexxs[is]);
959 this->Eexx = post_process_Eexx(this->Eexx);
960 this->exx_lri.set_symmetry(
false, {});
964template<
typename Tdata>
968 constexpr Tdata frac = -1 * 2;
969 const std::function<void(RI::Tensor<Tdata>&)>
970 multiply_frac = [&frac](RI::Tensor<Tdata> &t)
972 RI::Map_Operator::for_each( Hexxs_io, multiply_frac );
975template<
typename Tdata>
979 const double SPIN_multiple = std::map<int, double>{ {1,2}, {2,1}, {4,1} }.at(
PARAM.
inp.
nspin);
980 const double frac = -SPIN_multiple;
981 return frac * Eexx_in;