Hybrid interface: change external pieces to dummy functionals
We have a bunch of code sitting in side branches to handle interfaces for more complicated functionals such as double hybrids, which break the current API. This is all a big mess, since the API had already changed from the release branches to what is currently in master.
At present, the hybrid parameters are stored in release branches as
/**
Parameters for range-separated hybrids
cam_omega: the range separation constant
cam_alpha: fraction of full Hartree-Fock exchange, used both for
usual hybrids as well as range-separated ones
cam_beta: fraction of short-range only(!) exchange in
range-separated hybrids
N.B. Different conventions for alpha and beta can be found in
literature. In the convention used in libxc, at short range the
fraction of exact exchange is cam_alpha+cam_beta, while at long
range it is cam_alpha.
*/
double cam_omega, cam_alpha, cam_beta;
This is a problem, because this assumes that a functional can only have one range-separation constant, while the HISS functional has two. The code in the master branch was changed to
/**
Parameters for range-separated hybrids
hyb_type[i]: XC_HYB_NONE, XC_HYB_FOCK, XC_HYB_ERF_SR, etc.
hyb_omega[i]: the range separation constant
hyb_coeff[i]: fraction of exchange, used both for
usual hybrids as well as range-separated ones
N.B. Different conventions for alpha and beta can be found in
literature. In the convention used in libxc, at short range the
fraction of exact exchange is cam_alpha+cam_beta, while at long
range it is cam_alpha.
*/
int hyb_number_terms, *hyb_type;
double *hyb_coeff, *hyb_omega;
which enables parametrizing HISS and also enables extending the code more easily to new components, such as MP2 correlation energy.
But, in the hybrids branch, which implements double hybrids, this is again changed to
/* Parameters for functional containing external contributions (such
as a Fock, PT2, or a VDW term) */
int hyb_number_terms; /* number of external contibutions to the functional (max 5) */
int hyb_type[5]; /* type of external contibutions, such as XC_HYB_NONE, XC_HYB_FOCK, etc. */
xc_hybrid_params_type hyb_params[5]; /* Parameters defining the external contibution. This depends on the type */
which again breaks the API, which is the reason that code has been sitting for a year and a half because I never had the time to deal with the mess of what happens when you make such a large change. The special issue with this is that the code is very complicated
/* These are all possible parameters for the different hybrids that we
support. This information should be used by the caller program to
setup the extra terms in the energy */
typedef union {
double raw[3]; /* used to access directly the parameters */
struct {double alpha;} fock; /* amount of Fock */
struct {double gamma;} pt2; /* amount of PT2 */
struct {double beta, omega;} sr; /* amount of short-range Fock and screening parameter */
struct {double s6, alpha, r0;} d; /* (minus) amount of non-local term, damping parameter, and scaling of radius */
struct {double delta, a;} wb97; /* (minus) amount of non-local term, damping parameter */
struct {double delta, Zab;} df; /* amount of non-local term and Zab parameter */
struct {double b, C;} vv10; /* amount of non-local term and b, C parameters */
} xc_hybrid_params_type;
which makes it a pain in the ass to maintain the Fortran and Python bindings.
I believe that a much cleaner approach is possible: these entries should be eliminated from the API altogether! External contributions to the density functional approximation could be easily defined in terms of dummy functionals, e.g. XC_EXT_FOCK
, XC_EXT_MP2
, etc. We already have functionality to handle external parameters, which makes it very simple to handle such functionals. Any functional like B3LYP would simply be defined as a "mixed" functional with external components, which can be set to have unit weight. Now, adding new external components no longer breaks the API, since the number of external parameters is already different between functionals, and functionals can likewise be added without breaking the API. @hyllios