|
| 1 | +Fortran API |
| 2 | +=========== |
| 3 | + |
| 4 | +The *s-dftd3* library seamlessly integrates with other Fortran projects via module interfaces, |
| 5 | + |
| 6 | +.. note:: |
| 7 | + |
| 8 | + Generally, all quantities used in the library are stored in `atomic units <https://en.wikipedia.org/wiki/Hartree_atomic_units>`_. |
| 9 | + |
| 10 | +.. contents:: |
| 11 | + |
| 12 | + |
| 13 | +Handling of geometries and structure |
| 14 | +------------------------------------ |
| 15 | + |
| 16 | +The basic infrastructure to handle molecular and periodic structures is provided by the `modular computation tool chain library <https://github.com/grimme-lab/mctc-lib>`_. |
| 17 | +The library provides a structure type which is used to represent all geometry related informations in *s-dftd3*. |
| 18 | +A structure type can be constructed from arrays or read from a file. |
| 19 | + |
| 20 | +The constructor is provided with the generic interface ``new`` and takes an array of atomic numbers (``integer``) or element symbols (``character(len=*)``) as well as the cartesian coordinates in Bohr. |
| 21 | +Additionally, the molecular charge and the number of unpaired electrons can be provided the ``charge`` and ``uhf`` keyword, respectively. |
| 22 | +To create a periodic structure the lattice parameters can be passed as 3 by 3 matrix with the ``lattice`` keyword. |
| 23 | + |
| 24 | +An example for using the constructor is given here |
| 25 | + |
| 26 | +.. code-block:: fortran |
| 27 | +
|
| 28 | + subroutine example |
| 29 | + use mctc_env, only : wp |
| 30 | + use mctc_io, only : structure_type, new |
| 31 | + implicit none |
| 32 | + type(structure_type) :: mol |
| 33 | + real(wp), allocatable :: xyz(:, :) |
| 34 | + integer, allocatable :: num(:) |
| 35 | +
|
| 36 | + num = [6, 1, 1, 1, 1] |
| 37 | + xyz = reshape([ & |
| 38 | + & 0.00000000000000_wp, -0.00000000000000_wp, 0.00000000000000_wp, & |
| 39 | + & -1.19220800552211_wp, 1.19220800552211_wp, 1.19220800552211_wp, & |
| 40 | + & 1.19220800552211_wp, -1.19220800552211_wp, 1.19220800552211_wp, & |
| 41 | + & -1.19220800552211_wp, -1.19220800552211_wp, -1.19220800552211_wp, & |
| 42 | + & 1.19220800552211_wp, 1.19220800552211_wp, -1.19220800552211_wp],& |
| 43 | + & [3, size(num)]) |
| 44 | +
|
| 45 | + call new(mol, num, xyz, charge=0.0_wp, uhf=0) |
| 46 | +
|
| 47 | + ! ... |
| 48 | + end subroutine example |
| 49 | +
|
| 50 | +
|
| 51 | +To interact with common input file formats for structures the ``read_structure`` procedure is available. |
| 52 | +The file type is inferred from the name of the file automatically or if a file type hint is provided directly from the enumerator of available file types. |
| 53 | +The ``read_structure`` routine can also use an already opened unit, but in this case the file type hint is mandatory to select the correct format to read from. |
| 54 | + |
| 55 | +.. code-block:: fortran |
| 56 | +
|
| 57 | + subroutine example |
| 58 | + use mctc_env, only : error_type |
| 59 | + use mctc_io, only : structure_type, read_structure, file_type |
| 60 | + implicit none |
| 61 | + type(structure_type) :: mol |
| 62 | + type(error_type), allocatable :: error |
| 63 | + character(len=:), allocatable :: input |
| 64 | +
|
| 65 | + input = "struc.xyz" |
| 66 | +
|
| 67 | + call read_structure(mol, input, error, file_type%xyz) |
| 68 | + if (allocated(error)) then |
| 69 | + print '(a)', error%message |
| 70 | + stop 1 |
| 71 | + end if |
| 72 | +
|
| 73 | + ! ... |
| 74 | + end subroutine example |
| 75 | +
|
| 76 | +
|
| 77 | +The structure type as well as the error type are using only allocatable members and can therefore be used without requiring explicit deconstruction. |
| 78 | + |
| 79 | +Certain members of the structure type should be considered immutable, like the number of atoms (``nat``), the identifiers for unique atoms (``id``) and the boundary conditions (``periodic``). |
| 80 | +To change those specific structure parameters the structure type and all dependent objects should be reconstructed to ensure a consistent setup. |
| 81 | +Other properties, like the geometry (``xyz``), molecular charge (``charge``), number of unpaired electrons (``uhf``) and lattice parameters (``lattice``) can be changed without requiring to reconstruct dependent objects like calculators or restart data. |
| 82 | + |
| 83 | + |
| 84 | +Error handling |
| 85 | +-------------- |
| 86 | + |
| 87 | +The basic error handler is an allocatable derived type, available from ``mctc_env`` as ``error_type``, which signals an error by its allocation status. |
| 88 | + |
| 89 | +.. code-block:: fortran |
| 90 | +
|
| 91 | + use mctc_env, only : error_type, fatal_error |
| 92 | + implicit none |
| 93 | + type(error_type), allocatable :: error |
| 94 | +
|
| 95 | + call always_ok(error) |
| 96 | + if (allocated(error)) then |
| 97 | + print '(a)', "Unexpected failure:", error%message |
| 98 | + end if |
| 99 | +
|
| 100 | + call always_failed(error) |
| 101 | + if (allocated(error)) then |
| 102 | + print '(a)', "Error:", error%message |
| 103 | + end if |
| 104 | +
|
| 105 | + contains |
| 106 | + subroutine always_ok(error) |
| 107 | + type(error_type), allocatable, intent(out) :: error |
| 108 | + end subroutine always_ok |
| 109 | +
|
| 110 | + subroutine always_failed(error) |
| 111 | + type(error_type), allocatable, intent(out) :: error |
| 112 | +
|
| 113 | + call fatal_error(error, "Message associated with this error") |
| 114 | + end subroutine always_failed |
| 115 | + end |
| 116 | +
|
| 117 | +An unhandled error might get dropped by the next procedure call. |
| 118 | + |
| 119 | + |
| 120 | +Performing calculations |
| 121 | +----------------------- |
| 122 | + |
| 123 | +An example for performing a calculation with DFT-D3(BJ)-ATM is shown below |
| 124 | + |
| 125 | +.. code-block:: fortran |
| 126 | +
|
| 127 | + subroutine calc_dftd3(mol, method, energy, gradient, sigma, error) |
| 128 | + use mctc_env |
| 129 | + use mctc_io |
| 130 | + use dftd3 |
| 131 | + type(structure_type), intent(in) :: mol |
| 132 | + character(len=*), intent(in) :: method |
| 133 | + real(wp), intent(out) :: energy |
| 134 | + real(wp), intent(out) :: gradient(:, :) |
| 135 | + real(wp), intent(out) :: sigma(:, :) |
| 136 | + type(error_type), allocatable, intent(out) :: error |
| 137 | + type(d3_model) :: disp |
| 138 | + type(d3_param) :: inp |
| 139 | + class(damping_param), allocatable :: param |
| 140 | +
|
| 141 | + call get_rational_damping(inp, method, error, s9=1.0_wp) |
| 142 | + if (allocated(error)) return |
| 143 | + call new_rational_damping(param, inp, mol) |
| 144 | +
|
| 145 | + call new_d3_model(disp, mol) |
| 146 | +
|
| 147 | + call get_dispersion(mol, disp, param, realspace_cutoff(), energy, & |
| 148 | + & gradient, sigma) |
| 149 | +
|
| 150 | + end subroutine calc_dftd3 |
0 commit comments