How to use this library?#
This section contains a few self-contained examples on how to use D3.
Compute energy with rational damping#
This example shows how to compute the dispersion energy with the rational damping function.
energy.f90#
program test_simple_d3
use, intrinsic :: iso_fortran_env, only : r8 => real64
use mctc_env, only: error_type
use mctc_io, only: structure_type, new
use dftd3, only: d3_model, d3_param, rational_damping_param, get_rational_damping, &
& new_rational_damping, new_d3_model, get_dispersion, realspace_cutoff
implicit none
character(len=:), allocatable :: method
type(structure_type) :: mol
type(error_type), allocatable :: error
integer, allocatable :: num(:)
real(r8), allocatable :: xyz(:, :)
real(r8) :: energy
type(d3_model) :: disp
type(d3_param) :: inp
type(rational_damping_param) :: param
method = 'PBE0'
num = [6, 1, 1, 1, 1]
xyz = reshape([ & ! coordinates in Bohr
& 0.0000000_r8, -0.0000000_r8, 0.0000000_r8, &
& -1.1922080_r8, 1.1922080_r8, 1.1922080_r8, &
& 1.1922080_r8, -1.1922080_r8, 1.1922080_r8, &
& -1.1922080_r8, -1.1922080_r8, -1.1922080_r8, &
& 1.1922080_r8, 1.1922080_r8, -1.1922080_r8],&
& [3, size(num)])
call new(mol, num, xyz, charge=0.0_r8, uhf=0)
call get_rational_damping(inp, method, error, s9=1.0_r8)
if (allocated(error)) then
print '(2a)', "Error: ", error%message
return
end if
call new_rational_damping(param, inp)
call new_d3_model(disp, mol)
call get_dispersion(mol, disp, param, realspace_cutoff(), energy)
print '(3a, f13.10, a)', 'Dispersion energy for ', method, '-D3(BJ) is ', energy, ' Hartree'
end program test_simple_d3
energy.c#
#include <stdio.h>
#include <stdbool.h>
#include "dftd3.h"
int main(void)
{
dftd3_error error = dftd3_new_error();
dftd3_structure mol = NULL;
dftd3_model d3 = NULL;
dftd3_param param = NULL;
int nat = 5;
int num[5] = {6, 1, 1, 1, 1};
double xyz[15] = { // coordinates in Bohr
0.0000000, -0.0000000, 0.0000000,
-1.1922080, 1.1922080, 1.1922080,
1.1922080, -1.1922080, 1.1922080,
-1.1922080, -1.1922080, -1.1922080,
1.1922080, 1.1922080, -1.1922080};
mol = dftd3_new_structure(error, nat, num, xyz, NULL, NULL);
if (dftd3_check_error(error)) goto handle_error;
char method[5] = "PBE0";
param = dftd3_load_rational_damping(error, method, false);
if (dftd3_check_error(error)) goto handle_error;
d3 = dftd3_new_d3_model(error, mol);
if (dftd3_check_error(error)) goto handle_error;
double energy;
dftd3_get_dispersion(error, mol, d3, param, &energy, NULL, NULL);
if (dftd3_check_error(error)) goto handle_error;
printf("Dispersion energy for %s-D3(BJ) is %13.10lf Hartree\n", method, energy);
dftd3_delete(error);
dftd3_delete(mol);
dftd3_delete(d3);
dftd3_delete(param);
return 0;
handle_error:
char msg[512];
dftd3_get_error(error, msg, NULL);
printf("Error: %s\n", msg);
dftd3_delete(error);
dftd3_delete(mol);
dftd3_delete(d3);
dftd3_delete(param);
return 1;
}
energy.py#
import numpy as np
from dftd3.interface import RationalDampingParam, DispersionModel
num = np.array([6, 1, 1, 1, 1])
xyz = np.array( # coordinates in Bohr
[
[ 0.0000000, -0.0000000, 0.0000000],
[-1.1922080, 1.1922080, 1.1922080],
[ 1.1922080, -1.1922080, 1.1922080],
[-1.1922080, -1.1922080, -1.1922080],
[ 1.1922080, 1.1922080, -1.1922080],
]
)
method = "PBE0"
model = DispersionModel(num, xyz)
res = model.get_dispersion(RationalDampingParam(method=method), grad=False)
print(f"Dispersion energy for {method}-D3(BJ) is {res['energy']:13.10f} Hartree")
To test this example you can install the dependencies with
mamba create d3 simple-dftd3 fortran-compiler pkg-config
mamba activate d3
mamba create d3 simple-dftd3 c-compiler pkg-config
mamba activate d3
mamba create d3 dftd3-python
mamba activate d3
You can run the example code with
❯ $FC energy.f90 $(pkg-config s-dftd3 mctc-lib --cflags --libs) && ./a.out
Dispersion energy for PBE0-D3(BJ) is -0.0009218696 Hartree
❯ $CC energy.c $(pkg-config s-dftd3 mctc-lib --cflags --libs) && ./a.out
Dispersion energy for PBE0-D3(BJ) is -0.0009218696 Hartree
❯ python energy.py
Dispersion energy for PBE0-D3(BJ) is -0.0009219059 Hartree
Disable selected atoms with ghost indices#
The same idea works for all public interfaces. Use the atom indices of the fragment that should be excluded from the dispersion contribution, then pass them to the model or CLI entry point:
The Fortran constructor uses 1-based atom indices, while the C and Python interfaces use 0-based indices. For the CLI, the same selection is available as
❯ s-dftd3 run --ghost 4,5,6 structure.xyz