Skip to content

Commit 681e299

Browse files
committed
Implement C-API and internal parameter storage
1 parent de97077 commit 681e299

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+3132
-428
lines changed

.github/dco.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
require:
2+
members: false

.github/workflows/build.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: CI
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
build:
7+
runs-on: ${{ matrix.os }}
8+
strategy:
9+
fail-fast: false
10+
matrix:
11+
os: [ubuntu-latest, macos-latest, windows-latest]
12+
gcc_v: [9] # Version of GCC we want to use.
13+
14+
env:
15+
FC: gfortran
16+
GCC_V: ${{ matrix.gcc_v }}
17+
OMP_NUM_THREADS: 2,1
18+
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v2
22+
23+
- uses: actions/setup-python@v1
24+
with:
25+
python-version: '3.x'
26+
27+
- name: Install GCC (OSX)
28+
if: contains(matrix.os, 'macos')
29+
run: |
30+
ln -s /usr/local/bin/gfortran-${GCC_V} /usr/local/bin/gfortran
31+
which gfortran-${GCC_V}
32+
which gfortran
33+
34+
- name: Install GCC (Linux)
35+
if: contains(matrix.os, 'ubuntu')
36+
run: |
37+
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_V} 100 \
38+
--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-${GCC_V} \
39+
--slave /usr/bin/gcov gcov /usr/bin/gcov-${GCC_V}
40+
41+
- name: Install meson
42+
run: pip3 install meson ninja
43+
44+
- name: Configure build
45+
run: meson setup _build -Dopenmp=false
46+
47+
- name: Build library
48+
run: meson compile -C _build
49+
50+
- name: Run unit tests
51+
run: meson test -C _build --print-errorlogs --no-rebuild

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and [*JCC* **32**, 1456 (2011)](https://dx.doi.org/10.1002/jcc.21759) for detail
1010
It is mostly based on the [`dftd4`](https://github.com/dftd4/dftd4) program and
1111
borrows one or two ideas from the implementation in [`ased3`](https://github.com/ehermes/ased3).
1212

13+
1314
## Installation
1415

1516
To build this project from the source code in this repository you need to have
@@ -46,6 +47,31 @@ This might require administrator access.
4647
You can alter the install prefix by ``meson configure _build --prefix=/path/to/install``.
4748

4849

50+
## Usage
51+
52+
DFT-D3 calculations can be performed with the ``s-dftd3`` binary.
53+
To calculate the dispersion correction for PBE0-D3(BJ)-ATM run:
54+
55+
```
56+
s-dftd3 --bj pbe0 --atm coord
57+
```
58+
59+
In case you want to access the DFT-D3 results from other programs, dump the results to JSON with
60+
(the ``--noedisp`` flag prevents the ``.EDISP`` file generation):
61+
62+
```
63+
s-dftd3 --bj pbe0 --atm --json --noedisp --grad struct.xyz
64+
```
65+
66+
Dispersion related properties can be calculated as well:
67+
68+
```
69+
s-dftd3 --property geo.gen
70+
```
71+
72+
For an overview over all command line arguments use the ``--help`` argument.
73+
74+
4975
## License
5076

5177
This project is free software: you can redistribute it and/or modify it under

app/example.xyz

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
24
2+
-42.15450736
3+
C -3.2624567556 -1.0740397867 -0.0000043734
4+
N -2.2754344008 -0.0292896574 0.0000359020
5+
C -0.9120851382 -0.2075386125 -0.0004880509
6+
C -0.3749333299 1.0720554184 -0.0001564184
7+
N -1.3570794708 1.9998111614 0.0003858762
8+
C -2.4726070186 1.3013159995 0.0005402177
9+
H -3.4474896946 1.7467507266 0.0010080843
10+
N 0.9669701935 1.2880523079 -0.0003374012
11+
C 1.8275740716 0.2107859932 -0.0000027214
12+
O 3.0306801280 0.3524772071 0.0002192165
13+
N 1.2570001166 -1.0570195560 -0.0000714961
14+
C -0.0994181855 -1.3854842224 -0.0003307823
15+
O -0.4879332634 -2.5400052828 -0.0002686844
16+
C 2.2118766147 -2.1535108670 0.0005997875
17+
H 1.6458936552 -3.0819689593 0.0002644601
18+
H 2.8452151680 -2.0921377814 -0.8838098923
19+
H 2.8439724684 -2.0920881626 0.8858951171
20+
C 1.4878336345 2.6373781425 -0.0003075130
21+
H 1.1373305002 3.1659703185 -0.8863920642
22+
H 1.1383298601 3.1656042978 0.8863960393
23+
H 2.5739975007 2.5744621695 -0.0008973695
24+
H -3.8918239831 -1.0020514766 -0.8884978421
25+
H -3.8928014413 -1.0010907638 0.8876971655
26+
H -2.7437217829 -2.0316581902 0.0007283419

app/main.f90

Lines changed: 79 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
! This file is part of s-dftd3.
2-
! SPDX-Identifier: LGLP-3.0-or-later
2+
! SPDX-Identifier: LGPL-3.0-or-later
33
!
44
! s-dftd3 is free software: you can redistribute it and/or modify it under
55
! the terms of the GNU Lesser General Public License as published by
@@ -20,12 +20,14 @@ program dftd3_main
2020
use mctc_io
2121
use dftd3
2222
use dftd3_output
23+
use dftd3_utils
2324
implicit none
2425
character(len=*), parameter :: prog_name = "s-dftd3"
2526

2627
type :: d3_config
27-
logical :: json = .true.
28+
logical :: json = .false.
2829
character(len=:), allocatable :: json_output
30+
logical :: wrap = .true.
2931
logical :: tmer = .true.
3032
logical :: properties = .false.
3133
logical :: atm = .false.
@@ -49,37 +51,64 @@ program dftd3_main
4951
character(len=:), allocatable :: method
5052
type(zero_damping_param), allocatable :: zparam
5153
type(rational_damping_param), allocatable :: rparam
54+
real(wp), allocatable :: s9
5255
integer :: stat, unit
5356
logical :: echo, exist
5457

5558
call get_arguments(input, input_format, config, method, inp, echo, error)
5659
if (allocated(error)) then
57-
write(error_unit, '(a)') error%message
60+
write(error_unit, '("[Error]", 1x, a)') error%message
5861
error stop
5962
end if
6063

64+
if (config%verbosity > 1) then
65+
call header(output_unit)
66+
end if
67+
6168
if (input == "-") then
6269
if (.not.allocated(input_format)) input_format = filetype%xyz
6370
call read_structure(mol, input_unit, input_format, error)
6471
else
6572
call read_structure(mol, input, error, input_format)
6673
end if
6774
if (allocated(error)) then
68-
write(error_unit, '(a)') error%message
75+
write(error_unit, '("[Error]", 1x, a)') error%message
6976
error stop
7077
end if
78+
if (config%wrap) then
79+
call wrap_to_central_cell(mol%xyz, mol%lattice, mol%periodic)
80+
end if
7181

82+
if (config%atm) s9 = inp%s9
7283
if (config%zero) then
84+
if (.not.config%has_param) then
85+
call get_zero_damping_param(inp, method, error, s9)
86+
if (allocated(error)) then
87+
write(error_unit, '("[Error]", 1x, a)') error%message
88+
error stop
89+
end if
90+
end if
7391
allocate(zparam)
7492
call new_zero_damping(zparam, inp, mol%num)
7593
call move_alloc(zparam, param)
7694
end if
7795
if (config%rational) then
96+
if (.not.config%has_param) then
97+
call get_rational_damping_param(inp, method, error, s9)
98+
if (allocated(error)) then
99+
write(error_unit, '("[Error]", 1x, a)') error%message
100+
error stop
101+
end if
102+
end if
78103
allocate(rparam)
79104
call new_rational_damping(rparam, inp, mol%num)
80105
call move_alloc(rparam, param)
81106
end if
82107

108+
if (allocated(param) .and. config%verbosity > 0) then
109+
call ascii_damping_param(output_unit, param, method)
110+
end if
111+
83112
if (config%grad) then
84113
allocate(gradient(3, mol%nat))
85114
end if
@@ -186,6 +215,19 @@ subroutine property_calc(unit, mol, disp, verbosity)
186215
end subroutine property_calc
187216

188217

218+
subroutine header(unit)
219+
integer, intent(in) :: unit
220+
character(len=:), allocatable :: version_string
221+
222+
call get_dftd3_version(string=version_string)
223+
write(unit, '(a)') &
224+
"-----------------------------------", &
225+
" s i m p l e D F T - D 3 v"// version_string, &
226+
"-----------------------------------", ""
227+
228+
end subroutine header
229+
230+
189231
subroutine help(unit)
190232
integer, intent(in) :: unit
191233

@@ -195,21 +237,20 @@ subroutine help(unit)
195237
write(unit, '(a)') &
196238
"", &
197239
"Takes an geometry input to calculate the D3 dispersion correction.", &
198-
"Periodic calculations are performed automatically for periodic input formats", &
240+
"Periodic calculations are performed automatically for periodic input formats.", &
199241
"Specify the functional to select the correct parameters.", &
200242
""
201243

202244
write(unit, '(2x, a, t25, a)') &
203245
"-i, --input <format>", "Hint for the format of the input file", &
204-
"--func <method>", "Specify functional to use", &
205-
"--bj", "Use rational (Becke-Johnson) damping function", &
246+
"--bj <method>", "Use rational (Becke-Johnson) damping function", &
206247
"--bj-param <list>", "Specify parameters for rational damping,", &
207248
"", "expected order is s6, s8, a1, a2 (requires four arguments)", &
208-
"--zero", "Use zero (Chai-Head-Gordon) damping function", &
209-
"--zero-param <list>", "Specify functional to use,", &
249+
"--zero <method>", "Use zero (Chai-Head-Gordon) damping function", &
250+
"--zero-param <list>", "Specify parameters for zero damping,", &
210251
"", "expected order is s6, s8, rs6 (requires three arguments)", &
211-
"--atm", "Use ATM three-body dispersion,", &
212-
"--atm-scale <s9>", "Use scaled ATM three-body dispersion,", &
252+
"--atm", "Use ATM three-body dispersion", &
253+
"--atm-scale <s9>", "Use scaled ATM three-body dispersion", &
213254
"--noedisp", "Disable writing of dispersion energy to .EDISP file", &
214255
"--json [file]", "Dump results to JSON output (default: dftd3.json)", &
215256
"--grad", "Request gradient evaluation", &
@@ -340,7 +381,11 @@ subroutine get_arguments(input, input_format, config, method, inp, echo, error)
340381
call move_alloc(arg, input)
341382
cycle
342383
end if
343-
call fatal_error(error, "Too many positional arguments present")
384+
if (arg(1:1) == "-") then
385+
call fatal_error(error, "Unknown argument encountered: '"//arg//"'")
386+
else
387+
call fatal_error(error, "Too many positional arguments present")
388+
end if
344389
exit
345390
case("-i", "--input")
346391
iarg = iarg + 1
@@ -352,6 +397,7 @@ subroutine get_arguments(input, input_format, config, method, inp, echo, error)
352397
input_format = get_filetype("."//arg)
353398
case("--json")
354399
config%json = .true.
400+
config%json_output = "dftd3.json"
355401
iarg = iarg + 1
356402
call get_argument(iarg, arg)
357403
if (allocated(arg)) then
@@ -360,13 +406,13 @@ subroutine get_arguments(input, input_format, config, method, inp, echo, error)
360406
cycle
361407
end if
362408
call move_alloc(arg, config%json_output)
363-
else
364-
config%json_output = "dftd3.json"
365409
end if
366410
case("--property")
367411
config%properties = .true.
368412
case("--noedisp")
369413
config%tmer = .false.
414+
case("--nowrap")
415+
config%wrap = .false.
370416
case("--grad")
371417
config%grad = .true.
372418
case("--atm")
@@ -377,6 +423,15 @@ subroutine get_arguments(input, input_format, config, method, inp, echo, error)
377423
call get_argument_as_real(iarg, inp%s9, error)
378424
if (allocated(error)) exit
379425
config%atm = .true.
426+
case("--zero")
427+
config%zero = .true.
428+
iarg = iarg + 1
429+
call get_argument(iarg, arg)
430+
if (.not.allocated(arg)) then
431+
call fatal_error(error, "Missing argument for method")
432+
exit
433+
end if
434+
call move_alloc(arg, method)
380435
case("--zero-param")
381436
config%zero = .true.
382437
config%has_param = .true.
@@ -389,6 +444,15 @@ subroutine get_arguments(input, input_format, config, method, inp, echo, error)
389444
iarg = iarg + 1
390445
call get_argument_as_real(iarg, inp%rs6, error)
391446
if (allocated(error)) exit
447+
case("--bj")
448+
config%rational = .true.
449+
iarg = iarg + 1
450+
call get_argument(iarg, arg)
451+
if (.not.allocated(arg)) then
452+
call fatal_error(error, "Missing argument for method")
453+
exit
454+
end if
455+
call move_alloc(arg, method)
392456
case("--bj-param")
393457
config%rational = .true.
394458
config%has_param = .true.
@@ -404,16 +468,9 @@ subroutine get_arguments(input, input_format, config, method, inp, echo, error)
404468
iarg = iarg + 1
405469
call get_argument_as_real(iarg, inp%a2, error)
406470
if (allocated(error)) exit
407-
case("--func")
408-
iarg = iarg + 1
409-
call get_argument(iarg, arg)
410-
if (.not.allocated(arg)) then
411-
call fatal_error(error, "Missing argument for method")
412-
exit
413-
end if
414-
call move_alloc(arg, method)
415471
end select
416472
end do
473+
if (allocated(error)) return
417474

418475
if (.not.config%has_param .and. .not.allocated(method)) then
419476
config%properties = .true.

app/meson.build

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,12 @@ sdftd3_exe = executable(
2020
dependencies: sdftd3_dep,
2121
install: install,
2222
)
23+
24+
if os != 'windows'
25+
test('app-version', sdftd3_exe, args: '--version')
26+
test('app-help', sdftd3_exe, args: '--help')
27+
test('app-noargs', sdftd3_exe, should_fail: true)
28+
test('app-example', sdftd3_exe, args: files('example.xyz'))
29+
test('app-zero', sdftd3_exe, args: ['--json', '--zero-param', '1.0', '1.868', '1.613', files('example.xyz')])
30+
test('app-rational', sdftd3_exe, args: ['--bj-param', '1.0', '1.2576', '0.3768', '4.5865', files('example.xyz')])
31+
endif

config/meson.build

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ endif
2525

2626
fc = meson.get_compiler('fortran')
2727
fc_id = fc.get_id()
28+
if has_cc and not get_option('python')
29+
has_cc = fc_id == meson.get_compiler('c').get_id()
30+
endif
2831

2932
if fc_id == 'gcc'
3033
add_project_arguments(
@@ -46,6 +49,11 @@ elif fc_id == 'pgi'
4649
)
4750
endif
4851

52+
if get_option('openmp')
53+
omp_dep = dependency('OpenMP')
54+
lib_deps += omp_dep
55+
endif
56+
4957
# Create the tool chain library as subproject
5058
mctc_prj = subproject(
5159
'mctc-lib',

0 commit comments

Comments
 (0)