Interface to DFTD3 by S. Grimme

Code author: Lori A. Burns

Section author: Lori A. Burns

Module: Samples

https://img.shields.io/badge/home-DFTD3-5077AB.svg
https://img.shields.io/badge/docs-latest-5077AB.svg

Empirical Dispersion Implementations

Empirical dispersion correction packages

Package

Provides

before v1.7

since v1.7

Request

Source

Nickname

D3

psi4::dftd3

bin/dftd3

preferred

works

engine="dftd3"

https://github.com/loriab/dftd3

classic

conda-forge::dftd3-python

import dftd3

nyi

preferred

engine="s-dftd3"

https://github.com/dftd3/simple-dftd3

s-dftd3

(dep) conda-forge::simple-dftd3

bin/simple-dftd3

https://github.com/dftd3/simple-dftd3

D4

psi4::dftd4

bin/dftd4, import dftd4

preferred

works

engine="dftd4"

https://github.com/dftd4/dftd4

conda-forge::dftd4-python

import dftd4

nyi

preferred

engine="dftd4"

https://github.com/dftd4/dftd4

(dep) conda-forge::dftd4

bin/dftd4

https://github.com/dftd4/dftd4

GCP

psi4::gcp

bin/gcp

preferred

works

gcp_engine="gcp"

https://www.chemie.uni-bonn.de/pctc/mulliken-center/software/gcp/gcp_v202.tar.gz

classic

conda-forge::gcp-correction

bin/mctc-gcp

nyi

preferred

gcp_engine="mctc-gcp"

https://github.com/grimme-lab/gcp

mctc

Installation

Binary

  • https://anaconda.org/psi4/dftd3/badges/version.svg
  • There are two implementations of DFTD3; see Empirical dispersion correction packages . The newer “s-dftd3” one is preferred, while the older “classic” one will work for the immediate future. PSI4 will automatically select whichever is available. Starting with v1.9, only “s-dftd3” is supported, though the “classic” continues to work for many applications.

  • DFTD3 is available as a conda package for Linux and macOS and Windows.

  • If using the Psi4conda installer, DFTD3 has already been installed alongside.

  • If using the PSI4 conda package, the classic dftd3 conda package can be obtained through conda install dftd3 -c psi4 or the newer implementation through conda install dftd3-python -c conda-forge.

  • If using PSI4 built from source, and anaconda or miniconda has already been installed (instructions at Quick Installation), the dftd3 executable can be obtained through conda install dftd3 -c psi4 or conda install dftd3-python -c conda-forge.

  • To remove a conda installation, conda remove dftd3 or conda remove dftd3-python.

Source

  • https://img.shields.io/badge/home-DFTD3-5077AB.svg
  • If using PSI4 built from source and you want to build DFTD3 from from source also, follow the instructions provided with the source (essentially, download the freely available tarball, unpack the source, edit the Makefile to select a Fortran compiler, and run make). From version 3.1.0 onwards, DFTD3 can be used as-is; for earlier versions, patches are available: psi4/psi4/share/psi4/scripts/patch_grimme_dftd3.3.0.2.

To be used by PSI4, the classic program binary (dftd3) must be found in your PATH or the s-dftd3 module in your PYTHONPATH so QCEngine can detect it. Check if and where found through qcengine info. If PSI4 is unable to execute the binary, an error will be reported. To preferentially use a particular dftd3 compilation, simply adjust its position in the path environment variables.

Theory

The local or semilocal character of conventional density functionals necessarily leads to neglect of the long-range correlation interactions which capture attractive van der Waals forces. Initially proposed by Yang [Wu:2002:515] and assiduously developed by Grimme, [Grimme:2004:1463] [Grimme:2006:1787] [Grimme:2010:154104] the DFT+Dispersion method appends to the base functional a scaled, damped, and fitted leading term to the well-known dispersion energy series, \(E_{disp} = -C_6/R^6 -C_8/R^8 -C_{10}/R^{10}-\cdots\). The DFT-D2 [Grimme:2006:1787] variant takes the explicit form below. Here, dispersion coefficients, \(C_6^{ij}\), obtained from the geometric mean of tabulated elemental values, are summed over interatomic distances, \(R_{ij}\), modulated by a damping function, \(f_{damp}(R_{ij})\), that gradually activates the dispersion correction (at a rate characterized by \(\alpha_6\)) over a distance characterized by the sum of the two atomic vdW radii, \(R_{vdW}\), while an overall scaling term, \(s_6\), is optimized to be unique to each \(E_{xc}\) functional. (\(\alpha_6\) is sometimes allowed to vary as well.)

(1)\[E_{disp}^{\text{D2}}=-s_6 \sum_{i,j>i}^{N_{at}} \frac{C_6^{ij}}{(R_{ij})^6} f_{damp}(R_{ij})\]
\[f_{damp}(R_{ij}) = \frac{1}{1 + e^{- \alpha_6 (R_{ij}/R_{vdW} - 1)}}\]

Grimme recently presented a refined method, DFT-D3, [Grimme:2010:154104] which incorporates an additional \(R^{-8}\) term in the dispersion series and adjusts the \(C_{6}^{ij}\) combination formula and damping function. The individual atomic \(C_6^i\) are interpolated from several reference values based upon coordination numbers extracted from the molecular structure, rather than assigned solely by atomic identity as in DFT-D2, and thereby incorporate some awareness of the chemical environment into an otherwise largely heuristic correction. The -D3 dispersion has the following form, where \(s_{r,6}\) and \(s_8\) are the customary nonunity parameters fitted for individual functionals.

(2)\[E_{disp}^{\text{D3ZERO}}=-\sum_{n=6,8} s_n \sum_{i,j>i}^{N_{at}} \frac{C_n^{ij}}{(R_{ij})^n} f_{damp}(R_{ij})\]
\[f_{damp}(R_{ij}) = \frac{1}{1 + 6 (R_{ij}/(s_{r,n} R_0^{ij}))^{- \alpha_n}}\]

A modified damping scheme for DFT-D3 using the rational damping form of Becke and Johnson was introduced in [Grimme:2011:1456]. The parameters fit for individual functionals are now \(s_6\), \(s_8\), \(a_1\), and \(a_2\).

\[E_{disp}^{\text{D3BJ}}=-\sum_{n=6,8} s_n \sum_{i,j>i}^{N_{at}} \frac{C_n^{ij}}{(R_{ij})^n + (f_{damp})^n}\]
\[f_{damp} = a_1 \sqrt{\frac{C_8^{ij}}{C_6^{ij}}} + a_2\]

All parameters characterizing the dispersion correction are taken from Grimme’s website or else from the literature. With s-dftd3, parameters are also tabulated in the program source.

Running DFTD3 or DFTD4

A number of a posteriori dispersion corrections are available in PSI4. While some are computed within PSI4‘s codebase (-D1, -D2, -CHG, -DAS2009, -DAS2010), the -D3 or -D4 corrections and their variants are available only through the DFTD3 or DFTD4 programs. Once installed, the dftd3/PSI4 and dftd4/PSI4 interfaces are transparent, and all corrections are interfaced exactly alike. The -D3 interface can use classic or simple-dftd3 programs interchangeably and will prefer the latter. Starting in v1.9, the classic program is no longer supported or tested, though it isn’t deliberately disabled.

Despite different defaults in these programs when run independently, when run through PSI4 as EmpiricalDispersion engine, each should produce the same result. Moreover, PSI4‘s own defaults and aliases are unchanged by the new engines, so -D continues to mean -D2, -D3 continues to mean zero-damping without 3-body correction, and input files should continue producing the same results. Please file an issue if found otherwise.

Dispersion corrections are built into DFT functionals, so appending an a posteriori correction to a computation is as simple as energy('b2plyp-d') vs. energy('b2plyp'). For example, the following input file computes (with much redundant work) for water a B3LYP, a B3LYP-D2, a B3LYP-D3 (zero-damping), and a B3LYP-D4 (Becke-Johnson damping) energy.

molecule h2o {
     O
     H 1 1.0
     H 1 1.0 2 104.5
 }
 set {
     basis cc-pVDZ
 }
 energy('b3lyp')
 energy('b3lyp-d')
 energy('b3lyp-d3')
 energy('b3lyp-d4')

Consult the table -D Functionals to see for each functional what corrections are available and what default parameters define them. The dispersion correction is available after a calculation in the PSI variable DISPERSION CORRECTION ENERGY. By default, the output from the dftd3 program is suppressed; to see it in the output file, set print > 2. No text output is available from the dftd4 or s-dftd3 programs.

Variants of dispersion corrections

Extension [1] and Aliases

Variant

Computing Program (engine)

DFT_DISPERSION_PARAMETERS [11]

-D

alias to -D2

-D1

-D1 [2]

PSI4‘s libdisp

[\(s_6\)]

-D2

-D2 [3]

PSI4‘s libdisp OR dftd3

[\(s_6\), \(\alpha_6\), \(s_{r,6}\)]

-D3ZERO2B, -D3ZERO, -D32B, -D3

-D3 [4] w/ original zero-damping w/o 3-body ATM

s-dftd3 or dftd3

[\(s_6\), \(s_8\), \(s_{r,6}\), \(\alpha_6\), \(s_{r,8}\)]

-D3ZEROATM

-D3 [4] w/ original zero-damping w/ 3-body ATM

s-dftd3

[\(s_6\), \(s_8\), \(s_{r,6}\), \(\alpha_6\), \(s_{r,8}\), \(s_9\)]

-D3BJ2B, -D3BJ, -D3(BJ)

-D3 [5] w/ newer Becke-Johnson rational damping w/o 3-body ATM

s-dftd3 or dftd3

[\(s_6\), \(s_8\), \(a_1\), \(a_2\)]

-D3BJATM

-D3 [5] w/ newer Becke-Johnson rational damping w/ 3-body ATM

s-dftd3

[\(s_6\), \(s_8\), \(a_1\), \(a_2\), \(s_9\)]

-D3MZERO2B, -D3MZERO, -D3M2B, -D3M

-D3 [6] w/ reparameterized and more flexible original zero-damping w/o 3-body ATM

s-dftd3 OR dftd3

[\(s_6\), \(s_8\), \(s_{r,6}\), \(\beta\)]

-D3MZEROATM

-D3 [6] w/ reparameterized and more flexible original zero-damping w/ 3-body ATM

s-dftd3

[\(s_6\), \(s_8\), \(s_{r,6}\), \(\beta\), \(s_9\)]

-D3MBJ2B, -D3MBJ, -D3M(BJ)

-D3 [6] w/ reparameterized newer Becke-Johnson rational damping w/o 3-body ATM

s-dftd3 OR dftd3

[\(s_6\), \(s_8\), \(a_1\), \(a_2\)]

-D3MBJATM

-D3 [6] w/ reparameterized newer Becke-Johnson rational damping w/ 3-body ATM

s-dftd3

[\(s_6\), \(s_8\), \(a_1\), \(a_2\), \(s_9\)]

-NL

Grimme’s -NL (DFT plus VV10 correlation) [7]

PSI4‘s nl

[\(b\), \(c\)] via NL_DISPERSION_PARAMETERS

-CHG

Chai & Head-Gordon dispersion formula [8]

PSI4‘s libdisp

[\(s_6\)]

-DAS2009

Podeszwa & Szalewicz dispersion formula [9]

PSI4‘s libdisp

[\(s_6\)]

-DAS2010

Podeszwa & Szalewicz dispersion formula [10]

PSI4‘s libdisp

[\(s_6\)]

-D4BJEEQATM, -D4BJ, -D4

-D4 [12]

dftd4

[\(a_1\), \(a_2\), \(alp\), \(s_6\), \(s_8\), \(s_9\)]

Three-Body Dispersion Corrections

In addition to the previously discussed two-body dispersion corrections, the dftd3/PSI4 interface enables computations of three-body dispersion corrections. In DFT-D3, three-body dispersion is approximated with the Axilrod-Teller-Muto model:

\[E_{disp}^{(3)}=-\frac{1}{6}\sum_{A\neq B\neq C}\frac{C_{9}^{ABC}(3\cos{\theta_a}\cos{\theta_b}\cos{\theta_c}+1)}{(r_{AB}r_{BC}r_{AC})^{3}}f_{damp}(\bar{r}_{ABC})\]

where \(\theta_a\) is the angle at atom A corresponding to the triangle formed by atoms A, B, and C, and \(\bar{r}_{ABC}\) is the geometric mean of the corresponding atomic-pair distances. The dispersion coefficients are defined as

\[C_{9}^{ABC} = \sqrt{C_{6}^{AB}C_{6}^{BC}C_{6}^{AC}}\]

See the DFT-D3 documentation for more details.

For now, the three-body correction can be called by using the run_dftd3() function with d3-atmgr as the passed functional string. For example, the three-body ATM dispersion correction for a neon trimer could be computed with:

molecule ne3 {
Ne 0.0 0.0 0.0
Ne 0.0 0.0 1.0
Ne 0.0 1.0 1.0
}
ne.update_geometry()
energy = m.run_dftd3('d3-atmgr', dertype=0)
print(energy)

Since v1.7, it is preferred to use s-dftd3 for ATM since the 3-body can be run concurrent with the 2-body contribution.

Footnotes

A few practical examples:

  • DFT-D2 single point with default parameters (dftd3 not called)

    energy('bp86-d')
    
  • DFT-D3BJ optimization with default parameters

    optimize('pbe-d3bj')
    
  • DFT-D2 optimization with custom s6 parameter

    set dft_dispersion_parameters [1.20]
    optimize('b3lyp-d2')
    
  • DFT-D3ZERO single point (b3lyp) with custom s8 parameter (reset all four values)

    set dft_dispersion_parameters [1.0, 2.0, 1.261, 14.0]
    energy('b3lyp-d3')
    
  • DFT-D2 single point with dftd3 instead of PSI4‘s libdisp

    energy('pbe-d2', engine='dftd3')
    

If only dispersion corrections (rather than total energies) are of interest, the dispersion programs can be run independently of the scf through the python function run_dftd3() or run_dftd4(). (These functions call QCEngine, which is the same PSI4 + dftd3/dftd4 interface that is called during an scf job.) This “D-only” route is much faster than running a DFT-D energy. This route is NOT available for s-dftd3. File an issue if a definite need arises.

Note that in a DFT+D energy or gradient calculation, user-specified dispersion parameters override any information provided about the functional. The same holds true for a dftd3 “D-only” calculation. But in a dftd4 “D-only” calculation, functional information overrides any user-specified dispersion parameters.

  • Some set-up:

    molecule nene {
    Ne
    Ne 1 2.0
    }
    
    nene.update_geometry()
    
  • The same four dispersion corrections/gradients as the section above:

    >>> print nene.run_dftd3('bp86', 'd', dertype=0)
    -7.735e-05
    
    >>> E, G = nene.run_dftd3('pbe', 'd3bj')
    >>> print G
    [[0.0, 0.0, -1.1809087569358e-05], [0.0, 0.0, 1.1809087569358e-05]]
    
    >>> E, G = nene.run_dftd3('b3lyp', 'd2', {'s6': 1.20})
    >>> print E
    -8.84e-05
    
    >>> E, G = nene.run_dftd3(dashlvl='d3', dashparam={'s8': 2.0, 'alpha6': 14.0, 'sr6': 1.261, 's6': 1.0})
    >>> print E
    -0.00024762
    
qcdb.Molecule.run_dftd3(self, func=None, dashlvl=None, dashparam=None, dertype=None, verbose=1)

Compute dispersion correction via Grimme’s DFTD3 program.

Parameters:
  • func (Optional[str]) – Name of functional (func only, func & disp, or disp only) for which to compute dispersion (e.g., blyp, BLYP-D2, blyp-d3bj, blyp-d3(bj), hf+d). Any or all parameters initialized from dashcoeff[dashlvl][func] can be overwritten via dashparam.

  • dashlvl (Optional[str]) – Name of dispersion correction to be applied (e.g., d, D2, d3(bj), das2010). Must be key in dashcoeff or “alias” or “formal” to run.

  • dashparam (Optional[Dict]) – Values for the same keys as dashcoeff[dashlvl][‘default’] used to override any or all values initialized by func. Extra parameters will error.

  • dertype (Union[int, str, None]) – Maximum derivative level at which to run DFTD3. For large molecules, energy-only calculations can be significantly more efficient. Influences return values, see below.

  • verbose (int) – Amount of printing.

Returns:

  • energy (float) – When dertype=0, energy [Eh].

  • gradient (~numpy.ndarray) – When dertype=1, (nat, 3) gradient [Eh/a0].

  • (energy, gradient) (tuple of float and ~numpy.ndarray) – When dertype=None, both energy [Eh] and (nat, 3) gradient [Eh/a0].

qcdb.Molecule.run_dftd4(self, func=None, dashlvl=None, dashparam=None, dertype=None, verbose=1)

Compute dispersion correction via Grimme’s DFTD4 program.

Parameters:
  • func (Optional[str]) – Name of functional (func only, func & disp, or disp only) for which to compute dispersion (e.g., blyp, BLYP-D2, blyp-d3bj, blyp-d3(bj), hf+d). Unlike run_dftd3, func overwrites any parameter initialized via dashparam.

  • dashlvl (Optional[str]) – Name of dispersion correction to be applied (e.g., d, D2, d3(bj), das2010). Must be key in dashcoeff or “alias” or “formal” to run.

  • dashparam (Optional[Dict]) – Values for the same keys as dashcoeff[dashlvl][‘default’] used to provide custom values. Unlike run_dftd3, will not have effect if func given. Must provide all parameters. Extra parameters will error.

  • dertype (Union[int, str, None]) – Maximum derivative level at which to run DFTD3. For large molecules, energy-only calculations can be significantly more efficient. Influences return values, see below.

  • verbose (int) – Amount of printing.

Returns:

  • energy (float) – When dertype=0, energy [Eh].

  • gradient (ndarray) – When dertype=1, (nat, 3) gradient [Eh/a0].

  • (energy, gradient) (tuple of float and ndarray) – When dertype=None, both energy [Eh] and (nat, 3) gradient [Eh/a0].

Notes

This function wraps the QCEngine dftd4 harness which wraps the internal DFTD4 Python API. As such, the upstream convention of func trumping dashparam holds, rather than the run_dftd3() behavior of dashparam extending or overriding func.

class psi4.driver.procrouting.empirical_dispersion.EmpiricalDispersion(*, name_hint=None, level_hint=None, param_tweaks=None, engine=None, gcp_engine=None, save_pairwise_disp=False)[source]

Lightweight unification of empirical dispersion calculation modes.

dashlevel

{“d1”, “d2”, “chg”, “das2009”, “das2010”, “nl”, “dmp2”, “d3zero2b”, “d3bj2b”, “d3mzero2b”, “d3mbj2b”, “d3zeroatm”, “d3bjatm”, “d3mzeroatm”, “d3mbjatm”, “d4bjeeqatm”} Name of dispersion correction to be applied. Resolved from name_hint and/or level_hint into a key of empirical_dispersion_resources.dashcoeff.

Type:

str

dashparams

Complete set of parameter values defining the flexible parts of dashlevel. Number and parameter names vary by dashlevel. Resolved into a complete set (keys of dashcoeff[dashlevel][‘default’]) from name_hint and/or dashcoeff_supplement and/or user param_tweaks.

Type:

dict

fctldash

If dashparams for dashlevel corresponds to a defined, named, untweaked “functional-dashlevel” set, then that functional. Otherwise, empty string.

Type:

str

description

Tagline for dispersion dashlevel.

Type:

str

dashlevel_citation

Literature reference for dispersion dashlevel in general, not necessarily for dashparams.

Type:

str

dashparams_citation

Literature reference for dispersion parameters, if dashparams corresponds to a defined, named, untweaked “functional-dashlevel” set with a citation. Otherwise, empty string.

Type:

str

dashcoeff_supplement

See description in qcengine.programs.empirical_dispersion_resources.from_arrays. Used here to “bless” the dispersion definitions attached to the procedures/dft/<rung>_functionals-defined dictionaries as legit, non-custom, and of equal validity to qcengine.programs.empirical_dispersion_resources.dashcoeff itself for purposes of validating fctldash.

Type:

dict

engine

{‘libdisp’, “s-dftd3”, ‘dftd3’, ‘nl’, ‘mp2d’, “dftd4”} Compute engine for dispersion. One of Psi4’s internal libdisp library, external Grimme or Beran projects, or nl.

Type:

str

disp

Only present for engine =libdisp. Psi4 class instance prepared to compute dispersion.

Type:

Dispersion

ordered_params

Fixed-order list of relevant parameters for dashlevel. Matches DISPERSION CORRECTION ENERGY ordering. Used for printing.

Type:

list

Parameters:
  • name_hint (Optional[str]) – Name of functional (func only, func & disp, or disp only) for which to compute dispersion (e.g., blyp, BLYP-D2, blyp-d3bj, blyp-d3(bj), hf+d). Any or all parameters initialized from dashcoeff[dashlevel][functional-without-dashlevel] or dashcoeff_supplement[dashlevel][functional-with-dashlevel] can be overwritten via param_tweaks.

  • level_hint (Optional[str]) – Name of dispersion correction to be applied (e.g., d, D2, d3(bj), das2010). Must be key in dashcoeff or “alias” or “formal” to one.

  • param_tweaks (Union[Dict, List, None]) – Values for the same keys as dashcoeff[dashlevel][‘default’] (and same order if list) used to override any or all values initialized by name_hint. Extra parameters will error.

  • engine (Optional[str]) – Override which code computes dispersion. See above for allowed values. Formerly (pre Nov 2022) only relevant for -D2, which can be computed by libdisp or dftd3. Now (post Nov 2022) also relevant for -D3 variants, which can be computed by dftd3 executable or simple-dftd3 Python module.

  • gcp_engine (Optional[str]) – Override which code computes the gcp correction. Now can use classic gcp or mctc-gcp executables.

  • save_pairwise_disp (bool) – Whether to request atomic pairwise analysis.