|
| 1 | +--- |
| 2 | +project: Simple DFT-D3 |
| 3 | +summary: A simple reimplementation of the DFT-D3 dispersion model |
| 4 | +project_github: https://github.com/awvwgk/simple-dftd3 |
| 5 | +project_download: https://github.com/awvwgk/simple-dftd3/releases |
| 6 | +author: Sebastian Ehlert |
| 7 | +github: https://github.com/awvwgk |
| 8 | +src_dir: ./src |
| 9 | + ./app |
| 10 | +output_dir: ./docs |
| 11 | +exclude_dir: ./test |
| 12 | +docmark: < |
| 13 | +predocmark: > |
| 14 | +source: true |
| 15 | +graph: false |
| 16 | +sort: alpha |
| 17 | +print_creation_date: true |
| 18 | +extra_mods: iso_fortran_env:https://gcc.gnu.org/onlinedocs/gfortran/ISO_005fFORTRAN_005fENV.html |
| 19 | + mctc_io:https://grimme-lab.github.io/mctc-lib/modules/mctc_io.html |
| 20 | + mctc_env:https://grimme-lab.github.io/mctc-lib/modules/mctc_env.html |
| 21 | +creation_date: %Y-%m-%d %H:%M %z |
| 22 | +md_extensions: markdown.extensions.toc |
| 23 | + markdown.extensions.smarty |
| 24 | +--- |
| 25 | + |
| 26 | +A simple drop-in replacement for ``dftd3``. |
| 27 | + |
| 28 | +This program provides a small and easy to use implementation of the DFT-D3 dispersion correction |
| 29 | +(see [*JCP* **132**, 154104 (2010)](https://dx.doi.org/10.1063/1.3382344) |
| 30 | +and [*JCC* **32**, 1456 (2011)](https://dx.doi.org/10.1002/jcc.21759) for details). |
| 31 | + |
| 32 | +It is mostly based on the [`dftd4`](https://github.com/dftd4/dftd4) program and |
| 33 | +borrows one or two ideas from the implementation in [`ased3`](https://github.com/ehermes/ased3). |
| 34 | + |
| 35 | + |
| 36 | +[TOC] |
| 37 | + |
| 38 | + |
| 39 | +## Usage |
| 40 | + |
| 41 | +To use DFT-D3 in your application you can either use the Fortran API or the C API. |
| 42 | + |
| 43 | +### Fortran API |
| 44 | + |
| 45 | +To perform a D3(BJ)-ATM calculation in a Fortran program, the [[dftd3]] module should be imported. |
| 46 | +Other data types to communicate with the library are obtained from the [MCTC library](https://grimme-lab.github.io/mctc-lib) using the environment module ([[mctc_env]]) and the IO module ([[mctc_io]]). |
| 47 | + |
| 48 | +```fortran |
| 49 | +subroutine calc_dftd3(mol, method, energy, gradient, sigma, error) |
| 50 | + use mctc_env |
| 51 | + use mctc_io |
| 52 | + use dftd3 |
| 53 | + type(structure_type), intent(in) :: mol |
| 54 | + character(len=*), intent(in) :: method |
| 55 | + real(wp), intent(out) :: energy |
| 56 | + real(wp), intent(out) :: gradient(:, :) |
| 57 | + real(wp), intent(out) :: sigma(:, :) |
| 58 | + type(error_type), allocatable, intent(out) :: error |
| 59 | + type(d3_model) :: disp |
| 60 | + type(d3_param) :: inp |
| 61 | + class(damping_param), allocatable :: param |
| 62 | +
|
| 63 | + call get_rational_damping(inp, method, error, s9=1.0_wp) |
| 64 | + if (allocated(error)) return |
| 65 | + call new_rational_damping(param, inp, mol) |
| 66 | +
|
| 67 | + call new_d3_model(disp, mol) |
| 68 | +
|
| 69 | + call get_dispersion(mol, disp, param, realspace_cutoff(), energy, & |
| 70 | + & gradient, sigma) |
| 71 | +
|
| 72 | +end subroutine calc_dftd3 |
| 73 | +``` |
| 74 | + |
| 75 | + |
| 76 | +### C API |
| 77 | + |
| 78 | +An example wrapper for a DFT-D3(BJ)-ATM calculation is given here. |
| 79 | + |
| 80 | +```c |
| 81 | +#include <stdbool.h> |
| 82 | +#include <stdio.h> |
| 83 | +#include <stdlib.h> |
| 84 | + |
| 85 | +#include "dftd3.h" |
| 86 | + |
| 87 | +static const buffersize = 512; |
| 88 | + |
| 89 | +int |
| 90 | +calc_dftd3(int natoms, int* numbers, double* positions, |
| 91 | + double* lattice, bool* periodic, char* method, |
| 92 | + double* energy, double* gradient, double* sigma) |
| 93 | +{ |
| 94 | + // Local API objects from the s-dftd3 library |
| 95 | + dftd3_error error = dftd3_new_error(); |
| 96 | + dftd3_structure mol = NULL; |
| 97 | + dftd3_model disp = NULL; |
| 98 | + dftd3_param param = NULL; |
| 99 | + int stat = EXIT_SUCCESS; |
| 100 | + |
| 101 | + // Create a new geometry for the library to work with |
| 102 | + mol = dftd3_new_structure(error, natoms, numbers, positions, lattice, periodic); |
| 103 | + stat = dftd3_check_error(error); |
| 104 | + |
| 105 | + if (stat) { |
| 106 | + // Initialize the D3 dispersion model for the given structure, |
| 107 | + // this step depends on the atomic numbers, but not on the actual geometry |
| 108 | + disp = dftd3_new_d3_model(error, mol); |
| 109 | + stat = dftd3_check_error(error); |
| 110 | + } |
| 111 | + |
| 112 | + if (stat) { |
| 113 | + // Load D3(BJ)-ATM parameters for the given method from internal storage, |
| 114 | + // this step depends on the atomic numbers, but not on the actual geometry |
| 115 | + param = dftd3_load_rational_damping(error, mol, method, true); |
| 116 | + stat = dftd3_check_error(error); |
| 117 | + } |
| 118 | + |
| 119 | + if (stat) { |
| 120 | + // Evaluate the dispersion energy, gradient and virial, |
| 121 | + // the gradient and virial are optional and can be replaced by NULL |
| 122 | + dftd3_get_dispersion(error, mol, disp, param, &energy, gradient, sigma); |
| 123 | + stat = dftd3_check_error(error); |
| 124 | + } |
| 125 | + |
| 126 | + if (!stat) { |
| 127 | + char buffer[buffersize]; |
| 128 | + dftd3_get_error(error, buffer, buffersize); |
| 129 | + printf("[Error] %s\n", buffer); |
| 130 | + } |
| 131 | + |
| 132 | + // Always free the used memory |
| 133 | + dftd3_delete_error(&error); |
| 134 | + dftd3_delete_structure(&mol); |
| 135 | + dftd3_delete_model(&disp); |
| 136 | + dftd3_delete_param(¶m); |
| 137 | + |
| 138 | + return stat; |
| 139 | +} |
| 140 | +``` |
| 141 | +
|
| 142 | +Overall, any DFT-D3 calculation requires the creation of four API objects. |
| 143 | +
|
| 144 | +The error handling is done with a ``dftd3_error`` handle, it can be checked using the ``dftd3_error_check`` function and returns zero values on success and non-zero values on failures. |
| 145 | +On failures the error handle can be queried for the error message with ``dftd3_get_error``. |
| 146 | +The library itself will not attempt to write or terminate on any encounter of an error. |
| 147 | +
|
| 148 | +To pass the geometry information a ``dftd3_structure`` object is used. |
| 149 | +The object has immutable number of atoms, atomic numbers and boundary conditions, but allows updating the coordinates and lattice vectors after creation. |
| 150 | +The structure object is required to initialize system specific data of other API objects. |
| 151 | +Atomic numbers are allowed in a range of 1 to 118, but the used dispersion model might support a smaller range. |
| 152 | +
|
| 153 | +The actual D3 dispersion model is created as ``dftd3_model`` object using the ``new_d3_model`` constructor. |
| 154 | +It contains the interpolation scheme for the dispersion coefficients, which is common to all DFT-D3 dispersion corrections independently of the damping function. |
| 155 | +In principle this part can be replaced by a different scheme to evaluate the dispersion coefficients. |
| 156 | +This step might require an internal initialization on the first invocation. |
| 157 | +The internal initialization is done once and in an OpenMP thread-safe way in case the library is compiled OpenMP threading. |
| 158 | +Otherwise guard this API call with a ``critical`` pragma if you require thread-safe execution. |
| 159 | +
|
| 160 | +Finally, to evaluate dispersion energies and gradients a damping function is required to connect the dispersion model to a method like a density functional. |
| 161 | +The damping parameters are stored as ``dftd3_param`` object and can either be loaded from the internal storage of the library or created by supplying the parameters directly. |
| 162 | +
|
| 163 | +Make sure to delete the API objects after you are done with them. |
| 164 | +The deconstructor will return without any action in case a null pointer is passed. |
| 165 | +After deconstructing the API objects are overwritten with a null pointer. |
| 166 | +
|
| 167 | +
|
| 168 | +## Getting Started |
| 169 | +
|
| 170 | +### Meson |
| 171 | +
|
| 172 | +Create a new meson project and include `s-dftd3` either as git-submodule in your subprojects directory or create a wrap file to fetch it from upstream: |
| 173 | +
|
| 174 | +```ini |
| 175 | +[wrap-git] |
| 176 | +directory = s-dftd3 |
| 177 | +url = https://github.com/awvwgk/simple-dftd3 |
| 178 | +revision = head |
| 179 | +``` |
| 180 | + |
| 181 | +To load the project the necessary boilerplate code for subprojects is just |
| 182 | + |
| 183 | +<!--pygments doesn't know about meson, python highlighting looks okayish--> |
| 184 | +```python |
| 185 | +sdftd3_prj = subproject( |
| 186 | + 's-dftd3', |
| 187 | + version: '>=0.1', |
| 188 | + default_options: [ |
| 189 | + 'default_library=static', |
| 190 | + ], |
| 191 | +) |
| 192 | +sdftd3_dep = sdftd3_prj.get_variable('sdftd3_dep') |
| 193 | +``` |
| 194 | + |
| 195 | +Now you can add `sdftd3_dep` to your dependencies and access the public API by the `dftd3` module. |
| 196 | + |
| 197 | +We recommend to set the default library type of `s-dftd3` to static when linking your applications or library against it. |
| 198 | +Note for library type both and shared `s-dftd3` will install itself along with your project. |
| 199 | + |
| 200 | +For more fine-tuned control you can access: |
| 201 | + |
| 202 | +- the library target with `sdftd3_lib` |
| 203 | +- the private include dir of this target, containing the Fortran module files, with `sdftd3_inc` |
| 204 | +- the license files of `s-dftd3` with `sdftd3_lic` |
| 205 | + |
| 206 | +If you are linking your application statically against `s-dftd3` and still want to distribute the license files of `s-dftd3` (thank you), just use |
| 207 | + |
| 208 | +```python |
| 209 | +install_data( |
| 210 | + sdftd3_prj.get_variable('sdftd3_lic'), |
| 211 | + install_dir: get_option('datadir')/'licenses'/meson.project_name()/'s-dftd3', |
| 212 | +) |
| 213 | +``` |
| 214 | + |
| 215 | + |
| 216 | +### Fortran Package Manager (fpm) |
| 217 | + |
| 218 | +This project supports [fpm](https://github.com/fortran-lang/fpm) as build system as well. |
| 219 | +Just add it to the dependencies in your `fpm.toml` file: |
| 220 | + |
| 221 | +```toml |
| 222 | +[dependencies] |
| 223 | +[dependencies.s-dftd3] |
| 224 | +git = "https://github.com/awvwgk/s-dftd3" |
| 225 | +``` |
0 commit comments