Skip to content
Draft
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
6 changes: 6 additions & 0 deletions doc/api/python.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ Library interface

.. automodule:: dftd3.interface

.. note::

For periodic structures, cutoff selection, ATM settings, and unit
conversions across the executable, Python API, and ASE calculator are
summarized in :doc:`../guide/periodic-cutoffs`.


Structure
~~~~~~~~~
Expand Down
1 change: 1 addition & 0 deletions doc/guide/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ This section contains guides on how to use D3 for your applications.
.. toctree::

minimal-example
periodic-cutoffs
citing
133 changes: 133 additions & 0 deletions doc/guide/periodic-cutoffs.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
Real-space cutoffs for periodic calculations
============================================

For periodic structures D3 sums pair and, optionally, ATM three-body
contributions over lattice translations in real space. When comparing the
standalone executable, the Python API, the ASE calculator, or another code
such as VASP, check these settings first:

* whether the ATM term is enabled,
* whether the same real-space cutoffs are used,
* and whether the reported energies are compared in the same unit.

The library defaults are ``disp2 = 60 Bohr``, ``disp3 = 40 Bohr``, and
``cn = 40 Bohr``.


Units and defaults
------------------

+----------------------+----------------------------------------+-----------------------+
| Interface | Real-space cutoff input | Returned energy |
+======================+========================================+=======================+
| ``s-dftd3`` | not configurable from the CLI; uses | Hartree (``Eh``) |
| | the library defaults above | |
+----------------------+----------------------------------------+-----------------------+
| ``dftd3.interface`` | Bohr | Hartree |
+----------------------+----------------------------------------+-----------------------+
| ``dftd3.ase.DFTD3`` | Angstrom; use ``60 * Bohr`` to pass | eV, following ASE |
| | 60 Bohr through ASE | conventions |
+----------------------+----------------------------------------+-----------------------+

The standalone executable treats periodic input formats such as ``POSCAR`` or
``CONTCAR`` automatically as periodic structures. VASP reports energies in eV,
so convert the ``s-dftd3`` or Python API energies before comparing them.


Standalone executable
---------------------

The executable uses the default periodic cutoffs. Without ``--atm`` it computes
the two-body D3 energy; adding ``--atm`` enables the ATM term.

.. code-block:: shell

s-dftd3 CONTCAR --bj pbe
s-dftd3 CONTCAR --bj pbe --atm

If you need to study the cutoff dependence explicitly, use the Python API or
the ASE calculator below. Those interfaces expose the periodic cutoffs
directly.


Python API
----------

The low-level Python API expects coordinates, lattice vectors, and cutoffs in
Bohr and returns the energy in Hartree.

.. code-block:: python

from ase.io import read
from ase.units import Bohr, Hartree
from dftd3.interface import DispersionModel, RationalDampingParam

atoms = read("CONTCAR")
model = DispersionModel(
atoms.numbers,
atoms.positions / Bohr,
lattice=atoms.cell.array / Bohr,
periodic=atoms.pbc,
)

params = {
"D3(BJ)": RationalDampingParam(method="PBE", atm=False),
"D3(BJ)-ATM": RationalDampingParam(method="PBE", atm=True),
}

for disp2, disp3, cn in [(60.0, 40.0, 40.0), (95.0, 70.0, 70.0)]:
model.set_realspace_cutoff(disp2=disp2, disp3=disp3, cn=cn)
for label, param in params.items():
energy = model.get_dispersion(param=param, grad=False)["energy"]
print(
label,
f"cutoff=({disp2}, {disp3}, {cn}) Bohr",
f"{energy:.12f} Eh",
f"{energy * Hartree:.8f} eV",
)

Using ``atm=False`` reproduces the executable call without ``--atm``. The
default ``RationalDampingParam(method=\"PBE\")`` uses the ATM-enabled
parameterization.


ASE calculator
--------------

The ASE calculator expects cutoff values in Angstrom and returns energies in eV.
To pass the same numerical cutoff as the library defaults, multiply by
``ase.units.Bohr``.

.. code-block:: python

from ase.io import read
from ase.units import Bohr
from dftd3.ase import DFTD3

atoms = read("CONTCAR")

setups = {
"D3(BJ)": {"params_tweaks": {"method": "PBE", "atm": False}},
"D3(BJ)-ATM": {"params_tweaks": {"method": "PBE", "atm": True}},
}

cutoffs = [
{"disp2": 60 * Bohr, "disp3": 40 * Bohr, "cn": 40 * Bohr},
{"disp2": 95 * Bohr, "disp3": 70 * Bohr, "cn": 70 * Bohr},
]

for label, kwargs in setups.items():
for cutoff in cutoffs:
atoms.calc = DFTD3(
damping="d3bj",
realspace_cutoff=cutoff,
cache_api=False,
**kwargs,
)
print(label, cutoff, f"{atoms.get_potential_energy():.8f} eV")

``DFTD3(method=\"PBE\", damping=\"d3bj\")`` uses ATM-enabled parameters. To
match ``s-dftd3 CONTCAR --bj pbe``, request the pairwise-only parameterization
with ``params_tweaks={\"method\": \"PBE\", \"atm\": False}``.
If you prefer explicit damping parameters, setting ``s9 = 0.0`` in
``params_tweaks`` disables the ATM contribution as well.
3 changes: 3 additions & 0 deletions python/dftd3/ase.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@
Values provided in the dict are expected to be in Angstrom. When providing values
in Bohr multiply the inputs by the `ase.units.Bohr` constant.

All returned properties follow ASE conventions: energies are reported in eV,
forces in eV / Angstrom, and stress in eV / Angstrom^3.

Example
-------
>>> from ase.build import molecule
Expand Down
12 changes: 10 additions & 2 deletions python/dftd3/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ def __init__(
immutable atomic species and boundary condition, also the total number of
atoms cannot be changed.

Cartesian coordinates and lattice vectors are expected in atomic units
(Bohr). Periodicity is given as a boolean array for the three lattice
directions.

Raises
------
ValueError
Expand Down Expand Up @@ -488,12 +492,16 @@ def __init__(
self._disp = library.new_d3_model(self._mol)

def set_realspace_cutoff(self, disp2: float, disp3: float, cn: float):
"""Set realspace cutoff for evaluation of interactions"""
"""Set realspace cutoffs in Bohr for pair, triple, and CN evaluations."""

library.set_model_realspace_cutoff(self._disp, disp2, disp3, cn)

def get_dispersion(self, param: DampingParam, grad: bool) -> dict:
"""Perform actual evaluation of the dispersion correction"""
"""Perform actual evaluation of the dispersion correction.

Returns the dispersion energy in Hartree. If ``grad=True`` the gradient
is returned in Hartree / Bohr and the virial in Hartree.
"""

_energy = np.array(0.0)
if grad:
Expand Down