Research code for neural-network approximations of electronic density functionals. This code is attached to the following publication:
Neural network distillation of orbital dependent density functional theory (arXiv:2410.16408).
Code author: Matija Medvidović
Global density approximations (GDA) is not available through package managers yet. However, you can install it by pointing pip to this repository:
pip3 install 'gda@git+https://github.com/Matematija/global-density-approximation.git'GDA as a PyTorch module
The gda package exports only one PyTorch module you can construct in the following way:
import torch
from gda import GlobalDensityApprox
gda = GlobalDensityApprox(embed_dim=128, n_blocks=2)and call to evaluate the function
# Dummy data
n = torch.randn(20000) # shape = (..., grid_size,)
grad_n = torch.randn(20000, 3) # shape = (..., grid_size, 3)
coords = torch.randn(20000, 3) # shape = (..., grid_size, 3)
weights = torch.randn(20000) # shape = (..., grid_size,)
phi = gda(n, grad_n, coords, weights)
log_tau = gda.log_tau(n, grad_n, coords, weights)
# Log-tau implemented for numerical stabilitydefined by
where
The PySCF interface
We also provide a custom RKS (Restricted Kohn-Sham) DFT class that can be used to run DFT loops using trained GDA models. Example interface:
from ggda.scf import RKS
ks = RKS(mol)
ks.xc = 'tpss'
ks.gda = gda
ks.grids.level = 1
ks.conv_tol = 1e-5
ks.verbose = 4
ks.kernel()If RKS.gda field is not set, then the RKS.kernel() method will just run "normal" DFT using PySCF defaults. Furthermore, since the GDA approximation only models the kinetic energy density RKS.xc field is set to a functional that does not require
A differentiable LibXC wrapper
This library includes a differentiable PyTorch wrapper around LibXC as a convenience. In short - we make the eval_xc function available in PySCF transparent to PyTorch Autograd. This presents a convenient unified API for calculating XC potentials and higher-order derivatives for experimentation with general parametrized functionals.
An example calculation yielding the PBE potential matrix in a basis set
when the density is represented as
from pyscf import gto, dft
from torch import autograd
from gda.libxc import eval_xc
ao = torch.tensor(dft.numint.eval_ao(ks.mol, ks.grids.coords, deriv=1))
dm = torch.tensor(ks.make_rdm1()).requires_grad_(True)
def eval_energy(dm, ao):
ao_, grad_ao_ = ao[0], ao[1:]
density = torch.einsum('mn,im,in->i', dm, ao_, ao_)
grad_density = torch.einsum('mn,im,cin->ic', dm, ao_, grad_ao_)
exc = eval_xc('pbe', density, grad_density)
return weights @ exc
E = eval_energy(dm, ao)
V, = autograd.grad(E, dm)
V.shape # (n_ao, n_ao)
