Skip to content

Commit 87ca9af

Browse files
committed
Update documentation
1 parent 681e299 commit 87ca9af

File tree

7 files changed

+271
-21
lines changed

7 files changed

+271
-21
lines changed

.github/workflows/docs.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: docs
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
build-and-deploy:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v2
10+
- uses: actions/setup-python@v1
11+
with:
12+
python-version: '3.x'
13+
- name: Install dependencies
14+
run: pip install ford
15+
- name: Build Documentation
16+
run: ford docs.md
17+
- uses: JamesIves/github-pages-deploy-action@3.7.1
18+
if: github.event_name == 'push' && github.repository == 'awvwgk/simple-dftd3' && ( startsWith( github.ref, 'refs/tags/' ) || github.ref == 'refs/heads/master' )
19+
with:
20+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
21+
BRANCH: gh-pages
22+
FOLDER: docs
23+
CLEAN: true

app/main.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ program dftd3_main
8282
if (config%atm) s9 = inp%s9
8383
if (config%zero) then
8484
if (.not.config%has_param) then
85-
call get_zero_damping_param(inp, method, error, s9)
85+
call get_zero_damping(inp, method, error, s9)
8686
if (allocated(error)) then
8787
write(error_unit, '("[Error]", 1x, a)') error%message
8888
error stop
@@ -94,7 +94,7 @@ program dftd3_main
9494
end if
9595
if (config%rational) then
9696
if (.not.config%has_param) then
97-
call get_rational_damping_param(inp, method, error, s9)
97+
call get_rational_damping(inp, method, error, s9)
9898
if (allocated(error)) then
9999
write(error_unit, '("[Error]", 1x, a)') error%message
100100
error stop

docs.md

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
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(&param);
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+
```

src/dftd3.f90

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,14 @@ module dftd3
2222
use dftd3_damping_rational, only : rational_damping_param, new_rational_damping
2323
use dftd3_damping_zero, only : zero_damping_param, new_zero_damping
2424
use dftd3_model, only : d3_model, new_d3_model
25-
use dftd3_param, only : d3_param, get_rational_damping_param, &
26-
& get_zero_damping_param
25+
use dftd3_param, only : d3_param, get_rational_damping, get_zero_damping
2726
use dftd3_version, only : get_dftd3_version
2827
implicit none
2928
private
3029

3130
public :: get_dispersion, get_coordination_number, realspace_cutoff
3231
public :: damping_param, d3_param
33-
public :: get_rational_damping_param, get_zero_damping_param
32+
public :: get_rational_damping, get_zero_damping
3433
public :: rational_damping_param, new_rational_damping
3534
public :: zero_damping_param, new_zero_damping
3635
public :: d3_model, new_d3_model

src/dftd3/api.f90

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
! along with s-dftd3. If not, see <https://www.gnu.org/licenses/>.
1616

1717
!> Definition of the public C-API of s-dftd3
18+
!>
19+
!>```c
20+
!>{!./include/s-dftd3.h!}
21+
!>```
1822
module dftd3_api
1923
use iso_c_binding
2024
use mctc_env, only : wp, error_type, fatal_error
@@ -25,8 +29,7 @@ module dftd3_api
2529
use dftd3_damping, only : damping_param
2630
use dftd3_disp, only : get_dispersion
2731
use dftd3_model, only : d3_model, new_d3_model
28-
use dftd3_param, only : d3_param, get_rational_damping_param, &
29-
& get_zero_damping_param
32+
use dftd3_param, only : d3_param, get_rational_damping, get_zero_damping
3033
use dftd3_version, only : get_dftd3_version
3134
implicit none
3235
private
@@ -369,11 +372,11 @@ function load_rational_damping_api(verror, vmol, charptr, atm) &
369372
call c_f_character(charptr, method)
370373

371374
if (atm) s9 = 1.0_wp
372-
call get_rational_damping_param(inp, method, error%ptr, s9)
375+
call get_rational_damping(inp, method, error%ptr, s9)
376+
if (allocated(error%ptr)) return
373377

374378
allocate(tmp)
375379
call new_zero_damping(tmp, inp, mol%ptr%num)
376-
if (allocated(error%ptr)) return
377380

378381
allocate(param)
379382
call move_alloc(tmp, param%ptr)
@@ -453,7 +456,7 @@ function load_zero_damping_api(verror, vmol, charptr, atm) &
453456
call c_f_character(charptr, method)
454457

455458
if (atm) s9 = 1.0_wp
456-
call get_zero_damping_param(inp, method, error%ptr, s9)
459+
call get_zero_damping(inp, method, error%ptr, s9)
457460
if (allocated(error%ptr)) return
458461

459462
allocate(tmp)

src/dftd3/param.f90

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module dftd3_param
1919
implicit none
2020

2121
public :: d3_param
22-
public :: get_rational_damping_param, get_zero_damping_param
22+
public :: get_rational_damping, get_zero_damping
2323

2424

2525
type :: d3_param
@@ -138,7 +138,7 @@ function get_method_id(method) result(id)
138138
end function get_method_id
139139

140140

141-
subroutine get_rational_damping_param(param, method, error, s9)
141+
subroutine get_rational_damping(param, method, error, s9)
142142

143143
!> Loaded parameter record
144144
type(d3_param), intent(out) :: param
@@ -266,10 +266,10 @@ subroutine get_rational_damping_param(param, method, error, s9)
266266
param%s9 = s9
267267
end if
268268

269-
end subroutine get_rational_damping_param
269+
end subroutine get_rational_damping
270270

271271

272-
subroutine get_zero_damping_param(param, method, error, s9)
272+
subroutine get_zero_damping(param, method, error, s9)
273273

274274
!> Loaded parameter record
275275
type(d3_param), intent(out) :: param
@@ -389,7 +389,7 @@ subroutine get_zero_damping_param(param, method, error, s9)
389389
param%s9 = s9
390390
end if
391391

392-
end subroutine get_zero_damping_param
392+
end subroutine get_zero_damping
393393

394394

395395
end module dftd3_param

0 commit comments

Comments
 (0)