Using XCFun¶
To use the library, you will need to:
Link your executable to it. Either using the static,
libxcfun.a
or shared,libxcfun.so
, version.For C/C++ hosts, include the header file
xcfun.h
where appropriate:
#include "XCFun/xcfun.h"
For Fortran hosts, compile the
xcfun.f90
source file together with your sources. This will allow using the Fortran/C interoperability layer with:
use xcfun
Installing using Spack¶
XCFun can be installed in a Spack environment with:
spack env create myenv
spack env activate myenv
spack install xcfun
Installing using Conda¶
XCFun can be installed in a Conda environment with:
conda create -n myenv xcfun -c conda-forge
conda activate myenv
The package is built with derivatives up to 8th order and includes the Python bindings.
Integration with your build system¶
The set up of the build system for you code will change the details on how to
achieve the points above. In the following, we provide minimalistic instructions
for codes that use either CMake as their build system
generator or plain Makefile
.
CMake as build system¶
Note
You can find complete, standalone examples for C, C++, and
Fortran in the examples
folder.
If you use CMake as your build system, adding the command:
find_package(XCFun CONFIG)
in your CMakeLists.txt
will let CMake search for an XCFun installation. CMake will honor the hint variable:
-DXCFun_DIR=<install-prefix>/share/cmake/XCFun
and set up the target XCFun::xcfun
for you to link your target against:
target_link_libraries(<your-target-name>
PRIVATE
XCFun::xcfun
)
For Fortran hosts the xcfun.f90
will have to be compiled too. The following addition suffices:
target_sources(<your-target-name>
PRIVATE
${XCFun_Fortran_SOURCES}
)
Other build systems¶
You will need to set:
The linker path:
-L<install-prefix>/lib64 -lxcfun
note that on some systems it might be lib
rather than lib64
.
For C/C++ codes, the include path:
-I<install-prefix>/include
For Fortran codes, the location of the Fortran/C interoperability source file
xcfun.f90
:
<install-prefix>/include/XCFun/xcfun.f90
Writing an interface¶
Note
Please, read the full XCFun’s application programming interface documentation for a complete overview.
The library exposes an opaque type, xcfun_t
, through which you can
obtain the exchange-correlation functional derivatives to the desired order.
To do so:
Create one
xcfun_t
object. There should be only one such object per thread and per XC functional. In C/C++ this is achieved with:xcfun_t * fun = xcfun_new();
whereas in Fortran:
use, intrinsic :: iso_c_binding type(c_ptr) :: fun fun = xcfun_new()
The
xcfun_t
object is now a blank slate. You will need to set the exchange-correlation admixture, i.e. which functional and which amount to use for exchange and correlation. This is achieved with calls toxcfun_set()
:int ierr = 0; ierr = xcfun_set(fun, "blyp", 0.9); ierr = xcfun_set(fun, "pbec", 0.1);
We have now set up the BLYP GGA functional.
Next, you will have to set up the evaluation strategy, i.e. which variables will be passed in as input to the functional, which outputs are expected, and the order of the derivatives to return upon evaluation. This can be done by calling
xcfun_eval_setup()
:ierr = xcfun_eval_setup(fun, XC_A_B_AX_AY_AX_BX_BY_BZ, XC_PARTIAL_DERIVATIVES, 1);
The convenience function
xcfun_user_eval_setup()
is also available. With this set up, we will obtain functional derivatives of the BLYP functional up to first order, using \(\alpha\) and \(\beta\) variables and partial derivatives.We are now ready to run the evaluation and for this you will have to allocate a properly sized chunk of memory. The function
xcfun_output_length()
will return how large such a scratch array has to be:int nout = xcfun_output_length(fun); double * output = malloc(sizeof(double) * nout);
Finally, we proceed to the evaluation. We call
xcfun_eval()
with an array of density values:xcfun_eval(fun, d_elements, output);
The important last step is to clean up the used heap memory.
xcfun_delete()
is the function to call:free(output); xcfun_delete(fun);
Input, output and units¶
The library uses atomic units for all input and output variables.
The XC energy density and derivatives can be evaluated using local spin-up \((\alpha)\) and spin-down \((\beta)\) quantities. In the most general case these are:
\(n_\alpha\) The spin-up electron number density.
\(n_\beta\) The spin-down density.
\(\sigma_{\alpha \alpha} = \nabla n_\alpha.\nabla n_\alpha\) The square magnitude of the spin-up density gradient.
\(\sigma_{\alpha \beta} = \nabla n_\alpha.\nabla n_\beta\) The dot product between the spin-up and spin-down gradient vectors.
\(\sigma_{\beta \beta} = \nabla n_\beta.\nabla n_\beta\) The square magnitude of the spin-down density gradient.
\(\tau_\alpha = \frac{1}{2} \sum_i |\psi_{i \alpha}|^2\) The spin-up Kohn-Sham kinetic energy density.
\(\tau_\beta\) The spin-down Kohn-Sham kinetic energy density.
Alternatively you can use total density \((n = n_\alpha + n_\beta)\) and
spin density \((s = n_\alpha - n_\beta)\) variables. These also have
corresponding gradient and kinetic energy components. See xcfun_set()
below for more information.
The output is given in graded reverse lexicographical order. For example a spin-polarized second order GGA functional will give 21 output elements, starting with the XC energy density. Symbolically we may write this as a list starting with the energy E, followed by five gradient elements \(E_{\alpha} E_{\beta} E_{\sigma_{\alpha \alpha}} E_{\sigma_{\alpha \beta}} E_{\sigma_{\beta \beta}}\) and 15 second derivatives \(E_{\alpha \alpha} E_{\alpha \beta} E_{\alpha \sigma_{\alpha \alpha}} ... E_{\beta \beta} E_{\beta \sigma_{\alpha \alpha}} ... E_{\sigma_{\beta \beta} \sigma_{\beta \beta}}\) .