Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 27 additions & 16 deletions source/source_io/module_ctrl/ctrl_scf_lcao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,27 @@
#include "source_lcao/rho_tau_lcao.h" // mohan add 2025-10-24
#include "source_lcao/module_operator_lcao/overlap.h" // use hamilt::Overlap for NAMD

#ifdef __EXX
namespace
{
// C++11/14-compatible stand-in for `if constexpr (std::is_same<TK, double>::value)`.
// WriteDHParams/WriteHParams hold the gamma (TK==double) exx interfaces on purpose (see
// write_H_terms.h), so the assignment below is only well-formed for TK==double; overload
// resolution on Exx_NAO<TK> discards the ill-formed case instead of instantiating it.
// At multi-k the pointers stay null and the writers quit with an explicit message.
template <typename TParams>
void set_exx_interfaces(TParams& params, Exx_NAO<double>& exx_nao)
{
if (exx_nao.exd) { params.exd = exx_nao.exd.get(); }
if (exx_nao.exc) { params.exc = exx_nao.exc.get(); }
}
template <typename TParams>
void set_exx_interfaces(TParams& /*params*/, Exx_NAO<std::complex<double>>& /*exx_nao*/)
{
}
} // namespace
#endif

template <typename TK, typename TR>
void ModuleIO::ctrl_scf_lcao(UnitCell& ucell,
const Input_para& inp,
Expand Down Expand Up @@ -359,13 +380,9 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell,
#ifdef __EXX
// dV^EXX/dR output is wired for the gamma (TK==double) exx interfaces. exd/exc are
// mutually exclusive (real vs complex Hexx); write_dH_exx picks by info_ri.real_number.
if constexpr (std::is_same<TK, double>::value)
if (GlobalC::exx_info.info_global.cal_exx)
{
if (GlobalC::exx_info.info_global.cal_exx)
{
if (exx_nao.exd) { dh_params.exd = exx_nao.exd.get(); }
if (exx_nao.exc) { dh_params.exc = exx_nao.exc.get(); }
}
set_exx_interfaces(dh_params, exx_nao);
}
#endif
ModuleIO::write_dH_components(dh_params);
Expand Down Expand Up @@ -418,16 +435,10 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell,
#ifdef __EXX
if (inp.out_mat_h_exx[0] && GlobalC::exx_info.info_global.cal_exx)
{
// V^EXX(R) output is wired for the gamma (TK==double) exx interfaces.
if constexpr (std::is_same<TK, double>::value)
{
if (GlobalC::exx_info.info_global.cal_exx)
{
if (exx_nao.exd) { h_params.exd = exx_nao.exd.get(); }
if (exx_nao.exc) { h_params.exc = exx_nao.exc.get(); }
ModuleIO::write_h_exx(h_params);
}
}
// V^EXX(R) output is wired for the gamma (TK==double) exx interfaces; at multi-k
// this leaves exd/exc null and write_h_exx quits with an explicit message.
set_exx_interfaces(h_params, exx_nao);
ModuleIO::write_h_exx(h_params);
}
Comment on lines 436 to 442
#endif
}
Expand Down
17 changes: 17 additions & 0 deletions source/source_io/module_dhs/write_dH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include "source_io/module_parameter/parameter.h"
#include "source_lcao/module_hcontainer/hcontainer_funcs.h"
#include "source_lcao/module_hcontainer/output_hcontainer.h"
#ifdef __EXX
#include "source_hamilt/module_xc/exx_info.h"
#endif

#include <algorithm>
#include <complex>
Expand Down Expand Up @@ -138,6 +141,20 @@ void write_dH_components(WriteDHParams& params)
"nspin=4 (noncollinear) yet; only nspin=1 and nspin=2.");
}

#ifdef __EXX
// The EXX interfaces carried by WriteDHParams are gamma-only (see write_dH.h): at multi-k
// dH^EXX would be the derivative with respect to every mirror atom, which this output is
// not meant for. Quit instead of writing a dH sum that silently omits the EXX term.
if (GlobalC::exx_info.info_global.cal_exx && !PARAM.globalv.gamma_only_local
&& (PARAM.inp.out_mat_dh[0] || PARAM.inp.out_mat_dh_exx[0]))
Comment on lines +148 to +149
{
ModuleBase::WARNING_QUIT("write_dH_components",
"out_mat_dh (the dH sum) and out_mat_dh_exx are only supported for gamma-only when EXX is on. "
"Use gamma_only, or request the individual non-EXX terms (out_mat_dh_t, "
"out_mat_dh_vnl, out_mat_dh_vl, out_mat_dh_vh, out_mat_dh_vxc).");
}
#endif

GlobalV::ofs_running << " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << std::endl;
GlobalV::ofs_running << " | |" << std::endl;
GlobalV::ofs_running << " | #Print out dH/dR components# |" << std::endl;
Expand Down
11 changes: 9 additions & 2 deletions source/source_io/module_dhs/write_dH.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,15 @@ struct WriteDHParams
std::vector<const hamilt::HContainer<double>*> dmR;
const Charge* chg = nullptr; // ground-state charge for XC Hellmann-Feynman (FDM)
#ifdef __EXX
// gamma (TK==double) exx interfaces used by write_dH_exx; exactly one is set depending on
// GlobalC::exx_info.info_ri.real_number (exd: real Hexx, exc: complex Hexx).
// The gamma-only (TK==double) exx interfaces used by write_dH_exx.
// Deliberately NOT templated on TK, for two reasons:
// 1. Physics: at multi-k the derivative would be taken with respect to every mirror
// atom of the periodic images, which is not what this output is used for.
// 2. Cost: templating these pointers on TK would force WriteHParams, WriteDHParams and
// every free function taking them to become templates as well -- a large, purely
// mechanical change for a case nobody needs.
// Multi-k + EXX is therefore rejected up front (see write_dH_components)
// instead of silently producing output with the EXX term missing.
Exx_LRI_Interface<double, double>* exd = nullptr;
Exx_LRI_Interface<double, std::complex<double>>* exc = nullptr;
#endif
Expand Down
10 changes: 10 additions & 0 deletions source/source_io/module_hs/write_H_terms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "source_base/parallel_reduce.h"
#include "source_base/timer.h"
#include "source_base/tool_quit.h"
#include "source_estate/module_pot/H_Hartree_pw.h"
#include "source_hamilt/module_xc/xc_functional.h"
#include "source_io/module_hs/write_HS.h"
Expand Down Expand Up @@ -405,6 +406,15 @@ void write_h_exx(WriteHParams& params)
ModuleBase::TITLE("ModuleIO", "write_h_exx");
ModuleBase::timer::start("ModuleIO", "write_h_exx");

// The EXX interfaces carried by WriteHParams are gamma-only (see write_H_terms.h), so at
// multi-k exd/exc are both null. Quit with a clear message instead of writing nothing.
if (!PARAM.globalv.gamma_only_local)
{
ModuleBase::WARNING_QUIT("write_h_exx",
"out_mat_h_exx is only supported for gamma-only: the V^EXX(R) "
"output is not available at multi-k. Use gamma_only.");
}
Comment on lines +409 to +416

const UnitCell& ucell = *params.ucell;
const Parallel_Orbitals& pv = *params.pv;
const K_Vectors& kv = *params.kv;
Expand Down
8 changes: 6 additions & 2 deletions source/source_io/module_hs/write_H_terms.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ struct WriteHParams
int nat = 0;
bool also_hR = false; // H(k) is always written; H(R) (CSR) only when this is true
#ifdef __EXX
// gamma (TK==double) exx interfaces used by write_h_exx; exactly one is set depending on
// GlobalC::exx_info.info_ri.real_number (exd: real Hexx, exc: complex Hexx).
// The gamma-only (TK==double) exx interfaces used by write_h_exx.
// Deliberately NOT templated on TK, because it would force WriteHParams, WriteDHParams and
// every free function taking them to become templates as well -- a large, purely
// mechanical change for a case nobody needs.
// Multi-k + EXX is therefore rejected up front (see write_h_exx)
// instead of silently producing output with the EXX term missing.
Exx_LRI_Interface<double, double>* exd = nullptr;
Exx_LRI_Interface<double, std::complex<double>>* exc = nullptr;
#endif
Expand Down
Loading