DFT Using Python
DFT Using Python
2 Introduction to DFT
2.1 Background . . . . . . . . . . . . . . . . . . . . . .
2.2 Exchange correlation functionals . . . . . . . . . .
2.3 Basis sets . . . . . . . . . . . . . . . . . . . . . . .
2.4 Pseudopotentials . . . . . . . . . . . . . . . . . . .
2.5 Fermi Temperature and band occupation numbers
2.6 Spin polarization and magnetism . . . . . . . . . .
2.7 TODO Recommended reading . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3 Molecules
3.1 Defining and visualizing molecules . . . . . . . . . . . . .
3.1.1 From scratch . . . . . . . . . . . . . . . . . . . . .
3.1.2 Reading other data formats into a calculation . . .
3.1.3 Predefined molecules . . . . . . . . . . . . . . . . .
3.1.4 Combining Atoms objects . . . . . . . . . . . . . .
3.2 Simple properties . . . . . . . . . . . . . . . . . . . . . . .
3.2.1 Getting cartesian positions . . . . . . . . . . . . .
3.2.2 Molecular weight and molecular formula . . . . . .
3.2.3 Center of mass . . . . . . . . . . . . . . . . . . . .
3.2.4 Moments of inertia . . . . . . . . . . . . . . . . . .
3.2.5 Computing bond lengths and angles . . . . . . . .
3.3 Simple properties that require single computations . . . .
3.3.1 Energy and forces . . . . . . . . . . . . . . . . . .
3.3.2 Visualizing electron density . . . . . . . . . . . . .
3.3.3 Dipole moments . . . . . . . . . . . . . . . . . . .
3.3.4 The density of states (DOS) . . . . . . . . . . . . .
3.3.5 Atom-projected density of states on molecules . . .
3.3.6 Electrostatic potential . . . . . . . . . . . . . . . .
3.3.7 Bader analysis . . . . . . . . . . . . . . . . . . . .
3.4 Geometry optimization . . . . . . . . . . . . . . . . . . . .
3.4.1 Manual determination of a bond length . . . . . .
3.4.2 Automatic geometry optimization with VASP . . .
3.4.3 Relaxation of a water molecule . . . . . . . . . . .
3.5 Vibrational frequencies . . . . . . . . . . . . . . . . . . . .
3.5.1 Manual calculation of vibrational frequency . . . .
3.5.2 Automated vibrational calculations . . . . . . . . .
3.6 Simulated infrared spectra . . . . . . . . . . . . . . . . . .
3.7 Thermochemical properties of molecules . . . . . . . . . .
3.8 Molecular reaction energies . . . . . . . . . . . . . . . . .
3.8.1 O2 dissociation . . . . . . . . . . . . . . . . . . . .
3.8.2 Water gas shift example . . . . . . . . . . . . . . .
3.8.3 Temperature dependent water gas shift equilibrium
3.9 Molecular reaction barriers . . . . . . . . . . . . . . . . .
3.9.1 Get initial and final states . . . . . . . . . . . . . .
3.9.2 Run band calculation . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
8
9
9
10
11
11
12
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
constant
. . . . . .
. . . . . .
. . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
12
12
12
15
16
22
22
23
24
25
25
26
29
29
34
36
38
39
40
42
45
45
47
48
49
49
50
52
56
58
58
70
75
80
80
81
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4 Bulk systems
4.1 Defining and visualizing bulk systems . . . . . . . . . . . . . . . . . . . . . . .
4.1.1 Built-in functions in ase . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.2 Using http://materialsproject.org . . . . . . . . . . . . . . . . . . .
4.2 Computational parameters that are important for bulk structures . . . . . . . .
4.2.1 k-point convergence . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.2 Effect of SIGMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.3 The number of bands . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3 Determining bulk structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3.1 fcc/bcc crystal structures . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3.2 Optimizing the hcp lattice constant . . . . . . . . . . . . . . . . . . . .
4.3.3 Complex structures with internal degrees of freedom . . . . . . . . . . .
4.3.4 Effect of XC on bulk properties . . . . . . . . . . . . . . . . . . . . . . .
4.4 Cohesive energy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.5 TODO Elastic properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.5.1 Al elastic properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.5.2 Fe elastic properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.6 Bulk thermodynamics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.7 Effect of pressure on phase stability . . . . . . . . . . . . . . . . . . . . . . . .
4.8 Bulk reaction energies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.8.1 Alloy formation energies . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.8.2 Metal oxide oxidation energies . . . . . . . . . . . . . . . . . . . . . . .
4.9 Bulk density of states . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.10 Atom projected density of states . . . . . . . . . . . . . . . . . . . . . . . . . .
4.10.1 Effect of RWIGS on ADOS . . . . . . . . . . . . . . . . . . . . . . . . .
4.11 Band structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.11.1 create example showing band dispersion with change in lattice constant
4.12 Magnetism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.12.1 Determining if a magnetic solution is energetically favorable . . . . . . .
4.12.2 Antiferromagnetic spin states . . . . . . . . . . . . . . . . . . . . . . . .
4.12.3 TODO NiO-FeO formation energies with magnetism . . . . . . . . . . .
4.13 TODO phonons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.14 TODO solid state NEB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
82
82
82
87
90
90
91
92
96
96
99
100
105
107
109
109
110
112
113
116
116
121
125
127
129
131
134
135
135
136
136
136
136
5 Surfaces
5.1 Surface structures . . . . . . . . . . . . . . . . . . .
5.1.1 Simple surfaces . . . . . . . . . . . . . . . . .
5.1.2 Vicinal surfaces . . . . . . . . . . . . . . . . .
5.2 Surface calculation parameters . . . . . . . . . . . .
5.3 Surface relaxation . . . . . . . . . . . . . . . . . . .
5.4 Surface reconstruction . . . . . . . . . . . . . . . . .
5.4.1 Au(110) missing row reconstruction . . . . .
5.4.2 Ag(110) missing row reconstruction . . . . .
5.4.3 Cu(110) missing row reconstruction . . . . .
5.5 Work function . . . . . . . . . . . . . . . . . . . . . .
5.6 Surface energy . . . . . . . . . . . . . . . . . . . . .
5.6.1 Advanced topics in surface energy . . . . . .
5.7 Dipole correction . . . . . . . . . . . . . . . . . . . .
5.7.1 Slab with no dipole correction . . . . . . . . .
5.7.2 Slab with a dipole correction . . . . . . . . .
5.7.3 Comparing no dipole correction with a dipole
5.8 Adsorption energies . . . . . . . . . . . . . . . . . . .
5.8.1 Simple estimate of the adsorption energy . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
154
154
154
155
158
158
162
162
164
166
167
168
170
170
170
170
171
172
172
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
correction
. . . . . .
. . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5.9
5.10
5.11
5.12
5.13
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
181
183
184
186
186
186
187
188
188
188
189
6 Atomistic thermodynamics
199
6.1 Bulk phase stability of oxides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
6.2 Effect on adsorption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
6.3 Atomistic therodynamics and multiple reactions . . . . . . . . . . . . . . . . . . . . . . . . 207
7 Advanced electronic structure methods
7.1 DFT+U . . . . . . . . . . . . . . . . . . . . . . . . .
7.1.1 Metal oxide oxidation energies with DFT+U
7.2 Hybrid functionals . . . . . . . . . . . . . . . . . . .
7.2.1 FCC Ni DOS . . . . . . . . . . . . . . . . . .
7.3 TODO DFT+D . . . . . . . . . . . . . . . . . . . .
7.3.1 PBE . . . . . . . . . . . . . . . . . . . . . . .
7.3.2 DFT-D2 . . . . . . . . . . . . . . . . . . . . .
7.3.3 Advanced vdW-DF functionals . . . . . . . .
7.4 ELF . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.5 TODO Charge partitioning schemes . . . . . . . . .
7.6 TODO Modeling Core level shifts . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
8 Acknowledgments
208
208
208
212
212
213
214
215
216
216
217
217
220
9 Appendices
9.1 Recipes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.1.1 Modifying Atoms by deleting atoms . . . . . . . . . . . . .
9.1.2 Advanced tagging . . . . . . . . . . . . . . . . . . . . . . .
9.1.3 Using units in ase . . . . . . . . . . . . . . . . . . . . . . .
9.1.4 Extracting parts of an array . . . . . . . . . . . . . . . . . .
9.1.5 Statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.1.6 Curve fitting . . . . . . . . . . . . . . . . . . . . . . . . . .
9.1.7 Nonlinear curve fitting . . . . . . . . . . . . . . . . . . . . .
9.1.8 Nonlinear curve fitting by direct least squares minimization
9.1.9 Nonlinear curve fitting with confidence intervals . . . . . .
9.1.10 Interpolation with splines . . . . . . . . . . . . . . . . . . .
9.1.11 Interpolation in 3D . . . . . . . . . . . . . . . . . . . . . . .
9.1.12 Reading and writing data . . . . . . . . . . . . . . . . . . .
9.1.13 Integration . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.1.14 Numerical differentiation . . . . . . . . . . . . . . . . . . .
9.1.15 NetCDF files . . . . . . . . . . . . . . . . . . . . . . . . . .
9.1.16 Python modules . . . . . . . . . . . . . . . . . . . . . . . .
9.1.17 Writing and reading Excel files . . . . . . . . . . . . . . . .
9.1.18 TODO making movies . . . . . . . . . . . . . . . . . . . . .
9.2 Computational geometry . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
220
220
220
220
222
223
224
225
226
227
228
230
231
235
237
238
242
243
244
244
245
9.3
9.4
10 Python
268
10.1 easy_install as a user . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
10.2 pip as a user . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
10.3 Integer division math gotchas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
11 References
269
276
13 Index
285
This book serves two purposes: 1) to provide worked examples of using DFT to model materials properties, and 2) to provide references to more advanced treatments of these topics in the literature. It is
not a definitive reference on density functional theory. Along the way to learning how to perform the
calculations, you will learn how to analyze the data, make plots, and how to interpret the results. This
book is very much "recipe" oriented, with the intention of giving you enough information and knowledge
to start your research. In that sense, many of the computations are not publication quality with respect
to convergence of calculation parameters.
You will read a lot of python code in this book, as the comprehension of code is an integral part of
its design. I believe that computational work should always be scripted. As a result, a written record of
everything you have done will be available, allowing you to reproduce your code or report the method
of its execution exactly at a later time.
This book makes heavy use of many computational tools including:
Python
Module index
Atomic Simulation Environment (ase)
numpy
scipy
matplotlib
emacs
org-mode This book is written in org-mode, and is best read in emacs in org-mode. This
format provides clickable links, easy navigation, syntax highlighting, as well as the ability to
interact with the tables and code. The book is also available in PDF.
git This book is available at https://github.com/jkitchin/dft-book
jasp
mod:jasp is a sophisticated wrapper to the mod:ase.calculators.vasp python interface to the VASP calculator. It was written by me to facilitate writing this book and to develop the best possible way to
run DFT calculations. The best way to learn to use jasp is from this book. It probably requires the
latest svn version of ase to work since I have been adding new functionality to mod:ase.calculators.vasp
as mod:jasp is developed. mod:jasp is available at https://github.com/jkitchin/jasp.
The goal in writing mod:jasp was to create a computational environment where you write one script
to create, run and analyze your calculations. The code is smart, and submits jobs to a queue system
when required, does not submit jobs more than once, allows many jobs to run in parallel, and gives you
answers when available. mod:jasp takes care of changing into VASP calculation directories, and then
changing back to where you started from. mod:jasp has an interface to sqlite, and to version control
(git) software. mod:jasp has some features that mod:ase.calculators.vasp does not have yet. They may
get incorporated into ase one day.
jaspsum is a utility program provided in jasp which prints a pretty representation of the state of a
calculation, plots the relaxation trajectory, or prints a code representation of a VASP directory.
It is not critical that you use mod:jasp. You should be able to copy the actual VASP input files
(which were generated by jasp) from a directory and simply run vasp. mod:jasp is mostly compatible
with mod:ase.calculators.vasp, so you can replace this kind of code:
1
2
CWD = os.getcwd()
os.chdir(directory)
calc=Vasp(lotsofkeywords)
atoms.set_calculator(calc)
5
6
try:
#do stuff
finally:
os.chdir(CWD)
8
9
Introduction to DFT
A comprehensive overview of DFT is beyond the scope of this book, as excellent reviews on these subjects
are readily found in the literature, and are suggested reading in the following paragraph. Instead, this
chapter is intended to provide a useful starting point for a non-expert to begin learning about and using
DFT in the manner used in this book. Much of the information presented here is standard knowledge
among experts, but a consequence of this is that it is rarely discussed in current papers in the literature.
A secondary goal of this chapter is to provide new users with a path through the extensive literature
available and to point out potential difficulties and pitfalls in these calculations.
A modern and practical introduction to density functional theory can be found in Sholl and Steckel. 1
A fairly standard textbook on DFT is the one written by Parr and Yang. 2 The Chemists Guide to
DFT 3 is more readable and contains more practical information for running calculations, but both of
these books focus on molecular systems. The standard texts in solid state physics are by Kittel 4 and
Ashcroft and Mermin. 5 Both have their fine points, the former being more mathematically rigorous and
the latter more readable. However, neither of these books is particularly easy to relate to chemistry. For
this, one should consult the exceptionally clear writings of Roald Hoffman, 6,7 and follow these with the
work of Nrskov and coworkers. 8,9
In this chapter, only the elements of DFT that are relevant to this work will be discussed. An
excellent review on other implementations of DFT can be found in Reference 10 , and details on the
various algorithms used in DFT codes can be found in Refs. 11,12 .
One of the most useful sources of information has been the dissertations of other students, perhaps
because the difficulties they faced in learning the material are still fresh in their minds. Thomas Bligaard,
a coauthor of Dacapo, wrote a particularly relevant thesis on exchange/correlation functionals 13 and a
dissertation illustrating the use of DFT to design new alloys with desirable thermal and mechanical
properties. 14 The Ph.D. thesis of Ari Seitsonen contains several useful appendices on k-point setups,
and convergence tests of calculations, in addition to a thorough description of DFT and analysis of
calculation output. 15 Finally, another excellent overview of DFT and its applications to bimetallic alloy
phase diagrams and surface reactivity is presented in the PhD thesis of Robin Hirschl. 16
2.1
Background
In 1926, Erwin Schr\"odinger published the first accounts of his now famous wave equation. 17 He later
shared the Nobel prize with Paul A. M. Dirac in 1933 for this discovery. Schr\"odingers wave function
seemed extremely promising, as it contains all of the information available about a system. Unfortunately,
most practical systems of interest consist of many interacting electrons, and the effort required to find
solutions to Schr\"odingers equation increases exponentially with the number of electrons, limiting this
approach to systems with a small number of relevant electrons, N . O(10). 18 Even if this rough estimate
is off by an order of magnitude, a system with 100 electrons is still very small, for example, two Ru atoms
if all the electrons are counted, or perhaps ten Pt atoms if only the valence electrons are counted. Thus,
the wave function method, which has been extremely successful in studying the properties of small
molecules, is unsuitable for studies of large, extended solids. Interestingly, this difficulty was recognized
by Dirac as early as 1929, when he wrote "The underlying physical laws necessary for the mathematical
theory of a large part of physics and the whole of chemistry are thus completely known, and the difficulty
is only that the application of these laws leads to equations much too complicated to be soluble.". 19
In 1964, Hohenberg and Kohn showed that the ground state total energy of a system of interacting
electrons is a unique functional of the electron density. 20 By definition, a function returns a number
when given a number. For example, in f (x) = x2 , f (x) is the function, and itR equals four when
x = 2. A functional returns a number when given a function. Thus, in g(f (x)) = 0 f (x)dx, g(f (x))
is the functional, and it is equal to two when f (x) = sin(x). Hohenberg and Kohn further identified
a variational principle that appeared to reduce the problem of finding the ground state energy of an
electron gas in an external potential (i.e., in the presence of ion cores) to that of the minimization of
a functional of the three-dimensional density function. Unfortunately, the definition of the functional
involved a set of 3N-dimensional trial wave functions.
In 1965, Kohn and Sham made a significant breakthrough when they showed that the problem of
many interacting electrons in an external potential can be mapped exactly to a set of noninteracting
electrons in an effective external potential. 21 This led to a set of self-consistent, single particle equations
known as the Kohn-Sham (KS) equations:
1
2
2 + veff (r) -_j _j (r)=0, (1)
with
v
R
R
R
P
_j$\epsilon$_j + Exc [n(r)]- vxc (r) n(r) dr -1 2 {{
2.2
The two main types of exchange/correlation functionals used in DFT are the local density approximation (LDA) and the generalized gradient approximation (GGA). In the LDA, the exchange-correlation
functional is defined for an electron in a uniform electron gas of density n. 21 It is exact for a uniform electron gas, and is anticipated to be a reasonable approximation for slowly varying densities. In molecules
and solids, however, the density tends to vary substantially in space. Despite this, the LDA has been
very successfully used in many systems. It tends to predict overbonding in both molecular and solid
systems, 23 and it tends to make semiconductor systems too metallic (the band gap problem). 24
The generalized gradient approximation includes corrections for gradients in the electron density,
and is often implemented as a corrective function of the LDA. The form of this corrective function, or
"exchange enhancement" function determines which functional it is, e.g. PBE, RPBE, revPBE, etc. 25
In this book the PBE GGA functional is used the most. N{}rskov and coworkers have found that the
RPBE functional gives superior chemisorption energies for atomic and molecular bonding to surfaces,
but that it gives worse bulk properties, such as lattice constants compared to experimental data. 25
Finally, there are increasingly new types of functionals in the literature. The so-called hybrid functionals, such as B3LYP, are more popular with gaussian basis sets (e.g. in Gaussian), but they are
presently inefficient with planewave basis sets. None of these other types of functionals were used in this
work. For more details see Chapter 6 in Ref. 3 and Thomas Bligaards thesis on exchange and correlation
functionals. 13
2.3
Basis sets
Briefly, VASP utilizes planewaves as the basis set to expand the Kohn-Sham orbitals. In a periodic solid,
one can use Blochs theorem to show that the wave function for an electron can be expressed as the
product of a planewave and a function with the periodicity of the lattice: 5
nk (r) = exp(ik r)unk (r)
(5)
where r is a position vector, and k is a so-called wave vector that will only have certain allowed values
defined by the size of the unit cell. Blochs theorem sets the stage for using planewaves as a basis set,
because it suggests a planewave character of the wave function. If the periodic function unk (r) is also
expanded in terms of planewaves determined by wave vectors of the reciprocal lattice vectors, G, then
the wave function can be expressed completely in terms of a sum of planewaves: 11
X
i (r) =
ci,k+G exp(i(k + G) r).
(6)
G
where ci,k+G are now coefficients that can be varied to determine the lowest energy solution. This
also converts Eq. (2.1) from an integral equation to a set of algebraic equations that can readily be
solved using matrix algebra.
In aperiodic systems, such as systems with even one defect, or randomly ordered alloys, there is
no periodic unit cell. Instead one must represent the portion of the system of interest in a supercell,
which is then subjected to the periodic boundary conditions so that a planewave basis set can be used.
It then becomes necessary to ensure the supercell is large enough to avoid interactions between the
defects in neighboring supercells. The case of the randomly ordered alloy is virtually hopeless as the
energy of different configurations will fluctuate statistically about an average value. These systems were
9
not considered in this work, and for more detailed discussions the reader is referred to Ref. 26 . Once a
supercell is chosen, however, Blochs theorem can be applied to the new artificially periodic system.
To get a perfect expansion, one needs an infinite number of planewaves. Luckily, the coefficients of
the planewaves must go to zero for high energy planewaves, otherwise the energy of the wave function
would go to infinity. This provides justification for truncating the planewave basis set above a cutoff
energy. Careful testing of the effect of the cutoff energy on the total energy can be done to determine
a suitable cutoff energy. The cutoff energy required to obtain a particular convergence precision is also
element dependent, shown in Table 1. It can also vary with the "softness" of the pseudopotential. Thus,
careful testing should be done to ensure the desired level of convergence of properties in different systems.
Table 1 refers to convergence of total energies. These energies are rarely considered directly, it is usually
differences in energy that are important. These tend to converge with the planewave cutoff energy much
more quickly than total energies, due to cancellations of convergence errors. In this work, 350 eV was
found to be suitable for the H adsorption calculations, but a cutoff energy of 450 eV was required for O
adsorption calculations.
Table 1: Planewave cutoff energies (in eV) required for different convergence precisions for different
elements.
Precision Low High
Mo
168
293
O
300
520
O_sv
1066 1847
Blochs theorem eliminates the need to calculate an infinite number of wave functions, because there
are only a finite number of electrons in the unit (super) cell. However, there are still an infinite number
of discrete k points that must be considered, and the energy of the unit cell is calculated as an integral
over these points. It turns out that wave functions at k points that are close together are similar, thus
an interpolation scheme can be used with a finite number of k points. This also converts the integral
used to determine the energy into a sum over the k points, which are suitably weighted to account for
the finite number of them. There will be errors in the total energy associated with the finite number of
k, but these can be reduced and tested for convergence by using higher k-point densities. An excellent
discussion of this for aperiodic systems can be found in Ref. 26 .
The most common schemes for generating k points are the Chadi-Cohen scheme, 27 and the MonkhorstPack scheme. 28 The use of these k point setups amounts to an expansion of the periodic function in
reciprocal space, which allows a straight-forward interpolation of the function between the points that is
more accurate than with other k point generation schemes. 28
2.4
Pseudopotentials
The core electrons of an atom are computationally expensive with planewave basis sets because they are
highly localized. This means that a very large number of planewaves are required to expand their wave
functions. Furthermore, the contributions of the core electrons to bonding compared to those of the
valence electrons is usually negligible. In fact, the primary role of the core electron wave functions is to
ensure proper orthogonality between the valence electrons and core states. Consequently, it is desirable
to replace the atomic potential due to the core electrons with a pseudopotential that has the same effect on the valence electrons. 29 There are essentially two kinds of pseudopotentials, norm-conserving soft
pseudopotentials 29 and Vanderbilt ultrasoft pseudopotentials. 30 In either case, the pseudopotential function is generated from an all-electron calculation of an atom in some reference state. In norm-conserving
pseudopotentials, the charge enclosed in the pseudopotential region is the same as that enclosed by the
same space in an all-electron calculation. In ultrasoft pseudopotentials, this requirement is relaxed and
charge augmentation functions are used to make up the difference. As its name implies, this allows a
"softer" pseudopotential to be generated, which means fewer planewaves are required to expand it.
The pseudopotentials are not unique, and calculated properties depend on them. However, there are
10
standard methods for ensuring the quality and transferability (to different chemical environments) of the
pseudopotentials. 31
TODO PAW description
VASP provides a database of PAW potentials. 32,33
2.5
At absolute zero, the occupancies of the bands of a system are well-defined step functions; all bands
up to the Fermi level are occupied, and all bands above the Fermi level are unoccupied. There is a
particular difficulty in the calculation of the electronic structures of metals compared to semiconductors
and molecules. In molecules and semiconductors, there is a clear energy gap between the occupied
states and unoccupied states. Thus, the occupancies are insensitive to changes in the energy that occur
during the self-consistency cycles. In metals, however, the density of states is continuous at the Fermi
level, and there are typically a substantial number of states that are close in energy to the Fermi level.
Consequently, small changes in the energy can dramatically change the occupation numbers, resulting in
instabilities that make it difficult to converge to the occupation step function. A related problem is that
the Brillouin zone integral (which in practice is performed as a sum over a finite number of k points)
that defines the band energy converges very slowly with the number of k points due to the discontinuity
in occupancies in a continuous distribution of states for metals. 12,34 The difficulty arises because the
temperature in most DFT calculations is at absolute zero. At higher temperatures, the DOS is smeared
across the Fermi level, resulting in a continuous occupation function over the distribution of states. A
finite-temperature version of DFT was developed, 35 which is the foundation on which one solution to this
problem is based. In this solution, the step function is replaced by a smoothly varying function such as
the Fermi-Dirac function at a small, but non-zero temperature. 12 The total energy is then extrapolated
back to absolute zero.
2.6
There are two final points that need to be discussed about these calculations, spin polarization and
dipole corrections. Spin polarization is important for systems that contain net spin. For example, iron,
cobalt and nickel are magnetic because they have more electrons with spin "up" than spin "down" (or
vice versa). Spin polarization must also be considered in atoms and molecules with unpaired electrons,
such as hydrogen and oxygen atoms, oxygen molecules and radicals. For example, there are two spin
configurations for an oxygen molecule, the singlet state with no unpaired electrons, and the triplet state
with two unpaired electrons. The oxygen triplet state is lower in energy than the oxygen singlet state,
and thus it corresponds to the ground state for an oxygen atom. A classically known problem involving
spin polarization is the dissociation of a hydrogen molecule. In this case, the molecule starts with no
net spin, but it dissociates into two atoms, each of which has an unpaired electron. See section 5.3.5 in
Reference 3 for more details on this.
In VASP, spin polarization is not considered by default; it must be turned on, and an initial guess
for the magnetic moment of each atom in the unit cell must be provided (typically about one Bohrmagneton per unpaired electron). For Fe, Co, and Ni, the experimental values are 2.22, 1.72, and 0.61
Bohr-magnetons, respectively 4 and are usually good initial guesses. See Reference 31 for a very thorough
discussion of the determination of the magnetic properties of these metals with DFT. For a hydrogen
atom, an initial guess of 1.0 Bohr-magnetons (corresponding to one unpaired electron) is usually good.
An oxygen atom has two unpaired electrons, thus an initial guess of 2.0 Bohr-magnetons should be used.
The spin-polarized solution is sensitive to the initial guess, and typically converges to the closest solution.
Thus, a magnetic initial guess usually must be provided to get a magnetic solution. Finally, unless an
adsorbate is on a magnetic metal surface, spin polarization typically does not need to be considered,
although the gas-phase reference state calculation may need to be done with spin-polarization.
The downside of including spin polarization is that it essentially doubles the calculation time.
11
2.7
Molecules
In this chapter we consider how to construct models of molecules, how to manipulate them, and how to
calculate many properties of molecules. For a nice comparison of VASP and Gaussian see 40 .
3.1
We start by learning how to define a molecule and visualize it. We will begin with defining molecules
from scratch, then reading molecules from data files, and finally using some built-in databases in ase.
3.1.1
From scratch
When there is no data file for the molecule you want, or no database to get it from, you have to define
your atoms geometry by hand. Here is how that is done for a CO molecule (Figure 1). We must define
the type and position of each atom, and the unit cell the atoms are in.
1
2
3
4
5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
b = 7.1
atoms = Atoms([Atom(C, [0., 0., 0.]),
Atom(O, [1.1, 0., 0.])],
cell=[[b, b, 0.],
[b, 0., b],
[0., b, b]])
10
11
12
13
14
13
3
4
5
6
7
8
9
b = 7.1
atoms = Atoms([Atom(C, [0., 0., 0.]),
Atom(O, [1.1, 0., 0.])],
cell=[[b, b, 0.],
[b, 0., b],
[0., b, b]])
10
11
12
13
14
14
15
===========
short name
===========
gpw
dacapo
nc
vnl
traj
bundle
gpaw-text
cube
xsf
dacapo-text
xyz
vasp
vasp_out
struct_out
abinit
v_sim
pdb
cif
aims
aims_out
vti
vts
vtu
tmol
tmol-gradient
exi
cfg
struct
dftb
cell
castep
geom
etsf.nc
gen
db
cmr
15
lammps
gro
===========
You can read XYZ file format to create mod:ase.Atoms objects. Here is what an XYZ file format
might look like:
#+include: molecules/isobutane.xyz
The first line is the number of atoms in the file. The second line is often a comment. What follows
is one line per atom with the symbol and Cartesian coordinates in . Note that the XYZ format does
not have unit cell information in it, so you will have to figure out a way to provide it. In this example,
we center the atoms in a box with vacuum on all sides (Figure 3).
1
2
3
4
5
atoms = read(molecules/isobutane.xyz)
atoms.center(vacuum=5)
write(images/isobutane-xyz.png, atoms, show_unit_cell=2)
Predefined molecules
mod:ase defines a number of molecular geometries in the mod:ase.data.molecules database. For example,
the database includes the molecules in the G2/97 database. 41 This database contains a broad set of
atoms and molecules for which good experimental data exists, making them useful for benchmarking
studies. See this site for the original files.
The coordinates for the atoms in the database are MP2(full)/6-31G(d) optimized geometries. Here
is a list of all the species available in mod:ase.data.g2. You may be interested in reading about some of
the other databases in mod:ase.data too.
1
2
3
4
5
CH3CH2OH
CH3NO2
CCH
Si2H6
BCl3
H2CCl2
CH3CH2OCH3
CH4
SiH2_s1A1d
H
C3H4_C3v
methylenecyclopropane
HCF3
CH3CH2O
SiH2_s3B1d
H2CCO
16
CH3COOH
CF3CN
CH3CH2NH2
O3
CH2_s1A1d
C3H9C
BF3
S2
H3CNH2
BeH
C2F4
F2O
HCCl3
AlF3
H2CF2
PH2
HF
C3H4_C2v
isobutane
CH3ONO
SH
CS2
CH3S
S
C2H6
HCN
bicyclobutane
N2H4
H2CCHF
CH3OCH3
CH3SiH3
OCHCHO
NO2
H2O2
CH3COF
C5H8
NF3
P2
O
C3H7Cl
CH3CHO
C2H2
H2
C4H4NH
cyclobutane
Li2
NaCl
SiH4
17
C2H5
ClO
NO
HCO
CH3COCH3
CO
CH3COCl
Si
N2
F2
CH2OCH2
SO
ClF3
B
C3H6_Cs
LiF
LiH
C2H6SO
Na2
NH3
ClNO
CH3SCH3
SiH3
AlCl3
C2H3
CH3CONH2
C3H4_D2d
CN
N
C3H8
Cl2
CO2
H2O
HCOOCH3
Li
CH3SH
C2H6NH
H2COH
SiO
C5H5N
C4H4O
NH2
C3H6_D3h
H2CO
NH
CCl4
ClF
CH2SCH2
CH
F
CH3Cl
CS
NCCN
Cl
CH3CO
butadiene
PF3
CF4
N2O
cyclobutene
Si2
trans-butane
SO2
CH2_s3B1d
Al
CH3CN
isobutene
COF2
CH3OH
PH3
O2
Be
C3H9N
CH3
C2H6CHOH
CH3O
P
OH
SiCl4
C3H7
CH2NHCH2
SiF4
OCS
SH2
CH3CH2Cl
HCOOH
2-butyne
HOCl
C
C4H4S
H2CCHCl
C2H4
C2Cl4
C6H6
H2CCHCN
CH3CH2OH
CH3NO2
CCH
Si2H6
BCl3
H2CCl2
CH3CH2OCH3
CH4
SiH2_s1A1d
H
C3H4_C3v
methylenecyclopropane
HCF3
CH3CH2O
SiH2_s3B1d
H2CCO
HF
C3H4_C2v
isobutane
CH3ONO
SH
CS2
CH3S
S
C2H6
HCN
bicyclobutane
N2H4
H2CCHF
CH3COOH
CF3CN
CH3CH2NH2
O3
CH2_s1A1d
C3H9C
BF3
S2
H3CNH2
BeH
C2F4
F2O
HCCl3
AlF3
H2CF2
PH2
NO2
H2O2
CH3COF
C5H8
NF3
P2
O
C3H7Cl
CH3CHO
C2H2
H2
C4H4NH
cyclobutane
18
HCl
Na
CH3CH2SH
C2H5
ClO
NO
HCO
CH3COCH3
CO
CH3COCl
Si
N2
F2
CH2OCH2
SO
ClF3
B
C3H6_Cs
LiF
LiH
C2H6SO
Na2
NH3
ClNO
CH3SCH3
CH3OCH3
CH3SiH3
OCHCHO
SiH3
AlCl3
C2H3
CH3CONH2
C3H4_D2d
CN
N
C3H8
Cl2
CO2
H2O
HCOOCH3
Li
CH3SH
C2H6NH
H2COH
SiO
C5H5N
C4H4O
NH2
C3H6_D3h
H2CO
Li2
NaCl
SiH4
NH
CCl4
ClF
CH2SCH2
CH
F
CH3Cl
CS
NCCN
Cl
CH3CO
butadiene
PF3
CF4
N2O
cyclobutene
Si2
trans-butane
SO2
CH2_s3B1d
Al
CH3CN
Some other databases include the mod:ase.data.s22 for weakly interacting dimers and complexes, and
mod:ase.data.extra_molecules which has a few extras like biphenyl and C60.
Here is an example of getting the geometry of an acetonitrile molecule and writing an image to a file.
Note that the default unit cell is a 1 1 1 cubic cell. That is too small to use if your calculator
uses periodic boundary conditions. We center the atoms in the unit cell and add vacuum on each side.
We will add 6 of vacuum on each side. In the write command we use the option show_unit_cell =2
to draw the unit cell boundaries. See Figure 4.
1
2
3
4
atoms = molecule(CH3CN)
5
6
7
8
9
atoms.center(vacuum=6)
print unit cell
print ---------
print atoms.get_cell()
10
11
0.
13.537479
0.
0.
]
0.
]
15.014576]]
It is possible to rotate the atoms with func:ase.io.write if you wanted to see pictures from another
angle. In the next example we rotate 45 degrees about the x-axis, then 45 degrees about the y-axis.
Note that this only affects the image, not the actual coordinates. See Figure 5.
19
1
2
3
4
atoms = molecule(CH3CN)
5
6
7
8
9
atoms.center(vacuum=6)
print unit cell
print ---------
print atoms.get_cell()
10
11
12
write(images/ch3cn-rotated.png, atoms,
show_unit_cell=2, rotation=45x,45y,0z)
0.
13.537479
0.
0.
]
]
20
0.
0.
15.014576]]
4
5
6
7
atoms = molecule(CH3CN)
atoms.center(vacuum=6)
p1 = atoms.get_positions()
8
9
10
11
12
13
14
15
16
17
21
18
19
20
diff = p2 - p1
for i, d in enumerate(diff):
print {0} {1}.format(i, d)
It is frequently useful to combine two Atoms objects, e.g. for computing reaction barriers, or other types
of interactions. In ase, we simply add two Atoms objects together. Here is an example of getting an
ammonia and oxygen molecule in the same unit cell. See Figure 7. We set the Atoms about three
apart using the func:ase.Atoms.translate function.
1
2
3
4
atoms1 = molecule(NH3)
5
6
7
atoms2 = molecule(O2)
atoms2.translate([3, 0, 0])
8
9
10
11
12
3.2
Simple properties
Simple properties do not require a DFT calculation. They are typically only functions of the atom types
and geometries.
22
Figure 7: Image featuring ammonia and oxygen molecule in one unit cell.
3.2.1
If you want the (x, y, z) coordinates of the atoms, use the func:ase.Atoms.get_positions. If you are
interested in the fractional coordinates, use func:ase.Atoms.get_scaled_positions.
1
2
3
atoms = molecule(C6H6)
# benzene
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# get
sym =
pos =
num =
19
20
atom_indices = range(len(atoms))
21
22
23
24
25
print
print # sym
at#
p_x
p_y
p_z
print -------------------------------------
for i, s, n, p in zip(atom_indices, sym, num, pos):
23
26
27
28
px, py, pz = p
print {0:3d}{1:>3s}{2:8d}{3:-8.2f}{4:-8.2f}{5:-8.2f}.format(i, s, n,
px, py, pz)
We can quickly compute the molecular weight of a molecule with this recipe. We use func:ase.Atoms.get_masses to get an array of the atomic masses of each atom in the Atoms object, and then just sum them
up.
1
2
3
4
atoms = molecule(C6H6)
masses = atoms.get_masses()
5
6
7
molecular_weight = masses.sum()
molecular_formula = atoms.get_chemical_formula(mode=reduce)
8
9
10
11
Note that the argument reduce=True for func:ase.Atoms.get_chemical_formula collects all the symbols to provide a molecular formula.
3.2.3
Center of mass
The center of mass is essentially the average position of the atoms, weighted by the mass of each
atom. Here is an example of getting the center of mass from an Atoms object using func:ase.Atoms.get_center_of_mass.
1
2
3
4
5
# ammonia
atoms = molecule(NH3)
6
7
# cartesian coordinates
8
9
10
11
12
13
14
15
16
17
18
19
20
21
0.00000000e+00
0.00000000e+00
0.00000000e+00
5.91843349e-08
5.91843349e-08
5.91843349e-08
4.75457009e-02]
4.75457009e-02]
4.75457009e-02]
You can see see that these centers of mass, which are calculated by different methods, are the same.
3.2.4
Moments of inertia
PN
The moment of inertia is a measure of resistance to changes in rotation. It is defined by I = i=1 mi ri2
where ri is the distance to an axis of rotation. There are typically three moments of inertia, although
some may be zero depending on symmetry, and others may be degenerate. There is a convenient function
to get the moments of inertia: func:ase.Atoms.get_moments_of_inertia. Here are several examples of
molecules with different types of symmetry.:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
atoms = molecule(C6H6)
print C6H6 moments of inertia:, atoms.get_moments_of_inertia()
print
15
25
16
17
18
19
20
21
22
23
24
25
26
27
28
0.
44.45384271
44.45384271]
37.97009644
3.19145621
unsymmetric rotors Ia != Ib != Ic
C3H7Cl moments of inertia: [ 19.41351508
37.97009837]
3.19145621]
213.18961963
223.16255537]
If you want to know the principle axes of rotation, we simply pass vectors=True to the function,
and it returns the moments of inertia and the principle axes.
1
2
3
4
5
6
atoms = molecule(CH3Cl)
moments, axes = atoms.get_moments_of_inertia(vectors=True)
print Moments = {0}.format(moments)
print axes = {0}.format(axes)
37.97009644
37.97009837]
This shows the first moment is about the z-axis, the second moment is about the y-axis, and the
third moment is about the x-axis.
3.2.5
A typical question we might ask is, "What is the structure of a molecule?" In other words, what
are the bond lengths, angles between bonds, and similar properties. The Atoms object contains an
func:ase.Atoms.get_distance method to make this easy. To calculate the distance between two atoms,
you have to specify their indices, remembering that the index starts at 0.
26
2
3
4
# ammonia
atoms = molecule(NH3)
5
6
7
8
9
10
11
12
13
these vectors as the difference in positions of two atoms. For example, here we compute the angle H-N-H
in an ammonia molecule. This is the angle between N-H1 and N-H2 . In the next example, we utilize
functions in mod:numpy to perform the calculations, specifically the func:numpy.arccos function, the
func:numpy.dot function, and func:numpy.linalg.norm functions.
1
2
3
4
# ammonia
atoms = molecule(NH3)
5
6
7
8
9
10
11
12
a = atoms.positions[0] - atoms.positions[1]
b = atoms.positions[0] - atoms.positions[2]
13
14
15
16
17
# in radians
18
19
27
5
6
4
5
atoms = molecule(C2H6)
6
7
8
9
10
11
12
13
28
3.3
There are many properties that only require a single DFT calculation to obtain the energy, forces, density
of states, electron denisty and electrostatic potential. This section describes some of these calculations
and their analysis.
3.3.1
Two of the most important quantities we are interested in are the total energy and the forces on the
atoms. To get these quantities, we have to define a calculator and attach it to an mod:ase.Atoms object
so that ase knows how to get the data. After defining the calculator a DFT calculation must be run.
Here is an example of getting the energy and forces from a CO molecule. The forces in this case are
very high, indicating that this geometry is not close to the ground state geometry. Note that the forces
are only along the x-axis, which is along the molecular axis. We will see how to minimize this force in
Manual determination and Automatic geometry optimization with VASP.
Note:
This is your first DFT calculation in the book! See ISMEAR, incar:SIGMA, incar:NBANDS, and incar:ENCUT to learn more about these VASP keywords.
1
2
3
4
5
6
7
8
9
10
11
29
12
13
14
15
16
17
18
nbands=6,
# number of bands
encut=350,
# planewave cutoff
ismear=1,
# Methfessel-Paxton smearing
sigma=0.01, # very small smearing factor for a molecule
atoms=co) as calc:
print energy = {0} eV.format(co.get_potential_energy())
print co.get_forces()
5
6
7
8
9
L = [4, 5, 6, 8, 10]
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if not ready:
import sys; sys.exit()
27
28
29
30
31
32
33
30
Figure 10: Total energy of a CO molecule as a function of the unit cell length.
2
3
L = [4, 5, 6, 8, 10]
4
5
6
7
for a in L:
with jasp(molecules/co-L-{0}.format(a)) as calc:
print {0} {1} seconds.format(a, calc.get_elapsed_time())
4
5
6
7
L = np.linspace(4, 10)
31
V = L**3
9
10
n = 1
11
12
13
# convert to atmospheres
14
15
plt.plot(V, P, label={0}K.format(T))
16
17
18
19
20
Figure 11: Ideal gas pressure dependence on temperature and unit cell volume.
Convergence of ENCUT The total energy and forces also depend on the computational parameters,
notably incar:ENCUT.
1
2
3
4
5
6
7
8
9
10
11
32
12
13
14
15
16
17
18
19
20
21
22
23
energies = []
ready = True
for en in ENCUTS:
with jasp(molecules/co-en-{0}.format(en),
encut=en,
xc=PBE,
atoms=atoms) as calc:
try:
energies.append(atoms.get_potential_energy())
except (VaspSubmitted, VaspQueued):
ready = False
24
25
26
if not ready:
import sys; sys.exit()
27
28
29
30
31
32
33
Elapsed
Elapsed
Elapsed
Elapsed
Elapsed
Elapsed
time
time
time
time
time
time
(sec):
(sec):
(sec):
(sec):
(sec):
(sec):
3.590
6.016
6.014
7.883
12.421
15.167
Although here the times do not seem that unreasonable, note we increased the time by a factor of
three by simply doubling ENCUT. If the first time was a week, this is a significant increase in time!
3.3.2
The electron density is a 3d quantity: for every (x, y, z) point, there is a charge density. That means we
need 4 numbers for each point: (x, y, z) and (x, y, z). Below we show an example (Figure 13) of plotting
the charge density, and we consider some issues we have to consider when visualizing volumetric data in
unit cells with periodic boundary conditions. We will use the results from a previous calculation.
#TODO does not work in canopy
1
2
3
4
from
from
from
from
jasp import *
enthought.mayavi.mlab import *
ase.data import vdw_radii
ase.data.colors import cpk_colors
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
a3],
a3],
a2]]
38
39
40
41
42
43
44
45
46
47
48
49
50
mlab.savefig(images/co-cd.png)
mlab.show()
34
Figure 13: Charge density of a CO molecule that is located at the origin. The electron density that is
outside the cell is wrapped around to the other corners.
If we take care to center the CO molecule in the unit cell, we get a nicer looking result.
TODO broken in canopy
1
2
3
4
5
from
from
from
from
from
jasp import *
enthought.mayavi import mlab
ase.data import vdw_radii
ase.data.colors import cpk_colors
ase import Atom, Atoms
6
7
8
9
10
11
atoms.center()
12
13
14
15
16
with jasp(molecules/co-centered,
encut=350,
xc=PBE,
atoms=atoms) as calc:
17
18
19
atoms = calc.get_atoms()
x, y, z, cd = calc.get_charge_density()
20
21
mlab.figure(bgcolor=(1, 1, 1))
22
23
24
25
35
atom.y,
atom.z,
scale_factor=vdw_radii[atom.number]/5.,
resolution=20,
# a tuple is required for the color
color=tuple(cpk_colors[atom.number]),
scale_mode=none)
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
a3],
a3],
a2]]
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
mlab.savefig(images/co-centered-cd.png)
mlab.show()
Dipole moments
The dipole moment is a vector describing the separation of electrical (negative) and nuclear (positive)
charge. The magnitude of this vector is the dipole moment, which has units of Coulomb-meter, or more
commonly Debye. The symmetry of a molecule determines if a molecule has a dipole moment or not.
Below we compute the dipole moment of CO. We must integrate the electron density to find the center
of electrical charge, and compute a sum over the nuclei to find the center of positive charge.
1
2
3
4
5
6
7
8
vcd = VaspChargeDensity()
9
10
11
cd = np.array(vcd.chg[0])
n0, n1, n2 = cd.shape
12
13
14
15
s0 = 1.0 / n0
s1 = 1.0 / n1
s2 = 1.0 / n2
16
17
18
19
X, Y, Z = np.mgrid[0.0:1.0:s0,
0.0:1.0:s1,
0.0:1.0:s2]
20
21
22
23
C = np.column_stack([X.ravel(),
Y.ravel(),
Z.ravel()])
36
Figure 14: Charge density of a CO molecule centered in the unit cell. Now the electron density is centered
in the unit cell.
24
25
26
27
atoms = calc.get_atoms()
uc = atoms.get_cell()
real = np.dot(C, uc)
28
29
30
31
32
#
x
y
z
33
34
35
36
nelements = n0 * n1 * n2
voxel_volume = atoms.get_volume() / nelements
total_electron_charge = -cd.sum() * voxel_volume
37
38
39
40
41
42
43
44
45
46
47
# now the ion charge center. We only need the Zval listed in the potcar
from jasp.POTCAR import get_ZVAL
48
49
50
LOP = calc.get_pseudopotentials()
ppp = os.environ[VASP_PP_PATH]
51
52
53
54
zval = {}
for sym, ppath, hash in LOP:
fullpath = os.path.join(ppp, ppath)
37
55
56
57
58
59
60
61
62
63
z = get_ZVAL(fullpath)
zval[sym] = z
ion_charge_center = np.array([0.0, 0.0, 0.0])
total_ion_charge = 0.0
for atom in atoms:
Z = zval[atom.symbol]
total_ion_charge += Z
pos = atom.position
ion_charge_center += Z*pos
64
65
66
ion_charge_center /= total_ion_charge
ion_dipole_moment = ion_charge_center * total_ion_charge
67
68
69
70
71
72
3
4
5
6
7
The density of states (DOS) gives you the number of electronic states (i.e., the orbitals) that have a
particular energy. We can get this information from the last calculation we just ran without having to
run another DFT calculation.
Warning:
One way that jasp is unintuitive is that whenever you are "inside" (indented) a with
statement, the current working directory may be different than where your script started.
In this example that can lead to your figure not being saved where you expect it to be
saved!
1
2
3
4
5
6
7
8
9
10
11
12
13
# make sure you save the figure outside the with statement, or provide
# the correct relative or absolute path to where you want it.
plt.savefig(images/co-dos.png)
Let us consider which states in the density of states belong to which atoms in a molecule. This can
only be a qualitative consideration because the orbitals on the atoms often hybridize to form molecular
orbitals, e.g. in methane the s and p orbitals can form what we call sp3 orbitals. We can compute
atom-projected density of states in VASP, which is done by projecting the wave function onto localized
atomic orbitals. Here is an example. We will consider the CO molecule. To get atom-projected density
of states, we must set RWIGS for each atom. This parameter defines the radius of the sphere around the
atom which cuts off the projection. The total density of states and projected density of states information
comes from the DOSCAR file.
Note that unlike the DOS, here we must run another calculation because we did not specify the
atom-projected keywords above. Our strategy is to get the atoms from the previous calculation, and use
them in a new calculation. You could redo the calculation in the same directory, but you risk losing the
results of the first step. That can make it difficult to reproduce a result. We advocate our approach of
using multiple directories for the subsequent calculations, because it leaves a clear trail of how the work
was done.
Note:
The RWIGS is not uniquely determined for an element. There are various natural choices,
e.g. the ionic radius of an atom, or a value that minimizes overlap of neighboring spheres,
but these values can change slightly in different environments.
You can also get spin-polarized atom-projected DOS, and magnetization projected DOS.
See http://cms.mpi.univie.ac.at/vasp/vasp/DOSCAR_file.html#doscar for more
details.
39
1
2
3
4
5
6
7
8
9
10
11
12
13
14
with jasp(molecules/co-ados,
encut=300,
xc=PBE,
rwigs=[1.0, 1.0],
# these are the cutoff radii for projected states
atoms=atoms) as calc:
calc.calculate()
15
16
17
18
19
20
21
ados = VaspDos(efermi=calc.get_fermi_level())
energies = ados.energy
22
23
24
25
26
27
28
c_s
c_p
o_s
o_p
=
=
=
=
ados.site_dos(0,
ados.site_dos(0,
ados.site_dos(1,
ados.site_dos(1,
s)
p)
s)
p)
29
30
31
c_d = ados.site_dos(0, d)
o_d = ados.site_dos(1, d)
32
33
34
35
36
37
38
39
40
41
42
43
Electrostatic potential
This is an example of the so-called hole in a halogen bond. The coordinates for the CF3 Br molecule
were found at http://cccbdb.nist.gov/exp2.asp?casno=75638.
TODO mlab does not work
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0.0000,
0.0000,
1.2455,
-0.6228,
-0.6228,
-0.8088]),
1.1146]),
-1.2651]),
-1.2651]),
-1.2651])],
16
17
18
19
20
21
with jasp(molecules/CF3Br,
encut=350,
xc=PBE,
ibrion=1,
nsw=50,
40
Figure 16: Atom-projected DOS for a CO molecule. The total density of states and the s, p and d states
on the C and O are shown.
22
23
24
25
26
lvtot=True,
lvhar=True,
atoms=atoms) as calc:
calc.set_nbands(f=2)
calc.calculate()
27
28
29
x, y, z, lp = calc.get_local_potential()
x, y, z, cd = calc.get_charge_density()
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
41
tube_radius=0.02,
colormap=Reds)
55
56
57
58
59
60
mlab.contour3d(x, y, z, lp)
mlab.savefig(images/halogen-ep.png)
mlab.show()
Figure 17: Plot of the electrostatic potential of CF3 Br. TODO: figure out how to do an isosurface of
charge, colormapped by the local potential.
See http://www.uni-due.de/~hp0058/?file=manual03.html&dir=vmdplugins for examples of using VMD for visualization.
3.3.7
Bader analysis
Bader analysis is a charge partitioning scheme where charge is divided by surfaces of zero flux that
define atomic basins of charge. The most modern way of calculating the Bader charges is using the
bader program from Graeme Henkelmens group. 42,43 Let us consider a water molecule, centered in a
box. The strategy is first to run the calculation, then run the bader program on the results.
1
2
3
4
5
6
with jasp(molecules/h2o-bader,
42
7
8
9
10
xc=PBE,
encut=350,
atoms=atoms) as calc:
calc.calculate()
11
12
0.74 SECONDS
26.40 SECONDS
43
RUN TIME:
1.29 SECONDS
5407
10
7.99999
3.96 SECONDS
cat ACF.dat
4
5
6
7
8
9
10
symbols = np.array(atoms.get_chemical_symbols())[calc.sort]
pos = atoms.positions[calc.sort] * Bohr
newatoms = Atoms(symbols, positions=pos, cell=atoms.get_cell())
11
12
attach_charges(newatoms, ACF.dat)
13
14
15
16
17
18
19
44
3.4
Geometry optimization
3.4.1
The equilibrium bond length of a CO molecule is approximately the bond length that minimizes the
total energy. We can find that by computing the total energy as a function of bond length, and noting
where the minimum is. Here is an example in VASP. There are a few features to point out here. We want
to compute 5 bond lengths, and each calculation is independent of all the others. mod:jasp is set up to
automatically handle jobs for you by submitting them to the queue. It raises a variety of exceptions to
let you know what has happened, and you must handle these to control the workflow. We will illustrate
this by the following examples.
1
2
3
4
5
6
7
8
for d in bond_lengths:
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
]
]]
45
d = 1.10 ang
energy = -14.720 eV
forces = (eV/ang)
[[-5.8 0.
0. ]
[ 5.8 0.
0. ]]
d = 1.15 ang
energy = -14.838 eV
forces = (eV/ang)
[[ 0.645 0.
0.
[-0.645 0.
0.
]
]]
d = 1.20 ang
energy = -14.688 eV
forces = (eV/ang)
[[ 5.095 0.
0.
[-5.095 0.
0.
]
]]
d = 1.25 ang
energy = -14.352 eV
forces = (eV/ang)
[[ 8.141 0.
0.
[-8.141 0.
0.
]
]]
To find the minimum we could run more calculations, but a simpler and faster way is to fit a
polynomial to the data, and find the analytical minimum. The results are shown in Figure 18.
1
2
3
4
5
6
7
8
9
for d in bond_lengths:
10
11
12
13
14
15
16
17
18
19
20
21
# we expect two roots from the quadratic eqn. These are where the
# first derivative is equal to zero.
roots = np.roots(dp)
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
plt.plot(bond_lengths, energies, bo )
plt.plot(x, fit, r-)
plt.plot(minV, minE, m* )
plt.legend([DFT, fit, minimum], numpoints=1)
46
40
41
42
43
3.4.2
It is generally the case that the equilibrium geometry of a system is the one that minimizes the total
energy and forces. Since each atom has three degrees of freedom, you can quickly get a high dimensional
optimization problem. Luckily, VASP has built-in geometry optimization using the IBRION and NSW tags.
Here we compute the bond length for a CO molecule, letting VASP do the geometry optimization for us.
Here are the most common choices for IBRION.
IBRION value
1
2
algorithm
quasi-Newton (use if initial guess is good)
conjugate gradient
47
Note:
VASP applies a criteria for stopping a geometry optimization. When the change in
energy between two steps is less than 0.001 eV (or 10*EDIFF), the relaxation is stopped.
This criteria is controlled by the incar:EDIFFG tag. If you prefer to stop based on forces,
set EDIFFG=-0.05, i.e. to a negative number. The units of force is eV/. For most
work, a force tolerance of 0.05 eV/ is usually sufficient.
1
2
3
4
5
6
co = Atoms([Atom(C,[0, 0, 0]),
Atom(O,[1.2, 0, 0])],
cell=(6, 6, 6))
7
8
9
10
11
12
13
14
15
16
with jasp(molecules/co-cg,
xc=PBE,
nbands=6,
encut=350,
ismear=1,
sigma=0.01, # this is small for a molecule
ibrion=2,
# conjugate gradient optimizer
nsw=5,
# do at least 5 steps to relax
atoms=co) as calc:
17
18
19
20
print Forces
print =======
print co.get_forces()
21
22
23
24
pos = co.get_positions()
d = ((pos[0] - pos[1])**2).sum()**0.5
print Bondlength = {0:1.2f} angstroms.format(d)
It is not more complicated to relax more atoms, it just may take longer because there are more electrons
and degrees of freedom. Here we relax a water molecule which has three atoms.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
with jasp(molecules/h2o_relax,
xc=PBE,
encut=400,
ismear=0, # Gaussian smearing
ibrion=2,
ediff=1e-8,
nsw=10,
atoms=atoms) as calc:
17
18
19
20
print "forces"
print =======
print atoms.get_forces()
0.
0.
0.
]
]
]]
48
3.5
Vibrational frequencies
3.5.1
The principle idea in calculating vibrational frequencies is that we consider a molecular system as masses
connected by springs. If the springs are Hookean, e.g. the force is proportional to the displacement, then
we can readily solve the equations of motion and find that the vibrational frequencies are related to the
force constants and the masses of the atoms. For example, in a simple molecule like CO where there is
only one spring,
the frequency is:
p
1
k/ where 1 = m1C + m1O and k is the spring constant. We will compute the value of k from
= 2
DFT calculations as follows:
2
k = xE2 at the equilibrium bond length. We actually already have the data to do this from Manual
determination. We only need to fit an equation to the energy vs. bond-length data, find the minimum
energy bond-length, and then evaluate the second derivative of the fitted function at the minimum. We
will use a cubic polynomial for demonstration here. Polynomials are numerically convenient because
they are easy to fit, and it is trivial to get the roots and derivatives of the polynomials, as well as to
evaluate them at other points using func:numpy.polyfit, func:numpy.polyder, and func:numpy.polyval.
1
2
3
4
5
6
7
8
9
10
for d in bond_lengths:
with jasp(molecules/co-{0}.format(d)) as calc:
atoms = calc.get_atoms()
energies.append(atoms.get_potential_energy())
11
12
13
14
15
16
17
18
19
20
21
# first derivative
dpars = np.polyder(pars)
# find where the minimum is. chose the second one because it is the
# minimum we need.
droots = np.roots(dpars)
22
23
24
# second derivative
ddpars = np.polyder(dpars)
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
3
4
nu = 2143.6076625*c
# 1/s
5
6
E_zpe = 0.5*h*nu
7
8
VASP has built-in capability for performing vibrational calculations. We access the capability by using a
new value for incar:IBRION. The values of 5 and 6 calculated the Hessian matrix using finite differences.
For IBRION=5, all atoms that are not constrained are displaced. For IBRION=6, only symmetry
inequivalent displacements are considered, which makes the calculations slightly cheaper. You can specify
the number of displacements with incar:NFREE. The default number of displacements is 2. You can
also specify the size of the displacement with incar:POTIM (the default is 0.015 ).
1
2
3
4
5
# <<water-vib>>
# adapted from http://cms.mpi.univie.ac.at/wiki/index.php/H2O_vibration
from ase import Atoms, Atom
from jasp import *
import ase.units
6
7
8
9
10
11
-0.7677068,
0.0000000,
0.7677068,
0.0000000]),
0.0000000]),
0.0000000])],
12
13
14
15
16
17
18
19
20
21
22
with jasp(molecules/h2o_vib,
xc=PBE,
encut=400,
ismear=0,
# Gaussian smearing
ibrion=6,
# finite differences with symmetry
nfree=2,
# central differences (default)
potim=0.015, # default as well
ediff=1e-8,
# for vibrations you need precise energies
nsw=1,
# Set to 1 for vibrational calculation
atoms=atoms) as calc:
23
24
25
26
print Forces
print ======
print atoms.get_forces()
50
27
28
29
30
31
32
print
# vibrational energies are in eV
energies, modes = calc.get_vibrational_modes()
print energies\n========
for i, e in enumerate(energies):
print {0:02d}: {1} eV.format(i, e)
eV
eV
eV
eV
Note we get 9 frequencies here. Water has 3 atoms, with three degrees of freedom each, leading to 9
possible combinations of collective motions. Three of those collective motions are translations, i.e. where
all atoms move in the same direction (either x, y or z) and there is no change in the total energy of
the molecule. Another three of those motions are rotations, which also do not change the total energy
of the molecule. That leaves 3N-6 = 3 degrees of vibrational freedom where some or all of the bonds
are stretched, resulting in a change in the total energy. The modes of water vibration are (with our
calculated values in parentheses):
1. a symmetric stretch at 3657 cm-1 (3723)
2. an asymmetric stretch at 3756 cm-1 (3836)
3. and a bending mode at 1595 cm-1 (1583)
http://webbook.nist.gov/cgi/cbook.cgi?ID=C7732185&Mask=800#Electronic-Spec
The results are not too far off, and more accurate frequencies may be possible using tighter tolerance
on POTIM, or by using IBRION=7 or 8.
Let us briefly discuss how to determine which vectors are vibrations and which are rotations or translations. One way is to visualize the modes. The vibrations are easy to spot. The rotations/translations
are not always cleanly separable. This is an issue of accuracy and convergence. We usually do not worry
about this because these modes are usually not important.
1. mode 0 is an asymmetric stretch
2. mode 1 is a symmetric stretch
3. mode 2 is a bending mode
4. mode 3 is a mixed translation/rotation
5. mode 4 is a rotation
51
6. mode 5 is a translation
7. mode 6 is a rotation
8. mode 7 is a partial translation
9. mode 8 is a rotation
1
2
3
4
5
6
# <<h2o-vib-vis>>
from jasp import *
import numpy as np
with jasp(molecules/h2o_vib) as calc:
energies, modes = calc.get_vibrational_modes(mode=3, massweighted=True,
show=True)
5
6
7
8
9
10
11
12
13
14
15
ZPE = 0.0
for f in freq:
if not isinstance(f, float):
continue # skip complex numbers
nu = f * c # convert to frequency
ZPE += 0.5 * h * nu
16
17
18
19
20
21
# one liner
ZPE = np.sum([0.5 * h * f * c for f in freq if isinstance(f, float)])
print The ZPE of water is {0:1.3f} eV.format(ZPE)
3.6
52
1
2
3
4
5
6
7
-0.7677068,
0.0000000,
0.7677068,
0.0000000]),
0.0000000]),
0.0000000])],
8
9
10
11
12
13
14
15
16
17
18
19
with jasp(molecules/h2o_relax,
xc=PBE,
encut=400,
ismear=0, # Gaussian smearing
ibrion=2,
ediff=1e-8,
nsw=10,
atoms=atoms) as calc:
print Forces
print ===========================
print atoms.get_forces()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
# A utility for calculating the vibrational intensities from VASP output (OUTCAR)
# (C) David Karhanek, 2011-03-25, ICIQ Tarragona, Spain (www.iciq.es)
4
5
6
7
8
9
10
11
53
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
54
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/bin/bash
# reformat intensities, just normal modes: 3N -> (3N-6)
printf "..reformatting and normalizing intensities"
cd intensities/results/
nlns=wc -l exact.res.txt | awk {print $1} ; let bodylns=nlns-6
head -n $bodylns exact.res.txt > temp.reform.res.txt
max=awk (NR==1){max=$3} $3>=max {max=$3} END {print max} temp.reform.res.txt
awk -v max="$max" {print $1,$2,$3/max} temp.reform.res.txt > exact.reform.res.txt
awk -v max="$max" {printf "%03u %6.1f %5.3f\n",$1,$2,$3/max} temp.reform.res.txt > reform.res.txt
printf " ..done\n..normal modes:\n"
rm temp.reform.res.txt
cat reform.res.txt
cd ../..
The interpretation of these results is that the mode at 3713 cm-1 would be nearly invisible in the
IR spectrum. Earlier we interpreted that as the symmetric stretch. In this mode, there is only a small
change in the molecule dipole moment, so there is a small IR intensity.
See also. 45 For HREELS simulations see. 46
The shell script above has been translated to a convenient python function in mod:jasp.
1
2
3
4
5
Relative intensity
0.227
0.006
0.312
1.000
0.006
0.000
0.005
0.000
0.345
3.7
mod:ase.thermochemistry can be used to estimate thermodynamic properties of gases in the ideal gas
limit. The module needs as input the geometry, the total energy, the vibrational energies, and some
information about the molecular symmetry. We first consider an N2 molecule.
The symmetry numbers are determined by the molecular point group. 47 Here is a table of the most
common ones.
Table 3: Symmetry numbers for common point groups
point group
examples
C1
1
Cs
1
C2
2
C2v
2 H2 O
C3v
3 NH3
Cv
1 CO
D2h
4
D3h
6
D5h
10
Dh
2 CO2 , H2
D3d
6
Td
12 CH4
Oh
24
1
2
3
4
5
atoms = molecule(N2)
56
atoms.set_cell((10,10,10), scale_atoms=False)
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# # now we can get some properties. Note we only need one vibrational
# energy since there is only one mode. This example does not work if
# you give all the energies because one energy is zero.
thermo = IdealGasThermo(vib_energies=vib_energies[0:0],
electronicenergy=electronicenergy, atoms=atoms,
geometry=linear, symmetrynumber=2, spin=0)
43
44
45
S_trans (1 atm)
0.0015579 eV/K
0.464 eV
S_rot
0.0007870 eV/K
0.235 eV
S_elec
0.0000000 eV/K
0.000 eV
S_vib
0.0000000 eV/K
0.000 eV
S (1 atm -> P)
-0.0000000 eV/K
-0.000 eV
------------------------------------------------S
0.0023449 eV/K
0.699 eV
=================================================
Free energy components at T = 298.15 K and P = 101325.0 Pa:
=======================
H
-16.388 eV
-T*S
-0.699 eV
----------------------G
-17.087 eV
=======================
Let us compare this to what is in the Nist webbook via the Shomate equations.
1
2
3
4
5
6
7
8
9
import numpy as np
A = 28.98641
B = 1.853978
C = -9.647459
D = 16.63537
E = 0.000117
F = -8.671914
G = 226.4168
H = 0.0
10
11
12
T = 298.15
t = T/1000.
13
14
15
3.8
3.8.1
The first reaction we consider is a simple dissociation of oxygen molecule into two oxygen atoms: O2
2O. The dissociation energy is pretty straightforward to define: it is the energy of the products minus
the energy of the reactant. D = 2 EO EO2 . It would appear that we simply calculate the energy of
an oxygen atom, and the energy of an oxygen molecule and evaluate the formula. Let us do that.
Simple estimate of O2 dissociation energy
1
2
3
4
5
6
7
8
with jasp(molecules/O,
xc=PBE,
58
encut=400,
ismear=0,
atoms=atoms) as calc:
9
10
11
12
try:
13
E_O = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O = None
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
with jasp(molecules/O2,
xc=PBE,
encut=400,
ismear=0,
ibrion=2,
nsw=10,
atoms=atoms) as calc:
try:
E_O2 = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O2 = None
33
34
35
D = 8.521 eV
The answer we have obtained is way too high! Experimentally the dissociation energy is about 5.2
eV (need reference), which is very different than what we calculated! Let us consider some factors that
contribute to this error.
We implicitly neglected spin-polarization in the example above. That could be a problem, since the
O2 molecule can be in one of two spin states, a singlet or a triplet, and these should have different
energies. Furthermore, the oxygen atom can be a singlet or a triplet, and these would have different
energies. To account for spin polarization, we have to tell VASP to use spin-polarization, and give initial
guesses for the magnetic moments of the atoms. Let us try again with spin polarization.
Estimating O2 dissociation energy with spin polarization in triplet ground states To tell
VASP to use spin-polarization we use ISPIN=2, and we set initial guesses for magnetic moments on
the atoms with the magmom keyword. In a triplet state there are two electrons with spins of the same
sign.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
with jasp(molecules/O-sp-triplet,
xc=PBE,
encut=400,
ismear=0,
ispin=2, # turn spin-polarization on
atoms=atoms) as calc:
try:
E_O = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O = None
17
18
19
20
21
22
23
59
24
25
26
27
28
29
30
31
32
33
34
35
36
with jasp(molecules/O2-sp-triplet,
xc=PBE,
encut=400,
ismear=0,
ispin=2,
# turn spin-polarization on
ibrion=2, # make sure we relax the geometry
nsw=10,
atoms=atoms) as calc:
try:
E_O2 = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O2 = None
37
38
39
40
41
42
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
4
5
6
7
8
D = []
for encut in encuts:
atoms = Atoms([Atom(O, [5, 5, 5], magmom=2)],
cell=(10, 10, 10))
9
10
11
12
13
14
15
16
17
18
19
with jasp(molecules/O-sp-triplet-{0}.format(encut),
xc=PBE,
encut=encut,
ismear=0,
ispin=2,
atoms=atoms) as calc:
try:
E_O = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O = None
20
21
22
23
61
24
25
with jasp(molecules/O2-sp-triplet-{0}.format(encut),
xc=PBE,
encut=encut,
ismear=0,
ispin=2,
# turn spin-polarization on
ibrion=2, # this turns relaxation on
nsw=10,
atoms=atoms) as calc:
try:
E_O2 = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O2 = None
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
D = {1:1.3f} eV.format(encut, d)
43
44
45
46
47
48
->
->
->
->
->
->
->
2O
2O
2O
2O
2O
2O
2O
encut
encut
encut
encut
encut
encut
encut
=
=
=
=
=
=
=
250
300
350
400
450
500
550
D
D
D
D
D
D
D
=
=
=
=
=
=
=
6.696
6.727
6.708
6.668
6.650
6.648
6.650
eV
eV
eV
eV
eV
eV
eV
Based on these results (Figure 20), you could argue the dissociation energy is converged to about 2
meV at a planewave cutoff of 450 eV, and within 50 meV at 350 eV cutoff. You have to decide what
an appropriate level of convergence is. Note that increasing the planewave cutoff significantly increases
the computational time, so you are balancing level of convergence with computational speed. It would
appear that planewave cutoff is not the cause for the discrepancy between our calculations and literature
values.
1
2
3
4
5
6
7
8
9
10
11
67.926
300 eV:
121.296
350 eV:
150.808
62
400 eV:
307.465
450 eV:
199.381
500 eV:
240.705
550 eV:
266.318
Illustration of the effect of SIGMA The methodology for extrapolation of the total energy to
absolute zero is only valid for a continuous density of states at the Fermi level. 12 Consequently, it should
not be used for semiconductors, molecules or atoms. In VASP, this means a very small Fermi temperature
(SIGMA) should be used. The O2 dissociation energy as a function of SIGMA is shown in Figure 21.
A variation of nearly 0.2 eV is seen from the default Fermi temperature of kb T = 0.2 eV and the value
of kb T = 0.0001 eV. However, virtually no change was observed for a hydrogen atom or molecule or for
an oxygen molecule as a function of the Fermi temperature. It is recommended that the total energy be
calculated at several values of the Fermi temperature to make sure the total energy is converged with
respect to the Fermi temperature.
We were not careful in selecting a good value for SIGMA in the calculations above. The default value of
SIGMA is 0.2, which may be fine for metals, but it is not correct for molecules. SIGMA is the broadening
factor used to smear the electronic density of states at the Fermi level. For a metal with a continuous
density of states this is appropriate, but for molecules with discrete energy states it does not make sense.
We are somewhat forced to use the machinery designed for metals on molecules. The solution is to use a
63
very small SIGMA. Ideally you would use SIGMA=0, but that is not practical for convergence reasons,
so we try to find what is small enough. Let us examine the effect of SIGMA on the dissociation energy
here.
1
2
3
4
5
6
7
8
9
D = []
for sigma in sigmas:
atoms = Atoms([Atom(O,[5, 5, 5], magmom=2)],
cell=(10, 10, 10))
10
11
12
13
14
15
16
17
18
19
20
21
with jasp(molecules/O-sp-triplet-sigma-{0}.format(sigma),
xc=PBE,
encut=400,
ismear=0,
sigma=sigma,
ispin=2,
atoms=atoms) as calc:
try:
E_O = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O = None
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
with jasp(molecules/O2-sp-triplet-sigma-{0}.format(sigma),
xc=PBE,
encut=400,
ismear=0,
sigma=sigma,
ispin=2,
# turn spin-polarization on
ibrion=2, # make sure we relax the geometry
nsw=10,
atoms=atoms) as calc:
try:
E_O2 = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O2 = None
41
42
43
44
45
D = {1:1.3f} eV.format(sigma, d)
46
47
48
49
50
51
3
4
5
6
7
8
9
with jasp(molecules/O-sp-singlet,
xc=PBE,
encut=400,
64
ismear=0,
ispin=2,
atoms=atoms) as calc:
10
11
12
13
try:
14
E_O = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O = None
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
with jasp(molecules/O2-sp-singlet,
xc=PBE,
encut=400,
ismear=0,
ispin=2, # turn spin-polarization on
ibrion=2, # make sure we relax the geometry
nsw=10,
atoms=atoms) as calc:
try:
E_O2 = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O2 = None
37
38
39
40
41
42
65
2
3
4
5
6
7
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
with jasp(molecules/O-square-box-origin,
xc=PBE,
encut=400,
ismear=0,
sigma=0.01,
ispin=2,
atoms=atoms) as calc:
try:
print Square box (origin): E = {0} eV.format(atoms.get_potential_energy())
except (VaspSubmitted, VaspQueued):
pass
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
with jasp(molecules/O-square-box-center,
xc=PBE,
encut=400,
ismear=0,
sigma=0.01,
ispin=2,
atoms=atoms) as calc:
try:
print Square box (center): E = {0} eV.format(atoms.get_potential_energy())
except (VaspSubmitted, VaspQueued):
66
34
pass
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
with jasp(molecules/O-square-box-random,
xc=PBE,
encut=400,
ismear=0,
sigma=0.01,
ispin=2,
atoms=atoms) as calc:
try:
print Square box (random): E = {0} eV.format(atoms.get_potential_energy())
except (VaspSubmitted, VaspQueued):
pass
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
with jasp(molecules/O-orthorhombic-box-origin,
xc=PBE,
encut=400,
ismear=0,
sigma=0.01,
ispin=2,
atoms=atoms) as calc:
try:
print Orthorhombic box (origin): E = {0} eV.format(atoms.get_potential_energy())
except (VaspSubmitted, VaspQueued):
pass
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
with jasp(molecules/O-orthorhombic-box-center,
xc=PBE,
encut=400,
ismear=0,
sigma=0.01,
ispin=2,
atoms=atoms) as calc:
try:
print Orthorhombic box (center): E = {0} eV.format(atoms.get_potential_energy())
except (VaspSubmitted, VaspQueued):
pass
36
37
38
39
40
41
42
43
44
45
with jasp(molecules/O-orthorhombic-box-random,
xc=PBE,
encut=400,
ismear=0,
sigma=0.01,
67
ispin=2,
atoms=atoms) as calc:
46
47
48
try:
49
50
51
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
with jasp(molecules/O-sp-triplet-lowsym,
xc=PBE,
encut=400,
ismear=0,
sigma=0.01,
ispin=2,
atoms=atoms) as calc:
try:
E_O = atoms.get_potential_energy()
print Magnetic moment on O = {0} Bohr
except (VaspSubmitted, VaspQueued):
E_O = None
magnetons.format(atoms.get_magnetic_moment())
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
with jasp(molecules/O2-sp-triplet,
xc=PBE,
encut=400,
ismear=0,
sigma=0.01,
ispin=2,
# turn spin-polarization on
ibrion=2, # make sure we relax the geometry
nsw=10,
atoms=atoms) as calc:
try:
E_O2 = atoms.get_potential_energy()
# verify magnetic moment
print Magnetic moment on O2 = {0} Bohr magnetons.format(atoms.get_magnetic_moment())
38
39
40
41
42
43
44
This actually agrees within 30-50 meV of reported literature values, although still nearly an eV greater
than the experimental dissociation energy. Note that with a different "random" position, we get the lower
energy for the O atom. All the disagreement we had been seeing was apparently in the O atom energy.
So, if you do not need the dissociation energy in your analysis, you will not see the error. Also note that
this error is specific to there being a spherical atom in a symmetric cell. This is not a problem for most
molecules, which are generally non-spherical.
Verifying the magnetic moments on each atom It is one thing to see the total magnetic moment
of a singlet state, and another to ask what are the magnetic moments on each atom. In VASP you must
use LORBIT=11 to get the magnetic moments of the atoms written out.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
= 1421.493; ENMIN
= 1066.119 eV
3
4
5
6
7
with jasp(molecules/O-sp-triplet-lowsym-sv,
69
xc=PBE,
ismear=0,
ispin=2,
sigma=0.01,
setups={O: _sv},
atoms=atoms) as calc:
8
9
10
11
12
13
14
try:
15
E_O = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O = None
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
with jasp(molecules/O2-sp-triplet-sv,
xc=PBE,
ismear=0,
sigma=0.01,
ispin=2,
# turn spin-polarization on
ibrion=2, # make sure we relax the geometry
nsw=10,
setups={O: _sv},
atoms=atoms) as calc:
try:
E_O2 = atoms.get_potential_energy()
except (VaspSubmitted, VaspQueued):
E_O2 = None
39
40
41
42
43
44
We consider calculating the reaction energy of the water-gas shift reaction in this example.
CO + H2 O CO2 + H2
We define the reaction energy as the difference in energy between the products and reactants.
E = ECO2 + EH2 ECO EH2 O
For now, we compute this energy simply as the difference in DFT energies. In the next section we
will add zero-point energies and compute the energy difference as a function of temperature. For now,
we simply need to compute the total energy of each molecule in its equilibrium geometry.
1
2
3
4
# first we define our molecules. These will automatically be at the coordinates from the G2 database.
5
6
7
CO = molecule(CO)
CO.set_cell([8, 8, 8], scale_atoms=False)
8
9
H2O = molecule(H2O)
70
10
11
12
13
CO2 = molecule(CO2)
CO2.set_cell([8, 8, 8], scale_atoms=False)
14
15
16
H2 = molecule(H2)
H2.set_cell([8, 8, 8], scale_atoms=False)
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
with jasp(molecules/wgs/CO2,
xc=PBE,
encut=350,
ismear=0,
ibrion=2,
nsw=10,
atoms=CO2) as calc:
try:
eCO2 = CO2.get_potential_energy()
except (VaspSubmitted, VaspQueued):
eCO2 = None
42
43
44
45
46
47
48
49
50
51
52
53
with jasp(molecules/wgs/H2,
xc=PBE,
encut=350,
ismear=0,
ibrion=2,
nsw=10,
atoms=H2) as calc:
try:
eH2 = H2.get_potential_energy()
except (VaspSubmitted, VaspQueued):
eH2 = None
54
55
56
57
58
59
60
61
62
63
64
65
with jasp(molecules/wgs/H2O,
xc=PBE,
encut=350,
ismear=0,
ibrion=2,
nsw=10,
atoms=H2O) as calc:
try:
eH2O = H2O.get_potential_energy()
except (VaspSubmitted, VaspQueued):
eH2O = None
66
67
68
69
70
71
72
73
It is a good idea to verify your calculations and structures are what you expected. Let us print them
here. Inspection of these results shows the geometries were all relaxed, i.e., the forces on each atom are
less than 0.05 eV/.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
print ***** H2
with jasp(molecules/wgs/H2) as calc:
print #+begin_example
print calc
print #+end_example
21
22
23
24
25
26
ibrion:
encut:
magmom:
prec:
kpts:
reciprocal:
xc:
txt:
gamma:
2
350.0
None
Normal
[1, 1, 1]
False
PBE
False
Pseudopotentials used:
---------------------C: potpaw_PBE/C/POTCAR (git-hash: 2272d6745da89a3d872983542cef1d18750fc952)
O: potpaw_PBE/O/POTCAR (git-hash: 9a0489b46120b0cad515d935f44b5fbe3a3b1dfa)
CO2
: ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/molecules/wgs/CO2
converged: True
Energy = -22.959572 eV
Unit cell vectors (angstroms)
x
y
z
length
a0 [ 8.000 0.000 0.000] 8.000
a1 [ 0.000 8.000 0.000] 8.000
a2 [ 0.000 0.000 8.000] 8.000
a,b,c,alpha,beta,gamma (deg):8.000 8.000 8.000 90.0 90.0 90.0
Unit cell volume = 512.000 Ang^3
Stress (GPa):xx,
yy,
zz,
yz,
xz,
xy
0.009 0.009 0.008-0.000 -0.000 -0.000
Atom# sym
position [x,y,z]tag rmsForce constraints
0
C
[0.000
0.000
0.000] 0
0.00
T T T
1
O
[0.000
0.000
1.177] 0
0.01
T T T
2
O
[0.000
0.000
6.823] 0
0.01
T T T
-------------------------------------------------INCAR Parameters:
----------------nbands: 12
ismear: 0
nsw: 10
ibrion: 2
encut: 350.0
magmom: None
prec: Normal
kpts: [1, 1, 1]
reciprocal: False
xc: PBE
txt: gamma: False
Pseudopotentials used:
73
To correct the reaction energy for temperature effects, we must compute the vibrational frequencies of
each species, and estimate the temperature dependent contributions to vibrational energy and entropy.
We will break these calculations into several pieces. First we do each vibrational calculation. After
those are done, we can get the data and construct the thermochemistry objects we need to estimate the
reaction energy as a function of temperature (at constant pressure).
CO vibrations
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
75
16
17
18
19
20
atoms=CO) as calc:
calc.calculate()
vib_freq = calc.get_vibrational_frequencies()
for i, f in enumerate(vib_freq):
print {0:02d}: {1} cm^(-1).format(i,f)
2115.528894 cm^(-1)
60.594878 cm^(-1)
60.594878 cm^(-1)
(0.987178+0j) cm^(-1)
(17.958586+0j) cm^(-1)
(17.958586+0j) cm^(-1)
CO has only one vibrational mode (3N-5 = 6 - 5 = 1). The other 5 modes are 3 translations and 2
rotations.
CO2 vibrations
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2352.901285 cm^(-1)
1316.689504 cm^(-1)
635.015913 cm^(-1)
635.015913 cm^(-1)
(0.344306+0j) cm^(-1)
(1.763867+0j) cm^(-1)
(1.763867+0j) cm^(-1)
(62.700411+0j) cm^(-1)
(62.700411+0j) cm^(-1)
CO2 is a linear molecule with 3N-5 = 4 vibrational modes. They are the first four frequencies in the
output above.
H2 vibrations
1
2
3
4
76
H2 = calc.get_atoms()
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
4281.917749 cm^(-1)
129.146855 cm^(-1)
129.146855 cm^(-1)
0.0 cm^(-1)
0.0 cm^(-1)
(1e-05+0j) cm^(-1)
There is only one frequency of importance (the one at 4281 cm1 ) for the linear H2 molecule.
H2 O vibrations
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
3782.062213 cm^(-1)
3672.1246 cm^(-1)
1586.23055 cm^(-1)
135.82763 cm^(-1)
16.280411 cm^(-1)
(0.208582+0j) cm^(-1)
(26.297061+0j) cm^(-1)
(106.869518+0j) cm^(-1)
(131.286732+0j) cm^(-1)
77
Thermochemistry Now we are ready. We have the electronic energies and vibrational frequencies of
each species in the reaction.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
CO2_t = IdealGasThermo(vib_energies=CO2_vib_energies[0:4],
electronicenergy=E_CO2, atoms=CO2,
geometry=linear, symmetrynumber=2,
spin=0)
53
54
55
56
57
H2_t = IdealGasThermo(vib_energies=H2_vib_energies[0:0],
electronicenergy=E_H2, atoms=H2,
geometry=linear, symmetrynumber=2,
spin=0)
58
59
60
61
62
H2O_t = IdealGasThermo(vib_energies=H2O_vib_energies[0:3],
electronicenergy=E_H2O, atoms=H2O,
geometry=nonlinear, symmetrynumber=2,
spin=0)
63
64
65
66
67
68
69
70
# now we can compute G_rxn for a range of temperatures from 298 to 1000 K
Trange = np.linspace(298, 1000, 20) # K
P = 101325. # Pa
Grxn = np.array([(CO2_t.get_free_energy(temperature=T, pressure=P)
+ H2_t.get_free_energy(temperature=T, pressure=P)
- H2O_t.get_free_energy(temperature=T, pressure=P)
- CO_t.get_free_energy(temperature=T, pressure=P)) * 96.485 for T in Trange])
71
72
73
74
Hrxn = np.array([(CO2_t.get_enthalpy(temperature=T)
+ H2_t.get_enthalpy(temperature=T)
- H2O_t.get_enthalpy(temperature=T)
78
- CO_t.get_enthalpy(temperature=T)) * 96.485
for T in Trange])
75
76
77
78
79
80
81
82
83
84
85
86
plt.figure()
R = 8.314e-3
87
88
89
90
91
92
93
94
Keq = np.exp(-Grxn/R/Trange)
plt.plot(Trange, Keq)
plt.ylim([0, 100])
plt.xlabel(Temperature (K))
plt.ylabel($K_{eq}$)
plt.savefig(images/wgs-Keq.png)
plt.show()
Figure 22: Thermodynamic energies of the water gas shift reaction as a function of temperature.
You can see a few things here. One is that at near 298K, the Gibbs free energy is about -75 kJ/mol.
This is too negative compared to the experimental standard free energy, which we estimated to be about
-29 kJ/mol from the NIST webbook. There could be several reasons for this disagreement, but the most
likely one is errors in the exchange-correlation functional. The error in energy has a significant effect on
the calculated equilibrium constant, significantly overestimating it.
79
3.9
We will consider a simple example of the barrier for NH3 inversion. We have to create an NH3 molecule in
the initial and inverted state (these have exactly the same energy), and then interpolate a band of images.
Then, we use the NEB method 48 to compute the barrier to inversion. The NEB class of methods are
pretty standard, but other algorithms for finding barriers (saddle-points) exist that may be relevant. 49
3.9.1
1
2
3
4
5
6
7
8
9
10
atoms = molecule(NH3)
constraint = FixAtoms(mask=[atom.symbol == N for atom in atoms])
atoms.set_constraint(constraint)
11
12
Npos = atoms.positions[0]
13
14
15
16
# move N to origin
atoms.translate(-Npos)
atoms.set_cell((10, 10, 10), scale_atoms=False)
17
18
19
atoms2 = atoms.copy()
pos2 = atoms2.positions
20
21
22
80
23
24
25
# reflect through z
pos2[i] *= np.array([1, 1, -1])
atoms2.positions = pos2
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
with jasp(molecules/nh3-initial,
xc=PBE,
encut=350,
ibrion=1,
nsw=10,
atoms=atoms) as calc:
try:
calc.calculate()
except (VaspSubmitted, VaspQueued):
pass
41
42
43
44
45
46
47
48
49
50
51
with jasp(molecules/nh3-final,
xc=PBE,
encut=350,
ibrion=1,
nsw=10,
atoms=atoms2) as calc:
try:
calc.calculate()
except (VaspSubmitted, VaspQueued):
pass
4
5
6
7
8
9
10
11
12
13
14
15
16
17
neb = NEB(images)
neb.interpolate()
18
19
20
21
22
23
24
25
with jasp(molecules/nh3-neb,
xc=PBE,
ibrion=1,
nsw=90,
spring=-5, debug=logging.DEBUG,
atoms=images) as calc:
images, energies = calc.get_neb()
26
27
28
29
30
calc.plot_neb(show=False)
import matplotlib.pyplot as plt
plt.savefig(images/nh3-neb.png)
plt.show()
81
Bulk systems
See http://arxiv.org/pdf/1204.2733.pdf for a very informative comparison of DFT codes for computing different bulk properties.
4.1
4.1.1
As with molecules, mod:ase provides several helper functions to create bulk structures. We highlight a
few of them here. Particularly common ones are:
mod:ase.lattice.cubic.FaceCenteredCubic
mod:ase.lattice.cubic.BodyCenteredCubic
mod:ase.lattice.hexagonal.Graphite
mod:ase.lattice.compounds.NaCl
For others, see https://wiki.fysik.dtu.dk/ase/ase/lattice.html
We start with a simple example, fcc Ag. By default, mod:ase knows Ag is an fcc metal, and knows
the experimental lattice constant. We have to specify the directions (vectors along each axis) to get
something other than the default output. Here, the default fcc cell contains four atoms.
82
1
2
3
4
atoms = FaceCenteredCubic(Ag)
5
6
7
8
print atoms
3
4
5
6
7
8
9
10
print atoms
3
4
5
6
7
8
9
10
11
12
13
14
15
83
Figure 25: A simple fcc Ag bulk structure in the primitive unit cell.
Figure 27: A simple fcc Ag bulk structure in the traditional unit cell.
84
Figure 26: A simple fcc Ag bulk structure in the primitive unit cell.
3
4
5
6
7
8
9
10
11
12
write(images/graphite-top.png,
atoms.repeat((2, 2, 1)),
show_unit_cell=2)
85
3
4
5
86
2
3
4
5
6
7
a = 4.6
c = 2.95
rutile = crystal([Ti, O], basis=[(0, 0, 0), (0.3, 0.3, 0.0)],
spacegroup=136, cellpar=[a, a, c, 90, 90, 90])
print rutile
Using http://materialsproject.org
The Materials Project offers web access to a pretty large number of materials (over 21,000 at the time
of this writing), including structure and other computed properties. You must sign up for an account at
the website, and then you can access the information. You can search for materials with lots of different
criteria including formula, unit cell formula, by elements, by structure, etc. . . The website allows you to
download the VASP files used to create the calculations. They also develop the pymatgen project (which
requires python 2.7+).
For example, I downloaded this cif file for a RuO2 structure (Material ID 825).
1
2
3
4
5
6
7
8
9
10
11
12
#\#CIF1.1
##########################################################################
#
Crystallographic Information Format file
#
Produced by PyCifRW module
#
# This is a CIF file. CIF has been adopted by the International
# Union of Crystallography as the standard for data archiving and
# transmission.
#
# For information on this file format, follow the CIF links at
# http://www.iucr.org
##########################################################################
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
data_RuO2
_symmetry_space_group_name_H-M
_cell_length_a
_cell_length_b
_cell_length_c
_cell_angle_alpha
_cell_angle_beta
_cell_angle_gamma
_chemical_name_systematic
_symmetry_Int_Tables_number
_chemical_formula_structural
_chemical_formula_sum
_cell_volume
_cell_formula_units_Z
loop_
_symmetry_equiv_pos_site_id
_symmetry_equiv_pos_as_xyz
1 x, y, z
P 1
3.13970109
4.5436378
4.5436378
90.0
90.0
90.0
Generated by pymatgen
1
RuO2
Ru2 O4
64.8180127062
2
32
33
34
35
36
37
38
39
40
41
loop_
_atom_site_type_symbol
_atom_site_label
_atom_site_symmetry_multiplicity
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
_atom_site_attached_hydrogens
_atom_site_B_iso_or_equiv
87
42
43
44
45
46
47
48
_atom_site_occupancy
O O1 1 0.000000 0.694330 0.694330 0 . 1
O O2 1 0.500000 0.805670 0.194330 0 . 1
O O3 1 0.000000 0.305670 0.305670 0 . 1
O O4 1 0.500000 0.194330 0.805670 0 . 1
Ru Ru5 1 0.500000 0.500000 0.500000 0 . 1
Ru Ru6 1 0.000000 0.000000 0.000000 0 . 1
2
3
atoms = read(bulk/Ru2O4_1.cif)
4
5
2
3
4
5
6
7
with jasp(bulk/Ru2O4,
xc=PBE,
setups={Ru: _pv}) as calc:
calc.calculate()
print calc
T
T
T
T
T
T
INCAR Parameters:
----------------nbands: 31
ismear: 1
nelmin: 3
icharg: 1
nelm: 100
nsw: 99
ibrion: 2
npar: 1
isif: 3
encut: 520.0
sigma: 0.2
ediff: 0.0003
lwave: True
magmom: [0.6, 0.6, 0.6, 0.6, 0.6, 0.6]
prec: Normal
algo: Fast
lreal: Auto
kpts: [8, 6, 6]
reciprocal: False
setups: {Ru: _pv}
xc: PBE
txt: gamma: False
Pseudopotentials used:
---------------------Ru: potpaw_PBE/Ru_pv/POTCAR (git-hash: c29610ef9b7bfa353e710b09dfadcd2b0fb0d274)
O: potpaw_PBE/O/POTCAR (git-hash: 9a0489b46120b0cad515d935f44b5fbe3a3b1dfa)
Some notes: we had to specify the PBE functional. That is good habit, since the default may be
something else. We also had to specify the special setups used, since those were not defaults either.
We get exactly the same result as the website! Why is this helpful then? Well, we could use this as
a starting point to look at an equation of state, or to plot some interesting electronic structure, etc. . .
Or we can gain a little confidence that our version of VASP is working like the one they used.
89
4.2
4.2.1
In the section on molecules, we learned that the total energy is a function of the planewave cutoff energy
(ENCUT) used. In bulk systems that is true also. There is also another calculation parameter you
must consider, the k-point grid. The k-point grid is a computational tool used to approximate integrals
of some property, e.g. the electron density, over the entire unit cell. The integration is performed
in reciprocal space (i.e. in the Brillouin zone) for convenience and efficiency, and the k-point grid is
where the property is sampled for the integration. The higher the number of sampled points, the more
accurately the integrals are approximated.
We will typically use a Monkhorst-Pack 28 k-point grid, which is essentially a uniformly spaced grid
in the Brillouin zone. Another less commonly used scheme is the Chadi-Cohen k-point grid. 27 The
Monkhorst-Pack grids are specified as n1 n2 n3 grids, and the total number of k-points is n1 n2 n3.
The computational cost is linear in the total number of k-points, so a calculation on a 4 4 4 grid
will be roughly 8 times more expensive than on a 2 2 2 grid. Hence, one seeks again to balance
convergence with computational tractability. Below we consider the k-point convergence of fcc Ag.
1
2
3
4
atoms = FaceCenteredCubic(Ag)
5
6
7
8
TE = []
9
10
11
12
13
14
15
16
17
18
19
20
ready = True
for k in KPTS:
with jasp(bulk/Ag-kpts-{0}.format(k),
xc=PBE,
kpts=(k, k, k), # specifies the Monkhorst-Pack grid
encut=300,
atoms=atoms) as calc:
try:
TE.append(atoms.get_potential_energy())
except (VaspSubmitted, VaspQueued):
ready = False
21
22
23
if not ready:
import sys; sys.exit()
24
25
26
27
28
29
30
31
32
33
34
35
plt.plot(KPTS, TE)
plt.xlabel(number of k-points in each dimension)
plt.ylabel(Total Energy (eV))
plt.savefig(images/Ag-kpt-convergence.png)
plt.show()
90
show the same level of convergence with a 6 6 6 k-point grid. In other words, doubling the unit cell
vectors results in a halving of the number of k-points.
Sometimes you may see k-points described as k-points per reciprocal atom. For example, a 121212
k-point grid for a primitive fcc unit cell would be 1728 k-points per reciprocal atom. A 2 2 2 fcc unit
cell has eight atoms in it, or 0.125 reciprocal atoms, so a 6 6 6 k-point grid has 216 k-points in it, or
216/0.125 = 1728 k-points per reciprocal atom, the same as we discussed before.
In the k-point convergence example above, we used a 6 6 6 k-point grid on a unit cell with four
atoms in it, leading to 864 k-points per reciprocal atom. If we had instead used the primitive unit cell,
we would need either a 9 9 9 or 10 10 10 k-point grid to get a similar level of accuracy. In this
case, there is no exact matching of k-point grids due to the difference in shape of the cells.
4.2.2
Effect of SIGMA
In the self-consistent cycle of a DFT calculation, the total energy is minimized with respect to occupation
of the Kohn-Sham orbitals. At absolute zero, a band is either occupied or empty. This discrete occupation results in discontinuous changes in energy with changes in occupation, which makes it difficult
to converge. One solution is to artificially broaden the band occupancies, as if they were occupied at
a higher temperature where partial occupation is possible. This results in a continuous dependence of
energy on the partial occupancy, and dramatically increases the rate of convergence. SIGMA and ISMEAR
affect how the partial occupancies of the bands are determined.
Some rules to keep in mind:
1. The smearing methods were designed for metals. For molecules, semiconductors and insulators you
should use a very small SIGMA (e.g. 0.01).
2. Standard values for metallic systems is SIGMA=0.1, but the best SIGMA may be material specific.
The consequence of this finite temperature is that additional bands must be included in the calculation
to allow for the partially occupied states above the Fermi level; the number of extra bands depends on the
temperature used. An example of the maximum occupancies of the bands for an Cu bulk as a function
of SIGMA is shown in Figure 34. Obviously, as SIGMA approaches 0, the occupancy approaches a step
function. It is preferable that the occupancy of several of the highest bands be zero (or at least of order
1 108 ) to ensure enough variational freedom was available in the calculation. Consequently, it is
suggested that fifteen to twenty extra bands be used for a SIGMA of 0.20. In any case, it should be
determined that enough bands were used by examination of the occupancies. It is undesirable to have
too many extra bands, as this will add computational time.
Below we show the effect of SIGMA on the band occupancies.
1
2
3
4
5
6
7
8
9
a = 3.61
atoms = Atoms([Atom(Cu, (0, 0, 0))],
cell=0.5 * a * np.array([[1.0, 1.0, 0.0],
[0.0, 1.0, 1.0],
[1.0, 0.0, 1.0]])).repeat((2, 2, 2))
10
11
12
13
14
15
16
17
18
19
20
21
22
23
with jasp(bulk/Cu-sigma-{0}.format(sigma),
xc=PBE,
encut=350,
kpts=(4, 4, 4),
ismear=-1,
sigma=sigma,
nbands=9 * 8,
atoms=atoms) as calc:
e = atoms.get_potential_energy()
24
91
nbands = calc.nbands
nkpts = len(calc.get_ibz_k_points())
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
plt.xlabel(band number)
plt.ylabel(maximum occupancy (electrons))
plt.ylim([-0.1, 2.1])
plt.legend(loc=best)
plt.savefig(images/occ-sigma.png)
plt.show()
In the last figure, it is evident that due to the smearing of the electronic states you need to have extra
bands to accommodate the electrons above the Fermi level, and the higher the incar:SIGMA value is,
the more bands you need. You need enough bands so that the highest energy bands are unoccupied, and
VASP will give you a warning that looks like this:
----------------------------------------------------------------------------|
|
| ADVICE TO THIS USER RUNNING VASP/VAMP
(HEAR YOUR MASTERS VOICE ...): |
|
|
|
Your highest band is occupied at some k-points! Unless you are
|
|
performing a calculation for an insulator or semiconductor, without
|
|
unoccupied bands, you have included TOO FEW BANDS!! Please increase
|
|
the parameter NBANDS in file INCAR to ensure that the highest band
|
|
is unoccupied at all k-points. It is always recommended to
|
|
include a few unoccupied bands to accelerate the convergence of
|
|
molecular dynamics runs (even for insulators or semiconductors).
|
|
Because the presence of unoccupied bands improves wavefunction
|
|
prediction, and helps to suppress band-crossings.
|
|
Following all k-points will be listed (with the Fermi weights of
|
|
the highest band given in paranthesis) ... :
|
|
|
|
6
(-0.01472)
|
|
8
(-0.01413)
|
|
13
(-0.01733)
|
|
14
(-0.01838)
|
|
|
|
The total occupancy of band no.
49 is -0.00932 electrons ...
|
|
|
----------------------------------------------------------------------------We tell VASP the number of bands to use with the incar:NBANDS keyword. VASP will set the
NBANDS automatically if you do not provide a value, but this is in general bad practice (even though it
is often done in this book!). There are a few general guidelines for setting NBANDS. First we recognize
that a band can only have two electrons in it (one spin up, and one spin down) in an calculation without
spin-polarization, or one electron per band for a spin-polarized calculation (note that spin-polarization
doubles the number of bands). There absolutely must be enough bands to accommodate all the electrons,
so the minimum number of bands is int(ceil(nelectrons/2)).
92
import numpy as np
2
3
4
NELECT/2 + NIONS/2
0.6*NELECT + NMAGIONS
These do not always work, especially for small molecular systems where NIONS/2 may be only 1, or
transition metals where it may be necessary to add up to 2*NIONS extra bands.
To figure out how many bands you need, it is necessary to know how many electrons are in your
calculation. The func:jasp.get_valence_electrons provides this for you. Alternatively, you can look in
the Appendix for a table listing the number of valence electrons for each POTCAR file. Armed with this
information you can set NBANDS the way you want.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
with jasp(bulk/alloy/cu,
xc=PBE,
encut=350,
kpts=(13, 13, 13),
nbands=9,
ibrion=2,
isif=4,
nsw=10,
atoms=atoms) as calc:
print calc.get_valence_electrons()
93
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
with jasp(bulk/alloy/cu,
xc=PBE,
encut=350,
kpts=(13, 13, 13),
ibrion=2,
isif=4,
nsw=10,
atoms=atoms) as calc:
calc.set_nbands(9)
print calc
94
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
with jasp(bulk/alloy/cu-setnbands,
xc=PBE,
encut=350,
kpts=(13, 13, 13),
ibrion=2,
isif=4,
nsw=10,
atoms=atoms) as calc:
calc.set_nbands(f=3)
print calc
95
1. NBANDS = 0.65*NELECT + 10
2. NBANDS = 0.5*NELECT + 15
3. etc. . .
4.3
The fcc and bcc structures are simple. They only have one degree of freedom: the lattice constant. In
this section we show how to calculate the equilibrium volume of each structure, and determine which
one is more stable. We start with the fcc crystal structure of Cu. We will manually define the crystal
structure based on the definitions in Kittel 4 (Chapter 1).
1
2
3
4
5
6
7
8
9
10
11
12
# fcc
LC = [3.5, 3.55, 3.6, 3.65, 3.7, 3.75]
fcc_energies = []
ready = True
for a in LC:
atoms = Atoms([Atom(Cu, (0, 0, 0))],
cell=0.5 * a * np.array([[1.0, 1.0, 0.0],
[0.0, 1.0, 1.0],
[1.0, 0.0, 1.0]]))
13
14
15
16
17
18
with jasp(bulk/Cu-{0}.format(a),
xc=PBE,
encut=350,
kpts=(8, 8, 8),
atoms=atoms) as calc:
19
20
try:
21
e = atoms.get_potential_energy()
fcc_energies.append(e)
except (VaspSubmitted, VaspQueued):
ready = False
22
23
24
25
26
27
if not ready:
import sys; sys.exit()
28
29
30
31
32
33
34
35
36
37
38
lattice constant ()
3.5
3.55
3.6
3.65
3.7
3.75
Exercise 4.2
Use the data in the table above to plot the total energy as a function of the lattice
constant. Fit a cubic polynomial to the data, and find the volume that minimizes the
total energy.
If you want to know the lattice constant that gives the lowest energy, you would fit an equation of
state to the data. Here is an example using mod:ase.utils.eos. See also the appendix equations of state.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
print
v0 = {0} A^3
E0 = {1} eV
B = {2} eV/A^3.format(v0, e0, B)
19
20
eos.plot(images/Cu-fcc-eos.png)
4
5
6
7
8
9
10
97
3
4
5
6
7
8
9
10
for a in LC:
atoms = Atoms([Atom(Cu, [0, 0, 0])],
cell=0.5 * a * np.array([[ 1.0, 1.0, -1.0],
[-1.0, 1.0, 1.0],
[ 1.0, -1.0, 1.0]]))
11
12
13
14
15
16
17
with jasp(bulk/Cu-bcc-{0}.format(a),
xc=PBE,
encut=350,
kpts=(8, 8, 8),
atoms=atoms) as calc:
calc.calculate()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
The hcp lattice is more complicated than the fcc/bcc lattices because there are two lattice parameters: a
and c or equivalently: a and c/a. We will start by making a grid of values and find the set of parameters
that minimizes the energy. See Figure 38.
1
2
3
4
5
6
7
atoms = HexagonalClosedPacked(symbol=Ru,
latticeconstant={a: 2.7,
c/a: 1.584})
8
9
10
11
12
13
14
for a in a_list:
energies = []
for covera in covera_list:
15
16
17
18
atoms = HexagonalClosedPacked(symbol=Ru,
latticeconstant={a: a,
c/a: covera})
19
20
wd = bulk/Ru/{0:1.2f}-{1:1.2f}.format(a, covera)
21
22
23
24
25
26
27
28
29
30
31
32
33
with jasp(wd,
xc=PBE,
# the c-axis is longer than the a-axis, so we use
# fewer kpoints.
kpts=(6, 6, 4),
encut=350,
atoms=atoms) as calc:
try:
energies.append(atoms.get_potential_energy())
except (VaspSubmitted, VaspQueued):
pass
plt.plot(covera_list, energies, label=ra={0} $\AA$.format(a))
34
99
35
36
37
38
39
plt.xlabel($c/a$)
plt.ylabel(Energy (eV))
plt.legend()
plt.savefig(images/Ru-covera-scan.png)
plt.show()
3
4
5
6
7
8
X,Y = np.meshgrid(x, y)
Z = np.zeros(X.shape)
9
10
11
12
wd = bulk/Ru/{0:1.2f}-{1:1.2f}.format(a,covera)
13
14
15
16
17
18
19
20
21
22
23
cf = plt.contourf(X, Y, Z, 20,
cmap=plt.cm.jet)
24
25
26
cbar = plt.colorbar(cf)
cbar.ax.set_ylabel(Energy (eV))
27
28
29
plt.xlabel($a$ ($\AA$))
plt.ylabel($c/a$)
30
31
32
33
plt.legend()
plt.savefig(images/ru-contourf.png)
plt.show()
A unit cell has six degrees of freedom: the lengths of each unit cell vector, and the angle between each
vector. There may additionally be internal degrees of freedom for the atoms. It is impractical to try the
approach used for the hcp Ru on anything complicated. Instead, we rely again on algorithms to optimize
the unit cell shape, volume and internal degrees of freedom. It is usually not efficient to make a wild
guess of the geometry and then turn VASP loose on to optimize it. Instead, the following algorithm
works pretty well.
1. Find the volume (at constant shape, with relaxed ions) that minimizes the total energy (ISIF=2).
The goal here is to just get an idea of where the right volume is.
2. Using the results from step 1 as a starting point, perform a set of calculations at constant volume
around the minimum from step 1, but the shape and internal atom positions are allowed to change
(ISIF=4).
3. Finally, do a final calculation near the minimum energy allowing the volume to also change.
(ISIF=3).
100
This multistep process is pretty reasonable to get a converged structure pretty quickly. It is not
foolproof, however, and if you have materials such as graphite it may not work well. The problem with
graphite is that it is a layered compound that is held together by weak van der waal type forces which
are not modeled well by typical GGA functionals. Thus the change in energy due to a volume change is
larger in the plane of the graphite sheet than in the direction normal to the sheet. With a typical GGA,
the sheets may just move apart until they do not interact any more.
We will illustrate the process on a well-behaved system (rutile TiO2 ) which has two lattice parameters and one internal degree of freedom. There are a few subtle points to mention in doing these
calculations. The VASP manual recommends that you set incar:PREC to high, and that ENCUT be
set to 1.3*max(ENMAX) of the pseudopotentials. This is necessary to avoid problems caused by small
basis sets when the volume changes, and Pulay stress. It is important to ensure that the energies are
reasonably converged with respect to k-point grids. Hence, it can be a significant amount of work to do
this right! Let us start with determining the ENCUT value that is appropriate for TiO2 .
1
2
=
=
178.330; ENMIN
400.000; ENMIN
=
=
133.747 eV
300.000 eV
According to the manual, we should use ENCUT = 1.3*400 = 520 eV for good results.
Now we consider the k-point convergence. The lattice vectors of the rutile TiO2 structure are not
all the same length, which means it is not essential that we use the same number of k-points in each
direction. For simplicity, however, we do that here.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#primitive vectors
a1 = a * np.array([1.0, 0.0, 0.0])
a2 = a * np.array([0.0, 1.0, 0.0])
a3 = c * np.array([0.0, 0.0, 1.0])
20
21
22
23
24
25
26
27
28
29
30
KPOINTS = [2, 3, 4, 5, 6, 7, 8]
energies = []
31
32
33
34
35
36
37
38
39
ready = True
for k in KPOINTS:
with jasp(bulk/tio2/kpts-{0}.format(k),
encut=520,
kpts=(k, k, k),
xc=PBE,
sigma=0.05,
atoms=atoms) as calc:
101
40
try:
41
energies.append(atoms.get_potential_energy())
except (VaspSubmitted, VaspQueued):
ready = False
42
43
44
45
46
if not ready:
import sys; sys.exit()
47
48
49
50
51
52
plt.plot(KPOINTS, energies)
plt.xlabel(number of k-points in each vector)
plt.ylabel(Total energy (eV))
plt.savefig(images/tio2-kpt-convergence.png)
plt.show()
6
7
8
9
10
11
12
13
14
15
16
17
18
#primitive vectors
a1 = a * np.array([1.0, 0.0, 0.0])
a2 = a * np.array([0.0, 1.0, 0.0])
a3 = c * np.array([0.0, 0.0, 1.0])
19
20
21
22
23
24
25
26
27
28
29
v0 = atoms.get_volume()
cell0 = atoms.get_cell()
30
31
32
33
34
35
36
37
38
ready = True
for f in factors:
v1 = f * v0
cell_factor = (v1 / v0)**(1. / 3.)
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
with jasp(bulk/tio2/step1-{0:1.2f}.format(f),
encut=520,
kpts=(5,5,5),
isif=2, # relax internal degrees of freedom
ibrion=1,
nsw=50,
xc=PBE,
sigma=0.05,
atoms=atoms) as calc:
try:
energies.append(atoms.get_potential_energy())
volumes.append(atoms.get_volume())
except (VaspSubmitted, VaspQueued):
ready = False
56
102
57
58
if not ready:
import sys; sys.exit()
59
60
61
62
63
plt.plot(volumes, energies)
plt.xlabel(Vol. ($\AA^3)$)
plt.ylabel(Total energy (eV))
plt.savefig(images/tio2-step1.png)
64
65
66
67
68
69
70
2
3
# to change volume by
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if not ready:
import sys; sys.exit()
27
28
29
30
31
32
33
34
volume, but would have an effect on the bulk modulus, which is related to the curvature of the equation
of state. At this point, you could fit an equation of state to the step 2 data, and estimate the volume at
the minimum volume, and recalculate the total energy at that volume.
An alternative is a final calculation with ISIF=3, which optimizes the unit cell volume, shape and
internal coordinates. It looks like the calculation at bulk/tio2/step2-1.05 is close to the minimum, so we
will use that as a starting point for the final calculation.
1
2
3
4
5
6
7
8
9
10
with jasp(bulk/tio2/step3,
isif=3) as calc:
calc.calculate()
atoms = calc.get_atoms()
print calc
11
12
13
reciprocal:
xc:
txt:
gamma:
False
PBE
False
Pseudopotentials used:
---------------------O: potpaw_PBE/O/POTCAR (git-hash: 9a0489b46120b0cad515d935f44b5fbe3a3b1dfa)
Ti: potpaw_PBE/Ti/POTCAR (git-hash: a29a4f0f14083cf90544a3cf1ae7fc220b31829c)
The spacegroup is P4_2/mnm
(136)
This is the final result. You can see that the forces on all the atoms are less than 0.01 eV/, and
the stress is also very small. The final volume is close to where we expect it to be based on steps 1 and
2. The space group is still correct. The lattice vectors are close in length to the experimentally known
values, and the angles between the vectors has not changed much. Looks good!
As a final note, the VASP manual recommends you do not use the final energy directly from the
calculation, but rather run a final calculation with incar:ISMEAR set to -5. Here we examine the effect.
1
2
3
4
5
6
7
8
9
10
11
12
with jasp(bulk/tio2/step4,
ismear=-5,
nsw=0) as calc:
atoms = calc.get_atoms()
print ismear=-5:
, atoms.get_potential_energy()
-52.81861
-52.817345
The difference here is on the order of a meV. That does not seem significant here. I suspect the
recommended practice stems from early days when much smaller ENCUT values were used and changes
in the number of basis functions were more significant.
4.3.4
The exchange correlation functional can significantly affect computed bulk properties. Here, we examine
the effect on the bulk lattice constant of Pd (exp. 3.881). An excellent review of this can be found in. 50
We examine several functionals. The xc keyword in jasp is used to select the POTCARs. The value of
xc can be LDA, PW91 or PBE. Let us consider the LDA functional first.
1
2
3
4
5
6
7
8
9
10
11
12
13
105
encut=350,
kpts=(12, 12, 12),
xc=LDA,
atoms=atoms):
14
15
16
17
18
try:
19
e = atoms.get_potential_energy()
energies.append(e)
volumes.append(atoms.get_volume())
except (VaspSubmitted, VaspQueued):
pass
20
21
22
23
24
25
26
27
28
if len(energies) == len(LC):
eos = EquationOfState(volumes, energies)
v0, e0, B = eos.fit()
print LDA lattice constant is {0:1.3f} Ang^3.format((4*v0)**(1./3.))
4
5
6
7
8
9
10
GGA = {AM:
PE:
PS:
RP:
AM05,
PBE,
PBEsol,
RPBE}
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
if len(energies) == len(LC):
eos = EquationOfState(volumes, energies)
v0, e0, B = eos.fit()
print {1:6s} lattice constant is {0:1.3f} Ang^3.format((4*v0)**(1./3.),
GGA[key])
else:
print energies, LC
print {0} is not ready.format(GGA[key])
lattice
lattice
lattice
lattice
constant
constant
constant
constant
is
is
is
is
3.885
3.882
3.990
3.952
Ang^3
Ang^3
Ang^3
Ang^3
106
These results compare very favorably to those in. 50 It is typical that LDA functionals underestimate
the lattice constants, and that GGAs tend to overestimate the lattice constants. PBEsol and AM05 were
designed specifically for solids, and for Pd, these functionals do an exceptional job of reproducing the
lattice constants. RPBE is particularly bad at the lattice constant, but it has been reported to be a
superior functional for reactivity. 25
4.4
Cohesive energy
The cohesive energy is defined as the energy to separate neutral atoms in their ground electronic state
from the solid at 0K at 1 atm. We will compute this for rhodium. Rh is normally an fcc metal, so we
will use that structure and let VASP find the equilibrium volume for us.
1
2
3
4
5
6
7
8
9
10
# bulk system
atoms = FaceCenteredCubic(directions=[[0, 1, 1],
[1, 0, 1],
[1, 1, 0]],
size=(1, 1, 1),
symbol=Rh)
11
12
13
14
15
16
17
18
19
20
with jasp(bulk/bulk-rh,
xc=PBE,
encut=350,
kpts=(4, 4, 4),
isif=3,
ibrion=2,
nsw=10,
atoms=atoms) as calc:
bulk_energy = atoms.get_potential_energy()
21
22
23
24
# atomic system
atoms = Atoms([Atom(Rh,[5, 5, 5])],
cell=(7, 8, 9))
25
26
27
28
29
30
31
with jasp(bulk/atomic-rh,
xc=PBE,
encut=350,
kpts=(1, 1, 1),
atoms=atoms) as calc:
atomic_energy = atoms.get_potential_energy()
32
33
34
107
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for k in kpts:
with jasp(bulk/bulk-rh-kpts-{0}.format(k),
xc=PBE,
encut=350,
kpts=(k, k, k),
atoms=atoms) as calc:
e = atoms.get_potential_energy()
19
20
energy
energy
energy
energy
energy
energy
energy
=
=
=
=
=
=
=
-4.837472
-6.189573
-6.210668
-6.208576
-6.215367
-6.215319
-6.216032
eV
eV
eV
eV
eV
eV
eV
Using only 1 k-point for the bulk energy is a terrible approximation! It takes at least a 6 6 6
grid to get the total energy converged to less than 10 meV. Note we do not need to check the k-point
convergence of the atomic state because it is surrounded by vacuum on all sides, and so there should not
be any dispersion in the bands.
We will examine the magnetic state next.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
with jasp(bulk/bulk-rh,
xc=PBE,
encut=350,
kpts=(4, 4, 4),
isif=3,
ibrion=2,
nsw=10,
atoms=atoms) as calc:
bulk_energy = atoms.get_potential_energy()
20
21
22
23
# atomic system
atoms = Atoms([Atom(Rh,[5, 5, 5], magmom=1)],
cell=(7, 8, 9))
24
25
26
27
28
29
30
31
with jasp(bulk/atomic-rh-sp,
xc=PBE,
encut=350,
kpts=(1, 1, 1),
ispin=2,
atoms=atoms) as calc:
atomic_energy = atoms.get_potential_energy()
32
108
33
34
4.5
Al elastic properties
3
4
atoms = FaceCenteredCubic(symbol=Al)
5
6
7
8
9
10
11
12
13
14
15
16
with jasp(bulk/Al-bulk,
xc=PBE,
kpts=(12, 12, 12),
encut=350,
prec=High,
isif=3,
nsw=30,
ibrion=1,
atoms=atoms) as calc:
print atoms.get_potential_energy()
print atoms.get_stress()
0.
0.
0.
Ok, now with a relaxed geometry at hand, we proceed with the elastic constants. This is accomplished
with IBRION=6 and ISIF 3 in VASP. See this reference (from the VASP page).
1. Le Page and P. Saxe, Phys. Rev. B 65, 104104 (2002).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
with jasp(bulk/Al-elastic,
ibrion=6,
#
isif=3,
# gets elastic constants
potim=0.015, # displacements
nsw=1,
nfree=2) as calc:
atoms = calc.get_atoms()
print atoms.get_potential_energy()
EM = calc.get_elastic_moduli()
print EM
17
18
19
20
21
c11 = EM[0,0]
c12 = EM[0,1]
B = (c11 + 2 * c12) / 3.0
print B
109
66.153
66.153
98.944
0.
0.
0.
0.
0.
0.
1.687
0.
0.
0.
0.
0.
0.
1.687
0.
0.
]
0.
]
0.
]
0.
]
0.
]
1.687]]
This example shows the basic mechanics of getting the elastic constants. The C44 constant above
is too low, and probably we need to check these constants for convergence with respect to kpoints,
planewave cutoff, and maybe the value of POTIM.
4.5.2
1
2
Fe elastic properties
3
4
5
6
atoms = BodyCenteredCubic(symbol=Fe)
for atom in atoms:
atom.magmom = 3.0
7
8
9
10
11
12
13
14
15
16
17
18
with jasp(bulk/Fe-bulk,
xc=PBE,
kpts=(6, 6, 6),
encut=350,
ispin=2,
isif=3,
nsw=30,
ibrion=1,
atoms=atoms) as calc:
print atoms.get_potential_energy()
print atoms.get_stress()
-0.
-0.
Ok, now with a relaxed geometry at hand, we proceed with the elastic constants. This is accomplished
with IBRION=6 and ISIF 3 in VASP. See this reference (from the VASP page).
1. Le Page and P. Saxe, Phys. Rev. B 65, 104104 (2002).
1
2
3
4
5
6
7
8
9
10
11
12
13
with jasp(bulk/Fe-elastic,
ibrion=6,
#
isif=3,
# gets elastic constants
potim=0.05, # displacements
nsw=1,
nfree=2) as calc:
atoms = calc.get_atoms()
print atoms.get_potential_energy()
Now, the results are written out to the OUTCAR file. Actually, three sets of moduli are written out
1) the elastic tensor for rigid ions, 2) the contribution from allowing the atoms to relax, and 3) the total
elastic modulus, all in kBar.
SYMMETRIZED ELASTIC MODULI (kBar)
Direction
XX
YY
ZZ
XY
YZ
ZX
-------------------------------------------------------------------------------XX
2803.5081
1622.6085
1622.6085
0.0000
0.0000
0.0000
YY
1622.6085
2803.5081
1622.6085
0.0000
0.0000
0.0000
ZZ
1622.6085
1622.6085
2803.5081
0.0000
0.0000
0.0000
XY
0.0000
0.0000
0.0000
866.8792
0.0000
0.0000
YZ
0.0000
0.0000
0.0000
0.0000
866.8792
0.0000
ZX
0.0000
0.0000
0.0000
0.0000
0.0000
866.8792
-------------------------------------------------------------------------------and
ELASTIC MODULI CONTR FROM IONIC RELAXATION (kBar)
Direction
XX
YY
ZZ
XY
YZ
ZX
-------------------------------------------------------------------------------XX
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
YY
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
ZZ
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
XY
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
YZ
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
ZX
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
--------------------------------------------------------------------------------
import numpy as np
EM = []
3
4
5
6
7
8
9
10
with open(bulk/Fe-elastic/OUTCAR) as f:
lines = f.readlines()
for i, line in enumerate(lines):
if line.startswith( TOTAL ELASTIC MODULI (kBar)):
j = i + 3
data = lines[j:j+6]
break
11
12
13
14
15
print np.array(EM)
111
1622.6085
2803.5081
1622.6085
0.
0.
0.
1622.6085
1622.6085
2803.5081
0.
0.
0.
0.
0.
0.
866.8792
0.
0.
0.
0.
0.
0.
866.8792
0.
0.
]
0.
]
0.
]
0.
]
0.
]
866.8792]]
TODO: compare to a normal EOS, and maybe literature. Further discussion of symmetry.
Fe is in a BCC crystal structure, which is high in symmetry. Consequently, many of the elements in
the matrix are equal to zero.
see http://www.nist.gov/data/PDFfiles/jpcrd34.pdf for a lot of detail
4.6
Bulk thermodynamics
We can predict temperature dependent thermodynamic properties of bulk materials without too much
effort. As with the thermochemical properties of ideal gases, we must use some simple models that we
parameterize by DFT. Here we follow the example in Reference 52 for computing the thermal coefficient
of expansion, heat capacity, enthalpy and entropy for Ni as a function of temperature.
We start by computing the equation of state for fcc Ni.
1
2
3
4
5
6
7
8
9
10
11
# fcc
LC = [3.5, 3.55, 3.6, 3.65, 3.7, 3.75]
volumes, energies = [], []
for a in LC:
atoms = Atoms([Atom(Ni, (0, 0, 0), magmom=2.5)],
cell=0.5 * a * np.array([[1.0, 1.0, 0.0],
[0.0, 1.0, 1.0],
[1.0, 0.0, 1.0]]))
12
13
14
15
16
17
18
19
20
21
22
23
24
with jasp(bulk/Ni-{0}.format(a),
xc=PBE,
encut=350,
kpts=(12,12,12),
ispin=2,
atoms=atoms) as calc:
try:
e = atoms.get_potential_energy()
energies.append(e)
volumes.append(atoms.get_volume())
except:
pass
25
26
27
if len(energies) != len(LC):
import sys; sys.exit()
28
29
30
31
32
33
112
4.7
So far we have only considered relative stability at a pressure of 0 Pa. We now consider the relative
stability of two phases under pressure. Wewill consider TiO2 in the rutile and anatase phases.
E
The pressure is defined by: P = V
. So if we have an equation of state E(V ) we can calculate
T
the pressure at any volume, or alternatively, given a pressure, compute the volume. Pressure can affect
the energy of two phases differently, so that one may become stable under pressure. The condition where
a phase transition occurs is when the pressure in the two phases is the same, which occurs at a common
tangent.
To show this, we need Erutile (V ) and Eanatase (V ).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
nTiO2 = len(atoms) / 3.
v0 = atoms.get_volume()
cell0 = atoms.get_cell()
27
28
113
29
30
31
32
for v in volumes:
atoms.set_cell(cell0 * ((nTiO2 * v / v0)**(1. / 3.)),
scale_atoms=True)
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
with jasp(bulk/TiO2/rutile/rutile-{0}.format(v),
encut=350,
kpts=(6, 6, 6),
xc=PBE,
ismear=0,
sigma=0.001,
isif=2,
ibrion=2,
nsw=20,
atoms=atoms) as calc:
try:
calc.calculate()
except (VaspSubmitted, VaspQueued):
pass
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
nTiO2 = len(atoms) / 3.
v0 = atoms.get_volume()
cell0 = atoms.get_cell()
23
24
25
26
27
28
for v in volumes:
atoms.set_cell(cell0 * ((nTiO2*v/v0)**(1./3.)),
scale_atoms=True)
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
with jasp(bulk/TiO2/anatase/anatase-{0}.format(v),
encut=350,
kpts=(6, 6, 6),
xc=PBE,
ismear=0,
sigma=0.001,
isif=2,
ibrion=2,
nsw=20,
atoms=atoms) as calc:
try:
calc.calculate()
except (VaspSubmitted, VaspQueued):
pass
114
np.set_printoptions(precision=2)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# cubic polynomial fit to equation of state E(V) = pars*[V^3 V^2 V^1 V^0]
apars = np.polyfit(a_volumes, a_energies, 3)
rpars = np.polyfit(r_volumes, r_energies, 3)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
print
print P_anatase(V) = {0:1.2f}*V^2 + {1:1.2f}*V + {2:1.2f}.format(*dapars)
print P_rutile(V) = {0:1.2f}*V^2 + {1:1.2f}*V + {2:1.2f}.format(*drpars)
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
plt.xlabel(Volume ($\AA^3$/f.u.))
plt.ylabel(Total energy (eV/f.u.))
plt.legend()
plt.xlim([25, 40])
plt.ylim([-27, -26])
plt.savefig(images/rutile-anatase-eos.png)
3
4
5
6
7
8
1.30279404e-01,
1.42966536e-01,
-5.23520055e+00,
-5.33239733e+00,
9
10
11
12
5.23520055e+00])
5.33239733e+00])
13
14
15
16
17
def func(V):
V1 = V[0] # rutile volume
V2 = V[1] # anatase volume
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
34.60893508]
At a pressure of 4.5 GPa, we expect that anatase will start converting into rutile. Along this common
tangent, a mixture of the two phases will be more stable than either pure phase.
TODO add literature discussion
there is some controversy about the most stable phase. add
discussion here.
4.8
4.8.1
In this section we will consider how to calculate the formation energy of an fcc Cu-Pd alloy and how to
use that information to discuss relative stabilities. The kinds of questions we can easily answer are:
116
4
5
6
7
8
0.000,
1.818],
0.000],
1.818]])
0.000])],
9
10
11
12
13
14
15
16
17
18
19
with jasp(bulk/alloy/cu,
xc=PBE,
encut=350,
kpts=(13, 13, 13),
nbands=9,
ibrion=2,
isif=3,
nsw=10,
atoms=atoms) as calc:
cu = atoms.get_potential_energy()
20
21
22
23
24
0.000])],
25
26
27
28
29
30
31
32
33
34
35
with jasp(bulk/alloy/pd,
xc=PBE,
encut=350,
kpts=(13, 13, 13),
nbands=9,
ibrion=2,
isif=3,
nsw=10,
atoms=atoms) as calc:
pd = atoms.get_potential_energy()
36
37
38
1
2
3
4
5
6
7
8
0.000]),
2.039])],
9
10
11
12
13
14
15
16
17
18
19
with jasp(bulk/alloy/cupd-1,
xc=PBE,
encut=350,
kpts=(12, 12, 8),
nbands=17,
ibrion=2,
isif=3,
nsw=10,
atoms=atoms) as calc:
cupd1 = atoms.get_potential_energy()
20
21
22
23
24
25
26
27
0.049,
11.170,
7.415,
3.804,
5.629 ],
5.629 ],
3.701 ]])
0.049]),
11.170]),
7.415]),
3.804])],
28
29
30
31
32
33
34
35
36
37
38
with jasp(bulk/alloy/cupd-2,
xc=PBE,
encut=350,
kpts=(8,8,8),
nbands=34,
ibrion=2,
isif=3,
nsw=10,
atoms=atoms) as calc:
cupd2 = atoms.get_potential_energy()
39
40
41
2
3
4
5
6
7
8
9
10
11
12
After normalizing by number of atoms, we can see that cupd-1 is a more stable structure. However,
we are looking at total energies, and we might ask: is cupd-1 more stable than an unreacted mixture of
the parent compounds, fcc Cu and Pd? In other words, is the following reaction exothermic:
Cu + Pd CuPd for the two configurations we examined? Below, we show some pretty general
code that computes these formation energies, and normalizes them by the number of atoms in the unit
cell.
1
2
3
4
5
6
# bulk energy 1
with jasp(bulk/alloy/cu) as calc:
atoms = calc.get_atoms()
cu = atoms.get_potential_energy()/len(atoms)
7
8
9
10
11
# bulk energy 2
with jasp(bulk/alloy/pd) as calc:
atoms = calc.get_atoms()
pd = atoms.get_potential_energy()/len(atoms)
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
3
4
5
6
7
# parent metals
with jasp(bulk/alloy/cu) as calc:
atoms = calc.get_atoms()
cu = atoms.get_potential_energy()/len(atoms)
8
9
10
11
12
13
14
15
16
atoms = Atoms([Atom(Cu,
Atom(Cu,
Atom(Cu,
Atom(Pd,
[-3.672,
[0.000,
[-10.821,
[-7.246,
3.672,
0.000,
10.821,
7.246,
3.672]),
0.000]),
10.821]),
7.246])],
119
17
18
19
cell=[[-5.464,
[-3.565,
[-5.464,
3.565,
5.464,
5.464,
5.464],
5.464],
3.565]])
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
with jasp(bulk/alloy/cu3pd-1,
xc=PBE,
encut=350,
kpts=(8, 8, 8),
nbands=34,
ibrion=2,
isif=3,
nsw=10,
atoms=atoms) as calc:
e3 = atoms.get_potential_energy()
for atom in atoms:
if atom.symbol == Cu:
e3 -= cu
else:
e3 -= pd
e3 /= len(atoms)
print Delta Hf cu3pd-1 = {0:1.2f} eV/atom.format(e3)
3
4
5
6
7
= {0} eV.format(Hf1 +
(x0 - x)
/ (x0 - x3)
* (Hf3 - Hf1))
= -0.06 eV
We find the weighted composition formation energy of pure Cu and cupd-1 is more favorable than the
formation energy of cu3pd-1. Therefore, we could expect that structure to phase separate into a mixture
of pure Cu and cupd-1. Schematically what we are seeing is shown in Figure ??fig:alloy-phase-separation.
Finally, let us consider one more structure with the Cu3 Pd stoichiometry.
1
2
3
4
5
6
7
# parent metals
with jasp(bulk/alloy/cu) as calc:
atoms = calc.get_atoms()
cu = atoms.get_potential_energy()/len(atoms)
8
9
10
11
12
13
14
15
16
17
1.867,
0.000,
1.867,
0.000,
0.000],
0.000]),
0.000]),
1.867]),
1.86])],
120
[0.000,
[0.000,
18
19
0.000,
3.735,
3.735],
0.000]])
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
with jasp(bulk/alloy/cu3pd-2,
xc=PBE,
encut=350,
kpts=(8, 8, 8),
nbands=34,
ibrion=2,
isif=3,
nsw=10,
atoms=atoms) as calc:
e4 = atoms.get_potential_energy()
for atom in atoms:
if atom.symbol == Cu:
e4 -= cu
else:
e4 -= pd
e4 /= len(atoms)
print Delta Hf cu3pd-2 = {0:1.2f} eV/atom.format(e4)
4
5
6
# http://phycomp.technion.ac.il/~ira/types.html#Cu2O
a = 4.27
7
8
9
10
11
12
13
14
15
16
17
18
with jasp(bulk/Cu2O,
encut=400,
121
19
20
21
22
23
24
25
26
27
kpts=(8, 8, 8),
ibrion=2,
isif=3,
nsw=30,
xc=PBE,
atoms=atoms) as calc:
calc.set_nbands()
calc.calculate()
print calc
1
2
3
4
5
6
7
8
9
10
11
12
# CuO
# http://cst-www.nrl.navy.mil/lattice/struk/b26.html
# http://www.springermaterials.com/docs/info/10681727_51.html
a = 4.6837
b = 3.4226
c = 5.1288
beta = 99.54/180*np.pi
y = 0.5819
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
with jasp(bulk/CuO,
encut=400,
kpts=(8, 8, 8),
ibrion=2,
isif=3,
nsw=30,
xc=PBE,
atoms=atoms) as calc:
calc.set_nbands()
calc.calculate()
print calc
123
isif:
encut:
magmom:
prec:
kpts:
reciprocal:
xc:
txt:
gamma:
3
400.0
None
Normal
(8, 8, 8)
False
PBE
False
Pseudopotentials used:
---------------------O: potpaw_PBE/O/POTCAR (git-hash: 9a0489b46120b0cad515d935f44b5fbe3a3b1dfa)
Cu: potpaw_PBE/Cu/POTCAR (git-hash: a44c591415026f53deb16a99ca3f06b1e69be10b)
Reaction energy calculation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# make sure to use the same cutoff energy for the O2 molecule!
with jasp(molecules/O2-sp-triplet-400) as calc:
atoms = calc.get_atoms()
o2_energy = atoms.get_potential_energy()
18
19
20
4
5
6
H = 1. # kJ/g
print rxn energy = {0:1.1f} eV.format(-2 * H * MW / 96.4)
# convert to eV
124
4.9
The density of states refers to the number of electronic states in a particular energy range.
The solution to Eq. (2.1) yields a set of Kohn-Sham (K-S) orbitals and an associated set of eigenvalues
that correspond to the energies of these orbitals, neither of which have any known directly observable
meaning. 18 The sum of the squared K-S orbitals, however, is equal to the electron density (Eq. (2.1)), and
the sum of the eigenvalues is a significant part of the total energy (Eq. (2.1)). Thus, it seems reasonable
to suppose these quantities have other significant relationships to physical observables. Perdew et al.
showed that the highest occupied eigenvalue is equal to the ionization energy of a system within an exact
density functional theory, 24 but their interpretation has been vigorously debated in the literature, 5658
and is only true for the exact exchange/correlation functional, not the approximate ones used in practice. 3
Stowasser and Hoffmann discussed an approach to using the K-S orbitals in more traditional molecular
orbital interpretations, but the results were primarily qualitative. 59 More recently, a DFT analog of
Koopmans theorem has been developed that formally identifies the eigenvalues with vertical ionization
potentials, which can be measured with photoelectron spectroscopy. 60
Despite the arguments against ascribing physical meaning to the K-S orbitals and eigenvalues, it has
become fairly standard, especially for solids, to use them to calculate the density of states (DOS) 61 [Sec.
VI. B]. This has been found to yield reasonable results for the valence bands in metals, but poor results
for tightly bound orbitals and band gaps. 24 A highly technical discussion of this issue can be found in
Ref. 62 . The density of states can be calculated by a sum over the k-points: 15
()=
P
P
_\mathbf{k} _\mathbf{k} _i ( -i {k}) (7)
where k is the weight associated with the k-point, and is a broadening function, typically a
gaussian function, to account for the finite number of k-points used in the calculations. The amount of
broadening is arbitrary, and should tend to zero as the number of k-points approaches infinity.
1
2
3
4
npoints = 200
width = 0.1
5
6
7
8
9
10
11
12
13
# kpt weights
wk = calc.get_k_point_weights()
14
15
16
17
18
19
20
21
22
23
24
25
26
27
125
28
29
30
31
32
for j in range(npoints):
for k in range(len(wk)): # loop over all kpoints
for i in range(len(e_kn[k])): # loop over eigenvalues in each k
dos[j] += wk[k] * gaussian(energies[j], e_kn[k][i])
33
34
35
36
37
4
5
6
7
8
9
10
11
12
13
14
126
1
2
3
4
5
6
7
8
9
10
11
12
13
bulk.get_potential_energy()
dos = DOS(calc, width=0.2)
d = dos.get_dos()
e = dos.get_energies()
14
15
16
17
18
19
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
for k in kpts:
with jasp(bulk/pd-dos-k{0}-ismear-5.format(k),
encut=300,
xc=PBE,
kpts=(k, k, k),
atoms=bulk) as calc:
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
plt.plot(e,d, label=k={0}.format(k))
except:
pass
plt.xlabel(energy (eV))
plt.ylabel(DOS)
plt.legend()
plt.savefig(images/pd-dos-k-convergence-ismear-5.png)
plt.show()
4.10
One major disadvantage of a planewave basis set is that it is difficult to relate the completely delocalized
planewaves to localized phenomena such as bonding. Much insight into bonding has been gained by
127
atomic/molecular orbital theory, which has carried over to the solid-state arena. 7 Consequently, several
schemes have been developed to project the one-electron Kohn-Sham wave functions onto atomic wave
functions. 6365 In VASP, the one electron wave functions can be projected onto spherical harmonic
orbitals. The radial component of the atomic orbitals extends to infinity. In a solid, this means that
the projection on one atom may overlap with the projection on a neighboring atom, resulting in double
counting of electrons. Consequently, a cutoff radius was introduced, beyond which no contributions are
included. It is not obvious what the best cutoff radius is. If the radius is too small, it might not capture
all of the electrons associated with the atom. However, if it is too large, it may include electrons from
neighboring atoms. One might want to use different cutoff radii for different atoms, which have different
sizes. Furthermore, the ideal cutoff radius for an atom may change in different environments, thus it
would require an iterative procedure to determine it. This difficulty arises because the orbital-band
occupations are not observable, thus how the electrons are divided up between atoms is arbitrary and,
as will be seen later, is sensitive to the cutoff radius (and in other DFT implementations, the basis
set). However, Mulliken orbital populations have been used successfully for many years to examine the
qualitative differences between similar systems, and that is precisely what these quantities are used for
here. Thus, a discussion of the analysis and results is warranted.
The s and p states in a metal are typically delocalized in space and more like free-electrons, whereas
the d-orbitals are fairly localized in space and have been treated successfully with tight-binding theories
such as extended H\"u ckel theory, 7 and linear muffin tin orbital theory. 66 Consequently, the remaining
discussion will be focused on the properties of the projected d-states.
In this example, we consider how to get the atom-projected density of states (ADOS). We are interested in properties of the d-band on Pd, such as the d-band center and d-band width. You must set
the RWIGS tag to get ADOS, and these are the Wigner-Seitz radii for each atom. By integrating the
projected d-band up to the Fermi level, the d-band filling can be determined. It is not obvious what the
electron count in the d-band should be for an atom in a metal. For a gas-phase, neutral metal atom in
the ground state, however, the d-orbital electron count is well defined, so it will be used as an initial
reference point for comparison. 4
A powerful method for characterizing distributions is to examine various moments of the distribution
(see Chapter 4 in Ref. 67 and Chapter 6 in Refs. 68 and 69 ). The nth order moment, n , of a distribution
of states () with respect to a reference o is defined by
R n
( o )d
R
(8)
n =
( o )d
In this work, the reference energy is always the Fermi level. The zeroth moment is just the total number of
states, in this case it will be normalized to unity. The first moment is the average energy of distribution,
analogous to the center of mass for a mass density distribution. The second moment is the mean squared
width of the distribution. The third moment is a measure of skewness and the fourth moment is related
to kurtosis, but these moments are rarely used, and only the first and second moments are considered in
this work.
It is important to note that these projected density of states are not physical observables. They
are the wavefunctions projected onto atomic orbitals. For some situations this makes sense, e.g. the d
orbitals are fairly localized and reasonably approximated by atomic orbitals. The s valence orbitals in a
metal, in contrast, are almost totally delocalized. Depending on the cutoff radius (RWIGS) you choose,
you can see very different ADOS.
1
2
3
4
5
6
7
8
9
10
128
cell=[(0, b, b),
(b, 0, b),
(b, b, 0)])
11
12
13
14
15
16
17
18
19
20
21
with jasp(bulk/pd-ados,
encut=300,
xc=PBE,
lreal=False,
rwigs=[1.5], # wigner-seitz radii for ados
kpts=(8, 8, 8),
atoms=bulk) as calc:
22
23
24
25
26
27
28
29
30
energies = ados.energy
dos = ados.site_dos(0, d)
31
32
33
34
35
36
energies = energies[ind]
dos = dos[ind]
37
38
39
40
41
42
43
44
45
# second moment
wd2 = np.trapz(energies**2 * dos, energies) / np.trapz(dos, energies)
46
47
48
49
50
print
print
print
print
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
plt.savefig(images/pd-ados.png)
plt.show()
4.10.1
Here we examine the effect of changing RWIGS on the number of counted electrons, and properties of
the d-band moments.
1
2
3
129
import sys
5
6
7
8
9
10
11
12
13
14
15
16
RWIGS = [1.0, 1.1, 1.25, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0 ]
17
18
19
20
21
22
23
24
25
26
27
try:
28
calc.calculate()
except (VaspSubmitted, VaspQueued):
continue
29
30
31
32
33
34
35
36
energies = ados.energy
dos = ados.site_dos(0, d)
37
38
39
40
41
42
energies = energies[ind]
dos = dos[ind]
43
44
45
46
47
48
49
50
51
52
N.append(N_occupied_states)
ED.append(ed)
WD.append(wd2**0.5)
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
ax2 = ax1.twinx()
ax2.plot(RWIGS, WD, gs, label=d-band width (eV))
ax2.set_ylabel(d-band width (eV), color=g)
for tl in ax2.get_yticklabels():
tl.set_color(g)
73
74
75
plt.savefig(images/ados-rwigs-moments.png)
plt.show()
130
You can see the number of occupied states increases approximately linearly here with RWIGS. This
is due to overcounting of neighboring electrons.
The d-band center and width also change.
4.11
Band structures
To compute a band structure we do two things. First, we compute the self-consistent band structure.
Then we compute the band structure at the desired k-points. We will use Si as an example (adapted
from http://bbs.sciencenet.cn/bbs/upload/20083418325986.pdf).
First, we get the self-consistent electron density in a calculation.
1
2
3
4
5
6
7
a = 5.38936
atoms = Atoms([Atom(Si, [0, 0, 0]),
Atom(Si, [0.25, 0.25, 0.25])])
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
with jasp(bulk/Si-selfconsistent,
xc=PBE,
prec=Medium,
istart=0,
icharg=2,
ediff=0.1e-03,
kpts=(4, 4, 4), debug=logging.DEBUG,
atoms=atoms) as calc:
atoms.get_potential_energy()
print calc
ediff:
magmom:
prec:
kpts:
reciprocal:
xc:
txt:
gamma:
0.0001
None
Medium
(4, 4, 4)
False
PBE
False
Pseudopotentials used:
---------------------Si: potpaw_PBE/Si/POTCAR (git-hash: ae2291fdf186a34272463039fb5a87cde0e50174)
Now, we run a new calculation along the k-point path desired. The standard VASP way of doing this
is to modify the INCAR and KPOINTS file and rerun VASP. We will not do that. Doing that results in
some lost information if you overwrite the old files. We will copy the old directory to a new directory,
using code to ensure this only happens one time.
1
2
3
wd = bulk/Si-bandstructure
4
5
6
7
8
9
10
11
# L
# Gamma
# X
12
13
14
15
16
17
18
19
with jasp(wd,
kpts=kpts,
reciprocal=True,
kpts_nintersections=10,
icharg=11) as calc:
calc.calculate()
print(calc)
132
INCAR Parameters:
----------------nbands: 8
istart: 0
icharg: 11
ediff: 0.0001
magmom: None
prec: Medium
kpts: [[0.5, 0.5, 0.0], [0, 0, 0], [0, 0, 0], [0.5, 0.5, 0.5]]
kpts_nintersections: 10
reciprocal: True
xc: PBE
txt: gamma: False
Pseudopotentials used:
---------------------Si: potpaw_PBE/Si/POTCAR (git-hash: ae2291fdf186a34272463039fb5a87cde0e50174)
We will learn how to manually parse the EIGENVAL file here to generate the band structure. The
structure of the EIGENVAL file looks like this:
1
head -n 20 bulk/Si-bandstructure/EIGENVAL
0.3810853E-09
0.3810853E-09
0.5000000E+00 0.5000000E+00
1
-1.826311
2
-1.826306
3
3.153690
4
3.153716
5
6.744294
6
6.744321
7
16.392989
8
16.405965
0.0000000E+00
0.5000000E-01
0.4444444E+00 0.4444444E+00
1
-2.669062
2
-0.918013
0.0000000E+00
0.5000000E-01
f = open(bulk/Si-bandstructure/EIGENVAL, r)
2
3
4
5
6
line1
line2
line3
line4
=
=
=
=
f.readline()
f.readline()
f.readline()
f.readline()
133
0.5000000E-15
7
8
comment = f.readline()
unknown, nkpoints, nbands = [int(x) for x in f.readline().split()]
9
10
blankline = f.readline()
11
12
13
14
15
for i in range(nkpoints):
x, y, z, weight = [float(x) for x in f.readline().split()]
16
17
18
19
20
21
22
for j in range(nbands):
fields = f.readline().split()
id, energy = int(fields[0]), float(fields[1])
band_energies[id - 1].append(energy)
blankline = f.readline()
f.close()
23
24
25
26
27
for i in range(nbands):
plt.plot(range(nkpoints), band_energies[i])
28
29
30
31
32
33
34
35
ax = plt.gca()
ax.set_xticks([]) # no tick marks
plt.xlabel(k-vector)
plt.ylabel(Energy (eV))
ax.set_xticks([0, 10, 19])
ax.set_xticklabels([$L$, $\Gamma$, $X$])
plt.savefig(images/Si-bandstructure.png)
3
4
5
6
7
8
9
10
11
12
p.savefig(images/tio2-bandstructure-dos.png)
In this section, we examine the effect of the lattice constant on the band structure. Since the lattice
constant affects the overlap of neighboring atoms, we expect that smaller lattice constants will show
more dispersion, i.e. broader bands. Larger lattice constants, in contrast, should show narrower bands.
We examine this in silicon.
1
2
3
4
5
6
7
8
9
10
11
12
134
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
with jasp(bulk/Si-bs-{0}.format(i),
xc=PBE,
prec=Medium,
istart=0,
icharg=2,
ediff=0.1e-03,
kpts=(4, 4, 4),
atoms=atoms) as calc:
try:
n,bands,p = calc.get_bandstructure(kpts_path=[(L, [0.5,0.5,0.0]),
($\Gamma$, [0, 0, 0]),
($\Gamma$, [0, 0, 0]),
(X, [0.5, 0.5, 0.5])],
kpts_nintersections=10)
except (VaspSubmitted, VaspQueued):
print not ready {0}.format(i)
ready = False
32
33
34
if not ready:
import sys; sys.exit()
35
36
37
38
p.savefig(images/Si-bs-{0}.png.format(i))
p.show()
4.12
Magnetism
4.12.1
We can force a total magnetic moment onto a unit cell and compute the total energy as function of
the total magnetic moment. If there is a minimum in the energy, then we know there is a lower energy
magnetic solution than a non-magnetic solution. We use incar:NUPDOWN to enforce the magnetic
moment in the cell. Note that NUPDOWN can only be an integer. You cannot set it to be an arbitrary
float.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
NUPDOWNS
energies
for B in
with
25
26
27
135
28
29
30
31
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
with jasp(bulk/Fe-bcc-sp-1,
xc=PBE,
encut=300,
kpts=(4, 4, 4),
ispin=2,
lorbit=11, # you need this for individual magnetic moments
atoms=atoms) as calc:
try:
e = atoms.get_potential_energy()
B = atoms.get_magnetic_moment()
magmoms = atoms.get_magnetic_moments()
except (VaspSubmitted, VaspQueued):
pass
27
28
29
In an antiferromagnetic material, there are equal numbers of spin up and down electrons that align in a
regular pattern, but pointing in opposite directions so that there is no net magnetism. It is possible to
model this by setting the magnetic moments on each mod:ase.Atom object.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
with jasp(bulk/afm-feo,
encut=350,
prec=Normal,
ispin=2,
nupdown=0, # this forces a non-magnetic solution
lorbit=11, # to get individual moments
lreal=False,
136
atoms=atoms) as calc:
print Magnetic moments = , atoms.get_magnetic_moments()
print Total magnetic moment = , atoms.get_magnetic_moment()
[ 2.652 -2.652
0.
0.
137
138
139
140
Figure 35: Total energy vs. fcc lattice contant for Cu. It appears the minimum is near 3.65 .
Figure 36: Total energy vs. volume for fcc Cu with fitted cubic polynomial equation of state.
141
Figure 37: Comparison of energies between fcc and bcc Cu. The fcc structure is lower in energy.
142
143
Figure 39: Contour plot of the total energy of hcp Ru for different values of a and c/a.
144
145
Figure 41: Total energy vs. volume for rutile TiO2 in step 1 of the optimization.
146
Figure 42: Total energy vs. volume for step 2 of the unit cell optimization.
147
Figure 43: Equations of state (E(V)) for anatase and rutile TiO2 .
148
Figure 44: Illustration of the common tangent that shows the pressure where anatase and rutile coexist
before anatase converts to rutile.
149
Figure 45: Conceptual picture of two alloys with exothermic formation energies. The dashed line represents a composition weighted average energy of the parent metals. E4 and E3 are energies associated
with two different alloy structures at the same composition. Both structures are more stable than a
mixture of pure metals with the same composition, but E3 is more stable than E4.
150
Figure 46: Illustration of of an alloy structure with an exothermic formation energy that is not stable
with respect to phase separation. The solid line shows the composition weighted average energy of a
mixture of Cu and cupd-2. Since the energy of cu3pd-1 is above the solid line, it is less favorable than a
mixture of Cu and cupd-2 with the same composition.
151
Figure 47: Illustration that cu3pd-2 is more stable than cu3pd-1 and that is it is more stable than a
composition weighted mixture of Cu and cupd-1. The dotted line shows the energy of a composition
weighted average energy of a mixture of Cu and cupd-1. Since cu3pd-2 is below the dotted line, it is
more stable than the phase-separated mixture.
152
153
Surfaces
5.1
Surface structures
As with molecules and bulk systems mod:ase provides several convenience functions for making surfaces.
5.1.1
Simple surfaces
ase provides many utility functions to setup surfaces. Here is a simple example of an fcc111 Al surface.
There are built in functions for fcc111, bcc110, bcc111, hcp001 and diamond111.
1
2
3
4
5
6
154
Vicinal surfaces
The vast majority of surface calculations are performed on flat surfaces. This is partially because these
surfaces tend to have the lowest surface energies, and thus are likely to be experimentally observed. The
flat surfaces, also known as low Miller index surfaces, also have small unit cells, which tends to make
them computationally affordable. There are, however, many reasons to model the properties of surfaces
155
that are not flat. You may be interested in the reactivity of a step edge, for example, or you may use the
lower cooridnation of steps as a proxy for nanoparticle reactivity. Many stepped surfaces are not that
difficult to make now. The main idea in generating them is described here. mod:ase provides a general
function for making vicinal surfaces. Here is an example of a (211) surface.
1
2
3
4
5
6
7
8
9
10
11
write(images/Au-211.png,
s1.repeat((3, 3, 1)),
rotation=-30z,90x, # change the orientation for viewing
show_unit_cell=2)
156
157
5.2
There is one important parameter that is different for surfaces than for bulk calculations, the k-point
grid. Assuming you have followed the convention that the z-axis is normal to the surface, the k-point
grids for slab calculations always have the form of M N 1. To illustrate why, consider this example:
1
2
3
4
5
from
from
from
from
slab
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
with jasp(surfaces/Al-bandstructure,
xc=PBE,
encut=300,
kpts=(6, 6, 6),
atoms=slab) as calc:
n, bands, p = calc.get_bandstructure(kpts_path=[(r$\Gamma$, [0, 0, 0]),
($K1$, [0.5, 0.0, 0.0]),
($K1$, [0.5, 0.0, 0.0]),
($K2$, [0.5, 0.5, 0.0]),
($K2$, [0.5, 0.5, 0.0]),
(r$\Gamma$, [0, 0, 0]),
(r$\Gamma$, [0, 0, 0]),
($K3$, [0.0, 0.0, 1.0])],
kpts_nintersections=10)
21
22
23
p.savefig(images/Al-slab-bandstructure.png)
p.show()
5.3
Surface relaxation
When a surface is created, the bulk symmetry is broken and consequently there will be forces on the
surface atoms. We will examine some consequences of this with a simple Al slab. First, we show there
are forces on the slab atoms.
1
2
3
4
5
6
7
8
9
10
11
12
with jasp(surfaces/Al-slab-unrelaxed,
xc=PBE,
kpts=(6, 6, 1),
encut=350,
atoms=atoms) as calc:
atoms.get_forces()
print calc
Figure 62: Band structure of an Al slab in the plane (path from Gamma to K1 to K2 to Gamma) and
normal to the surface (Gamma to K3). Note the bands are flat in the direction normal to the surface,
hence only one k-point is needed in this direction.
Unit cell volume = 191.872 Ang^3
Stress (GPa):xx,
yy,
zz,
yz,
xz,
xy
0.007 0.007 0.002-0.000 -0.000 -0.000
Atom# sym
position [x,y,z]tag rmsForce constraints
0
Al [0.000
0.000
10.000] 0
0.01
T T
1
Al [1.432
0.827
12.338] 0
0.18
T T
2
Al [2.864
1.653
14.677] 0
0.18
T T
3
Al [0.000
0.000
17.015] 0
0.01
T T
-------------------------------------------------INCAR Parameters:
----------------nbands: 10
encut: 350.0
magmom: None
prec: Normal
kpts: (6, 6, 1)
reciprocal: False
xc: PBE
txt: gamma: False
159
T
T
T
T
Pseudopotentials used:
---------------------Al: potpaw_PBE/Al/POTCAR (git-hash: c8d9ecb0b6ebec0256c5f5072cee4de6a046dac2)
Some points to note. The forces on the atoms have symmetry to them. That is because the slab is
centered. Had the slab had an odd number of atoms, it is likely the center atom would have no forces
on it. Next we consider the spacing between each layer in the slab. We do this for comparison later.
1
2
3
4
5
6
7
8
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
with jasp(surfaces/Al-slab-relaxed,
xc=PBE,
kpts=(6, 6, 1),
encut=350,
ibrion=2,
isif=2,
nsw=10,
atoms=atoms) as calc:
calc.calculate()
print calc
Energy = -14.181417 eV
Unit cell vectors (angstroms)
x
y
z
length
a0 [ 2.864 0.000 0.000] 2.864
a1 [ 1.432 2.480 0.000] 2.864
a2 [ 0.000 0.000 27.015] 27.015
a,b,c,alpha,beta,gamma (deg):2.864 2.864 27.015 90.0 90.0 90.0
Unit cell volume = 191.872 Ang^3
Stress (GPa):xx,
yy,
zz,
yz,
xz,
xy
0.006 0.006 0.001-0.000 -0.000 -0.000
Atom# sym
position [x,y,z]tag rmsForce constraints
0
Al [0.000
0.000
10.000] 4
0.00
F F F
1
Al [1.432
0.827
12.338] 3
0.00
F F F
2
Al [2.864
1.653
14.637] 2
0.05
T T T
3
Al [0.000
0.000
16.982] 1
0.02
T T T
-------------------------------------------------INCAR Parameters:
----------------nbands: 10
nsw: 10
ibrion: 2
isif: 2
encut: 350.0
magmom: None
kpts: (6, 6, 1)
reciprocal: False
xc: PBE
txt: gamma: False
Pseudopotentials used:
---------------------Al: potpaw_PBE/Al/POTCAR (git-hash: c8d9ecb0b6ebec0256c5f5072cee4de6a046dac2)
You can see that atoms 2 and 3 (the ones we relaxed, because the have tags of 1 and 2, which are less
than 3) now have very low forces on them and it appears that atoms 0 and 1 have no forces on them.
That is because the FixAtoms constraint works by setting the forces on those atoms to zero. We can see
in the next example that the z-positions of the relaxed atoms have indeed relaxed and changed, while
the position of the frozen atoms did not change.
Note there are two versions of the forces. The true forces, and the forces when constraints are applied.
1
2
3
4
5
6
7
8
[[ 0.
0.
0.
]
161
[ 0.
0.
0.
]
[ 0.
0.
-0.049]
[ 0.
0.
-0.019]]
Constraints = False: [[ 0.
[ 0.
0.
0.069]
[ 0.
0.
-0.049]
[ 0.
0.
-0.019]]
1
2
0.
-0.002]
3
4
5
6
7
8
9
10
5.4
Surface reconstruction
We previously considered how relaxation can lower the surface energy. For some surfaces, a more extreme
effect can reduce the surface energy: reconstruction. In a simple surface relaxation, the basic structure
of a surface is preserved. However, sometimes there is a different
We first consider the Au(110) case, where the reconstruction is known to be favorable.
162
from
from
from
from
jasp import *
ase.lattice.surface import fcc110
ase.io import write
ase.constraints import FixAtoms
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
with jasp(surfaces/Au-110,
xc=PBE,
kpts=(6, 6, 1),
encut=350,
ibrion=2,
isif=2,
nsw=10,
atoms=atoms) as calc:
calc.calculate()
from
from
from
from
jasp import *
ase.lattice.surface import fcc110
ase.io import write
ase.constraints import FixAtoms
5
6
7
8
9
10
11
12
13
14
15
write(images/Au-110-missing-row.png,
atoms.repeat((2, 2, 1)),
rotation=-90x,
show_unit_cell=2)
16
17
18
19
20
21
22
23
24
25
with jasp(surfaces/Au-110-missing-row,
xc=PBE,
kpts=(6, 6, 1),
encut=350,
ibrion=2,
isif=2,
nsw=10,
atoms=atoms) as calc:
calc.calculate()
4
5
6
7
8
9
10
11
12
13
14
15
16
with jasp(bulk/Au-fcc,
xc=PBE,
encut=350,
kpts=(12, 12, 12),
atoms=atoms) as calc:
calc.calculate()
163
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from
from
from
from
jasp import *
ase.lattice.surface import fcc110
ase.io import write
ase.constraints import FixAtoms
5
6
7
8
9
10
11
12
13
14
15
16
17
18
with jasp(surfaces/Ag-110,
xc=PBE,
kpts=(6, 6, 1),
encut=350,
ibrion=2,
isif=2,
nsw=10,
atoms=atoms) as calc:
calc.calculate()
164
from
from
from
from
jasp import *
ase.lattice.surface import fcc110
ase.io import write
ase.constraints import FixAtoms
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
with jasp(surfaces/Ag-110-missing-row,
xc=PBE,
kpts=(6, 6, 1),
encut=350,
ibrion=2,
isif=2,
nsw=10,
atoms=atoms) as calc:
calc.calculate()
4
5
6
7
8
9
10
11
12
13
14
15
16
with jasp(bulk/Ag-fcc,
xc=PBE,
encut=350,
kpts=(12, 12, 12),
atoms=atoms) as calc:
calc.calculate()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
165
natoms slab
= 12
natoms missing row = 11
natoms bulk
= 1
dE = -0.008 eV
For Ag(110), the missing row formation energy is practically thermoneutral, i.e. not that favorable.
This energy is so close to 0eV, that we cannot confidently say whether the reconstruction is favorable or
not. Experimentally, the reconstruction is not seen on very clean Ag(110) although it is reported that
some adsorbates may induce the reconstruction. 76
5.4.3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
with jasp(surfaces/Cu-110,
xc=PBE,
kpts=(6, 6, 1),
encut=350,
ibrion=2,
isif=2,
nsw=10,
atoms=atoms) as calc:
calc.calculate()
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
4
5
6
7
166
size=(1, 1, 1),
symbol=Cu)
8
9
10
11
12
13
14
15
16
with jasp(bulk/Cu-fcc,
xc=PBE,
encut=350,
kpts=(12, 12, 12),
atoms=atoms) as calc:
calc.calculate()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
5.5
Work function
To get the work function, we need to have the local potential. This is not written by default in VASP,
and we have to tell it to do that with the LVTOT and LVHAR keywords.
1
2
3
4
5
6
7
8
9
10
11
12
13
with jasp(surfaces/Al-slab-locpot,
xc=PBE,
kpts=(6, 6, 1),
encut=350,
lvtot=True, # write out local potential
lvhar=True, # write out only electrostatic potential, not xc pot
atoms=atoms) as calc:
14
15
16
calc.calculate()
ef = calc.get_fermi_level()
17
167
18
atoms = calc.get_atoms()
19
20
x, y, z, lp = calc.get_local_potential()
21
22
23
24
25
26
27
28
29
30
31
32
33
plt.plot(xaxis, axy)
plt.plot([min(xaxis), max(xaxis)], [ef, ef], k:)
plt.xlabel(Position along z-axis)
plt.ylabel(x-y averaged electrostatic potential)
plt.savefig(images/Al-wf.png)
34
35
36
37
5.6
Surface energy
N
= limN 12 (Eslab
N EN )
N 1
N
where EN = Eslab Eslab
.
We will examine this approach here. We will use unrelaxed slabs for computational efficiency.
1
2
3
4
5
6
7
8
9
for n in Nlayers:
10
11
12
13
14
15
16
17
18
19
20
21
22
23
with jasp(bulk/Cu-layers/{0}.format(n),
xc=PBE,
encut=350,
kpts=(8, 8, 1),
atoms=slab) as calc:
calc.set_nbands(f=2) # the default nbands in VASP is too low for Al
try:
energies.append(slab.get_potential_energy())
except (VaspSubmitted, VaspQueued):
pass
24
25
26
27
28
29
30
31
32
33
34
35
= 3
= 4
= 5
= 6
= 7
= 8
= 9
= 10
sigma
sigma
sigma
sigma
sigma
sigma
sigma
sigma
=
=
=
=
=
=
=
=
0.551
0.399
0.590
0.319
0.578
0.322
0.592
0.403
eV/atom
eV/atom
eV/atom
eV/atom
eV/atom
eV/atom
eV/atom
eV/atom
One reason for the oscillations may be quantum size effects. 79 In 80 the surface energy of Cu(111) is
reported as 0.48 eV/atom, or 1.36 J/m2 . Here is an example showing a conversion between these two
units. We use ase to compute the area of the unit cell from the norm of the cross-product of the vectors
defining the surface unit cell.
1
2
3
4
5
6
7
8
9
10
sigma = 0.48
# eV/atom
11
12
169
The surface energies can be used to estimate the shapes of nanoparticles using a Wulff construction.
See 81 for an example of computing Mo2 C surface energies and particle shapes, and 82 for an example of
the influence of adsorbates on surface energies and particle shapes of Cu.
For a classic paper on trends in surface energies see. 83
5.7
Dipole correction
A subtle problem can arise when an adsorbate is placed on one side of a slab with periodic boundary
conditions, which is currently the common practice. The problem is that this gives the slab a dipole
moment. The array of dipole moments created by the periodic boundary conditions generates an electric
field that can distort the electron density of the slab and change the energy. The existence of this field
in the vacuum also makes the zero-potential in the vacuum ill-defined, thus the work function is not
well-defined. One solution to this problem is to use slabs with adsorbates on both sides, but then very
thick (eight to ten layers) slabs must be used to ensure the adsorbates do not interact through the slab.
An alternative solution, the dipole correction scheme, was developed by Neugebauer and Scheffler 84 and
later corrected by Bengtsson. 85 In this technique, an external field is imposed in the vacuum region that
exactly cancels the artificial field caused by the slab dipole moment. The advantage of this approach is
that thinner slabs with adsorbates on only one side can be used.
There are also literature reports that the correction is small. 86 Nevertheless, in the literature the use
of this correction is fairly standard, and it is typical to at least consider the correction.
Here we will just illustrate the effect.
5.7.1
We simply run the calculation here, and compare the results later.
1
2
3
4
5
6
7
8
9
10
11
slab.center()
write(images/Na-Al-slab.png, slab, rotation=-90x, show_unit_cell=2)
12
13
14
15
16
17
18
19
20
with jasp(surfaces/Al-Na-nodip,
xc=PBE,
encut=340,
kpts=(2, 2, 1),
lvtot=True, # write out local potential
lvhar=True, # write out only electrostatic potential, not xc pot
atoms=slab) as calc:
calc.calculate()
Note this takes a considerably longer time to run than without a dipole correction! In VASP there are
several levels of dipole correction to apply. You can use the IDIPOL tag to turn it on, and specify which
direction to apply it in (1=x, 2=y, 3=z, 4=(x, y, z)). This simply corrects the total energy and forces. It
170
does not change the contents of LOCPOT. For that, you have to also set the LDIPOL and DIPOL tags. It
is not efficient to set all three at the same time for some reason. The VASP manual recommends you first
set IDIPOL to get a converged electronic structure, and then set LDIPOL to True, and set the center
of electron density in DIPOL. That makes these calculations a multistep process, because we must run
a calculation, analyze the charge density to get the center of charge, and then run a second calculation.
1
2
3
4
5
6
7
8
slab.center()
9
10
11
12
13
14
15
16
17
with jasp(surfaces/Al-Na-dip,
xc=PBE,
encut=340,
kpts=(2, 2, 1),
idipol=3,
# only along z-axis
lvtot=True, # write out local potential
lvhar=True, # write out only electrostatic potential, not xc pot
atoms=slab) as calc:
18
19
calc.calculate()
20
21
22
23
24
25
x, y, z, cd = calc.get_charge_density()
n0, n1, n2 = cd.shape
nelements = n0 * n1 * n2
voxel_volume = slab.get_volume() / nelements
total_electron_charge = cd.sum() * voxel_volume
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# we only write 4 decimal places out to the INCAR file, so we round here.
sedc = np.round(sedc, 4)
41
42
calc.clone(surfaces/Al-Na-dip-step2)
43
44
45
46
47
# now run step 2 with dipole set at scaled electron charge density center
with jasp(surfaces/Al-Na-dip-step2,
ldipol=True, dipol=sedc) as calc:
calc.calculate()
4.212
2.419
10.657]
To see the difference in what the dipole correction does, we now plot the potentials from each calculation.
1
2
3
4
5
6
7
8
x, y, z, lp = calc.get_local_potential()
nx, ny, nz = lp.shape
171
10
11
12
13
14
15
e1 = atoms.get_potential_energy()
16
17
18
19
20
21
x, y, z, lp = calc.get_local_potential()
nx, ny, nz = lp.shape
22
23
24
25
26
27
28
29
ef2 = calc.get_fermi_level()
e2 = atoms.get_potential_energy()
30
31
32
33
34
35
36
37
38
39
5.8
5.8.1
Adsorption energies
Simple estimate of the adsorption energy
Calculating an adsorption energy amounts to computing the energy of the following kind of reaction:
slab + gas-phase molecule slab_adsorbate + products
There are many variations of this idea. The slab may already have some adsorbates on it, the slab
may reconstruct on adsorption, the gas-phase molecule may or may not dissociate, and the products may
or may not stick to the surface. We have to decide where to put the adsorbates, i.e. what site to put
them on, and some sites will be more stable than others. We will consider the dissociative adsorption of
O2 on three sites of a Pt(111) slab. We will assume the oxygen molecule has split in half, and that the
atoms have moved far apart. We will model the oxygen coverage at 0.25 ML, which means we need to
use a 2 2 surface unit cell. For computational speed, we will freeze the slab, but allow the adsorbate
to relax.
Hads (eV /O) = Eslab+O Eslab 0.5 EO2
172
Calculations
clean slab calculation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
with jasp(surfaces/Pt-slab,
xc=PBE,
kpts=(4, 4, 1),
encut=350,
atoms=atoms) as calc:
print atoms.get_potential_energy()
fcc site
1
2
3
4
5
6
7
8
9
# note this function only works when atoms are created by the surface module.
add_adsorbate(atoms, O, height=1.2, position=fcc)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
with jasp(surfaces/Pt-slab-O-fcc,
xc=PBE,
kpts=[4, 4, 1],
encut=350,
ibrion=2,
nsw=25,
atoms=atoms) as calc:
24
25
print atoms.get_potential_energy()
173
4
5
6
7
8
# note this function only works when atoms are created by the surface module.
add_adsorbate(atoms, O, height=1.2, position=bridge)
9
10
11
12
13
14
15
16
17
18
19
with jasp(surfaces/Pt-slab-O-bridge,
xc=PBE,
kpts=(4, 4, 1),
encut=350,
ibrion=2,
nsw=25,
atoms=atoms) as calc:
20
21
22
calc.calculate()
print atoms.get_potential_energy()
174
Figure 72: Initial geometry of the bridge site. It is definitely on the bridge.
hcp site
1
2
3
4
5
6
7
8
# note this function only works when atoms are created by the surface module.
add_adsorbate(atoms, O, height=1.2, position=hcp)
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
with jasp(surfaces/Pt-slab-O-hcp,
xc=PBE,
kpts=(4, 4, 1),
encut=350,
ibrion=2,
nsw=25,
atoms=atoms) as calc:
calc.calculate()
175
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
= -1.0384925 eV/O
176
Hads (hcp)
= -0.5986145 eV/O
Hads (bridge) = -1.0381835 eV/O
You can see the hcp site is not as energetically favorable as the fcc site. Interestingly, the bridge
site seems to be as favorable as the fcc site. This is not correct, and to see why, we have to look at the
final geometries of each calculation. First the fcc (Figure 73 and hcp (Figure 74 sites, which look like we
expect.
177
Figure 75: Final geometry of the bridge site. You can see that the oxygen atom ended up in the fcc site.
Let us see what the original geometry and final geometry for the bridge site were. The POSCAR contains the initial geometry (as long as you havent copied CONTCAR to POSCAR), and the CONTCAR
contains the final geometry.
1
2
3
4
atoms = read(surfaces/Pt-slab-O-bridge/POSCAR)
write(images/Pt-o-brige-ori.png, atoms, show_unit_cell=2)
5
6
7
atoms = read(surfaces/Pt-slab-O-bridge/CONTCAR)
write(images/Pt-o-brige-final.png, atoms, show_unit_cell=2)
Figure 76: Initial geometry of the bridge site. It is definitely on the bridge.
178
Figure 77: Final geometry of the bridge site. It has fallen into the fcc site.
You can see the problem. We should not call the adsorption energy from this calculation a bridge
site adsorption energy because the O atom is actually in an fcc site! This kind of result can happen with
relaxation, and you should always check that the result you get makes sense. Next, we consider how to
get a bridge site adsorption energy by using constraints.
Some final notes:
1. We did not let the slabs relax in these examples, and allowing them to relax is likely to have a
big effect on the adsorption energies. You have to decide how many layers to relax, and check for
convergence with respect to the number of layers.
2. The slabs were pretty thin. It is typical these days to see slabs that are 4-5 or more layers thick.
3. We did not consider how well converged the calculations were with respect to k-points or incar:ENCUT.
4. We did not consider the effect of the error in O2 dissociation energy on the adsorption energies.
5. We did not consider coverage effects (see Coverage dependence).
Adsorption on bridge site with constraints To prevent the oxygen atom from sliding down into
the fcc site, we have to constrain it so that it only moves in the z-direction. This is an artificial constraint;
the bridge site is only metastable. But there are lots of reasons you might want to do this anyway. One is
the bridge site is a transition state for diffusion between the fcc and hcp sites. Another is to understand
the role of coordination in the adsorption energies. We use a func:ase.constraints.FixScaled constraint
in ase to constrain the O atom so it can only move in the z-direction (actually so it can only move in
the direction of the third unit cell vector, which only has a z-component).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# note this function only works when atoms are created by the surface module.
add_adsorbate(atoms, O, height=1.2, position=bridge)
constraint1 = FixAtoms(mask=[atom.symbol != O for atom in atoms])
# fix in xy-direction, free in z. actually, freeze movement in surface
# unit cell, and free along 3rd lattice vector
constraint2 = FixScaled(atoms.get_cell(), 12, [True, True, False])
15
16
17
18
atoms.set_constraint([constraint1, constraint2])
write(images/Pt-O-bridge-constrained-initial.png, atoms, show_unit_cell=2)
print Initial O position: {0}.format(atoms.positions[-1])
179
19
20
21
22
23
24
25
26
27
with jasp(surfaces/Pt-slab-O-bridge-xy-constrained,
xc=PBE,
kpts=(4, 4, 1),
encut=350,
ibrion=2,
nsw=25,
atoms=atoms) as calc:
e_bridge = atoms.get_potential_energy()
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
0.
0.
15.726]
15.977]
You can see that only the z-position of the O atom changed. Also, the adsorption energy of O on the
bridge site is much less favorable than on the fcc or hcp sites.
180
Figure 79: Final state of the constrained O atom, still on the bridge site.
5.8.2
Coverage dependence
The adsorbates on the surface can interact with each other which results in coverage dependent adsorption
energies. 87 Coverage dependence is not difficult to model; we simply compute adsorption energies in
different size unit cells, and/or with different adsorbate configurations. Here we consider dissociative
oxygen adsorption at 1ML on Pt(111) in an fcc site, which is one oxygen atom in a 1 1 unit cell.
For additional reading, see these references from our work:
Correlations of coverage dependence of oxygen adsorption on different metals 88,89
Coverage effects of atomic adsorbates on Pd(111) 90
Simple model for estimating coverage dependence 87
Coverage effects on alloys 91
clean slab calculation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
with jasp(surfaces/Pt-slab-1x1,
xc=PBE,
kpts=(8, 8, 1),
encut=350,
atoms=atoms) as calc:
slab_e = atoms.get_potential_energy()
print slab_e
181
2
3
4
5
6
7
8
9
10
# note this function only works when atoms are created by the surface module.
add_adsorbate(atoms, O, height=1.2, position=fcc)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
with jasp(surfaces/Pt-slab-1x1-O-fcc,
xc=PBE,
kpts=(8, 8, 1),
encut=350,
ibrion=2,
nsw=25,
atoms=atoms) as calc:
print atoms.get_potential_energy()
182
2
3
4
5
6
7
8
9
10
# clean slab
with jasp(surfaces/Pt-slab-1x1) as calc:
atoms = calc.get_atoms()
e_slab = atoms.get_potential_energy()
11
12
13
14
15
16
17
There is a small point to make here about what adsorption does to surface energies. Let us define a
general surface formation energy scheme like this:
183
Let us presume the surfaces are symmetric, and that each surface contributes half of the energy
change. The overall change in energy:
E = Eslab,ads Eads Ebulk
where the the energies are appropriately normalized for the stoichiometry. Let us rearrange the terms,
and add and subtract a constant term Eslab .
E = Eslab,ads Eslab Eads Ebulk + Eslab
1
(Eslab Ebulk ), and we defined Hads = Eslab,ads Eslab Eads for adsorption
We defined clean = 2A
on a single side of a slab. In this case, there are adsorbates on both sides of the slab, so Eslab,ads
Eslab Eads = 2Hads . If we normalize by 2A, the area for both sides of the slab, we get
Hads
E
2A = = clean + A
You can see here that the adsorption energy serves to stabilize, or reduce the surface energy, provided
that the adsorption energy is negative.
Some final notes about the equations above:
We were not careful about stoichiometry. As written, it is assumed there are the same number
of atoms (not including the adsorbates) in the slabs and bulk, and the same number of adsorbate
atoms in the slab and Eads . Appropriate normalization factors must be included if that is not true.
It is not necessary to perform a symmetric slab calculation to determine the effect of adsorption
on the surface energy! You can examine clean with knowledge of only the adsorption energies!
5.9
Adsorbate vibrations
Adsorbates also have vibrational modes. Unlike a free molecule, the translational and rotational modes
of an adsorbate may actually have real frequencies. Sometimes they are called frustrated translations or
rotations. For metal surfaces with adsorbates, it is common to only compute vibrational modes of the
adsorbate on a frozen metal slab. The rationale is that the metal atoms are so much heavier than the
adsorbate that there will be little coupling between the surface and adsorbates. You can limit the number
of modes calculated with constraints (func:ase.constraints.FixAtoms or func:ase.constraints.FixScaled) if
you use IBRION=5. The other IBRION settings (6, 7, 8) do not respect the selective dynamics constraints.
Below we consider the vibrational modes of an oxygen atom in an fcc site on Pt(111).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
print
print
print
print
print
print
vibrational
vibrational
vibrational
vibrational
energy
energy
freq
freq
=
=
=
=
{0}
{0}
{0}
{0}
eV.format(f)
meV.format(f/meV)
1/s.format(f/h)
cm^{{-1}}.format(f/(h*c))
184
There are three modes for the free oxygen atom. One of them is a mode normal to the surface (the
one with highest frequency. The other two are called frustrated translations. Note that we did not
include the surface Pt atoms in the calculation, and this will have an effect on the result because the O
atom could be coupled to the surface modes. It is typical to neglect this coupling because of the large
difference in mass between O and Pt. Next we look at the difference in results when we calculate all the
modes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
f, m = calc.get_vibrational_modes(0)
allfreq = calc.get_vibrational_modes()[0]
17
18
19
20
21
22
23
24
25
26
27
28
print
print
print
print
print
print
print
For mode 0:
vibrational energy
vibrational energy
vibrational freq
vibrational freq
=
=
=
=
{0}
{0}
{0}
{0}
eV.format(f)
meV.format(f / meV)
1/s.format(f / h)
cm^{{-1}}.format(f / (h * c))
Note that now there are 39 modes, which is 3*N where N=13 atoms in the unit cell. Many of
the modes are low in frequency, which correspond to slab modes that are essentially phonons. The O
frequencies are not that different from the previous calculation (497 vs 512 cm1 . This is why it is
common to keep the slab atoms frozen.
Calculating these results took 39*2 finite differences. It took about a day to get these results on a
single CPU. It pays to use constraints to minimize the number of these calculations.
185
5.9.1
Here we consider the vibrations of an O atom in a bridge site, which we saw earlier is a metastable saddle
point.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
f, v = calc.get_vibrational_modes(2)
print calc.get_vibrational_modes()[0]
21
22
23
24
25
26
27
28
29
print
print
print
print
vibrational
vibrational
vibrational
vibrational
energy
energy
freq
freq
=
=
=
=
{0}
{0}
{0}
{0}
eV.format(f)
meV.format(f/meV)
1/s.format(f/h)
cm^(-1).format(f/(h*c))
5.10
Here we illustrate a standard NEB method. You need an initial and final state to start with. We will
use the results from previous calculations of oxygen atoms in an fcc and hcp site. then we will construct
a band of images connecting these two sites. Finally, we let VASP optimize the band and analyze the
results to get the barrier.
1
2
3
4
5
6
186
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
neb = NEB(images)
# Interpolate linearly the positions of these images:
neb.interpolate()
26
27
28
29
30
31
32
33
neb2 = NEB(images2)
neb2.interpolate()
34
35
36
# collect final band. Note we do not repeat the TS in the second half
final_images = images + images2[1:]
37
38
39
40
41
42
with jasp(surfaces/Pt-O-fcc-hcp-neb,
ibrion=1,
nsw=90,
spring=-5,
atoms=final_images) as calc:
43
44
try:
images, energies = calc.get_neb()
p = calc.plot_neb(show=False)
45
46
47
48
49
50
51
52
53
One issue with the standard NEB method is there is no image that is exactly at the transition state.
That means there is some uncertainty of the true energy of the transition state, and there is no way
to verify the transition state by vibrational analysis. The climbing image NEB method 93 solves that
problem by making one image climb to the top. You set LCLIMB==True= in jasp to turn on the climbing
image method. Here we use the previous calculation as a starting point and turn on the climbing image
method.
187
1
2
3
4
5
6
7
8
with jasp(surfaces/Pt-O-fcc-hcp-cineb,
debug=logging.DEBUG) as calc:
calc.set(ichain=0, lclimb=True)
9
10
11
12
13
14
A transition state should have exactly one imaginary degree of freedom which corresponds to the mode
that takes reactants to products. See Vibrations of the bridge site for an example.
5.11
5.12
Electric fields can polarize adsorbates, i.e. shift their electron density around, which changes their
stability . We can model this to some extent in VASP. We have to set the incar:EFIELD parameter to
specify the field strength (in V/), and incar:LDIPOL to True, and finally specify which lattice vector
the field should be applied to with incar:IDIPOL. Usually, incar:IDIPOL will be set to 3 for surfaces so
it points in the direction of the third lattice vector, which is conventionally in the z-direction and normal
to the surface.
We will illustrate the effect using an example from 94 for the effect of electric field on the adsorption
energy of a CO molecule on Pt(111) at 0.25 ML. For simplicity, we will use a frozen slab, with the CO
molecule in the geometry reported in that reference.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
These energies are crazy different, and the forces on the atoms with the field on are insanely high.
This section is on hold until I figure that out.
5.13
http://cst-www.nrl.navy.mil/users/sullivan/stm_backup/stm2.html
189
Figure 63: The unreconstructed Au(110) surface viewed from the side.
190
193
194
Figure 69: Comparison of the electrostatic potentials with a dipole correction and without it.
195
196
Figure 80: Schematic of forming a surface with adsorbates. First we form two clean surfaces by cleaving
the bulk, then allow adsorption to occur on the surfaces.
197
Figure 81: Energy pathway for O diffusion from an fcc to hcp site with a spline fit to determine the
barrier.
198
Atomistic thermodynamics
Let us consider how much the Gibbs free energy of an O2 molecule changes as a function of temperature,
at 1 atm. We use the Shomate polynomials to approximate the temperature dependent entropy and
enthalpy, and use the parameters from the NIST Webbook for O2 .
1
2
3
4
print J, mol, K
5
6
7
8
import numpy as np
import matplotlib.pyplot as plt
from ase.units import *
K = 1. # Kelvin not defined in ase.units!
5
6
7
8
9
#
A
D
G
Shomate parameters
= 31.32234; B = -20.23531; C = 57.86644
= -36.50624; E = -0.007374; F = -8.903471
= 246.7945; H = 0.0
10
11
12
13
14
15
16
17
18
19
def entropy(T):
entropy returned as eV/K
T in K
t = T / 1000.
s = (A * np.log(t) + B * t + C * (t**2) / 2.
+ D * (t**3) / 3. - E / (2. * t**2) + G)
return s * J / mol / K
20
21
22
23
24
25
26
27
def enthalpy(T):
H - H(298.15) returned as eV/molecule
t = T / 1000.
h = (A * t + B * (t**2) / 2. + C * (t**3) / 3.
+ D * (t**4) / 4. - E / t + F - H)
return h * kJ / mol
28
29
T = np.linspace(10, 700)
30
31
G = enthalpy(T) - T * entropy(T)
32
33
34
35
36
plt.plot(T, G)
plt.xlabel(Temperature (K))
plt.ylabel(r$\Delta G^\circ$ (eV))
plt.savefig(images/O2-mu.png)
199
Figure 82: Effect of temperature on the Gibbs free energy of an O_2 molecule at standard state (1 atm).
4
5
6
7
8
9
10
11
12
13
14
15
16
200
Figure 83: Effects of pressure on the ideal gas Gibbs free energy of O2 .
6.1
We will consider the effects of oxygen pressure and temperature on the formation energy of Ag2 O and
Cu2 O. For now, we neglect the effect of pressure and temperature on the solid phases. Neglecting pressure
is pretty reasonable, as the solids are not that compressible, and we do not expect the energy to change
for small pressures. For neglecting the temperature, we assume that the temperature dependence of the
oxide is similar to the temperature dependence of the metal, and that these dependencies practically
cancel each other in the calculations. That is an assumption, and it may not be correct.
2Cu + 1/2O2 Cu2 O
In atomistic thermodynamics, we define the free energy of formation as:
Gf = GCu2 O 2GCu 0.5GO2
We will at this point assume that the solids are incompressible so that pV 0, and that SCu2 O
2SCu 0, which leads to GCu2 O 2GCu ECu2 O 2ECu , which we directly compute from DFT. We
DF T
ZP E
express GO2 = O2 = EO
+ EO
+ (T ) + kT ln(P/P0 ). In this example we neglect the zero-point
2
2
energy of the oxygen molecule, and finally arrive at:
DF T
Gf ECu2 O 2ECu 0.5(EO
+ (T ) + kT ln(P/P0 ))
2
Which, after grouping terms is:
DF T
Gf ECu2 O 2ECu 0.5(EO
) 0.5 O2 (P, T )
2
with O2 (P, T ) = (T ) + kT ln(P/P0 ). We get (T ) from the Janaf Tables, or the NIST
Webbook.
we are explicitly neglecting all entropies of the solid: configurational, vibrational and electronic
we also neglect enthalpic contributions from temperature dependent electronic and vibrational
states
201
You will recognize in this equation the standard formation energy we calculated in Metal oxide
oxidation energies plus a correction for the non standard state pressure and temperature (O2 (P, T ) = 0
at standard state).
Gf Hf 0.5 O2 (P, T )
The formation energy of Cu2 O is -1.9521 eV/formula unit. The formation energy for Ag2 O is -0.99
eV/formula unit. Let us consider what temperature the oxides decompose at a fixed oxygen pressure of
11010 atm. We need to find the temperature where:
Hf = 0.5 O2 (P, T )
which will make the formation energy be 0.
1
2
3
4
import numpy as np
import matplotlib.pyplot as plt
from ase.units import *
from scipy.optimize import fsolve
5
6
7
8
9
10
11
12
#
A
D
G
13
14
15
16
17
18
19
20
21
22
def entropy(T):
entropy returned as eV/K
T in K
t = T/1000.
s = (A * np.log(t) + B * t + C * (t**2) / 2.
+ D * (t**3) / 3. - E / (2. * t**2) + G)
return s * J / mol / K
23
24
25
26
27
28
29
30
def enthalpy(T):
H - H(298.15) returned as eV/molecule
t = T / 1000.
h = (A * t + B * (t**2) / 2. + C * (t**3) / 3.
+ D * (t**4) / 4. - E / t + F - H)
return h * kJ / mol
31
32
33
34
35
36
37
38
39
40
41
P = 1e-10*atm
42
43
44
45
46
def func(T):
Cu2O
return -1.95 - 0.5*DeltaMu(T, P)
47
48
49
50
51
52
53
def func(T):
Ag2O
return -0.99 - 0.5 * DeltaMu(T, P)
54
55
56
57
58
59
60
61
62
63
64
T = np.linspace(100, 1000)
# Here we plot delta mu as a function of temperature at different pressures
# you have use \\times to escape the first \ in pyplot
plt.plot(T, DeltaMu(T, 1e10*atm), label=r1$\times 10^{10}$ atm)
plt.plot(T, DeltaMu(T, 1e5*atm), label=r1$\times 10^5$ atm)
plt.plot(T, DeltaMu(T, 1*atm), label=1 atm)
202
65
66
67
68
69
70
71
plt.xlabel(Temperature (K))
plt.ylabel(r$\Delta \mu_{O_2}(T,p)$ (eV))
plt.legend(loc=best)
plt.savefig(images/O2-mu-diff-p.png)
import numpy as np
import matplotlib.pyplot as plt
from ase.units import *
from scipy.optimize import fsolve
5
6
7
8
9
10
11
12
#
A
D
G
13
14
203
15
16
17
18
19
20
21
22
def entropy(T):
entropy returned as eV/K
T in K
t = T/1000.
s = (A*np.log(t) + B*t + C*(t**2)/2.
+ D*(t**3)/3. - E/(2.*t**2) + G)
return s*J/mol/K
23
24
25
26
27
28
29
30
def enthalpy(T):
H - H(298.15) returned as eV/molecule
t = T/1000.
h = (A*t + B*(t**2)/2. + C*(t**3)/3.
+ D*(t**4)/4. - E/t + F - H)
return h*kJ/mol
31
32
33
34
35
36
37
38
T in K
P in atm
39
40
41
42
43
44
45
46
def func(T):
return -0.99 - 0.5 * DeltaMu(T, p)
T.append(fsolve(func, 450)[0])
47
48
49
50
51
52
53
plt.semilogy(T, P / atm)
plt.xlabel(Temperature (K))
plt.ylabel(Pressure (atm))
plt.text(800, 1e-7, Ag)
plt.text(600, 1e-3, Ag$_2$O)
plt.savefig(images/Ag2O-decomposition.png)
import numpy as np
import matplotlib.pyplot as plt
from ase.units import *
4
5
6
7
8
9
P = 1 * atm
10
11
Dmu = np.linspace(-4, 0)
12
13
Hf = -0.99 - 0.5*Dmu
14
15
16
17
18
19
6.2
Effect on adsorption
We now consider the question: Given a pressure and temperature, what coverage would you expect on
a surface? We saw earlier that adsorption energies depend on the site and coverage. We lso know the
coverage depends on the pressure and temperature. Above some temperature, desorption occurs, and
below some pressure adsorption will not be favorable. We seek to develop a quantitative method to
determine those conditions.
We redefine the adsorption energy as:
Gads Eslab,ads Eslab ads
where again we neglect all contributions to the free energy of the slabs from vibrational energy
and entropy, as well as configurational entropy if that is relevant. That leaves only the pressure and
temperature dependence of the adsorbate, which we treat in the ideal gas limit.
We expand ads as Eads + (T, p), and thus:
Gads Eslab,ads Eslab Eads (T, p)
or
Gads Hads (T, p)
where Hads is the adsorption energy we defined earlier. Now we can examine the effect of (T, p)
on the adsorption energies. We will use the adsorption energies for the oxygen on Pt(111) system we
computed earlier:
1
2
import numpy as np
import matplotlib.pyplot as plt
3
4
5
6
fcc25 = -1.04
hcp25 = -0.60
bridge25 = -0.49
205
Figure 86: Dependence of the formation energy on the oxygen chemical potential.
Table 6: Adsorption site dependence of adsorption energies of oxygen on Pt(111).
system
H(eV /O)
fcc (0.25 ML)
-1.04
hcp (0.25 ML)
-0.60
bridge (0.25 ML)
-0.49
fcc(1ML)
-0.10
fcc1 = -0.10
8
9
Dmu = np.linspace(-4, 2)
10
11
12
13
14
15
plt.plot(Dmu,
plt.plot(Dmu,
plt.plot(Dmu,
plt.plot(Dmu,
plt.plot(Dmu,
np.zeros(Dmu.shape), label=Pt(111))
0.25 * (fcc25 - 0.5*Dmu), label=fcc - 0.25 ML)
0.25 * (hcp25 - 0.5*Dmu), label=hcp - 0.25 ML)
0.25 * (bridge25 - 0.5*Dmu), label=bridge - 0.25 ML)
1.0 * (fcc1 - 0.5*Dmu), label=fcc - 1.0 ML)
16
17
18
19
20
21
206
6.3
7.1
DFT+U
We will reconsider here the reaction (see Metal oxide oxidation energies) 2 Cu2 O + O2
4 CuO. We
need to compute the energy of each species, now with DFT+U. In 55 they use a U parameter of 4 eV for
Cu which gave the best agreement with the experimental value. We will also try that.
Cu2 O calculation with U=4.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
----------------nbands: 37
nsw: 0
ibrion: -1
ldautype: 2
isif: 3
ldauprint: 1
encut: 400.0
ldau: True
magmom: None
ldaul: [-1.0, 2.0]
ldauj: [0.0, 0.0]
ldauu: [0.0, 4.0]
ldau_luj: {O: {J: 0.0, U: 0.0, L: -1}, Cu: {J: 0.0,
U: 4.0, L: 2}}
prec: Normal
kpts: [8, 8, 8]
reciprocal: False
xc: PBE
txt: gamma: False
Pseudopotentials used:
---------------------O: potpaw_PBE/O/POTCAR (git-hash: 9a0489b46120b0cad515d935f44b5fbe3a3b1dfa)
Cu: potpaw_PBE/Cu/POTCAR (git-hash: a44c591415026f53deb16a99ca3f06b1e69be10b)
1
2
-1
0.0
0.0
2
4.0
0.0
3
4
5
6
7
8
9
10
11
12
13
14
15
16
209
210
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# make sure to use the same cutoff energy for the O2 molecule!
with jasp(molecules/O2-sp-triplet-400) as calc:
atoms = calc.get_atoms()
o2_energy = atoms.get_potential_energy()
18
19
20
21
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
## CuO ########################################
with jasp(bulk/CuO) as calc:
calc.clone(bulk/CuO-U={0}.format(U))
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
## O2 ########################################
# make sure to use the same cutoff energy for the O2 molecule!
with jasp(molecules/O2-sp-triplet-400) as calc:
atoms = calc.get_atoms()
o2_energy = atoms.get_potential_energy()
38
211
39
40
In, 55 the difference in reaction energy from U=2 eV to U=4 eV was about 0.5 eV (estimated from
graph). Here we see a range of 0.48 eV from U=2 eV to U=4 eV. Note that for U=0 eV, we had a
(corrected reaction energy of -3.96 eV). Overall, the effect of adding U decreases this reaction energy.
This example highlights the challenge of using an approach like DFT+U. On one hand, U has a
clear effect of changing the reaction energy. On the other hand, so does the correction factor for the O2
binding energy. In 55 the authors tried to get the O2 binding energy correction from oxide calculations
where U is not important, so that it is decoupled from the non-cancelling errors that U fixes. See 96 for
additional discussion of how to mix GGA and GGA+U results.
In any case, you should be careful to use well converged results to avoid compensating for convergence
errors with U.
7.2
7.2.1
Hybrid functionals
FCC Ni DOS
4
5
6
7
8
9
10
atoms = FaceCenteredCubic(directions=[[0,1,1],
[1,0,1],
[1,1,0]],
size=(1,1,1),
symbol=Ni)
atoms[0].magmom = 1
11
12
13
14
15
16
17
18
19
20
21
with jasp(bulk/Ni-PBE,
ismear=-5,
kpts=(5,5,5),
xc=PBE,
ispin=2,lorbit=11,
atoms=atoms) as calc:
print PBE energy:
,atoms.get_potential_energy()
dos = DOS(calc, width=0.2)
e_pbe = dos.get_energies()
d_pbe = dos.get_dos()
22
23
24
calc.clone(bulk/Ni-PBE0)
calc.clone(bulk/Ni-HSE06)
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
212
42
43
44
45
46
47
48
49
50
51
52
53
-5.530247
-6.848931
-6.293369
Figure 88: Comparison of DOS from GGA, and two hybrid GGAs (PBE0 ad HSE06).
7.3
TODO DFT+D
http://cms.mpi.univie.ac.at/vasp/vasp/DFT_D2_method_Grimme.html 97
Van der Waal forces can play a considerable role in binding of aromatic molecules to metal surfaces
(ref). Here we consider the effects of these forces on the adsorption energy of benzene on an Au(111)
surface.First, we consider the regular PBE functional.
213
7.3.1
PBE
gas-phase benzene
1
2
3
4
5
benzene = molecule(C6H6)
benzene.center(vacuum=5)
6
7
8
9
10
11
12
13
14
with jasp(molecules/benzene-pbe,
xc=PBE,
encut=350,
kpts=(1,1,1),
ibrion=1,
nsw=100,
atoms=benzene) as calc:
print benzene.get_potential_energy()
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
with jasp(surfaces/Au-pbe,
xc=PBE,
encut=350,
kpts=(4,4,1),
ibrion=1,
nsw=100,
atoms=atoms) as calc:
print atoms.get_potential_energy()
6
7
8
9
10
11
12
13
14
15
16
17
214
18
19
benzene.translate(p)
atoms += benzene
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
with jasp(surfaces/Au-benzene-pbe,
xc=PBE,
encut=350,
kpts=(4,4,1),
ibrion=1,
nsw=100,
atoms=atoms) as calc:
print atoms.get_potential_energy()
DFT-D2
3
4
5
benzene = molecule(C6H6)
benzene.center(vacuum=5)
6
7
8
9
10
11
12
13
14
15
with jasp(molecules/benzene-pbe-d2,
xc=PBE,
encut=350,
kpts=(1,1,1),
ibrion=1,
nsw=100,
lvdw=True,
atoms=benzene) as calc:
print benzene.get_potential_energy()
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
with jasp(surfaces/Au-pbe-d2,
xc=PBE,
encut=350,
kpts=(4,4,1),
ibrion=1,
nsw=100,
lvdw=True,
atoms=atoms) as calc:
print atoms.get_potential_energy()
benzene on Au(111)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
benzene.translate(p)
atoms += benzene
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
with jasp(surfaces/Au-benzene-pbe-d2,
xc=PBE,
encut=350,
kpts=(4,4,1),
ibrion=1,
nsw=100,
lvdw=True,
atoms=atoms) as calc:
print atoms.get_potential_energy()
There is a more sophisticated (i.e. more parameters) treatment of van der Waal forces in VASP (http:
//cms.mpi.univie.ac.at/vasp/vasp/vdW_DF_functional_Langreth_Lundqvist_et_al.html).
7.4
ELF
5
6
7
atoms = molecule(CF4)
atoms.center(vacuum=5)
8
9
10
11
12
13
14
15
16
17
with jasp(molecules/cf4-elf,
encut=350,
prec=high,
ismear=0,
sigma=0.01,
xc=PBE,
lelf=True,
atoms=atoms) as calc:
calc.calculate()
18
19
20
21
x, y, z, elf = calc.get_elf()
mlab.contour3d(x, y, z, elf,contours=[0.3])
mlab.savefig(../../images/cf4-elf-3.png)
22
23
mlab.figure()
216
24
25
mlab.contour3d(x, y, z, elf,contours=[0.75])
mlab.savefig(../../images/cf4-elf-75.png)
./images/mlab-test.png
These images (Figure 89 and 90) are basically consistent with those in Reference. 99
7.5
7.6
217
218
219
Acknowledgments
I would like to thank Zhongnan Xu for sending me some examples on magnetism. Alan McGaughey and
Lars Grabow for sending me some NEB examples. Matt Curnan for examples of phonons.
Many thanks to students in my class who have pointed out typos, places of confusion, etc. . . These
include Bruno Calfa, Matt Curnan, Charlie Janini, Feng Cao, Gamze Gumuslu, Nicholas Chisholm,
Prateek Mehta, Qiyang Duan, Shubhaditya Majumdar, Steven Illes, Wee-Liat Ong, Ye Wang, Yichun
Sun, Yubing Lu, and Zhongnan Xu.
Appendices
9.1
Recipes
9.1.1
Sometimes it is convenient to create an Atoms object by deleting atoms from an existing object. Here
is a recipe to delete all the hydrogen atoms in a molecule. The idea is to make a list of indices of which
atoms to delete using list comprehension, then use list deletion to delete those indices.
1
2
import textwrap
from ase.data.molecules import molecule
3
4
5
atoms = molecule(CH3CH2OH)
print atoms
6
7
8
9
10
11
del atoms[ind2del]
12
13
14
Advanced tagging
We can label atoms with integer tags to help identify them later, e.g. which atoms are adsorbates, or
surface atoms, or near an adsorbate, etc. . . We might want to refer to those atoms later for electronic
structure, geometry analysis, etc. . .
The method uses integer tags that are powers of two, and then uses binary operators to check for
matches. & is a bitwise AND. The key to understanding this is to look at the tags in binary form. The
tags [1 2 4 8] can be represented by a binary string:
1
2
4
8
=
=
=
=
[1
[0
[0
[0
0
1
0
0
0
0
1
0
0]
0]
0]
1]
So, an atom tagged with 1 and 2 would have a tag of [1 1 0 0] or equivalently in decimal numbers, a
tag of 3.
220
1
2
3
4
5
6
7
8
from
from
from
from
ase import *
ase.io import write
ase.lattice.surface import bcc111, add_adsorbate
ase.constraints import FixAtoms
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# let us tag LAYER1 atoms to be FREE too. we can address it by LAYER1 or FREE
tags = slab.get_tags()
for i,tag in enumerate(tags):
if tag == LAYER1:
tags[i] += FREE
slab.set_tags(tags)
32
33
34
35
#create a CO molecule
co= Atoms([Atom(C,[0., 0., 0. ], tag=ADSORBATE),
Atom(O,[0., 0., 1.1], tag=ADSORBATE+FREE)]) #we will relax only O
36
37
add_adsorbate(slab,co,height=1.2,position=hollow)
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#atoms in LAYER1
layer1 = slab[(slab.get_tags() & LAYER1) == LAYER1]
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
221
Figure 91: The tagged bcc(111) structure created above. Unfortunately, the frozen atoms do not show
up in the figure.
9.1.3
mod:ase uses a base set of atomic units.These are eV for energy, for distance, seconds for time, and
amu for mass. Other units are defined in terms of those units, and you can easily convert to alternative
222
units by dividing your quantity in atomic units by the units you want.
Not too many units are defined: [A, AUT, Ang, Angstrom, Bohr, C, Debye, GPa, Ha,
Hartree, J, Pascal, Ry, Rydberg, alpha, cm, eV, erg, fs, kB, kJ, kcal, kg, m, meV,
mol, nm, s, second]
It is not that hard to define your own derived units though. Note these are only conversion factors.
No units algebra is enforced (i.e. it will be ok to add a m and a kg)!
1
2
3
4
d = 1*Angstrom
print d = {0} nm.format(d/nm)
5
6
7
8
9
print
print
print
print
1
1
1
1
eV
eV
eV
eV
=
=
=
=
{0}
{0}
{0}
{0}
Hartrees.format(eV/Hartree)
Rydbergs.format(eV/Rydberg)
kJ/mol.format(eV/(kJ/mol))
kcal/mol.format(eV/(kcal/mol))
10
11
12
13
14
15
16
# derived units
minute = 60*s
hour = 60*minute
17
18
19
import numpy as np
import matplotlib as mpl
#http://matplotlib.sourceforge.net/users/customizing.html
mpl.rcParams[legend.numpoints] = 1 #default is 2
import matplotlib.pyplot as plt
6
7
8
x = np.linspace(0,6,100)
y = np.cos(x)
9
10
plt.plot(x,y,label=full)
11
12
13
223
14
15
subx = x[ind]
suby = y[ind]
16
17
18
19
20
21
plt.plot(subx,suby,bo,label=sliced)
xlabel(x)
ylabel(cos(x))
plt.legend(loc=lower right)
plt.savefig(images/np-array-slice.png)
Figure 92: Example of slicing out part of an array. The solid line represents the whole array, and the
symbols are the array between 2 < x < 4.
The expression x > 2 returns an array of booleans (True where the element of x is greater than 2,
and False where it is not) equal in size to x. Similarly x < 4 returns a boolean array where x is less
than 4. We take the logical and of these two boolean arrays to get another boolean array where both
conditions are True (i.e. x < 2 and x > 4). This final boolean array is True for the part of the arrays
we are interested in, and we can use it to extract the subarrays we want.
9.1.5
Statistics
Confidence intervals mod:scipy has a statistical package available for getting statistical distributions.
This is useful for computing confidence intervals using the student-t tables. Here is an example of
computing a 95% confidence interval on an average.
224
1
2
import numpy as np
from scipy.stats.distributions import
3
4
5
6
7
n = 10 #number of measurements
dof = n - 1 #degrees of freedom
avg_x = 16.1 #average measurement
std_x = 0.01 #standard deviation of measurements
8
9
10
11
12
13
14
15
16
17
Curve fitting
Linear fitting
1
2
3
4
5
xdata = np.array([0.,1.,2.,3.,4.,5.,6.])
ydata = np.array([0.1, 0.81, 4.03, 9.1, 15.99, 24.2, 37.2])
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
A^TAx = A^Tb
x = (A^TA)^-1 A^T b
32
33
34
35
36
37
38
39
40
41
42
43
44
45
9.1.7
1
2
3
4
5
6
7
8
9
10
11
12
13
def Murnaghan(parameters,vol):
From Phys. Rev. B 28, 5480 (1983)
E0 = parameters[0]
B0 = parameters[1]
BP = parameters[2]
V0 = parameters[3]
14
15
E = E0 + B0*vol/BP*(((V0/vol)**BP)/(BP-1)+1) - V0*B0/(BP-1.)
16
17
return E
18
19
20
21
22
def objective(pars,y,x):
#we will minimize this function
err = y - Murnaghan(pars,x)
return err
23
24
226
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
0.57233217,
2.7407944 ,
16.55905648]), 1)
3
4
227
5
6
7
8
9
10
11
12
13
def Murnaghan(parameters,vol):
From PRB 28,5480 (1983
E0 = parameters[0]
B0 = parameters[1]
BP = parameters[2]
V0 = parameters[3]
14
E = E0 + B0*vol/BP*(((V0/vol)**BP)/(BP-1)+1) - V0*B0/(BP-1.)
15
16
return E
17
18
19
20
21
22
def objective(pars,vol):
#we will minimize this function
err = energies - Murnaghan(pars,vol)
return np.sum(err**2) #we return the summed squared error directly
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
9.1.9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from Matlab
b =
16
4.9671
2.1100
17
18
19
20
21
bint =
22
4.6267
1.7671
23
24
25
5.3075
2.4528
26
228
16.59341303]
27
28
29
x = np.array([ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
y = np.array([ 4.70192769, 4.46826356, 4.57021389, 4.29240134, 3.88155125,
3.78382253, 3.65454727, 3.86379487, 4.16428541, 4.06079909])
30
31
32
33
34
35
36
37
38
39
40
n = len(y)
# number of data points
p = len(pars) # number of parameters
41
42
43
44
tval = t.ppf(1.0-alpha/2., dof) # student-t value for the dof and confidence level
45
46
47
48
49
50
51
52
53
54
55
56
57
58
5.30753456558]
2.45278603188]
9.1.10
When you do not know the functional form of data to fit an equation, you can still fit/interpolate with
splines.
1
2
3
4
5
6
7
8
x = np.array([ 0,
y = np.array([ 0.,
1,
0.308,
2,
0.55,
3,
0.546,
4
])
0.44 ])
9
10
11
12
13
14
15
16
17
18
xfit = np.linspace(0,4)
19
20
21
22
plt.plot(x,y,bo)
plt.plot(xfit, f(xfit),r-)
plt.plot(xmax, f(xmax),g*)
230
23
24
25
26
27
28
Figure 97: Illustration of a spline fit to data and finding the maximum point.
There are other good examples at http://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.
html
9.1.11
Interpolation in 3D
You might ask, why would I need to interpolate in 3D? Suppose you want to plot the charge density along
a line through a unit cell that does not correspond to grid points. What are you to do? Interpolate. In
contrast to an abundance of methods for 1D and 2D interpolation, I could not find any standard library
methods for 3D interpolation.
The principle we will use to develop an interpolation function in 3D is called trilinear interpolation,
where we use multiple linear 1D interpolations to compute the value of a point inside a cube. As
developed here, this solution only applies to rectangular grids. Later we will generalize the approach.
We state the problem as follows:
We know a scalar field inside a unit cell on a regularly spaced grid. In VASP these fields may be the
charge density or electrostatic potential for example, and they are known on the fft grids. We want to
estimate the value of the scalar field at a point not on the grid, say P=(a,b,c).
231
Solution: Find the cube that contains the point, and is defined by points P1-P8 as shown in Figure
??.
We use 1D interpolation formulas to compute the value of the scalar field at points I1 by interpolating
between P1 and P2, and the value of the scalar field at I2 by interpolating between P3 and P4. In these
points the only variable changing is x, so it is a simple 1D interpolation. We can then compute the
value of the scalar field at I5 by interpolating between I1 and I2. We repeat the process on the top of
the cube, to obtain points I3, I4 and I5. Finally, we compute the value of the scalar field at point P
by interpolating between points I5 and I6. Note that the point I5 has coordinates (a,b,z1) and I6 is at
(a,b,z2), so the final interpolation is again a 1D interpolation along z evaluated at z=c to get the final
value of the scalar field at P=(a,b,c).
1
2
3
4
5
6
7
8
9
10
11
def interp3d(x,y,z,cd,xi,yi,zi):
232
12
13
14
15
16
17
18
19
20
21
22
def get_index(value,vector):
23
24
25
26
xv = x[:,0,0]
yv = y[0,:,0]
zv = z[0,0,:]
27
28
29
30
31
32
i = get_index(a,xv)
j = get_index(b,yv)
k = get_index(c,zv)
33
34
35
36
37
38
39
x1
x2
y1
y2
z1
z2
=
=
=
=
=
=
x[i,j,k]
x[i+1,j,k]
y[i,j,k]
y[i,j+1,k]
z[i,j,k]
z[i,j,k+1]
u1
u2
u3
u4
u5
u6
u7
u8
=
=
=
=
=
=
=
=
cd[i, j, k]
cd[i+1, j, k]
cd[i, j+1, k]
cd[i+1, j+1, k]
cd[i, j, k+1]
cd[i+1, j, k+1]
cd[i, j+1, k+1]
cd[i+1, j+1, k+1]
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
w1 = u2
w2 = u4
w3 = w2
w4 = u5
w5 = u7
w6 = w4
w7 = w3
u = w7
+
+
+
+
+
+
+
(u2-u1)/(x2-x1)*(a-x2)
(u4-u3)/(x2-x1)*(a-x2)
(w2-w1)/(y2-y1)*(b-y2)
(u6-u5)/(x2-x1)*(a-x1)
(u8-u7)/(x2-x1)*(a-x1)
(w5-w4)/(y2-y1)*(b-y1)
(w6-w3)/(z2-z1)*(c-z1)
58
59
return u
60
61
pos = atoms.get_positions()
62
63
64
65
66
npoints = 60
67
68
69
70
71
72
73
# interpolated line
icd = [interp3d(x,y,z,cd,p[0],p[1],p[2]) for p in points]
74
75
76
77
78
79
80
81
82
83
84
85
plt.plot(R, icd)
cR = np.linalg.norm(pos[0] - P1)
oR = np.linalg.norm(pos[1] - P1)
plt.plot([cR, cR], [0, 2], r-) #markers for where the nuclei are
plt.plot([oR, oR], [0, 8], r-)
plt.xlabel(|R| ($\AA$))
plt.ylabel(Charge density (e/$\AA^3$))
plt.savefig(images/CO-charge-density.png)
plt.show()
Figure 98: An example of interpolated charge density of a CO molecule along the axis of molecule.
To generalize this to non-cubic cells, we need to do interpolation along arbitrary vectors. The overall
strategy is the same:
Find the cell that contains the point (a,b,c). compute the scaled coordinates (sa,sb,sc) of the point
inside the cell. Do the interpolations along the basis vectors. Given u1 at P1(x1,y1,z1) and u2 at
P2(x2,y2,z2) where (P2-P1) is a cell basis vector a, u = u1 + sa*(u2-u1). There are still 7 interpolations
to do.
Below is an example of this code, using a the python library bisect to find the cell.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def vinterp3d(x,y,z,u,xi,yi,zi):
17
18
p = np.array([xi,yi,zi])
19
20
21
22
23
24
234
25
26
27
28
29
30
#
#
#
i
j
k
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#cell basis vectors, not the unit cell, but the voxel cell containing the point
cbasis = np.array([P2-P1,
P3-P1,
P5-P1])
52
53
54
55
56
57
58
59
#now s =
#next we
ui1 = u1
ui2 = u3
(sa, sb, sc) which are fractional coordinates in the vector space
do the interpolations
+ s[0]*(u2-u1)
+ s[0]*(u4-u3)
60
61
62
ui3 = u5 + s[0]*(u6-u5)
ui4 = u7 + s[0]*(u8-u7)
63
64
65
66
67
68
69
return ui7
70
71
72
73
74
75
npoints = 60
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
plot(R,icd)
pos = atoms.get_positions()
cR = np.linalg.norm(pos[0]-P1)
oR = np.linalg.norm(pos[1]-P1)
plot([cR,cR],[0,2],r-) #markers for where the nuclei are
plot([oR,oR],[0,8],r-)
xlabel(|R| ($\AA$))
ylabel(Charge density (e/$\AA^3$))
savefig(images/interpolated-charge-density.png)
show()
235
pylab.save(pdat.dat,(x,y))
x,y = pylab.load(pdat.dat)
A standard approach would be to read in all the lines, skip the first two lines, split each line (remember
each line is a string) at the ,, and append the first field to one variable, and append the second field to
another variable as an integer. For example:
1
2
3
v1 = []
v2 = []
lines = open(somefile,r).readlines()
4
5
6
7
8
Integration
Numerical integrations is easy with the numpy.trapz() method. Use it like this: func:numpy.trapz(y,x).
Note that y comes first. y and x must be the same length.
Integration can be used to calculate average properties of continuous distributions. Suppose for
example, we have a density of states, as a function of energy E. We can integrate the density of states
to find the total
R number of states:
Nstates = dE
or, in python:
1
Nstates = np.trapz(rho,E)
or, in python:
1
e_avg = np.trapz(rho*E,E)/np.trapz(rho,E)
237
n = 2
mom_2 = np.trapz(rho*E**n,E)/np.trapz(rho,E)
Numerical differentiation
numpy has a function called func:numpy.diff that is similar to the one found in Matlab. It calculates the
differences between the elements in your list, and returns a list that is one element shorter, which makes
it unsuitable for plotting the derivative of a function.
Simple loops to define finite difference derivatives Loops in python are pretty slow (relatively
speaking) but they are usually trivial to understand. In this script we show some simple ways to construct
derivative vectors using loops. It is implied in these formulas that the data points are equally spaced.
1
2
3
import numpy as np
import matplotlib.pyplot as plt
import time
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
tf1 = time.time()
dyf = [0.0]*len(x)
for i in range(len(y)-1):
dyf[i] = (y[i+1] - y[i])/(x[i+1]-x[i])
#set last element by backwards difference
dyf[-1] = (y[-1] - y[-2])/(x[-1] - x[-2])
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
238
44
45
46
47
48
49
50
51
52
53
54
55
56
plt.plot(x,dy_analytical,label=analytical derivative)
plt.plot(x,dyf,--,label=forward)
plt.plot(x,dyb,--,label=backward)
plt.plot(x,dyc,--,label=centered)
57
58
59
plt.legend(loc=lower left)
plt.savefig(images/simple-diffs.png)
239
1
2
import numpy as np
import matplotlib.pyplot as plt
3
4
5
6
x = np.linspace(0,2*np.pi,100)
y = np.sin(x)
dy_analytical = np.cos(x)
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
plt.plot(x,y)
plt.plot(x,dy_analytical,label=analytical derivative)
plt.plot(x,dy,label=forward diff)
plt.plot(x,dy2,k--,lw=2,label=centered diff)
plt.legend(loc=lower left)
plt.savefig(images/vectorized-diffs.png)
import numpy as np
import matplotlib.pyplot as plt
3
4
5
6
x = np.linspace(0,2*np.pi,100)
y = np.sin(x) + 0.1*np.random.random(size=x.shape)
dy_analytical = np.cos(x)
7
8
9
10
11
12
13
#2-point formula
dyf = [0.0]*len(x)
for i in range(len(y)-1):
dyf[i] = (y[i+1] - y[i])/(x[i+1]-x[i])
#set last element by backwards difference
dyf[-1] = (y[-1] - y[-2])/(x[-1] - x[-2])
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
dy[0] = (y[1]-y[0])/(x[1]-x[0])
dy[1] = (y[2]-y[1])/(x[2]-x[1])
dy[-2] = (y[-2] - y[-3])/(x[-2] - x[-3])
dy[-1] = (y[-1] - y[-2])/(x[-1] - x[-2])
32
33
plt.plot(x,y)
240
34
35
36
37
38
plt.plot(x,dy_analytical,label=analytical derivative)
plt.plot(x,dyf,r-,label=2pt-forward diff)
plt.plot(x,dy,k--,lw=2,label=4pt-centered diff)
plt.legend(loc=lower left)
plt.savefig(images/multipt-diff.png)
import numpy as np
import matplotlib.pyplot as plt
3
4
5
6
7
8
9
10
11
12
13
14
http://sci.tech-archive.net/Archive/sci.math/2008-05/msg00401.html
15
16
241
17
18
19
20
21
22
if N % 2 == 0:
k = np.asarray(range(0,N/2)+[0] + range(-N/2+1,0))
else:
k = np.asarray(range(0,(N-1)/2) +[0] + range(-(N-1)/2,0))
23
24
k *= 2*np.pi/L
25
26
fd = np.fft.ifft(1.j*k * np.fft.fft(y))
27
28
29
30
31
plt.plot(x,y)
plt.plot(x,dy_analytical,label=analytical der)
plt.plot(x,fd,label=fft der)
plt.legend(loc=lower left)
32
33
plt.savefig(images/fft-der.png)
NetCDF files
NetCDF is a binary, but cross-platform structured data format. The input file and output file for Dacapo
is the NetCDF format. On creating a NetCDF file you must define the dimensions and variables before
you can store data in them. You can create and read NetCDF files in python using one of the following
modules:
mod:Scientific.IO.NetCDF (http://dirac.cnrs-orleans.fr/plone/software/scientificpython/)
242
Python modules
The comma separated values (mod:csv) module in python allows you to easily create datafiles:
csv writing:
1
import numpy as np
2
3
4
x = np.linspace(0.0,6.0,100)
y = np.cos(x)
5
6
7
8
import csv
writer = csv.writer(open("some.csv", "w"))
writer.writerows(zip(x,y))
import csv
reader = csv.reader(open("some.csv",r),delimiter=,)
3
4
5
x,y = [],[]
for row in reader:
243
6
7
8
9
Writing Excel files It is sometimes convenient to do some analysis in Excel. We can create Excel
files in python with mod:xlwt. Google this module if you need to do this a lot.
1
2
import numpy as np
import xlwt
3
4
5
wbk = xlwt.Workbook()
sheet = wbk.add_sheet(sheet 1)
6
7
8
9
10
11
12
13
14
15
import xlrd
wbk = xlrd.open_workbook(images/test-write.xls)
sheet1 = wbk.sheet_by_name(sheet 1)
print sheet1.col_values(0)
print sheet1.col_values(1)
1. using animate
2. using swftools (png2swf, pdf2swf)
#http://wiki.swftools.org/wiki/Main_Page#SWF_Tools_0.9.2_.28_Current_Stable_Version_.29_
Documentation
244
9.2
Computational geometry
9.2.1
(9)
(10)
(11)
and we want to find the vector [s1, s2, s3] so that P = s1A + s2B + s3C
if we expand this, we get:
A1
A2
A3
and z, we can
B1 C1
B2 C2
B3 C3
p1
s1
s2 = p2
p3
s3
(12)
4
5
6
7
8
slab = fcc111(Pd,
a=3.92,
# Pd lattice constant
size=(2,2,3), #3-layer slab in 1x1 configuration
vacuum=10.0)
9
10
11
12
13
14
15
16
s = np.dot(np.linalg.inv(newbasis.T),pos.T).T
print Coordinates in new basis are: \n,s
17
18
19
9
10
11
12
13
14
15
pos = bulk.get_positions()
16
17
18
19
s = np.dot(np.linalg.inv(newbasis.T),pos.T).T
print atom positions in primitive basis
print s
20
21
22
23
#let us see the unit cell in terms of the primitive basis too
print unit cell in terms of the primitive basis
print np.dot(np.linalg.inv(newbasis.T),bulk.get_cell().T).T
[ 1. 0. 1.]
[ 2. 1. 2.]
[ 1. 1. 2.]
[ 2. 2. 3.]
[ 1. 1. 0.]
[ 2. 2. 1.]
[ 1. 2. 1.]
[ 2. 3. 2.]
[ 2. 1. 1.]
[ 3. 2. 2.]
[ 2. 2. 2.]
[ 3. 3. 3.]]
unit cell in terms of the primitive basis
[[ 0. 2. 2.]
[ 2. 0. 2.]
[ 2. 2. 0.]]
9.2.2
Scientific.Geometry contains several useful functions for performing vector algebra including computing lengths and angles.
1
2
import numpy as np
from Scientific.Geometry import Vector
3
4
5
A = Vector([1,1,1])
#Scientfic
a = np.array([1,1,1]) #numpy
6
7
B = Vector([0.0,1.0,0.0])
8
9
10
11
12
13
14
15
16
17
18
#cross products
print Scientific A .cross. B = ,A.cross(B)
print numpy A .cross. B
= ,np.cross(A,B) #you can use Vectors in numpy
The volume of a unit cell can be calculated from V = (a1 a2 ) a3 where a1 , a2 and a3 are the unit
cell vectors. It is more convenient, however, to simply evaluate that equation as the determinant of the
matrix describing the unit cell, where each row of the matrix is a unit cell vector.
V = | det(ucell)|
Why do we need to take the absolute value? The sign of the determinant depends on the handedness
of the order of the unit cell vectors. If they are right-handed the determinant will be positive, and if
they are left-handed the determinant will be negative. Switching any two rows will change the sign of
the determinant and the handedness. mod:ase implements a convenient function to get the volume of
an mod:Atoms object: func:ase.Atoms.get_volume.
Here are three equivalent ways to compute the unit cell volume.
1
import numpy as np
2
3
a1 = [2, 0, 0]
247
4
5
a2 = [1, 1, 0]
a3 = [0, 0, 10]
6
7
8
9
10
11
12
13
14
15
d-spacing
If you like to set up the vacuum in your slab calculations in terms of equivalent layers of atoms, you need
to calculate the d-spacing (which is the spacing between parallel planes of atoms) for the hkl plane you
are using. The script below shows several ways to accomplish that.
1
2
import numpy as np
from ase.lattice.cubic import FaceCenteredCubic
3
4
5
6
7
8
9
ag = FaceCenteredCubic(directions=[[1,0,0],
[0,1,0],
[0,0,1]],
size=(1,1,1),
symbol=Ag,
latticeconstant=4.0)
10
11
12
13
14
15
16
17
18
19
20
h,k,l = (1,1,1)
d = 1./np.linalg.norm(h*b1 + k*b2 + l*b3)
21
22
23
24
25
26
#method #2
hkl = np.array([h,k,l])
G = np.array([b1,b2,b3]) #reciprocal unit cell
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Gstar = np.dot(G,G.T)
42
43
id2 = np.dot(hkl,np.dot(Gstar,hkl))
44
45
46
47
# http://books.google.com/books?id=nJHSqEseuIUC&lpg=PA118&ots=YA9TBldoVH
248
48
49
# &dq=reciprocal%20metric%20tensor&pg=PA119#v=onepage
# &q=reciprocal%20metric%20tensor&f=false
50
51
52
53
54
55
56
57
58
59
60
61
62
unitcell = ag.get_cell()
A = Vector(unitcell[0])
B = Vector(unitcell[1])
C = Vector(unitcell[2])
63
64
65
66
67
#
a
b
c
68
69
70
71
72
73
74
75
76
77
print
print a
b
c
alpha beta gamma
print {0:1.3f} {1:1.3f} {2:1.3f} {3:1.3f} {4:1.3f} {5:1.3f}\n.format(a,b,c,
alpha,beta,gamma)
78
79
h,k,l = (1,1,1)
80
81
82
83
84
85
86
87
88
89
90
id2 = ((h**2/a**2*sin(alpha)**2
+ k**2/b**2*sin(beta)**2
+ l**2/c**2*sin(gamma)**2
+2*k*l/b/c*(cos(beta)*cos(gamma)-cos(alpha))
+2*h*l/a/c*(cos(alpha)*cos(gamma)-cos(beta))
+2*h*k/a/b*(cos(alpha)*cos(beta)-cos(gamma)))
/(1-cos(alpha)**2-cos(beta)**2 - cos(gamma)**2
+2*cos(alpha)*cos(beta)*cos(gamma)))
91
92
d = 1/math.sqrt(id2)
93
94
9.3
Equations of State
The module mod:ase.utils.eos uses a simple polynomial equation of state to find bulk unit cell equilibrium
volumes and bulk modulus. There are several other choices you could use that are more standard in
the literature. Here we summarize them and provide references to the relevant literature. In each of
these cases we show equations for the energy as a function of volume, although sometimes the volume is
transformed or normalized.
9.3.1
Birch-Murnaghan
This is probably the most common equation of state used most often, and is a modification of the original
Murnaghan EOS described below. A current description of the equation is in reference. 100 You can also
find the equations for the Vinet and Poirier-Tarantola equations of state in that reference.
249
Birch-Murnaghan EOS:
0 V0
( 2 1)2 (6 + B00 ( 2 1) 4 2 )
E() = E0 + 9B16
where = (V /V0 )1/3 , B0 and B00 are the bulk modulus and its pressure derivative at the equilibrium
volume V0 . You may find other derivations of this equation in the literature too.
Two other equations of state in that reference are the Vinet EOS:
2B0 V0
0
3(B00 1)(1)/2
E() = E0 + (B
)
0
2 (2 (5 + 3B0 ( 1)e
0 1)
and the Poirier-Tarantola
EOS:
2
E(%) = E0 + B0 V60 % (3 + %(B00 2))
with % = 3 ln().
9.3.2
Murnaghan
The equation mostoften used inthe Murnaghan 101 equation of state is described in 102 .
B0
V0 B0
0 /V ) 0
+1 B
E = ET + BB00V (VB
0 1
0 1
0
where V is the volume, B0 and B00 are the bulk modulus and its pressure derivative at the equilibrium
volume V0 . All of these are parameters that are fitted to energy vs. unit cell volume (V ) data. When
fitting data to this equation a guess of 2-4 for B00 is usually a good start.
9.3.3
Birch
9
0
16 B0 V0 (B0
4)
V
V0
2/3
3
1
9.3.5
To use these equations of state to find the equilibrium cell volume and bulk modulus we need a set of
calculations that give us the energy of the unit cell as a function of the cell volume. We then fit that
data to one of the above equations to extract the parameters we want. All of these equations of state are
non-linear in the cell volume, which means you have to provide some initial guesses for the parameters.
Here we describe a strategy for getting some estimates of the parameters using a linear least squares
fitting of a parabola to the data to estimate E0 , V0 , B and B00 which are used as initial guess for a
non-linear least squares fit of the equation of state to the data.
The following example illustrates one approach to this problem for the Murnaghan equation of state:
1
2
3
4
5
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import leastsq
6
7
8
9
10
11
12
13
14
250
15
16
# y = ax^2 + bx + c
a,b,c = np.polyfit(v,e,2) #this is from pylab
17
18
19
20
the parabola does not fit the data very well, but we can use it to get
some analytical guesses for other parameters.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#now
v0 =
e0 =
b0 =
bP =
40
41
42
43
44
45
46
47
48
49
50
E0 = parameters[0]
B0 = parameters[1]
BP = parameters[2]
V0 = parameters[3]
51
52
E = E0 + B0*vol/BP*(((V0/vol)**BP)/(BP-1)+1) - V0*B0/(BP-1.)
53
54
return E
55
56
57
58
59
60
61
62
x0 = [e0, b0, bP, v0] #initial guesses in the same order used in the Murnaghan function
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
np.set_printoptions(precision=3)
print initial guesses : , np.array(x0) #array for easy printing
print fitted parameters: , murnpars
[-56.472
[-56.466
0.631
0.49
4.
4.753
251
16.79 ]
16.573]
Figure 104: Fitted equation of state for bulk data. The initial fitted parabola is shown to illustrate how
it is useful for making initial guesses of the minimum and bulk modulus.
You can see the Murnaghan equation of state fits the data better than the parabola.
Here is a comparison of the initial guesses and final parameters. You can see our guesses from the
parabola were actually pretty good, and are the main reason we converged to a solution. If you try other
guesses you will probably find the scipy.optimize.leastsq function does not converge.
9.4
9.4.1
You need to create an executable script named runvasp.py on your executable path. Here is an example
script that works for both serial and parallel versions of VASP. This script is located in jasp/bin.
1
2
#!/usr/bin/env python
import os
3
4
5
serial_vasp = /home/jkitchin/src/vasp/bin/vasp_serial_intel_mkl
parallel_vasp = /home/jkitchin/src/vasp/bin/vasp_openmpi_intel_mkl
6
7
8
if PBS_NODEFILE in os.environ:
NPROCS = len(open(os.environ[PBS_NODEFILE]).readlines())
9
10
11
12
13
14
15
16
17
if NPROCS == 1:
print NPROCS = ,NPROCS
exitcode = os.system(serial_vasp)
else:
print NPROCS = ,NPROCS
parcmd = mpirun -np %i %s % (NPROCS,parallel_vasp)
exitcode = os.system(parcmd)
else:
252
exitcode = os.system(serial_vasp)
18
19
#end
export VASP_SCRIPT=$HOME/kitchinpython/jasp/bin/run_vasp.py
export VASP_PP_PATH=$HOME/vasp/my_vasp_potentials
VASP provides special setups for some elements. The following guidelines tell you what is in a potential:
No extension means the standard potential. The following extensions mean:
Table 7: Meaning of extensions on POTCAR files for special setups.
extension
_h
_s
_sv
_pv
_d
means the potential is harder than the standard (i.e. needs a higher cutoff energy)
means the potential is softer than the standard (i.e. needs a lower cutoff energy)
s and p semi-core states are treated as valence states
p semi-core states are treated as valence states
d semi-core states are treated as valence states
Here are some links to information in the VASP manual for the setups.
1st row elements
Alkali and alkali-earth metals
d-elements
p-elements
f-elements
Here we show how to select the O_sv potential in a calculation.
253
1
2
3
4
5
6
7
8
9
10
11
12
13
14
with jasp(molecules/O_sv,
encut=300,
xc=PBE,
ispin=2,
ismear=0,
sigma=0.001,
setups={O:_sv}, # specifies O_sv potential
atoms=atoms) as calc:
15
16
head -n 1 molecules/O_sv/POTCAR
jasp is smart. If you ask for more than one node, it will automatically try to run in parallel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
with jasp(molecules/O_sv-4nodes,
encut=300,
xc=PBE,
ispin=2,
ismear=0,
sigma=0.001,
setups={O:_sv}, # specifies O_sv potential
atoms=atoms) as calc:
15
16
print calc.calculate()
head molecules/O_sv-4nodes/OUTCAR
254
09:10:10
4 groups
----------------------------------------------------------------------------------------------------9.4.4
mod:jasp was designed to enable asynchronous, parallel running processes through a queuing system.
This is ideal for submitting large numbers of independent calculations in one script. The design uses
exceptions to exit the script if the results are not available for subsequent analysis. The design expects
that you run the script often, and the results are analyzed only when they are finally available.
Sometimes it is convenient to run a set of calculations and then wait for them to finish so that a
second set of calculations that depend on the first results can be run. In this scenario, it is inconvenient
to have to rerun your script again after the first set of calculations is done. The challenge is how to tell
the computer to run a set of calculations in parallel, and wait for the calculations to finish. This can be
achieved using the mod:multiprocessing module in python.
The principle idea is to set up the calculations you want to run, and use mod:multiprocessing to
handle running them and waiting for you. To do this, you must instruct mod:jasp to use a "run mode",
and construct a script with a function that runs a calculation, and a section that only runs in the "main"
script.
1
2
3
4
5
import multiprocessing
from jasp import *
from ase import Atom, Atoms
from ase.utils.eos import EquationOfState
import numpy as np
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# this only runs in the main script, not in processes on other cores
if __name__ == __main__:
NCORES = 6 # number of cores to run processes on
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Step 1
COUNTER = 0
calculators = [] # list of calculators to be run
factors = [-0.1, 0.05, 0.0, 0.05, 0.1]
for f in factors:
newatoms = atoms.copy()
newatoms.set_volume(v0*(1 + f))
label = bulk/cu-mp/step1-{0}.format(COUNTER)
COUNTER += 1
38
39
40
41
42
calc = jasp(label,
xc=PBE,
encut=350,
kpts=(6,6,6),
255
isym=2,
atoms=newatoms)
43
44
45
46
calculators.append(calc)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
eos = EquationOfState(V, E)
v1, e1, B = eos.fit()
print step1: v1 = {v1}.format(**locals())
63
64
65
66
67
68
69
### ################################################################
## STEP 2, eos around the minimum
## #################################################################
factors = [-0.06, -0.04, -0.02,
0.0,
0.02, 0.04, 0.06]
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
calc = jasp(label,
xc=PBE,
encut=350,
kpts=(6,6,6),
isym=2,
atoms=newatoms)
calculators.append(calc)
85
86
pool = multiprocessing.Pool(processes=NCORES)
87
88
89
90
91
92
93
94
95
96
97
V = np.array(V)
E = np.array(E)
98
99
f = np.array(V)/v1
100
101
102
103
104
105
106
107
256
#!/usr/bin/env python
import multiprocessing
from jasp import *
from ase import Atom, Atoms
from ase.utils.eos import EquationOfState
import numpy as np
7
8
JASPRC[queue.nodes] = 1
9
10
11
12
13
14
15
16
17
18
19
20
21
22
257
23
24
25
26
27
28
29
30
# this only runs in the main script, not in processes on other cores
if __name__ == __main__:
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# Step 1
COUNTER = 0
calculators = [] # list of calculators to be run
factors = [-0.1, 0.05, 0.0, 0.05, 0.1]
for f in factors:
newatoms = atoms.copy()
newatoms.set_volume(v0*(1 + f))
label = bulk/cu-mp2/step1-{0}.format(COUNTER)
COUNTER += 1
49
50
51
52
53
54
55
56
calc = jasp(label,
xc=PBE,
encut=350,
kpts=(6,6,6),
isym=2,
debug=logging.DEBUG,
atoms=newatoms)
57
58
calculators.append(calc)
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
eos = EquationOfState(V, E)
v1, e1, B = eos.fit()
print step1: v1 = {v1}.format(**locals())
75
76
77
78
79
80
81
### ################################################################
## STEP 2, eos around the minimum
## #################################################################
factors = [-0.06, -0.04, -0.02,
0.0,
0.02, 0.04, 0.06]
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
calc = jasp(label,
xc=PBE,
encut=350,
kpts=(6,6,6),
isym=2,
debug=logging.DEBUG,
atoms=newatoms)
calculators.append(calc)
98
99
pool = multiprocessing.Pool(processes=3)
100
258
101
102
103
104
105
106
107
108
109
110
V = np.array(V)
E = np.array(E)
111
112
f = np.array(V)/v1
113
114
115
116
117
118
119
120
9.4.5
jasp has some capability for representing a calculation result in an archival format. The formats currently
under development are json, xml, python and sqlite. The main point of these methods is to make it easy
to create archive files that are machine readable for supplementary information in publications. These
are under development.
259
python This is code that should reconstruct the python code needed to run a particular calculation.
There are some limitations, e.g. it does not currently get magnetic moments on the atoms.
1
2
3
4
2
3
4
"bmix_mag": null,
"ddr": null,
"deper": null,
"dfnmax": null,
"dfnmin": null,
"dipol": null,
"drotmax": null,
"ebreak": null,
"ediff": null,
"ediffg": null,
"eint": null,
"emax": null,
"emin": null,
"enaug": null,
"encut": 350.0,
"encutfock": null,
"encutgw": null,
"falpha": null,
"falphadec": null,
"fdstep": null,
"ferdo": null,
"ferwe": null,
"fnmin": null,
"ftimedec": null,
"ftimeinc": null,
"ftimemax": null,
"gga": null,
"hfscreen": null,
"ialgo": null,
"iband": null,
"ibrion": 2,
"ichain": null,
"icharg": null,
"idipol": null,
"images": null,
"iniwav": null,
"invcurve": null,
"iopt": null,
"isif": 4,
"ismear": null,
"ispin": null,
"istart": null,
"isym": null,
"iwavpr": null,
"jacobian": null,
"kgamma": null,
"kpuse": null,
"kspacing": null,
"laechg": null,
"lasph": null,
"lasync": null,
"lbfgsmem": null,
261
"lcharg": null,
"lclimb": null,
"lcorr": null,
"ldau": null,
"ldau_luj": null,
"ldauj": null,
"ldaul": null,
"ldauprint": null,
"ldautype": null,
"ldauu": null,
"ldiag": null,
"ldipol": null,
"ldneb": null,
"lelf": null,
"lepsilon": null,
"lglobal": null,
"lhfcalc": null,
"llineopt": null,
"lmaxmix": null,
"lnebcell": null,
"loptics": null,
"lorbit": null,
"lpard": null,
"lplane": null,
"lscalapack": null,
"lscalu": null,
"lsepb": null,
"lsepk": null,
"ltangentold": null,
"lthomas": null,
"luse_vdw": null,
"lvdw": null,
"lvhar": null,
"lvtot": null,
"lwave": null,
"magmom": null,
"maxmix": null,
"maxmove": null,
"nbands": 9,
"nblk": null,
"nbmod": null,
"nelect": null,
"nelm": null,
"nelmdl": null,
"nelmin": null,
"nfree": null,
"ngx": null,
"ngxf": null,
"ngy": null,
"ngyf": null,
"ngz": null,
"ngzf": null,
262
"nkred": null,
"nkredx": null,
"nkredy": null,
"nkredz": null,
"nomega": null,
"nomegar": null,
"npar": null,
"nsim": null,
"nsw": 10,
"nupdown": null,
"nwrite": null,
"param1": null,
"param2": null,
"pomass": null,
"potim": null,
"prec": "Normal",
"precfock": null,
"ropt": null,
"rwigs": null,
"sdalpha": null,
"sdr": null,
"sigma": null,
"smass": null,
"snl": null,
"spring": null,
"stol": null,
"symprec": null,
"system": null,
"tebeg": null,
"teend": null,
"time": null,
"timestep": null,
"vdwgr": null,
"vdwrn": null,
"voskown": null,
"weimin": null,
"zab_vdw": null,
"zval": null
},
"atoms": {
"cell": [
[
1.818,
0.0,
1.818
],
[
1.818,
1.818,
0.0
],
[
263
0.0,
1.818,
1.818
]
],
"pbc": [
true,
true,
true
],
"positions": [
[
0.0,
0.0,
0.0
]
],
"symbols": [
"Cu"
],
"tags": [
0
]
},
"input": {
"gamma": false,
"kpts": [
13,
13,
13
],
"kpts_nintersections": null,
"reciprocal": false,
"setups": null,
"txt": "-",
"xc": "PBE"
}
}
xml This relies on the pyxser module.
1
2
3
4
265
9.4.6
Recommended values for ENCUT and valence electrons for different POTCAR files
The incar:ENCUT tag and incar:PREC tag affect the accuracy/convergence of your calculations.
1
2
3
4
5
6
7
8
9
print
print
print
print
print
#+tblname: POTCAR
#+caption: Parameters for POTPAW_PBE POTCAR files.
#+ATTR_LaTeX: longtable
| POTCAR | ENMIN | ENMAX | prec=high (eV) | # val. elect. |
|-
10
11
12
chemical_symbols.sort()
for symbol in chemical_symbols:
13
14
15
potcars = glob.glob({0}/POTPAW_PBE/{1}*/POTCAR.format(os.environ[VASP_PP_PATH],
symbol))
16
17
18
19
20
21
22
23
24
POTCAR = os.path.relpath(potcar,
os.environ[VASP_PP_PATH]+/POTPAW_PBE)[:-7]
ENMIN = get_ENMIN(potcar)
ENMAX = get_ENMAX(potcar)
HIGH = 1.3*ENMAX
ZVAL = get_ZVAL(potcar)
25
26
print |{POTCAR:30s}|{ENMIN}|{ENMAX}|{HIGH:1.3f}|{ZVAL}|.format(**locals())
266
elect.
11.0
11.0
11.0
17.0
3.0
17.0
8.0
15.0
15.0
5.0
5.0
17.0
7.0
11.0
11.0
10.0
2.0
4.0
3.0
15.0
5.0
21.0
3.0
7.0
3.0
10.0
2.0
4.0
15.0
5.0
21.0
7.0
2.0
8.0
10.0
4.0
12.0
11.0
12.0
12.0
4.0
4.0
4.0
7.0
7.0
9.0
9.0
17.0
4.0
6.0
12.0
12.0
14.0
14.0
4.0
9.0
11.0
11.0
10
Python
10.1
easy_install as a user
easy_install is a python command-line utility that automatically installs python packages. Usually
you need root access to install a python package, but you can also tell easy_install where to install a
package. This usually works if the directory is on your PYTHONPATH
easy_install -d ~/lib/python2.6/site-packages/ pymatgen
10.2
pip as a user
10.3
It pays to be careful when dividing by integers because you can get unexpected results if you do not
know the integer division rules. In python 2.6, if you divide two integers, you get an integer! This is
usually not a problem if there is no emainder in the division, e.g. 6/3=2. But, if there is a remainder,
and that remainder is important, you will lose it. Here is an example of calculating the mole fraction
of a species from integer numbers of atoms in the unit cell. If you are not careful, you get the wrong
answer! You can convert (also called casting) a number to a float using the float command.
1
2
3
4
nPd = 4
nCu = 5
x_Cu = nCu/(nPd + nCu)
print x_cu = {0} (integer division).format(x_Cu)
5
6
7
8
nPd = 4
nCu = 5
3
4
5
6
268
Finally, you can tell python a number is a float by adding a decimal to it. You do not need to put a
0 after the decimal, but you can.
1
2
nPd = 4.
nCu = 5
# this is a float
3
4
5
11
References
References
[1] David S. Sholl and Janice A. Steckel. Density Functional Theory: A Practical Introduction. Wiley,
2009.
[2] R. G. Parr and W. Yang. Density-Functional Theory of Atoms and Molecules. Oxford Science
Publications, 1989.
[3] W. Koch and M. C. Holthausen. A Chemists Guide to Density Functional Theory. Wiley-VCH,
2 edition, 2001.
[4] Charles Kittel. Introduction to Solid State Physics. Wiley, 8th edition, 2005.
[5] N. W. Ashcroft and N. David Mermin. Solid State Physics. Saunders College Publishing, 1976.
[6] Roald Hoffmann. How chemistry and physics meet in the solid state. Angewandte Chemie International Edition in English, 26(9):846878, 1987. ISSN 1521-3773. doi: 10.1002/anie.198708461.
URL http://dx.doi.org/10.1002/anie.198708461.
[7] Roald Hoffmann. A chemical and theoretical way to look at bonding on surfaces. Rev. Mod. Phys.,
60:601628, Jul 1988. doi: 10.1103/RevModPhys.60.601. URL http://link.aps.org/doi/10.
1103/RevModPhys.60.601.
[8] B. Hammer and J.K. Nrskov. Theoretical surface science and catalysiscalculations and concepts.
In Helmut Knozinger Bruce C. Gates, editor, Impact of Surface Science on Catalysis, volume 45 of
Advances in Catalysis, pages 71 129. Academic Press, 2000. doi: 10.1016/S0360-0564(02)45013-4.
URL http://www.sciencedirect.com/science/article/pii/S0360056402450134.
[9] Jeff Greeley, Jens K. Nrskov, and Manos Mavrikakis. Electronic structure and catalysis on
metal surfaces. Annual Review of Physical Chemistry, 53(1):319348, 2002. doi: 10.1146/
annurev.physchem.53.100301.131630. URL http://www.annualreviews.org/doi/abs/10.1146/
annurev.physchem.53.100301.131630.
[10] A J Freeman and E Wimmer. Density functional theory as a major tool in computational materials
science. Annual Review of Materials Science, 25(1):736, 1995. doi: 10.1146/annurev.ms.25.080195.
000255.
[11] M. C. Payne, M. P. Teter, D. C. Allan, T. A. Arias, and J. D. Joannopoulos. Iterative minimization
techniques for ab initio total-energy calculations: molecular dynamics and conjugate gradients. Rev.
Mod. Phys., 64:10451097, Oct 1992. doi: 10.1103/RevModPhys.64.1045. URL http://link.aps.
org/doi/10.1103/RevModPhys.64.1045.
269
[12] G. Kresse and J. Furthmller. Efficiency of ab-initio total energy calculations for metals and
semiconductors using a plane-wave basis set. Computational Materials Science, 6(1):15 50, 1996.
ISSN 0927-0256. doi: 10.1016/0927-0256(96)00008-0. URL http://www.sciencedirect.com/
science/article/pii/0927025696000080.
[13] T. Bligaard. Exchange and Correlation Functionals - a study toward improving the precision of
electron density functional calculations of atomistic systems. Masters thesis, Technical University
of Denmark, 2000. http://www.fysik.dtu.dk/~{}bligaard/masterthesis/masterdirectory/
project/project.pdf.
[14] T. Bligaard. Understanding Materials Properties on the Basis of Density Functional Theory
Calculations. PhD thesis, Technical University of Denmark, 2003. http://www.fysik.dtu.dk/
~{}bligaard/phdthesis/phdproject.pdf.
[15] A. P. Seitsonen. Theoretical Investigations into adsorption and co-adsorption on transition-metal
surfaces as models to heterogeneous catalysis. PhD thesis, Technical University of Berlin, School of
Mathematics and Natural Sciences, 2000. http://edocs.tu-berlin.de/diss/2000/seitsonen_ari.pdf.
[16] R. Hirschl. Binary Transition Metal Alloys and Their Surfaces. PhD thesis, Institut fr Materialphysik, University of Vienna, 2002. http://www.hirschl.at/download/diss_part1.pdf and
http://www.hirschl.at/download/diss_part2.pdf.
[17] L. Pauling and E. B. Wilson, Jr. Introduction to Quantum Mechanics with Applications to Chemistry. Dover Publications, Inc., 1963.
[18] W. Kohn. Nobel lecture: Electronic structure of matter-wave functions and density functionals.
Rev. Mod. Phys., 71:12531266, Oct 1999. doi: 10.1103/RevModPhys.71.1253. URL http://
link.aps.org/doi/10.1103/RevModPhys.71.1253.
[19] P. A. M. Dirac. Quantum mechanics of many-electron systems. Proceedings of the Royal Society
of London. Series A, Containing Papers of a Mathematical and Physical Character, 123(792):pp.
714733, 1929. ISSN 09501207. URL http://www.jstor.org/stable/95222.
[20] P. Hohenberg and W. Kohn. Inhomogeneous electron gas. Phys. Rev., 136:B864B871, Nov 1964.
doi: 10.1103/PhysRev.136.B864. URL http://link.aps.org/doi/10.1103/PhysRev.136.B864.
[21] W. Kohn and L. J. Sham. Self-consistent equations including exchange and correlation effects.
Phys. Rev., 140:A1133A1138, Nov 1965. doi: 10.1103/PhysRev.140.A1133. URL http://link.
aps.org/doi/10.1103/PhysRev.140.A1133.
[22] John A. Pople. Nobel lecture: Quantum chemical models. Rev. Mod. Phys., 71:12671274,
Oct 1999. doi: 10.1103/RevModPhys.71.1267. URL http://link.aps.org/doi/10.1103/
RevModPhys.71.1267.
[23] M. Fuchs, M. Bockstedte, E. Pehlke, and M. Scheffler. Pseudopotential study of binding properties
of solids within generalized gradient approximations: The role of core-valence exchange correlation.
Phys. Rev. B, 57:21342145, Jan 1998. doi: 10.1103/PhysRevB.57.2134. URL http://link.aps.
org/doi/10.1103/PhysRevB.57.2134.
[24] John P. Perdew, Robert G. Parr, Mel Levy, and Jose L. Balduz. Density-functional theory for
fractional particle number: Derivative discontinuities of the energy. Phys. Rev. Lett., 49:1691
1694, Dec 1982. doi: 10.1103/PhysRevLett.49.1691. URL http://link.aps.org/doi/10.1103/
PhysRevLett.49.1691.
[25] B. Hammer, L. B. Hansen, and J. K. Nrskov. Improved adsorption energetics within densityfunctional theory using revised perdew-burke-ernzerhof functionals. Phys. Rev. B, 59:7413
7421, Mar 1999. doi: 10.1103/PhysRevB.59.7413. URL http://link.aps.org/doi/10.1103/
PhysRevB.59.7413.
270
[26] G. Makov and M. C. Payne. Periodic boundary conditions in ab initio calculations. Phys. Rev. B,
51:40144022, Feb 1995. doi: 10.1103/PhysRevB.51.4014. URL http://link.aps.org/doi/10.
1103/PhysRevB.51.4014.
[27] D. J. Chadi and Marvin L. Cohen. Special points in the brillouin zone. Phys. Rev. B, 8:57475753,
Dec 1973. doi: 10.1103/PhysRevB.8.5747. URL http://link.aps.org/doi/10.1103/PhysRevB.
8.5747.
[28] Hendrik J. Monkhorst and James D. Pack. Special points for brillouin-zone integrations. Phys.
Rev. B, 13:51885192, Jun 1976. doi: 10.1103/PhysRevB.13.5188. URL http://link.aps.org/
doi/10.1103/PhysRevB.13.5188.
[29] N. Troullier and Jos Luriaas Martins. Efficient pseudopotentials for plane-wave calculations. Phys.
Rev. B, 43:19932006, Jan 1991. doi: 10.1103/PhysRevB.43.1993. URL http://link.aps.org/
doi/10.1103/PhysRevB.43.1993.
[30] David Vanderbilt. Soft self-consistent pseudopotentials in a generalized eigenvalue formalism. Phys.
Rev. B, 41:78927895, Apr 1990. doi: 10.1103/PhysRevB.41.7892. URL http://link.aps.org/
doi/10.1103/PhysRevB.41.7892.
[31] E. G. Moroni, G. Kresse, J. Hafner, and J. Furthmller. Ultrasoft pseudopotentials applied to
magnetic fe, co, and ni: From atoms to solids. Phys. Rev. B, 56:1562915646, Dec 1997. doi:
10.1103/PhysRevB.56.15629. URL http://link.aps.org/doi/10.1103/PhysRevB.56.15629.
[32] P. E. Blchl. Projector augmented-wave method. Phys. Rev. B, 50:1795317979, Dec 1994. doi:
10.1103/PhysRevB.50.17953. URL http://link.aps.org/doi/10.1103/PhysRevB.50.17953.
[33] G. Kresse and D. Joubert. From ultrasoft pseudopotentials to the projector augmented-wave
method. Phys. Rev. B, 59:17581775, Jan 1999. doi: 10.1103/PhysRevB.59.1758. URL http:
//link.aps.org/doi/10.1103/PhysRevB.59.1758.
[34] M J Gillan. Calculation of the vacancy formation energy in aluminium. Journal of Physics:
Condensed Matter, 1(4):689, 1989. URL http://stacks.iop.org/0953-8984/1/i=4/a=005.
[35] N. David Mermin. Thermal properties of the inhomogeneous electron gas. Phys. Rev., 137:A1441
A1443, Mar 1965. doi: 10.1103/PhysRev.137.A1441. URL http://link.aps.org/doi/10.1103/
PhysRev.137.A1441.
[36] J. J. Mortensen, L. B. Hansen, and K. W. Jacobsen. Real-space grid implementation of the projector
augmented wave method. Phys. Rev. B, 71:035109, Jan 2005. doi: 10.1103/PhysRevB.71.035109.
URL http://link.aps.org/doi/10.1103/PhysRevB.71.035109.
[37] G. Kresse and J. Furthmller. Efficient iterative schemes for ab initio total-energy calculations using
a plane-wave basis set. Phys. Rev. B, 54:1116911186, Oct 1996. doi: 10.1103/PhysRevB.54.11169.
URL http://link.aps.org/doi/10.1103/PhysRevB.54.11169.
[38] G. Kresse and J. Hafner. Ab initio molecular-dynamics simulation of the liquid-metal/amorphoussemiconductor transition in germanium. Phys. Rev. B, 49:1425114269, May 1994. doi: 10.1103/
PhysRevB.49.14251. URL http://link.aps.org/doi/10.1103/PhysRevB.49.14251.
[39] G. Kresse and J. Hafner. Ab initio molecular dynamics for liquid metals. Phys. Rev. B, 47:558561,
Jan 1993. doi: 10.1103/PhysRevB.47.558. URL http://link.aps.org/doi/10.1103/PhysRevB.
47.558.
[40] Joachim Paier, Robin Hirschl, Martijn Marsman, and Georg Kresse. The PerdewBurkeErnzerhof
exchange-correlation functional applied to the G2-1 test set using a plane-wave basis set. The
Journal of Chemical Physics, 122(23):234102, 2005. doi: 10.1063/1.1926272. URL http://link.
aip.org/link/?JCP/122/234102/1.
271
[41] Larry A. Curtiss, Krishnan Raghavachari, Paul C. Redfern, and John A. Pople. Assessment of
gaussian-2 and density functional theories for the computation of enthalpies of formation. The
Journal of Chemical Physics, 106(3):10631079, 1997. doi: 10.1063/1.473182. URL http://link.
aip.org/link/?JCP/106/1063/1.
[42] Graeme Henkelman, Andri Arnaldsson, and Hannes Jnsson. A fast and robust algorithm for
bader decomposition of charge density. Computational Materials Science, 36(3):354 360, 2006.
ISSN 0927-0256. doi: 10.1016/j.commatsci.2005.04.010. URL http://www.sciencedirect.com/
science/article/pii/S0927025605001849.
[43] Thomas A. Manz and David S. Sholl. Chemically meaningful atomic charges that reproduce the
electrostatic potential in periodic and nonperiodic materials. Journal of Chemical Theory and
Computation, 6(8):24552468, 2010. doi: 10.1021/ct100125x. URL http://pubs.acs.org/doi/
abs/10.1021/ct100125x.
[44] Jr. E. Bright Wilson, J.C. Decius, and Paul C. Cross. Molecular Vibrations: The Theory of Infrared
and Raman Vibrational Spectra. Dover Publications, 1955.
[45] Paolo Giannozzi and Stefano Baroni. Vibrational and dielectric properties of c6 0 from densityfunctional perturbation theory. The Journal of Chemical Physics, 100(11):85378539, 1994. doi:
10.1063/1.466753. URL http://link.aip.org/link/?JCP/100/8537/1.
[46] David Karhnek, Tom Buko, and Jrgen Hafner. A density-functional study of the adsorption
of methane-thiol on the (111) surfaces of the Ni-group metals: II. vibrational spectroscopy. Journal
of Physics: Condensed Matter, 22(26):265006, 2010. URL http://stacks.iop.org/0953-8984/
22/i=26/a=265006.
[47] Antonio Fernndez-Ramos, Benjamin Ellingson, Rubn Meana-Paeda, Jorge Marques, and Donald Truhlar. Symmetry numbers and chemical reaction rates. Theoretical Chemistry Accounts:
Theory, Computation, and Modeling (Theoretica Chimica Acta), 118:813826, 2007. ISSN 1432881X. URL http://dx.doi.org/10.1007/s00214-007-0328-0. 10.1007/s00214-007-0328-0.
[48] Daniel Sheppard, Rye Terrell, and Graeme Henkelman. Optimization methods for finding minimum
energy paths. The Journal of Chemical Physics, 128(13):134106, 2008. doi: 10.1063/1.2841941.
URL http://link.aip.org/link/?JCP/128/134106/1.
[49] R. A. Olsen, G. J. Kroes, G. Henkelman, A. Arnaldsson, and H. Jonsson. Comparison of methods
for finding saddle points without knowledge of the final states. The Journal of Chemical Physics,
121(20):97769792, 2004. doi: 10.1063/1.1809574. URL http://link.aip.org/link/?JCP/121/
9776/1.
[50] Ann E. Mattsson, Rickard Armiento, Joachim Paier, Georg Kresse, John M. Wills, and Thomas R.
Mattsson. The am05 density functional applied to solids. The Journal of Chemical Physics, 128(8):
084714, 2008. doi: 10.1063/1.2835596. URL http://link.aip.org/link/?JCP/128/084714/1.
[51] Yvon Le Page and Paul Saxe. Symmetry-general least-squares extraction of elastic data for strained
materials from ab initio calculations of stress. Phys. Rev. B, 65:104104, Feb 2002. doi: 10.1103/
PhysRevB.65.104104. URL http://link.aps.org/doi/10.1103/PhysRevB.65.104104.
[52] Shun-Li Shang, Yi Wang, DongEung Kim, and Zi-Kui Liu. First-principles thermodynamics from
phonon and debye model: Application to ni and ni3al. Computational Materials Science, 47(4):
1040 1048, 2010. ISSN 0927-0256. doi: 10.1016/j.commatsci.2009.12.006. URL http://www.
sciencedirect.com/science/article/pii/S0927025609004558.
[53] A. van de Walle, M. Asta, and G. Ceder. The alloy theoretic automated toolkit: A user guide.
Calphad, 26(4):539 553, 2002. ISSN 0364-5916. doi: 10.1016/S0364-5916(02)80006-2. URL
http://www.sciencedirect.com/science/article/pii/S0364591602800062.
272
[54] Axel van de Walle. Multicomponent multisublattice alloys, nonconfigurational entropy and other
additions to the alloy theoretic automated toolkit. Calphad, 33(2):266 278, 2009. ISSN 0364-5916.
doi: 10.1016/j.calphad.2008.12.005. URL http://www.sciencedirect.com/science/article/
pii/S0364591608001314. <ce:title>Tools for Computational Thermodynamics</ce:title>.
[55] Lei Wang, Thomas Maxisch, and Gerbrand Ceder. Oxidation energies of transition metal oxides
within the GGA + U framework. Phys. Rev. B, 73:195107, May 2006. doi: 10.1103/PhysRevB.73.
195107. URL http://link.aps.org/doi/10.1103/PhysRevB.73.195107.
[56] Leonard Kleinman. Significance of the highest occupied Kohn-Sham eigenvalue. Phys. Rev. B, 56:
1204212045, Nov 1997. doi: 10.1103/PhysRevB.56.12042. URL http://link.aps.org/doi/10.
1103/PhysRevB.56.12042.
[57] John P. Perdew and Mel Levy. Comment on "Significance of the highest occupied Kohn-Sham
eigenvalue". Phys. Rev. B, 56:1602116028, Dec 1997. doi: 10.1103/PhysRevB.56.16021. URL
http://link.aps.org/doi/10.1103/PhysRevB.56.16021.
[58] Leonard Kleinman. Reply to "Comment on Significance of the highest occupied Kohn-Sham
eigenvalue ". Phys. Rev. B, 56:1602916030, Dec 1997. doi: 10.1103/PhysRevB.56.16029. URL
http://link.aps.org/doi/10.1103/PhysRevB.56.16029.
[59] Ralf Stowasser and Roald Hoffmann. What do the Kohn-Sham Orbitals and Eigenvalues Mean?
Journal of the American Chemical Society, 121(14):34143420, 1999. doi: 10.1021/ja9826892. URL
http://pubs.acs.org/doi/abs/10.1021/ja9826892.
[60] O. V. Gritsenko and E. J. Baerends. The analog of Koopmans theorem in spin-density functional
theory. The Journal of Chemical Physics, 117(20):91549159, 2002. doi: 10.1063/1.1516800. URL
http://link.aip.org/link/?JCP/117/9154/1.
[61] R. O. Jones and O. Gunnarsson. The density functional formalism, its applications and prospects.
Rev. Mod. Phys., 61:689746, Jul 1989. doi: 10.1103/RevModPhys.61.689. URL http://link.
aps.org/doi/10.1103/RevModPhys.61.689.
[62] J. P. Perdew and Alex Zunger. Self-interaction correction to density-functional approximations for
many-electron systems. Phys. Rev. B, 23:50485079, May 1981. doi: 10.1103/PhysRevB.23.5048.
URL http://link.aps.org/doi/10.1103/PhysRevB.23.5048.
[63] Daniel Sanchez-Portal, Emilio Artacho, and Jose M Soler. Projection of plane-wave calculations
into atomic orbitals. Solid State Communications, 95(10):685 690, 1995. ISSN 0038-1098. doi:
10.1016/0038-1098(95)00341-X. URL http://www.sciencedirect.com/science/article/pii/
003810989500341X.
[64] M. D. Segall, R. Shah, C. J. Pickard, and M. C. Payne. Population analysis of plane-wave electronic
structure calculations of bulk materials. Phys. Rev. B, 54:1631716320, Dec 1996. doi: 10.1103/
PhysRevB.54.16317. URL http://link.aps.org/doi/10.1103/PhysRevB.54.16317.
[65] M. D. Segall, C. J. Pickard, R. Shah, and M. C. Payne. Population analysis in plane wave electronic
structure calculations. Mol. Phys., 89(2):571577, 1996.
[66] A Ruban, B Hammer, P Stoltze, H.L Skriver, and J.K Nrskov. Surface electronic structure
and reactivity of transition and noble metals. Journal of Molecular Catalysis A: Chemical, 115
(3):421 429, 1997. ISSN 1381-1169. doi: 10.1016/S1381-1169(96)00348-2. URL http://www.
sciencedirect.com/science/article/pii/S1381116996003482.
[67] A. Cottrell. Introduction to the Modern Theory of Metals. The Institute of Metals, 1988.
[68] F. Ducastelle. Order and Phase Stability in Alloys. Elsevier Science Publishers, 1991.
273
[69] D. G. Pettifor and A. H. Cottrell, editors. Electon Theory in Alloy Design. The Institute of
Materials, 1992.
[70] Stefano Baroni, Stefano de Gironcoli, Andrea Dal Corso, and Paolo Giannozzi. Phonons and related
crystal properties from density-functional perturbation theory. Rev. Mod. Phys., 73:515562, Jul
2001. doi: 10.1103/RevModPhys.73.515. URL http://link.aps.org/doi/10.1103/RevModPhys.
73.515.
[71] Kyle J. Caspersen and Emily A. Carter. Finding transition states for crystalline solid/solid phase
transformations. Proceedings of the National Academy of Sciences of the United States of America,
102(19):67386743, 2005. doi: 10.1073/pnas.0408127102. URL http://www.pnas.org/content/
102/19/6738.abstract.
[72] Daniel Sheppard, Penghao Xiao, William Chemelewski, Duane D. Johnson, and Graeme Henkelman. A generalized solid-state nudged elastic band method. The Journal of Chemical Physics, 136
(7):074103, 2012. doi: 10.1063/1.3684549. URL http://link.aip.org/link/?JCP/136/074103/
1.
[73] G. Ritz, M. Schmid, P. Varga, A. Borg, and M. Rnning. Pt(100) quasihexagonal reconstruction:
A comparison between scanning tunneling microscopy data and effective medium theory simulation
calculations. Phys. Rev. B, 56:1051810525, Oct 1997. doi: 10.1103/PhysRevB.56.10518. URL
http://link.aps.org/doi/10.1103/PhysRevB.56.10518.
[74] Paula Havu, Volker Blum, Ville Havu, Patrick Rinke, and Matthias Scheffler. Large-scale surface
reconstruction energetics of pt(100) and au(100) by all-electron density functional theory. Phys.
Rev. B, 82:161418, Oct 2010. doi: 10.1103/PhysRevB.82.161418. URL http://link.aps.org/
doi/10.1103/PhysRevB.82.161418.
[75] Wei Chen, David Schmidt, William F. Schneider, and C. Wolverton. First-principles cluster expansion study of missing-row reconstructions of fcc (110) surfaces. Phys. Rev. B, 83:075415, Feb
2011. doi: 10.1103/PhysRevB.83.075415. URL http://link.aps.org/doi/10.1103/PhysRevB.
83.075415.
[76] J. W. M. Frenken, R. L. Krans, J. F. van der Veen, E. Holub-Krappe, and K. Horn. Missing-row
surface reconstruction of ag(110) induced by potassium adsorption. Phys. Rev. Lett., 59:2307
2310, Nov 1987. doi: 10.1103/PhysRevLett.59.2307. URL http://link.aps.org/doi/10.1103/
PhysRevLett.59.2307.
[77] J. C. Boettger. Nonconvergence of surface energies obtained from thin-film calculations. Phys.
Rev. B, 49:1679816800, Jun 1994. doi: 10.1103/PhysRevB.49.16798. URL http://link.aps.
org/doi/10.1103/PhysRevB.49.16798.
[78] J. C. Boettger, John R. Smith, Uwe Birkenheuer, Notker Rsch, S. B. Trickey, John R. Sabin, and
S. Peter Apell. Extracting convergent surface formation energies from slab calculations. Journal
of Physics: Condensed Matter, 10(4):893, 1998. URL http://stacks.iop.org/0953-8984/10/
i=4/a=017.
[79] Carlos Fiolhais, L.M. Almeida, and C. Henriques. Extraction of aluminium surface energies from
slab calculations: perturbative and non-perturbative approaches. Progress in Surface Science, 74
(18):209 217, 2003. ISSN 0079-6816. doi: 10.1016/j.progsurf.2003.08.017. URL http://www.
sciencedirect.com/science/article/pii/S0079681603000777.
[80] Fabien Tran, Robert Laskowski, Peter Blaha, and Karlheinz Schwarz. Performance on molecules,
surfaces, and solids of the Wu-Cohen GGA exchange-correlation energy functional. Phys. Rev. B,
75:115131, Mar 2007. doi: 10.1103/PhysRevB.75.115131. URL http://link.aps.org/doi/10.
1103/PhysRevB.75.115131.
274
[81] Jeong Woo Han, Liwei Li, and David S. Sholl. Density functional theory study of H and CO
adsorption on alkali-promoted Mo2 C surfaces. The Journal of Physical Chemistry C, 115(14):6870
6876, 2011. doi: 10.1021/jp200950a. URL http://pubs.acs.org/doi/abs/10.1021/jp200950a.
[82] Nilay nolu and John R. Kitchin. Atomistic thermodynamics study of the adsorption and the
effects of watergas shift reactants on cu catalysts under reaction conditions. Journal of Catalysis,
261(2):188 194, 2009. ISSN 0021-9517. doi: 10.1016/j.jcat.2008.11.020. URL http://www.
sciencedirect.com/science/article/pii/S0021951708004314.
[83] L. Vitos, A.V. Ruban, H.L. Skriver, and J. Kollr. The surface energy of metals. Surface Science,
411(12):186 202, 1998. ISSN 0039-6028. doi: 10.1016/S0039-6028(98)00363-X. URL http:
//www.sciencedirect.com/science/article/pii/S003960289800363X.
[84] Jrg Neugebauer and Matthias Scheffler. Adsorbate-substrate and adsorbate-adsorbate interactions
of Na and K adlayers on Al(111). Phys. Rev. B, 46:1606716080, Dec 1992. doi: 10.1103/PhysRevB.
46.16067. URL http://link.aps.org/doi/10.1103/PhysRevB.46.16067.
[85] Lennart Bengtsson. Dipole correction for surface supercell calculations. Phys. Rev. B, 59:12301
12304, May 1999. doi: 10.1103/PhysRevB.59.12301. URL http://link.aps.org/doi/10.1103/
PhysRevB.59.12301.
[86] Yoshitada Morikawa. Adsorption geometries and vibrational modes of C2 H2 on the si(001) surface.
Phys. Rev. B, 63:033405, Jan 2001. doi: 10.1103/PhysRevB.63.033405. URL http://link.aps.
org/doi/10.1103/PhysRevB.63.033405.
[87] Nilay nolu and John R. Kitchin. Simple model explaining and predicting coverage-dependent
atomic adsorption energies on transition metal surfaces. Phys. Rev. B, 82:045414, Jul 2010. doi:
10.1103/PhysRevB.82.045414. URL http://link.aps.org/doi/10.1103/PhysRevB.82.045414.
[88] Spencer D. Miller, Nilay Inoglu, and John R. Kitchin. Configurational correlations in the coverage
dependent adsorption energies of oxygen atoms on late transition metal fcc(111) surfaces. The
Journal of Chemical Physics, 134(10):104709, 2011. doi: 10.1063/1.3561287. URL http://link.
aip.org/link/?JCP/134/104709/1.
[89] Spencer D. Miller and John R. Kitchin. Relating the coverage dependence of oxygen adsorption
on Au and Pt fcc(111) surfaces through adsorbate-induced surface electronic structure effects.
Surface Science, 603(5):794 801, 2009. ISSN 0039-6028. doi: 10.1016/j.susc.2009.01.021. URL
http://www.sciencedirect.com/science/article/pii/S0039602809001186.
[90] John R. Kitchin. Correlations in coverage-dependent atomic adsorption energies on pd(111). Phys.
Rev. B, 79:205412, May 2009. doi: 10.1103/PhysRevB.79.205412. URL http://link.aps.org/
doi/10.1103/PhysRevB.79.205412.
[91] John R. Kitchin, Karsten Reuter, and Matthias Scheffler. Alloy surface segregation in reactive environments: First-principles atomistic thermodynamics study of Ag3 Pd(111) in oxygen
atmospheres. Phys. Rev. B, 77:075437, Feb 2008. doi: 10.1103/PhysRevB.77.075437. URL
http://link.aps.org/doi/10.1103/PhysRevB.77.075437.
[92] Anand Udaykumar Nilekar, Jeff Greeley, and Manos Mavrikakis. A simple rule of thumb for
diffusion on transition-metal surfaces. Angewandte Chemie International Edition, 45(42):7046
7049, 2006. ISSN 1521-3773. doi: 10.1002/anie.200602223. URL http://dx.doi.org/10.1002/
anie.200602223.
[93] Graeme Henkelman, Blas P. Uberuaga, and Hannes Jonsson. A climbing image nudged elastic band
method for finding saddle points and minimum energy paths. The Journal of Chemical Physics,
113(22):99019904, 2000. doi: 10.1063/1.1329672. URL http://link.aip.org/link/?JCP/113/
9901/1.
275
[94] P. Deshlahra, E. E. Wolf, and W. F. Schneider. A periodic density functional theory analysis of
co chemisorption on pt(111) in the presence of uniform electric fields. The Journal of Physical
Chemistry A, 113(16):41254133, 2009. doi: 10.1021/jp810518x. URL http://pubs.acs.org/
doi/abs/10.1021/jp810518x.
[95] B. Meredig, A. Thompson, H. A. Hansen, C. Wolverton, and A. van de Walle. Method for locating
low-energy solutions within DFT + u. Phys. Rev. B, 82:195128, Nov 2010. doi: 10.1103/PhysRevB.
82.195128. URL http://link.aps.org/doi/10.1103/PhysRevB.82.195128.
[96] Anubhav Jain, Geoffroy Hautier, Shyue Ping Ong, Charles J. Moore, Christopher C. Fischer,
Kristin A. Persson, and Gerbrand Ceder. Formation enthalpies by mixing GGA and GGA +
U calculations. Phys. Rev. B, 84:045115, Jul 2011. doi: 10.1103/PhysRevB.84.045115. URL
http://link.aps.org/doi/10.1103/PhysRevB.84.045115.
[97] Kyuho Lee, amonn D. Murray, Lingzhu Kong, Bengt I. Lundqvist, and David C. Langreth.
Higher-accuracy van der waals density functional. Phys. Rev. B, 82:081101, Aug 2010. doi: 10.
1103/PhysRevB.82.081101. URL http://link.aps.org/doi/10.1103/PhysRevB.82.081101.
[98] Stefan Grimme. Semiempirical gga-type density functional constructed with a long-range dispersion
correction. Journal of Computational Chemistry, 27(15):17871799, 2006. ISSN 1096-987X. doi:
10.1002/jcc.20495. URL http://dx.doi.org/10.1002/jcc.20495.
[99] B. Silvi and A Savin. Classification of chemical bonds based on topological analysis of electron
localization functions. Nature, 371:683686, 1994. URL http://dx.doi.org/10.1038/371683a0.
[100] M. Hebbache and M. Zemzemi. Ab initio study of high-pressure behavior of a low compressibility
metal and a hard material: osmium and diamond. Phys. Rev. B, 70:224107, Dec 2004. doi:
10.1103/PhysRevB.70.224107. URL http://link.aps.org/doi/10.1103/PhysRevB.70.224107.
[101] F. D. Murnaghan. The compressibility of media under extreme pressures. Proceedings of the
National Academy of Sciences of the United States of America, 30(9):pp. 244247, 1944. ISSN
00278424. URL http://www.jstor.org/stable/87468.
[102] C. L. Fu and K. M. Ho. First-principles calculation of the equilibrium ground-state properties
of transition metals: Applications to Nb and Mo. Phys. Rev. B, 28:54805486, Nov 1983. doi:
10.1103/PhysRevB.28.5480. URL http://link.aps.org/doi/10.1103/PhysRevB.28.5480.
[103] Michael J. Mehl, Barry M. Klein, and Dimitri A. Papaconstantopoulos. Intermetallic Compounds:
Principles and Principles, Volume I: Principles, volume I, chapter First principles calculations of
elastic properties of metals, pages 195210. John Wiley and Sons, 1995. URL http://cst-www.
nrl.navy.mil/users/mehl/papers/cij453.pdf.
[104] B. Mayer, H. Anton, E. Bott, M. Methfessel, J. Sticht, J. Harris, and P.C. Schmidt. Ab-initio
calculation of the elastic constants and thermal expansion coefficients of laves phases. Intermetallics, 11(1):23 32, 2003. ISSN 0966-9795. doi: 10.1016/S0966-9795(02)00127-9. URL
http://www.sciencedirect.com/science/article/pii/S0966979502001279.
12
Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
<http://fsf.org/>
276
277
them.
The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License. If a
section does not fit the above definition of Secondary then it is not
allowed to be designated as Invariant. The Document may contain zero
Invariant Sections. If the Document does not identify any Invariant
Sections then there are none.
The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License. A Front-Cover Text may
be at most 5 words, and a Back-Cover Text may be at most 25 words.
A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters. A copy made in an otherwise Transparent file
format whose markup, or absence of markup, has been arranged to thwart
or discourage subsequent modification by readers is not Transparent.
An image format is not Transparent if used for any substantial amount
of text. A copy that is not "Transparent" is called "Opaque".
Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification. Examples of
transparent image formats include PNG, XCF and JPG. Opaque formats
include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML, PostScript or PDF produced by some word
processors for output purposes only.
The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page. For works in
formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the works title,
preceding the beginning of the body of the text.
The "publisher" means any person or entity that distributes copies of
the Document to the public.
A section "Entitled XYZ" means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language. (Here XYZ stands for a
278
3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
Documents license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover. Both covers must also clearly and legibly identify
you as the publisher of these copies. The front cover must present
the full title with all words of the title equally prominent and
visible. You may add other material on the covers in addition.
Copying with changes limited to the covers, as long as they preserve
the title of the Document and satisfy these conditions, can be treated
as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.
If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a computer-network location from which the general network-using
279
4. MODIFICATIONS
You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy
of it. In addition, you must do these things in the Modified Version:
A. Use in the Title Page (and on the covers, if any) a title distinct
from that of the Document, and from those of previous versions
(which should, if there were any, be listed in the History section
of the Document). You may use the same title as a previous version
if the original publisher of that version gives permission.
B. List on the Title Page, as authors, one or more persons or entities
responsible for authorship of the modifications in the Modified
Version, together with at least five of the principal authors of the
Document (all of its principal authors, if it has fewer than five),
unless they release you from this requirement.
C. State on the Title page the name of the publisher of the
Modified Version, as the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications
adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a license notice
giving the public permission to use the Modified Version under the
terms of this License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections
and required Cover Texts given in the Documents license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled "History", Preserve its Title, and add
to it an item stating at least the title, year, new authors, and
publisher of the Modified Version as given on the Title Page. If
there is no section Entitled "History" in the Document, create one
stating the title, year, authors, and publisher of the Document as
given on its Title Page, then add an item describing the Modified
Version as stated in the previous sentence.
280
5. COMBINING DOCUMENTS
You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
281
6. COLLECTIONS OF DOCUMENTS
You may make a collection consisting of the Document and other
documents released under this License, and replace the individual
copies of this License in the various documents with a single copy
that is included in the collection, provided that you follow the rules
of this License for verbatim copying of each of the documents in all
other respects.
You may extract a single document from such a collection, and
distribute it individually under this License, provided you insert a
copy of this License into the extracted document, and follow this
License in all other respects regarding verbatim copying of that
document.
282
8. TRANSLATION
Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections. You may include a
translation of this License, and all the license notices in the
Document, and any Warranty Disclaimers, provided that you also include
the original English version of this License and the original versions
of those notices and disclaimers. In case of a disagreement between
the translation and the original version of this License or a notice
or disclaimer, the original version will prevail.
If a section in the Document is Entitled "Acknowledgements",
"Dedications", or "History", the requirement (section 4) to Preserve
its Title (section 1) will typically require changing the actual
title.
9. TERMINATION
You may not copy, modify, sublicense, or distribute the Document
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense, or distribute it is void, and
will automatically terminate your rights under this License.
However, if you cease all violation of this License, then your license
from a particular copyright holder is reinstated (a) provisionally,
unless and until the copyright holder explicitly and finally
terminates your license, and (b) permanently, if the copyright holder
fails to notify you of the violation by some reasonable means prior to
60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, receipt of a copy of some or all of the same material does
not give you any rights to use it.
283
284
13
Index
285
Index
adsorption energy, 168
atomistic thermodynamics, 195
bader, 38
band structure, 127
center of mass, 21
cohesive energy, 103
convergence
ENCUT, 57
KPOINTS, 103
DFT+U, 204
dipole correction, 166
dipole moment, 32
HSE06, 208
infrared intensity, 48
ISMEAR, 87
jasp, 2
molecular weight, 20
moment of inertia, 21
nudged elastic band, 77
reconstruction, 158
SIGMA, 87
thermochemistry, 52
vibrations, 45
work function, 163
286