At first, you have to create the input for the code. DFTB+ accepts
either Human-readable Structured Data (HSD) or eXtended Markup
Language (XML) input. In this tutorial HSD will be used, and
in this case the input file must be called dftb_in.hsd. The
input file used in this howto looks as follows: (You can obtain this
file by downloading the provided tar.gz archive for this howto from
the howto overview page.)
Geometry = GenFormat {
3 C
O H
1 1 0.00000000000E+00 -0.10000000000E+01 0.00000000000E+00
2 2 0.00000000000E+00 0.00000000000E+00 0.78306400000E+00
3 2 0.00000000000E+00 0.00000000000E+00 -0.78306400000E+00
}
Driver = ConjugateGradient {
MovedAtoms = Range { 1 -1 }
MaxForceComponent = 1.0e-4
MaxSteps = 100
OutputPrefix = "geom.out"
}
Hamiltonian = DFTB {
SCC = Yes
SCCTolerance = 1.0e-5
MaxSCCIterations = 1000
Mixer = Broyden {
MixingParameter = 0.2
}
SlaterKosterFiles = {
O-O = "O-O.skf"
O-H = "O-H.skf"
H-O = "O-H.skf"
H-H = "H-H.skf"
}
MaxAngularMomentum = {
O = "p"
H = "s"
}
Charge = 0.0
SpinPolarisation = {}
Filling = Fermi {
Temperature [Kelvin] = 0.0
}
}
Options = {}
ParserOptions = {
ParserVersion = 3
}
The order of the specified properties in the HSD input is arbitrary. You are free to capitalise the keywords and physical units as you like, since they are case-insensitive. This is not valid, however, for string values, especially if they are specifying file names.
The Geometry property contains the types and coordiantes of the atoms in
your system. The geometry of the system in the sample input file is provided in
the so called "gen" format, which was the traditional geometry input format of
the DFTB method. The formal description of this format can be found in the
DFTB+ manual. The current example
Geometry = GenFormat {
3 C # Cluster with 3 atoms
O H # Two elements, 1 - O, 2 - H
# Index Type Coordinates
1 1 0.00000000000E+00 -0.10000000000E+01 0.00000000000E+00
2 2 0.00000000000E+00 0.00000000000E+00 0.78306400000E+00
3 2 0.00000000000E+00 0.00000000000E+00 -0.78306400000E+00
}
specifies a cluster system with 3 atoms of the type O and H. The
coordinates of the atoms in the "gen" format are given in Angstroms.
The first column of integers contains the sequential number of the
atoms in the sytem (ignored by the parser). The second column
contains the type of each atom, given as the position of the
appropriate element in the element list in the second line. The
GenFormat{} is not the only method to specify the geometry, you
should check the manual for other methods.
As demonstrated above, it is possible to put arbitrary comments in the
HSD input after a hashmark (#) character. Everything between the
hash and the end of the line is ignored by the parser.
Very often, the geometry is stored in an external file different from
dftb_in.hsd. To save you the copying and pasting from that file into the
input file, you can use the file inclusion feature of the HSD format:
Geometry = GenFormat {
<<< "input_geometry.gen"
}
The <<< operator includes the specified file as raw data. (The file is
not checked for any HSD constructs.) In the example above, the file
input_geometry.gen must be in gen format of course.
After having specified the geometry of your system, you should decide,
what to do with that geometry. The Driver property determines,
how the geometry should be changed (if at all) during the run. If you
only would like to make a static calculation, you must set it to an
empty value like
Driver = {} # Empty value for the driver
In the current example, however,
# Do conjugate gradient optimisation
Driver = ConjugateGradient {
MovedAtoms = Range { 1 -1 } # Move all atoms in the system
MaxForceComponent = 1.0e-4 # Stop if maximal force below 1.0e-4
MaxSteps = 100 # Stop after maximal 100 steps
OutputPrefix = "geom.out" # Final geometry in geom.out.{xyz,gen}
}
the molecule is relaxed using the conjugate gradient method. The
entire range of atoms from the first (1) until and including the last
one (-1) is allowed to move. Instead of Range { 1 -1 } you
could also have written
MovedAtoms = Range { 1 3 } # Atoms from the 1st until the 3rd
or
MovedAtoms = { 1 2 3 } # Explicitely listing the atoms to move
In our case the geometry optimisation continues as long as the maximal force component is bigger than 1e-4 atomic units (Hartree/Bohr). Numeric values are per default interpreted in atomic units. The HSD format offers, however, the possibility to use alternative units by specifying the unit (modifier) of the value in square brackets before the equal sign. For example instead of the original specification, you could have used
MaxForceComponent [eV/AA] = 5.14e-3 # Force in Electronvolt/Angstromor
MaxForceComponent [Electronvolt/Angstrom] = 5.14e-3
The MaxSteps property specifies, after how many geometry
optimisation steps the program should stop, even if the specified tolerance
for the maximal force component could not reached.
Finally, the OutputPrefix property specifies the name of the
file containing the actual geometry during the optimisation (end the
final geometry at the end of the calculation). The geometry is written
in gen and xyz formats to the files obtained by appending ".gen" and
".xyz" suffixes to the specified name (geom.out.gen and
geom.out.xyz in our case).
In order to calculate the various properties of your system, you have to decide upon the way how the Hamiltonian for your system should be built. At the moment DFTB+ eases the decision quite a lot, since it only supports a Density Functional based Tight Binding Hamiltonian (with some extensions). In our example, the chosen self-consistent DFTB Hamiltonian has the following properties:
Hamiltonian = DFTB { # DFTB Hamiltonian
SCC = Yes # Use self consistent charges
SCCTolerance = 1.0e-5 # Tolerance for charge consistence
MaxSCCIterations = 1000 # Nr. of maximal SCC iterations
Mixer = Broyden { # Broyden mixer for charge mixing
MixingParameter = 0.2 # Mixing parameter
}
SlaterKosterFiles = { # Specifying Slater-Koster files
O-O = "O-O.skf"
O-H = "O-H.skf"
H-O = "O-H.skf"
H-H = "H-H.skf"
}
MaxAngularMomentum = { # Maximal l-value of the various species
O = "p"
H = "s"
}
Charge = 0.0 # System neutral
SpinPolarisation = {} # No spin polarisation
Filling = Fermi { # No temperature
Temperature [Kelvin] = 0.0
}
}
In this example the SCC-DFTB method is used for building up the
Hamiltonian (and calculating the total energy, forces, etc.). The
charges are considered to be converged if the difference between the
charges using to build the Hamiltonian and the charges obtained after
the diagonalisation of the Hamiltonian is below 1e-5. If the
convergence is not reached within the specified number of cycles
(MaxSCCIterations), the code calculates the total energy using
the charges obtained so far. (Appropriate warning messages are printed
out.)
In order to damp charge oscillations and to speed up convergence, the
charges of the subsequent iterations are mixed together. The
Mixer property specifies the type of mixer to use. The mixers
usually requires further properties, like the mixing factor for the
Broyden mixer above.
The integral tables (together with other atomic and diatomic parameters) necessary for the build up of the Hamiltonian are stored in the so called Slater-Koster files. Those files always describe the interaction between atom pairs. Therefore, you have to specify for every atom pair the corresponding Slater-Koster file.
SlaterKosterFiles = { # Specifying Slater-Koster files
O-O = "O-O.skf"
O-H = "O-H.skf"
H-O = "O-H.skf"
H-H = "H-H.skf"
}
If you are using a certain file name convention, you can avoid typing all the file names by specifying only the generating pattern. The input
SlaterKosterFiles = Type2FileNames { # File names with two atom type names
Prefix = "" # No prefix before first type name
Separator = "-" # Dash between type names
Suffix = ".skf" # Suffix after second type name
}
would generate exactly the same file names as in the example above. If
the Slater-Koster files are in a different directory as the input file
dftb_in.hsd, you can append the path as prefix:
SlaterKosterFiles = Type2FileNames { # File names from two atom type names
Prefix = "/home/aradi/slako/mio-0-1" # Path as prefix
Separator = "-" # Dash between type names
Suffix = ".skf" # Suffix after second type name
}
The historical Slater-Koster file format does not contain any
information about the orbitals, which were considered when generating
the interaction tables. Therefore, you must provide the highest
angular momentum for every element as s, p, d or
f. This information can be obtained from the documentation of
the Slater-Koster files. In the distributed standardised sets (as
distributed on dftb.org) this
information is contained in the documentation appended to the end of each
SK-file.
The charge of the system (Charge) can be specified as real
number. It's the real total charge of your system, so that negative numbers
mean excess electrons in the system.
For the spin polarisation you have to specify the type of the spin polarisation to use. If you don't need spin polarisation, you should assign the empty value to it:
SpinPolarisation = {}
If you wanted to make a spin polarised calculation with colinear
spins, you should write something like
SpinPolarisation = Colinear {
UnpairedElectrons = 2.0 # Magnitude of the spin polarisation
}
In that latter case you would also have to specify the spin coupling
constants in the SpinConstants property. (See the manual for details.)
Finally, the Filling property describes the method to use for
filling up the one electron levels with electrons. The filling
functions usually require further parameters (e.g the temperature).
The Options property contains a few global settings for the
code. In the current example, no options are specified, so that the
empty value is assigned to that property:
Options = {}
You could even leave out this line, since the default value for the
Options property is the empty value anyway.
This block contains options which are interpreted by the parser itself
and are not passed to the main program. The most important of those
options is the ParserVersion option, which tells the parser,
for which parser the current input file was created for. If this is
not the current parser but an older one, this allows backwards
compatibility.
The version number of the parser in the current DFTB+ code is always printed out at the program start. It is a good habit to set this value in your input files explicitely, like in our case
ParserVersion = 3It allows you namely to use your input file with the future versions of DFTB+ without adapting it by hand, if the input format changed in the new versions.