DFT using python

March 26, 2018 | Author: Avanindra Kumar Pandeya | Category: Density Functional Theory, Electron, Condensed Matter Physics, Physical Sciences, Science


Comments



Description

Contents1 Introduction to this book 6 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 . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.9 5.10 5.11 5.12 5.13 5.8.2 Coverage dependence . . . . . . . . . . . . . 5.8.3 Effect of adsorption on the surface energy . . Adsorbate vibrations . . . . . . . . . . . . . . . . . . 5.9.1 Vibrations of the bridge site . . . . . . . . . . Surface Diffusion barrier . . . . . . . . . . . . . . . . 5.10.1 Standard nudged elastic band method . . . . 5.10.2 Climbing image NEB . . . . . . . . . . . . . 5.10.3 Using vibrations to confirm a transition state TODO Diffusion rates with transition state theory . TODO Effects of electric fields on adsorbates . . . . TODO Simulating STM images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 . . . . . . . . . . . . . . . . . . . . . . . . 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 9.2.1 Changing coordinate systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 9.2.2 Simple distances, angles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 9.2.3 Unit cell properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 9.2.4 d-spacing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 Equations of State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 9.3.1 Birch-Murnaghan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 9.3.2 Murnaghan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 9.3.3 Birch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 9.3.4 The Anton-Schmidt Equation of state 104 . . . . . . . . . . . . . . . . . . . . . . . 250 9.3.5 Fitting data to these equations of state . . . . . . . . . . . . . . . . . . . . . . . . 250 Miscellaneous jasp/VASP tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 9.4.1 Installing jasp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 9.4.2 Using a special setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 9.4.3 Running jasp in parallel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 9.4.4 Running multiple instances of jasp in parallel . . . . . . . . . . . . . . . . . . . . . 255 9.4.5 Exporting data json, xml, python, sqlite . . . . . . . . . . . . . . . . . . . . . . . . 259 9.4.6 Recommended values for ENCUT and valence electrons for different POTCAR files 266 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 12 GNU Free Documentation License 276 13 Index 285 4 Copyright ©2012–2015\ John Kitchin Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". 5 1 Introduction to this book This book serves two purposes: 1) to provide worked examples of using DFT to model materials properties. does not submit jobs more than once. so you can replace this kind of code: 1 2 with jasp(’directory’. In that sense. with the intention of giving you enough information and knowledge to start your research. atoms=atoms) as calc: #do stuff 6 . plots the relaxation trajectory. and to version control (git) software. and then changing back to where you started from. The goal in writing mod:jasp was to create a computational environment where you write one script to create.vasp. The code is smart. run and analyze your calculations. and 2) to provide references to more advanced treatments of these topics in the literature. 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. I believe that computational work should always be scripted. and is best read in emacs in org-mode. as well as the ability to interact with the tables and code. jaspsum is a utility program provided in jasp which prints a pretty representation of the state of a calculation. mod:jasp takes care of changing into VASP calculation directories. You should be able to copy the actual VASP input files (which were generated by jasp) from a directory and simply run vasp.vasp as mod:jasp is developed. lotsofkeywords. The best way to learn to use jasp is from this book. as the comprehension of code is an integral part of its design. mod:jasp has some features that mod:ase. and how to interpret the results. The book is also available in PDF. syntax highlighting. This format provides clickable links. easy navigation. allowing you to reproduce your code or report the method of its execution exactly at a later time. It was written by me to facilitate writing this book and to develop the best possible way to run DFT calculations.vasp does not have yet. mod:jasp has an interface to sqlite. They may get incorporated into ase one day. You will read a lot of python code in this book. and gives you answers when available. you will learn how to analyze the data.calculators. It is not critical that you use mod:jasp.calculators. many of the computations are not publication quality with respect to convergence of calculation parameters.com/jkitchin/dft-book • jasp mod:jasp is a sophisticated wrapper to the mod:ase. or prints a code representation of a VASP directory. It probably requires the latest svn version of ase to work since I have been adding new functionality to mod:ase. mod:jasp is available at https://github. a written record of everything you have done will be available. This book is very much "recipe" oriented.vasp python interface to the VASP calculator. As a result. Along the way to learning how to perform the calculations. make plots. It is not a definitive reference on density functional theory.calculators. mod:jasp is mostly compatible with mod:ase. and submits jobs to a queue system when required.calculators. • git This book is available at https://github. allows many jobs to run in parallel.com/jkitchin/jasp. but both of these books focus on molecular systems. and replace the code that defines the calculator. 14 The Ph.py). but a consequence of this is that it is rarely discussed in current papers in the literature. The DFT code used primarily in this book is VASP. only the elements of DFT that are relevant to this work will be discussed. • VASP wiki • VASP Manual Similar code would be used for other calculators. One of the most useful sources of information has been the dissertations of other students.1 Review all the hyperlinks in this chapter. 2 The Chemist’s Guide to DFT 3 is more readable and contains more practical information for running calculations. A modern and practical introduction to density functional theory can be found in Sholl and Steckel. a coauthor of Dacapo.set_calculator(calc) 5 6 try: 7 #do stuff finally: os. Thomas Bligaard. 15 Finally. 8.chdir(CWD) 8 9 Open the python script (dft-scripts/script-2. Jacapo. and convergence tests of calculations. Exercise 1. you would just have to import the python modules for those codes. with code similar to this: 1 2 3 4 CWD = os. An excellent review on other implementations of DFT can be found in Reference 10 . one should consult the exceptionally clear writings of Roald Hoffman. as excellent reviews on these subjects are readily found in the literature. 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.chdir(’directory’) calc=Vasp(lotsofkeywords) atoms. GPAW.py). etc. 11. and are suggested reading in the following paragraph. in addition to a thorough description of DFT and analysis of calculation output.Open the python script (dft-scripts/script-1. e. 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. neither of these books is particularly easy to relate to chemistry. However.D. 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. 5 Both have their fine points. and details on the various algorithms used in DFT codes can be found in Refs. 1 A fairly standard textbook on DFT is the one written by Parr and Yang. For this. . thesis of Ari Seitsonen contains several useful appendices on k-point setups. Much of the information presented here is standard knowledge among experts.7 and follow these with the work of Nørskov and coworkers. 16 7 .9 In this chapter. The standard texts in solid state physics are by Kittel 4 and Ashcroft and Mermin. perhaps because the difficulties they faced in learning the material are still fresh in their minds. 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. 2 Introduction to DFT A comprehensive overview of DFT is beyond the scope of this book. the former being more mathematically rigorous and the latter more readable.12 .getcwd() os. Instead.g. . 6. 1). (2. (2. The ground state density is given by: n(r) = PN j=1 |ϕ_j(r)|ˆ2 (3) To solve Eq.1) then. the density needs to be known in order to define the effective potential so that Eq. this difficulty was recognized by Dirac as early as 1929.1). single particle equations known as the Kohn-Sham (KS) equations:  1 − 2  ∇ˆ2 + veff (r) -_j ϕ_j (r)=0. This equation is then solved for ϕj (r) iteratively until the ϕj (r) that result from the solution are the same as the ϕj (r) that are used to define the equations. (2) where v(r) is the external potential and vxc (r) is the exchange-correlation potential. in f (x) = x2 .1) can be solved. 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. Thus. Schr\"odinger’s wave function seemed extremely promising. as it contains all of the information available about a system. limiting this approach to systems with a small number of relevant electrons. which has been extremely successful in studying the properties of small molecules. 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. which is subsequently used in Eq. in the presence of ion cores) to that of the minimization of a functional of the three-dimensional density function. For example. (2.1 Background In 1926. 17 He later shared the Nobel prize with Paul A. which depends on the entire density function. extended solids. Finally.2. M. the definition of the functional involved a set of 3N-dimensional trial wave functions. N . Unfortunately.. and itR equals four when π x = 2. most practical systems of interest consist of many interacting electrons. is unsuitable for studies of large. the solutions are self-consistent.e. a system with 100 electrons is still very small. and it is equal to two when f (x) = sin(x). Thus. (2.". O(10). (1) with v R _eff(r) = v(r)+ { n(r0 )}{|r−r0 |}dr0 +v _xc(r). f (x) is the function. 21 This led to a set of self-consistent. the wave function method. Unfortunately. 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. Thus. A functional returns a number when given a function. ϕj (r) corresponds to the j th KS orbital of energy j . two Ru atoms if all the electrons are counted. a function returns a number when given a number. for example. and the effort required to find solutions to Schr\"odinger’s equation increases exponentially with the number of electrons. 18 Even if this rough estimate is off by an order of magnitude. an initial guess is used for ϕj (r) which is used to generate Eq. 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. g(f (x)) is the functional. the ground state energy is given by: E= 8 . Dirac in 1933 for this discovery. 20 By definition. Erwin Schr\"odinger published the first accounts of his now famous wave equation. that is. Interestingly. or perhaps ten Pt atoms if only the valence electrons are counted. and the difficulty is only that the application of these laws leads to equations much too complicated to be soluble. in g(f (x)) = 0 f (x)dx. In 1965. Walter Kohn shared the Nobel prize in Chemistry in 1998 for this work. In molecules and solids. such as lattice constants compared to experimental data.(4) where Exc [n(r)] is the exchange-correlation energy functional. 13 2. etc. Bloch’s theorem sets the stage for using planewaves as a basis set. In aperiodic systems. 24 The generalized gradient approximation includes corrections for gradients in the electron density. however. If the periodic function unk (r) is also expanded in terms of planewaves determined by wave vectors of the reciprocal lattice vectors. PBE. the exchange-correlation functional is defined for an electron in a uniform electron gas of density n. the density tends to vary substantially in space. The so-called hybrid functionals.1) is exact.3 Basis sets Briefly. or randomly ordered alloys. Eq. there is no periodic unit cell. In a periodic solid. 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. revPBE. This also converts Eq.k+G are now coefficients that can be varied to determine the lowest energy solution. 25 In this book the PBE GGA functional is used the most. None of these other types of functionals were used in this work. The form of this corrective function. or "exchange enhancement" function determines which functional it is. in Gaussian).k+G exp(i(k + G) · r). For more details see Chapter 6 in Ref. 3 and Thomas Bligaard’s thesis on exchange and correlation functionals. These systems were 9 .2 Exchange correlation functionals The two main types of exchange/correlation functionals used in DFT are the local density approximation (LDA) and the generalized gradient approximation (GGA). and is often implemented as a corrective function of the LDA. are more popular with gaussian basis sets (e.g. (2. RPBE. the exact form of the exchange-correlation energy functional is not known. and k is a so-called wave vector that will only have certain allowed values defined by the size of the unit cell. Despite this. which is then subjected to the periodic boundary conditions so that a planewave basis set can be used. (6) G where ci.vxc (r) n(r) dr -1 2 {{ n(r)n(r0 )}{|r−r0 |}dr0 r}. 25 Finally. However. 18 The other half of the prize went to John Pople for his efforts in wave function based quantum mechanical methods. (2. 2. thus approximations for this functional must be used. such as systems with even one defect. one can use Bloch’s 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. then the wave function can be expressed completely in terms of a sum of planewaves: 11 X ψi (r) = ci. Instead one must represent the portion of the system of interest in a supercell. 22 Provided the exchange-correlation energy functional is known. In the LDA. such as B3LYP. The case of the randomly ordered alloy is virtually hopeless as the energy of different configurations will fluctuate statistically about an average value. 21 It is exact for a uniform electron gas.g. It then becomes necessary to ensure the supercell is large enough to avoid interactions between the defects in neighboring supercells.R R P _j$\epsilon$_j + Exc [n(r)]. but they are presently inefficient with planewave basis sets. there are increasingly new types of functionals in the literature. because it suggests a planewave character of the wave function. It tends to predict overbonding in both molecular and solid systems. e. and is anticipated to be a reasonable approximation for slowly varying densities. the LDA has been very successfully used in many systems.1) from an integral equation to a set of algebraic equations that can readily be solved using matrix algebra. G. VASP utilizes planewaves as the basis set to expand the Kohn-Sham orbitals. 23 and it tends to make semiconductor systems too metallic (the band gap problem). The cutoff energy required to obtain a particular convergence precision is also element dependent. It can also vary with the "softness" of the pseudopotential. there are 10 . 27 and the MonkhorstPack scheme. which are suitably weighted to account for the finite number of them. the charge enclosed in the pseudopotential region is the same as that enclosed by the same space in an all-electron calculation. this allows a "softer" pseudopotential to be generated. This means that a very large number of planewaves are required to expand their wave functions. there are still an infinite number of discrete k points that must be considered. Furthermore. In this work.4 Pseudopotentials The core electrons of an atom are computationally expensive with planewave basis sets because they are highly localized. thus an interpolation scheme can be used with a finite number of k points. norm-conserving soft pseudopotentials 29 and Vanderbilt ultrasoft pseudopotentials. and the energy of the unit cell is calculated as an integral over these points. which means fewer planewaves are required to expand it. Precision Low High Mo 168 293 O 300 520 O_sv 1066 1847 Bloch’s theorem eliminates the need to calculate an infinite number of wave functions. It turns out that wave functions at k points that are close together are similar. but these can be reduced and tested for convergence by using higher k-point densities. However. Once a supercell is chosen. The most common schemes for generating k points are the Chadi-Cohen scheme. 29 There are essentially two kinds of pseudopotentials. Table 1 refers to convergence of total energies. one needs an infinite number of planewaves. As its name implies. Bloch’s theorem can be applied to the new artificially periodic system. otherwise the energy of the wave function would go to infinity. 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. and calculated properties depend on them. This also converts the integral used to determine the energy into a sum over the k points. it is usually differences in energy that are important. 28 2. which allows a straight-forward interpolation of the function between the points that is more accurate than with other k point generation schemes. In norm-conserving pseudopotentials. however. To get a perfect expansion. this requirement is relaxed and charge augmentation functions are used to make up the difference. the primary role of the core electron wave functions is to ensure proper orthogonality between the valence electrons and core states. An excellent discussion of this for aperiodic systems can be found in Ref. These energies are rarely considered directly. careful testing should be done to ensure the desired level of convergence of properties in different systems. shown in Table 1. This provides justification for truncating the planewave basis set above a cutoff energy. because there are only a finite number of electrons in the unit (super) cell. and for more detailed discussions the reader is referred to Ref. Luckily. However. 26 . Thus. the contributions of the core electrons to bonding compared to those of the valence electrons is usually negligible. 28 The use of these k point setups amounts to an expansion of the periodic function in reciprocal space. The pseudopotentials are not unique. There will be errors in the total energy associated with the finite number of k. These tend to converge with the planewave cutoff energy much more quickly than total energies.not considered in this work. Consequently. 350 eV was found to be suitable for the H adsorption calculations. Careful testing of the effect of the cutoff energy on the total energy can be done to determine a suitable cutoff energy. due to cancellations of convergence errors. In fact. the coefficients of the planewaves must go to zero for high energy planewaves. but a cutoff energy of 450 eV was required for O adsorption calculations. 30 In either case. the pseudopotential function is generated from an all-electron calculation of an atom in some reference state. 26 . Table 1: Planewave cutoff energies (in eV) required for different convergence precisions for different elements. In ultrasoft pseudopotentials. 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). the DOS is smeared across the Fermi level.5 in Reference 3 for more details on this. spin polarization is not considered by default. The downside of including spin polarization is that it essentially doubles the calculation time. and there are typically a substantial number of states that are close in energy to the Fermi level. At higher temperatures. and all bands above the Fermi level are unoccupied.0 Bohr-magnetons should be used. the step function is replaced by a smoothly varying function such as the Fermi-Dirac function at a small. The spin-polarized solution is sensitive to the initial guess.61 Bohr-magnetons. For a hydrogen atom. the density of states is continuous at the Fermi level.5 Fermi Temperature and band occupation numbers At absolute zero. 11 .3. Thus.6 Spin polarization and magnetism There are two final points that need to be discussed about these calculations. the experimental values are 2. resulting in instabilities that make it difficult to converge to the occupation step function. An oxygen atom has two unpaired electrons. however. the molecule starts with no net spin. and 0. and the triplet state with two unpaired electrons. See Reference 31 for a very thorough discussion of the determination of the magnetic properties of these metals with DFT. small changes in the energy can dramatically change the occupation numbers. Consequently. There is a particular difficulty in the calculation of the electronic structures of metals compared to semiconductors and molecules. 2.33 2. such as hydrogen and oxygen atoms. spin polarization and dipole corrections. the occupancies of the bands of a system are well-defined step functions. it must be turned on. each of which has an unpaired electron. Co. there is a clear energy gap between the occupied states and unoccupied states. oxygen molecules and radicals. 12 The total energy is then extrapolated back to absolute zero. iron. spin polarization typically does not need to be considered.22.0 Bohr-magnetons (corresponding to one unpaired electron) is usually good. Finally. 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. but it dissociates into two atoms. and Ni. respectively 4 and are usually good initial guesses. all bands up to the Fermi level are occupied. A classically known problem involving spin polarization is the dissociation of a hydrogen molecule. there are two spin configurations for an oxygen molecule. Spin polarization must also be considered in atoms and molecules with unpaired electrons. 1. The oxygen triplet state is lower in energy than the oxygen singlet state. Thus. and thus it corresponds to the ground state for an oxygen atom. In VASP. although the gas-phase reference state calculation may need to be done with spin-polarization. In metals. a magnetic initial guess usually must be provided to get a magnetic solution.standard methods for ensuring the quality and transferability (to different chemical environments) of the pseudopotentials. See section 5. cobalt and nickel are magnetic because they have more electrons with spin "up" than spin "down" (or vice versa). the occupancies are insensitive to changes in the energy that occur during the self-consistency cycles. an initial guess of 1. For Fe. but non-zero temperature.34 The difficulty arises because the temperature in most DFT calculations is at absolute zero. In this solution. unless an adsorbate is on a magnetic metal surface. the singlet state with no unpaired electrons. 12. 35 which is the foundation on which one solution to this problem is based. In this case. thus an initial guess of 2. and typically converges to the closest solution. 32. For example. For example. Spin polarization is important for systems that contain net spin. In molecules and semiconductors. resulting in a continuous occupation function over the distribution of states.72. A finite-temperature version of DFT was developed. 31 TODO PAW description VASP provides a database of PAW potentials. which is not convenient for visualization later (see Visualizing electron density). Original papers on DFT 20.21 Kohn’s Nobel Lecture.1. Atom from ase.py). 0.]). For a nice comparison of VASP and Gaussian see 40 . then reading molecules from data files. 10. [0.1 From scratch When there is no data file for the molecule you want. and the overlap makes the energy increase significantly. 12 .37–39 with the projector augmented wave (PAW) potentials provided in VASP. how to manipulate them. 3. you have to define your atoms geometry by hand. The volume of the unit cell is 1000 Å3 . This will result in less computational time to compute properties.1. The first problem is easily solved by centering the atoms in the unit cell. Monkhorst-Pack k-points 28 3 Molecules In this chapter we consider how to construct models of molecules. 0.0f} Angstrom^3’. and the unit cell the atoms are in. V = 1000 Angstrom^3 There are two inconvenient features of the simple cubic cell: 1. We show the results of the centering in Figure 2. We will begin with defining molecules from scratch. and finally using some built-in databases in ase. which is smaller than the cube.get_volume()) 10 11 write(’images/simple-cubic-cell.7 This section needs cleaning up. Here is how that is done for a CO molecule (Figure 1).1 Defining and visualizing molecules We start by learning how to define a molecule and visualize it. its electron density is spread over the 8 corners of the box. 0. Atom(’O’. 18 Pople’s Nobel Lecture 22 7 Hoffman PAW in GPAW 36 All calculations were performed using VASP 12. 2. Electron-electron interactions are repulsive. you need fairly large cubes to make sure the electron density of the molecule does not overlap with that of its images. atoms. or no database to get it from. which is the lattice with the closest packing..])]. show_unit_cell=2) Open the python script (dft-scripts/script-3. Since the CO molecule is at the corner. Note the final volume is only about 715 Å3 . Here. the CO molecule has 6 images due to periodic boundary conditions that are 10 Å away. where we have guessed values for b until the CO molecules are on average 10 Å apart. The second problem can be solved by using a face-centered cubic lattice. and how to calculate many properties of molecules. cell=(10.format(atoms. We must define the type and position of each atom.TODO Recommended reading 2. 0. Due to the geometry of the cube. 10)) 8 9 print ’V = {0:1.. [1.. 3.io import write 3 4 5 6 7 # define an Atoms object atoms = Atoms([Atom(’C’. 1 2 from ase import Atoms.png’. show_unit_cell=2) Open the python script (dft-scripts/script-4. 0. 0.Figure 1: Image of a CO molecule with the C at the origin.].io import write 3 4 5 6 7 8 9 b = 7.])]. 0. [b.. 0. [1.format(atoms. 1 2 from ase import Atoms..center() # translate atoms to center of unit cell write(’images/fcc-cell.png’. b..1 atoms = Atoms([Atom(’C’.get_volume())) 12 13 14 atoms.1..0f} Ang^3’. atoms. cell=[[b. 0. b. Atom(’O’. [0. b]. Atom from ase. V = 716 Ang^3 13 .]). 0.. [0.py). b]]) 10 11 print(’V = {0:1. . 0.sum(a1**2)**0. 0.5) 14 . because these are what separate the atoms in the images. b... Atom(’O’. but we can use code to determine this too. We use the mod:numpy module to compute the distance of a vector as the square root of the sum of squared elements. Atom import numpy as np 3 4 5 6 7 8 9 b = 7. b]]) 10 11 12 13 # get unit cell vectors and their lengths (a1.])]. 0..get_cell() print ’|a1| = {0:1. [b. a2. At this point you might ask..]. cell=[[b. All we have to do is figure out the length of each lattice vector.1 atoms = Atoms([Atom(’C’. 1 2 from ase import Atoms. [1. 0.2f} Ang’. 0. b. 0.1.format(np. [0. [0.]). b].Figure 2: CO in a face-centered cubic unit cell. "How do you know the distance to the neighboring image?" The ag viewer lets you compute this graphically. a3) = atoms. io.sum(a3**2)**0.py).format(np.norm(a2)) print ’|a3| = {0:1.04 Ang |a2| = 10.1.2f} Ang’.format(np.04 Ang 3.read supports many different file formats: Known formats: ========================= format ========================= GPAW restart-file Dacapo netCDF output file Old ASE netCDF trajectory Virtual Nano Lab file ASE pickle trajectory ASE bundle trajectory GPAW text output CUBE file XCrySDen Structure File Dacapo text output XYZ-file VASP POSCAR/CONTCAR file VASP OUTCAR file SIESTA STRUCT file ABINIT input file V_Sim ascii file Protein Data Bank CIF-file FHI-aims geometry file FHI-aims output file VTK XML Image Data VTK XML Structured Grid VTK XML Unstructured Grid TURBOMOLE coord file TURBOMOLE gradient file exciting input AtomEye configuration WIEN2k structure file DftbPlus input file CASTEP geom file CASTEP output file CASTEP trajectory file ETSF format DFTBPlus GEN format CMR db/cmr-file CMR db/cmr-file =========== 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.5) Open the python script (dft-scripts/script-5.04 Ang |a3| = 10.2f} Ang’.2 Reading other data formats into a calculation mod:ase.nc gen db cmr 15 .linalg.14 15 print ’|a2| = {0:1. |a1| = 10. In this example.data. 3. The second line is often a comment. Here is what an XYZ file format might look like: #+include: molecules/isobutane. Note that the XYZ format does not have unit cell information in it.io import read.py).keys() # print in 3 columns for i in range(len(keys) / 3): print ’{0:25s}{1:25s}{2:25s}’.LAMMPS dump file Gromacs coordinates ========================= lammps gro =========== You can read XYZ file format to create mod:ase. isobutene COF2 CH3OH PH3 O2 Be C3H9N CH3 C2H6CHOH CH3O P OH SiCl4 C3H7 CH2NHCH2 SiF4 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 . 1 2 3 4 5 from ase.g2. write 2 3 4 5 atoms = read(’molecules/isobutane. the database includes the molecules in the G2/97 database. 1 from ase.data import g2 keys = g2.data too. atoms. What follows is one line per atom with the symbol and Cartesian coordinates in Å.format(*tuple(keys[i * 3: i * 3 + 3])) Open the python script (dft-scripts/script-7. For example.Atoms objects. The coordinates for the atoms in the database are MP2(full)/6-31G(d) optimized geometries.png’. You may be interested in reading about some of the other databases in mod:ase.py). See this site for the original files.center(vacuum=5) write(’images/isobutane-xyz.xyz The first line is the number of atoms in the file.1.data. Here is a list of all the species available in mod:ase. 41 This database contains a broad set of atoms and molecules for which good experimental data exists. show_unit_cell=2) Open the python script (dft-scripts/script-6.molecules database.xyz’) atoms. so you will have to figure out a way to provide it.data.3 Predefined molecules mod:ase defines a number of molecular geometries in the mod:ase. we center the atoms in a box with vacuum on all sides (Figure 3). making them useful for benchmarking studies. OCS SH2 CH3CH2Cl HCOOH 2-butyne HOCl C C4H4S H2CCHCl C2H4 C2Cl4 C6H6 H2CCHCN HCl Na CH3CH2SH 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 .Figure 3: An isobutane molecule read in from an XYZ formatted data file. 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 . See Figure 5.extra_molecules which has a few extras like biphenyl and C60. 1 2 from ase.data.io import write 3 4 atoms = molecule(’CH3CN’) 5 6 7 8 9 atoms. That is too small to use if your calculator uses periodic boundary conditions.png’.py).structure import molecule from ase.center(vacuum=6) print ’unit cell’ print ’---------’ print atoms. Note that the default unit cell is a 1Å × 1Å × 1Å cubic cell. and mod:ase.data.s22 for weakly interacting dimers and complexes. unit cell --------[[ 13. See Figure 4. show_unit_cell=2) Open the python script (dft-scripts/script-8.get_cell() 10 11 write(’images/ch3cn. ] 0. [ 0.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. 19 .014576]] It is possible to rotate the atoms with func:ase. We will add 6 Å of vacuum on each side. ] 15. 0.io. not the actual coordinates. We center the atoms in the unit cell and add vacuum on each side. In the next example we rotate 45 degrees about the x-axis.write if you wanted to see pictures from another angle.537479 0. In the write command we use the option show_unit_cell =2 to draw the unit cell boundaries. 13. atoms. Note that this only affects the image.775328 [ 0. Here is an example of getting the geometry of an acetonitrile molecule and writing an image to a file. 0. then 45 degrees about the y-axis. Figure 4: A CH3 CN molecule in a box.io import write 3 4 atoms = molecule(’CH3CN’) 5 6 7 8 9 atoms.45y. 0.structure import molecule from ase. show_unit_cell=2.py).537479 0.0z’) Open the python script (dft-scripts/script-9.775328 [ 0. 0. rotation=’45x.get_cell() 10 11 12 write(’images/ch3cn-rotated. ] ] 20 . 1 2 from ase. 13.png’. unit cell --------[[ 13.center(vacuum=6) print ’unit cell’ print ’---------’ print atoms. atoms. while the rotate function uses radians.get_positions() 8 9 10 atoms.center(vacuum=6) p1 = atoms. One rotates the molecule an angle (in radians) around a vector.rotate method. center=’COM’. If you actually want to rotate the coordinates.png’.structure import molecule from ase. rotate_cell=False) 11 12 13 14 15 16 write(’images/ch3cn-rotated-2. Note that the write function uses the rotation angle in degrees.get_positions() 17 21 . 1 2 3 from ase. You also must decide whether or not the unit cell should be rotated. rotate_cell=False) atoms. but you have to choose whether the center of mass should be fixed or not. there is a nice way to do that too. pi/4. show_unit_cell=2) print ’difference in positions after rotating’ print ’atom difference vector’ print ’--------------------------------------’ p2 = atoms. 15.rotate(’x’. 0.rotate(’y’. with the func:ase.Atoms.014576]] Figure 5: The rotated version of CH3 CN.[ 0. Actually there are some subtleties in rotation.io import write from numpy import pi 4 5 6 7 atoms = molecule(’CH3CN’) atoms. pi/4. In the next example you can see the coordinates have changed due to the rotations. center=’COM’. atoms. py).65009456] 1 [ 0. since we chose not to rotate the unit cell.center(5) 11 12 write(’images/bothatoms. bothatoms. 1 2 from ase.io import write 3 4 atoms1 = molecule(’NH3’) 5 6 7 atoms2 = molecule(’O2’) atoms2.p1 for i.Atoms. show_unit_cell=2. for computing reaction barriers.format(i.66947344 -0. See Figure 7.65009456 0.4 Combining Atoms objects It is frequently useful to combine two Atoms objects.94677841 -0.91937255 0.32532156 0.translate([3. d in enumerate(diff): print ’{0} {1}’. e. 22 . They are typically only functions of the atom types and geometries.g.08030744 -0.py).35030756] 4 [-1.8340703 1.33495444 -0.04610517] 5 [-0. Here is an example of getting an ammonia and oxygen molecule in the same unit cell.18 19 20 diff = p2 . We set the Atoms about three Å apart using the func:ase. 0.2 Simple properties Simple properties do not require a DFT calculation. d) Open the python script (dft-scripts/script-10.88463727 1. In ase.png’.08030744] 2 [ 0.66947344] 3 [-0. 3. or other types of interactions. difference in positions after rotating atom difference vector -------------------------------------0 [-0.translate function. 3.35405183 1.11357187 -0.2092413 ] Figure 6: Rotated CH3 CN molecule Note in this last case the unit cell is oriented differently than the previous example. rotation=’90x’) Open the python script (dft-scripts/script-11. 0]) 8 9 10 bothatoms = atoms1 + atoms2 bothatoms.structure import molecule from ase. we simply add two Atoms objects together.33495444 1.1. get_atomic_numbers() 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.get_scaled_positions.Atoms.2f}’. atom. p in zip(atom_indices. atom.y. s.z) 14 15 16 17 18 # get sym = pos = num = all properties in arrays atoms. atom. use func:ase.structure import molecule 2 3 atoms = molecule(’C6H6’) # benzene 4 5 6 7 8 9 10 11 12 13 # access properties on each atom print ’ # sym p_x p_y p_z’ print ’------------------------------’ for i. num.format(i.get_positions. atom in enumerate(atoms): print ’{0:3d}{1:^4s}{2:-8.x.2f}{4:-8. pos): 23 .Figure 7: Image featuring ammonia and oxygen molecule in one unit cell.symbol. 3. n.2f}{3:-8. z) coordinates of the atoms.get_chemical_symbols() atoms. use the func:ase.get_positions() atoms.1 Getting cartesian positions If you want the (x.Atoms.2. If you are interested in the fractional coordinates. sym. atom. y. 1 from ase. 70 0.00 3.00 6 H 1 0.21 0.get_chemical_formula(mode=’reduce’) 8 9 10 11 # note use of two lines to keep length of line reasonable s = ’The molecular weight of {0} is {1:1.48 0.48 0.15 -1.00 9 H 0.24 0.21 -0.00 -1.70 0. The molecular weight of C6H6 is 78.00 1 C 6 1.py).00 10 H -2.format(molecular_formula.structure import molecule 2 3 4 atoms = molecule(’C6H6’) masses = atoms.00 8 H 1 2.00 7 H 1 2.00 3 C 6 0.15 1.21 -0.24 0.15 1.00 11 H 1 -2. py. We use func:ase. px. # sym p_x p_y p_z -----------------------------0 C 0.48 0.70 0.2.15 -1. molecular_weight) Open the python script (dft-scripts/script-13.24 0.21 0.00 3 C 0.00 1 C 1.00 1.2 Molecular weight and molecular formula We can quickly compute the molecular weight of a molecule with this recipe.15 1.70 0.00 1.00 -2.get_masses to get an array of the atomic masses of each atom in the Atoms object.get_masses() 5 6 7 molecular_weight = masses.24 0.00 2.70 0.26 27 28 px.sum() molecular_formula = atoms.00 5 C -1.00 -1.15 -1.70 0.00 2.format(i.70 0. n.00 7 H 2.70 0.21 0.00 2 C 6 1.24 0.24 0.21 -0. pz = p print ’{0:3d}{1:>3s}{2:8d}{3:-8.2f}{4:-8.48 0.21 -0.00 8 H 2.2f}’.00 6 H 0.00 4 C -1.40 0.00 10 H 1 -2. py. s.11 gm/mol 24 .00 11 H -2.2f}{5:-8.40 0.15 -1.00 -2.Atoms.00 5 C 6 -1.00 9 H 1 0.24 0.py). pz) Open the python script (dft-scripts/script-12. and then just sum them up.40 0.24 0.21 0.00 2 C 1. 1 from ase.00 # sym at# p_x p_y p_z ------------------------------------0 C 6 0.15 1.40 0.00 4 C 6 -1.2f} gm/mol’ print s. get_moments_of_inertia() print 7 8 9 10 print ’symmetric rotors (Ia = Ib) < Ic’ atoms = molecule(’NH3’) print ’ NH3 moments of inertia: ’. p in zip(masses. 3.get_moments_of_inertia.format(np.get_center_of_mass()) # cartesian coordinates 8 9 10 11 # compute the center of mass by hand pos = atoms.structure import molecule import numpy as np 3 4 5 # ammonia atoms = molecule(’NH3’) 6 7 print ’COM1 = {0}’.Atoms. and others may be degenerate.get_moments_of_inertia() print 15 25 . although some may be zero depending on symmetry.get_masses() 12 13 14 15 16 COM = np.array([0.]) for m.get_moments_of_inertia() 11 12 13 14 atoms = molecule(’C6H6’) print ’ C6H6 moments of inertia:’.75457009e-02] 4.sum() 17 18 print ’COM2 = {0}’. pos): COM += m*p COM /= masses.2. pos) / np. which are calculated by different methods.91843349e-08 5.py).2..00000000e+00 5. There is a convenient function to get the moments of inertia: func:ase. There are typically three moments of inertia. COM1 = [ COM2 = [ COM3 = [ 0.Atoms.positions masses = atoms.75457009e-02] You can see see that these centers of mass. weighted by the mass of each atom.get_chemical_formula collects all the symbols to provide a molecular formula. atoms.dot(masses. Here are several examples of molecules with different types of symmetry. It is defined by I = i=1 mi ri2 where ri is the distance to an axis of rotation.00000000e+00 0.Atoms.3 Center of mass The center ofPmass (COM) is defined as: mi ·ri COM = P mi The center of mass is essentially the average position of the atoms. 3. atoms.Note that the argument reduce=True for func:ase. atoms.00000000e+00 0.sum(masses)) Open the python script (dft-scripts/script-14.format(COM) 19 20 21 # one-line linear algebra definition of COM print ’COM3 = {0}’.: 1 from ase.4 Moments of inertia PN The moment of inertia is a measure of resistance to changes in rotation.structure import molecule 2 3 4 5 6 print ’linear rotors: I = [0 Ia Ia]’ atoms = molecule(’CO2’) print ’ CO2 moments of inertia: ’. 0. Here is an example of getting the center of mass from an Atoms object using func:ase. are the same..91843349e-08 4.format(atoms.91843349e-08 5.75457009e-02] 4.get_center_of_mass. 1 2 from ase. 0. 19145621 37. 0.] [ 0. what are the bond lengths.77916799 177. linear rotors: I = [0 Ia Ia] CO2 moments of inertia: [ 0. and the third moment is about the x-axis. 3.get_distance method to make this easy.get_moments_of_inertia() Open the python script (dft-scripts/script-15.]] 37. you have to specify their indices.16255537] If you want to know the principle axes of rotation.20372189 axes = [[ 0.format(moments) print ’axes = {0}’.py). The Atoms object contains an func:ase.19145621 unsymmetric rotors Ia != Ib != Ic C3H7Cl moments of inertia: [ 19. 0. 1.18961963 223.Atoms.20372189 spherical rotors Ia = Ib = Ic CH4 moments of inertia: [ 3. atoms. 0.get_moments_of_inertia() print 25 26 27 28 print ’unsymmetric rotors Ia != Ib != Ic’ atoms = molecule(’C3H7Cl’) print ’ C3H7Cl moments of inertia: ’. angles between bonds. To calculate the distance between two atoms.5 Computing bond lengths and angles A typical question we might ask is.format(axes) Open the python script (dft-scripts/script-16.97009837] 3. Moments = [ 3.structure import molecule 2 3 4 5 6 atoms = molecule(’CH3Cl’) moments. and it returns the moments of inertia and the principle axes.2.97009644 37.45384271 44. the second moment is about the y-axis. atoms.97009644 3. 1.py). "What is the structure of a molecule?" In other words. 1 from ase. 26 . axes = atoms.71012548 2.get_moments_of_inertia() print 20 21 22 23 24 print ’spherical rotors Ia = Ib = Ic’ atoms = molecule(’CH4’) print ’ CH4 moments of inertia: ’. remembering that the index starts at 0.get_moments_of_inertia(vectors=True) print ’Moments = {0}’. and similar properties.77914641 88. we simply pass vectors=True to the function.] [ 1.19145621] 213. 0.67031768] C6H6 moments of inertia: [ 88.97009837] This shows the first moment is about the z-axis. atoms.71012426 1. 44.5583144 ] symmetric rotors Ia < (Ib = Ic) CH3Cl moments of inertia: [ 3.41351508 37.45384271] symmetric rotors (Ia = Ib) < Ic NH3 moments of inertia: [ 1.16 17 18 19 print ’symmetric rotors Ia < (Ib = Ic)’ atoms = molecule(’CH3Cl’) print ’CH3Cl moments of inertia: ’. py).1 from ase. specifically the func:numpy. atom symbol =========== 0 N 1 H 2 H 3 H The N-H distance is 1.get_distance(0. the func:numpy. In the next example. dot. 1 from ase. here we compute the angle H-N-H in an ammonia molecule.format(atoms.arccos function. We compute can calculate the angle as θ = arccos |~ a||~b| these vectors as the difference in positions of two atoms.1f} degrees’.positions[0] .symbol) 10 11 12 a = atoms.linalg import norm 16 17 theta_rad = arccos(dot(a./pi) Open the python script (dft-scripts/script-18. atom symbol =========== 0 N 1 H 2 H 3 H theta = 106.017 angstroms Bond angles are a little trickier. So we   compute ~ a·~b .atoms. For example. atom. atom in enumerate(atoms): print ’{0:2d} {1:3s}’ . we utilize functions in mod:numpy to perform the calculations.positions[1] b = atoms. pi from numpy.linalg.py). b) / (norm(a) * norm(b))) # in radians 18 19 print ’theta = {0:1.structure import molecule 2 3 4 # ammonia atoms = molecule(’NH3’) 5 6 7 8 9 print ’atom symbol’ print ’===========’ for i. atom in enumerate(atoms): print ’{0:2d} {1:3s}’.positions[0] .atoms. and func:numpy. we just have to define our two vectors ~a and ~b.format(i.format(i.positions[2] 13 14 15 from numpy import arccos. This is the angle between N-H1 and N-H2 .norm functions.dot function. If we had vectors describing the directions between two atoms.format(theta_rad * 180. atom.3 degrees 27 .structure import molecule 2 3 4 # ammonia atoms = molecule(’NH3’) 5 6 7 8 9 print ’atom symbol’ print ’===========’ for i.symbol) 10 11 12 13 # N-H bond length s = ’The N-H distance is {0:1. 1)) Open the python script (dft-scripts/script-17.3f} angstroms’ print s. we could use some simple trigonometry to the angle between the vectors: ~a ·~b = |~a||~b| cos(θ). 1 2 3 # calculate an ethane dihedral angle from ase. 0. That is a H-C-C-H dihedral angle. 0. 0. atom.py).pi print ’dihedral angle = {0:1. 1. / pi) Open the python script (dft-scripts/script-19.334624232 degrees Dihedral angles There is support in ase for computing dihedral angles. We will compute the dihedral angle between atoms 5.format(atoms.get_angle. Let us illustrate that for ethane. 1. / np.2f} degrees’. and 4. and one can visually see (although not here) that these atoms have a dihedral angle of 60Θ (Figure 9). 0.get_dihedral([5.symbol) 11 12 13 da = atoms. 2]) * 180. theta = 106. 4]) * 180.Figure 8: Schematic of the vectors defining the H-N-H angle. Alternatively you could use func:ase.format(da) 28 . Note we want the angle between atoms with indices [1.Atoms. 1 2 3 4 from ase. 2] to get the H-N-H angle.structure import molecule from numpy import pi # ammonia atoms = molecule(’NH3’) 5 6 print ’theta = {0} degrees’. atom in enumerate(atoms): print ’{0:2d} {1:3s}’.get_angle([1.format(i.structure import molecule import numpy as np 4 5 atoms = molecule(’C2H6’) 6 7 8 9 10 print ’atom symbol’ print ’===========’ for i. After defining the calculator a DFT calculation must be run. we have to define a calculator and attach it to an mod:ase.1 Energy and forces Two of the most important quantities we are interested in are the total energy and the forces on the atoms. suppress=True) 5 6 7 8 co = Atoms([Atom(’C’. indicating that this geometry is not close to the ground state geometry. forces. Atom from jasp import * import numpy as np np. and incar:ENCUT to learn more about these VASP keywords. Here is an example of getting the energy and forces from a CO molecule. 3. 0. Atom(’O’. 0])]. 0]). incar:SIGMA. which is along the molecular axis. cell=(6. but not DFT calculations.00 degrees Figure 9: Schematic of the calculated ethane dihedral angle.3. The forces in this case are very high.)) 9 10 11 with jasp(’molecules/simple-co’.3 Simple properties that require single computations There are many properties that only require a single DFT calculation to obtain the energy. We will see how to minimize this force in Manual determination and Automatic geometry optimization with VASP.. 0. incar:NBANDS. electron denisty and electrostatic potential. atom symbol =========== 0 C 1 C 2 H 3 H 4 H 5 H 6 H 7 H dihedral angle = 60. 6. To get these quantities.Atoms object so that ase knows how to get the data. [0. 3. # output dir xc=’PBE’. density of states. to compute. Note that the forces are only along the x-axis.Open the python script (dft-scripts/script-20.set_printoptions(precision=3.py). 6. 1 2 3 4 from ase import Atoms. This section describes some of these calculations and their analysis. Note: This is your first DFT calculation in the book! See ISMEAR. [1. In this section we covered properties that require simple calculations.. # the exchange-correlation functional 29 .2. append(atoms. Doubling a lattice vector here leads to a 20-fold increase in computational time! Note that doubling a lattice vector length increases the volume by a factor of 8 for a cube. We have to decide what an appropriate volume for our calculation is.2. Atom(’O’. 0. 0])]) 8 9 L = [4. encut=350. 10] 10 11 12 13 14 15 16 17 18 19 20 21 22 23 volumes.py). 6. We will first consider the effect of the unit cell on the total energy and forces.plot(L.get_potential_energy()) except (VaspSubmitted. Atom import numpy as np np. 0]).format(co.g. 30 .pyplot as plt plt. 1 2 3 4 from jasp import * from ase import Atoms. VaspQueued): ready = False 24 25 26 if not ready: import sys. ]] Convergence with unit cell size There are a number of parameters that affect the energy and forces including the calculation parameters and the unit cell. In that case we need a large unit cell so the electron density from the molecule does not go outside the unit cell where it would overlap with neighboring images. # very small smearing factor for a molecule atoms=co) as calc: print ’energy = {0} eV’.xlabel(’Unit cell length ($\AA$)’) plt. # planewave cutoff ismear=1.py). atoms=atoms) as calc: try: energies. The reason that the unit cell affects the total energy is that it can change the distribution of electrons in the molecule. 5. The cost of running the calculation goes up steeply with increasing cell size. ] [-5. a. energies.get_forces() Open the python script (dft-scripts/script-21. scale_atoms=False) atoms. energy = -14. xc=’PBE’.01.12 13 14 15 16 17 18 nbands=6. 0. suppress=True) 5 6 7 atoms = Atoms([Atom(’C’. energies = [].png’) plt.show() Open the python script (dft-scripts/script-22.set_printoptions(precision=3. in the ideal gas limit.095 0. [0. ’bo-’) plt.format(a). sys.center() with jasp(’molecules/co-L-{0}’. # Methfessel-Paxton smearing sigma=0. and the choice depends on the goal.set_cell([a.savefig(’images/co-e-v. # number of bands encut=350. 0. [] ready = True for a in L: atoms.095 0. We may wish to know the total energy of a molecule that is not interacting with any other molecules. It pays to check for convergence.get_potential_energy()) print co.687906 eV [[ 5. e.ylabel(’Total energy (eV)’) plt. Here there are evidently attractive interactions between the CO molecules which lower the total energy for small box sizes. 0. a].exit() 27 28 29 30 31 32 33 import matplotlib. [1. 8. The cost goes up because the number of planewaves that fit in the cube grows as the cube gets larger. which gives a pressure of zero at absolute zero. At non-zero temperatures.678 seconds 10 36.543 seconds 8 19. 10] 4 5 6 7 for a in L: with jasp(’molecules/co-L-{0}’.format(a. 6. 1 from jasp import * 2 3 L = [4. we have P = n/V RT .format(a)) as calc: print ’{0} {1} seconds’. In the ideal gas limit we have P V = nRT . 10) 31 . calc.Figure 10: Total energy of a CO molecule as a function of the unit cell length. 4 1.py).pyplot as plt 4 5 atm = 101325 * Pascal 6 7 L = np.601 seconds 5 3.932 seconds 6 6. 8. In atomic units we use kB instead of R. 1 2 3 from ase. Let us consider some examples.units import kB. Pascal import numpy as np import matplotlib.013 seconds Let us consider what the pressure in the unit cell is.get_elapsed_time()) Open the python script (dft-scripts/script-23. 5.linspace(4. 350.py). 300. 6)) atoms.set_printoptions(precision=3.plot(V. notably incar:ENCUT.center() 10 11 ENCUTS = [250. 0. P.xlabel(’Unit cell volume ($\AA^3$)’) plt. cell=(6.png’) Open the python script (dft-scripts/script-24. 1 2 3 4 from ase import Atoms. 600. 400.2.format(T)) 16 17 18 19 20 plt. Convergence of ENCUT The total energy and forces also depend on the computational parameters.legend(loc=’best’) plt. 1000]: P = n / V * kB * T / atm # convert to atmospheres 14 15 plt.savefig(’images/ideal-gas-pressure. suppress=True) 5 6 7 8 9 atoms = Atoms([Atom(’C’. Figure 11: Ideal gas pressure dependence on temperature and unit cell volume. label=’{0}K’. 0.8 V = L**3 9 10 n = 1 # one atom per unit cell 11 12 13 for T in [298. [1. 0]). 0])]. Atom from jasp import * import numpy as np np. 450. [0. Atom(’O’. 6. 500] 32 .ylabel(’Pressure (atm)’) plt. energies.py).xlabel(’ENCUT (eV)’) plt. VaspQueued): ready = False 24 25 26 if not ready: import sys. 1 grep "Elapsed time (sec):" molecules/co-en-*/OUTCAR 33 . atoms=atoms) as calc: try: energies.ylabel(’Total energy (eV)’) plt. The reason we do not just use very high ENCUT all the time is it is expensive. You can see in this figure that it takes a cutoff energy of about 400 eV to achieve a convergence level around 10 meV.savefig(’images/co-encut-v. Figure 12: Dependence of the total energy of CO molecule on ENCUT. and that even at 500 meV the energy is still changing slightly. and the differences tend to converge faster than a single total energy.append(atoms.png’) Open the python script (dft-scripts/script-25.format(en).plot(ENCUTS. sys. Also it is important to note that it is usually a single element that determines the rate of convergence.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}’.get_potential_energy()) except (VaspSubmitted. Keep in mind that we are generally interested in differences in total energy. xc=’PBE’.exit() 27 28 29 30 31 32 import matplotlib.pyplot as plt plt. encut=en. ’bo-’) plt. show() 34 .contour3d(x. # x-positions [p1[1]. and we consider some issues we have to consider when visualizing volumetric data in unit cells with periodic boundary conditions.02) 44 45 46 47 # Now plot the charge density mlab.get_charge_density() 9 10 mlab.883 12. [a3.z.3.py).get_cell() origin = [0. [a1. [origin.590 6.number]). [a1 + a2. a1 + a2 + [a2 + a3.points3d(atom.x. # y-positions [p1[2].Open the python script (dft-scripts/script-26.colors import cpk_colors 5 6 7 8 with jasp(’molecules/simple-co’) as calc: atoms = calc.data import vdw_radii ase. [origin.png’) mlab. molecules/co-en-250/OUTCAR: molecules/co-en-300/OUTCAR: molecules/co-en-350/OUTCAR: molecules/co-en-400/OUTCAR: molecules/co-en-450/OUTCAR: molecules/co-en-500/OUTCAR: Elapsed Elapsed Elapsed Elapsed Elapsed Elapsed time time time time time time (sec): (sec): (sec): (sec): (sec): (sec): 3. bgcolor=(1. y. [a2.there are 8 a1.get_atoms() x. a2. a2]] 38 39 40 41 42 43 for p1. 1. a1 + a2 + [a1 + a3. z. scale_factor=vdw_radii[atom.savefig(’images/co-cd. p2[2]]. p2 in cell_matrix: mlab. a1 + a3]. distance=’auto’) 48 49 50 mlab.plot3d([p1[0]. scale_mode=’none’) 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 # draw the unit cell . atom. z) and ρ(x. there is a charge density. [a2.data. [a1. a1 + a2]. # a tuple is required for the color color=tuple(cpk_colors[atom. this is a significant increase in time! 3. a2 + a3].mlab import * ase. If the first time was a week. y.167 Although here the times do not seem that unreasonable. a3]. y. a2]. a1 + a3]. a1 + a3 + corners..mayavi.016 6. p2[1]]. [a3. cd) mlab. # z-positions tube_radius=0. elevation=90. note we increased the time by a factor of three by simply doubling ENCUT. z. a2 + a1].y. That means we need 4 numbers for each point: (x. z). #this determines the size of the atom resolution=20. z) point. cd = calc. p2[0]]. 1)) # make a white figure 11 12 13 14 15 16 17 18 19 20 21 # plot the atoms as spheres for atom in atoms: mlab.number]/5.421 15.014 7. 0. y.view(azimuth=-90.2 Visualizing electron density The electron density is a 3d quantity: for every (x. y. 0] cell_matrix = [[origin. a2 + a3]. atom. Below we show an example (Figure 13) of plotting the charge density. and 12 connections a3]. a3 = atoms. We will use the results from a previous calculation.figure(1. #TODO does not work in canopy 1 2 3 4 from from from from jasp import * enthought. a3]. a1]. 10)) 10 11 atoms.x.mayavi import mlab ase.data import vdw_radii ase. 1. TODO broken in canopy 1 2 3 4 5 from from from from from jasp import * enthought. [2. 35 .data. Atom(’O’. If we take care to center the CO molecule in the unit cell. Figure 13: Charge density of a CO molecule that is located at the origin. we get a nicer looking result. 1)) 22 23 24 25 # plot the atoms as spheres for atom in atoms: mlab. 0. atoms=atoms) as calc: 17 18 19 atoms = calc.578. cell=(10. Atoms 6 7 8 9 atoms = Atoms([Atom(’C’.0]).422. 0.py). 0.10.get_charge_density() 20 21 mlab.points3d(atom. xc=’PBE’. y. The electron density that is outside the cell is wrapped around to the other corners.colors import cpk_colors ase import Atom.Open the python script (dft-scripts/script-27.get_atoms() x. 0. encut=350.figure(bgcolor=(1. [3.0.0])].center() 12 13 14 15 16 with jasp(’molecules/co-centered’.0. z. cd = calc. p2 in cell_matrix: mlab. a1 + a2]. Z.0:1. a1 + a3]. [origin.png’) mlab. a3].0:s2] 20 21 22 23 C = np.plot3d([p1[0]. elevation=90. 0. Z = np.py). 0..number]/5. resolution=20. # y-positions [p1[2].0:1. The symmetry of a molecule determines if a molecule has a dipole moment or not.there are 8 a1. p2[0]]. atom. [a2. [a2. a2 + a1].y. a1].number]).array(vcd. [a3. # z-positions tube_radius=0. and 12 connections a3]. The magnitude of this vector is the dipole moment. [a1.0 / n0 s1 = 1. p2[1]]. 3. a1 + a2 + [a1 + a3. Y.column_stack([X. a3 = atoms. p2[2]]. or more commonly Debye. [a1 + a2. cd.atom. a1 + a3 + corners. which has units of Coulomb-meter.0:1.view(azimuth=-90. a2]] 49 50 51 52 53 54 for p1.get_atoms() atoms.contour3d(x.02) 55 56 57 58 # Now plot the charge density mlab. 0.0 / n1 s2 = 1. transparent=True) 59 60 61 # this view was empirically found by iteration mlab.3 Dipole moments The dipole moment is a vector describing the separation of electrical (negative) and nuclear (positive) charge. a2.savefig(’images/co-centered-cd. [a1.3.0:s0.ravel().get_potential_energy() 7 8 vcd = VaspChargeDensity() 9 10 11 cd = np. a2 + a3]. # a tuple is required for the color color=tuple(cpk_colors[atom. # x-positions [p1[1]. a2 + a3]. n2 = cd. a1 + a3].z. 1 2 from jasp import * from ase. [a3. We must integrate the electron density to find the center of electrical charge. scale_factor=vdw_radii[atom. n1. y.units import Debye 3 4 5 6 with jasp(’molecules/co-centered’) as calc: atoms = calc.shape 12 13 14 15 s0 = 1. and compute a sum over the nuclei to find the center of positive charge.0:s1.chg[0]) n0.mgrid[0. a3].ravel()]) 36 . 0] cell_matrix = [[origin.ravel(). a2].show() Open the python script (dft-scripts/script-28. a1 + a2 + [a2 + a3.0 / n2 16 17 18 19 X. Y. Below we compute the dipole moment of CO. 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 # draw the unit cell .get_cell() origin = [0. z. [origin. distance=’auto’) 62 63 64 mlab. 2].dot(C. n2)) 33 34 35 36 nelements = n0 * n1 * n2 voxel_volume = atoms. 0].path. (n0. n1. ppath) 37 . (n0.sum(). n1.join(ppp.sum()]) electron_density_center *= voxel_volume electron_density_center /= total_electron_charge 43 44 electron_dipole_moment = -electron_density_center * total_electron_charge 45 46 47 # now the ion charge center. (cd * z).reshape(real[:.POTCAR import get_ZVAL 48 49 50 LOP = calc.reshape(real[:. n2)) = np. We only need the Zval listed in the potcar from jasp. (cd * y). (n0.sum() * voxel_volume 37 38 39 40 41 42 electron_density_center = np.get_atoms() uc = atoms. 1].reshape(real[:. ppath.get_pseudopotentials() ppp = os. 24 25 26 27 atoms = calc.sum(). uc) 28 29 30 31 32 # x y z now convert arrays back to unitcell shape = np. hash in LOP: fullpath = os.get_volume() / nelements total_electron_charge = -cd.environ[’VASP_PP_PATH’] 51 52 53 54 zval = {} for sym. n1.Figure 14: Charge density of a CO molecule centered in the unit cell. n2)) = np. Now the electron density is centered in the unit cell.get_cell() real = np.array([(cd * x). Warning: One way that jasp is unintuitive is that whenever you are "inside" (indented) a with statement..png’) Open the python script (dft-scripts/script-31.savefig(’images/co-dos. or provide # the correct relative or absolute path to where you want it. dos.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 dipole_vector = (ion_dipole_moment + electron_dipole_moment) 69 70 dipole_moment = ((dipole_vector**2).0.units import Debye 3 4 5 6 7 with jasp(’molecules/co-centered’) as calc: dipole_vector = calc.$E_f$ (eV)’) plt.sum())**0. 1 2 from jasp import * from ase. 38 .0]) total_ion_charge = 0.py).py).sum())**0. the orbitals) that have a particular energy.get_dipole_moment() dipole_moment = ((dipole_vector**2).get_dos()) plt.dft.format(dipole_moment) Open the python script (dft-scripts/script-30.py). The dipole moment is 0.get_energies().symbol] total_ion_charge += Z pos = atom. 0.0 for atom in atoms: Z = zval[atom. In this example that can lead to your figure not being saved where you expect it to be saved! 1 2 3 from jasp import * from ase.10 Debye Note that a function using the code above exists in jasp which makes it trivial to compute the dipole moment.2f} Debye’. Here is an example of its usage.5 / Debye 71 72 print ’The dipole moment is {0:1.10 Debye 3.55 56 57 58 59 60 61 62 63 z = get_ZVAL(fullpath) zval[sym] = z ion_charge_center = np.format(dipole_moment) Open the python script (dft-scripts/script-29. The dipole moment is 0.3.0.dos import DOS import matplotlib. the current working directory may be different than where your script started.array([0. plt.xlabel(’Energy .4 The density of states (DOS) The density of states (DOS) gives you the number of electronic states (i.2f} Debye’. 0.ylabel(’DOS’) 10 11 12 13 # make sure you save the figure outside the with statement.5/Debye print ’The dipole moment is {0:1.e. We can get this information from the last calculation we just ran without having to run another DFT calculation.plot(dos.pyplot as plt 4 5 6 7 8 9 with jasp(’molecules/simple-co’) as calc: # we already ran this! dos = DOS(calc) plt. html#doscar for more details. and magnetization projected DOS. in methane the s and p orbitals can form what we call sp3 orbitals. To get atom-projected density of states. There are various natural choices. we must set RWIGS for each atom. Here is an example. We advocate our approach of using multiple directories for the subsequent calculations. e.mpi. You could redo the calculation in the same directory. This can only be a qualitative consideration because the orbitals on the atoms often hybridize to form molecular orbitals. 39 . here we must run another calculation because we did not specify the atom-projected keywords above. because it leaves a clear trail of how the work was done. but these values can change slightly in different environments.ac. but you risk losing the results of the first step. This parameter defines the radius of the sphere around the atom which cuts off the projection. or a value that minimizes overlap of neighboring spheres.g. and use them in a new calculation. That can make it difficult to reproduce a result. You can also get spin-polarized atom-projected DOS. We will consider the CO molecule. Note: The RWIGS is not uniquely determined for an element.5 Atom-projected density of states on molecules Let us consider which states in the density of states belong to which atoms in a molecule. The total density of states and projected density of states information comes from the DOSCAR file.3. which is done by projecting the wave function onto localized atomic orbitals.g.at/vasp/vasp/DOSCAR_file. See http://cms. We can compute atom-projected density of states in VASP. e. 3. Our strategy is to get the atoms from the previous calculation.univie. Note that unlike the DOS. the ionic radius of an atom.Figure 15: Density of states for a CO molecule. 6 Electrostatic potential This is an example of the so-called σ hole in a halogen bond. -0. 1.0.1 2 3 from jasp import * from ase.0000.asp?casno=75638. [ 0. ’ADOS’. [ 1. c_p + 4.plot(energies. 1. ’O$_p$’.0000. cell=(10.io import write 4 5 6 7 from enthought. c_s + 6.py). ’d’) o_d = ados.get_energies().gov/exp2. 10)) atoms. -0.0000. loc=’best’) plt. xc=’PBE’. 0. ibrion=1. energies.2455.plot(energies.data import vdw_radii from ase. dos.6228.mayavi import mlab from ase. 40 . [ 0.get_fermi_level()) energies = ados.6228. energies. encut=300.site_dos(0. ’O$_s$’. Atom(’F’.colors import cpk_colors 8 9 10 11 12 13 14 15 atoms = Atoms([Atom(’C’. -1. 16 17 18 19 20 21 with jasp(’molecules/CF3Br’. o_d + 2) plt.0787.site_dos(1. -1. c_d. 1.legend([’DOS’. ados.2651])].0000. nsw=50. ados.nist. ’O$_d$’]. encut=350. # these are the cutoff radii for projected states atoms=atoms) as calc: calc.$E_f$ (eV)’) plt.0787.energy 22 23 plt. Atom(’F’. o_s + 5) plt.dos + 8. Atom(’Br’. [-1.get_atoms() 8 9 10 11 12 13 14 with jasp(’molecules/co-ados’. -0.data. 3.center() 0.dft. ’C$_d$’.site_dos(0.dos import DOS import matplotlib.site_dos(1.1146]). label=’ADOS’) # these are the total DOS 24 25 26 27 28 c_s c_p o_s o_p = = = = ados.site_dos(0. -1. ’s’) ’p’) ’s’) ’p’) 29 30 31 c_d = ados. ados. energies. ’C$_s$’. ncol=2.png’) Open the python script (dft-scripts/script-32.2651]).0000. [ 0.2651]). ados. ’d’) 32 33 34 35 36 37 38 39 40 41 42 43 plt.get_dos() + 10) 19 20 21 ados = VaspDos(efermi=calc. xc=’PBE’.ylabel(’DOS’) plt.site_dos(1. ’C$_p$’.xlabel(’Energy .calculate() 15 16 17 18 # now get results dos = DOS(calc) plt.savefig(’images/co-ados. Atom(’F’. rwigs=[1. TODO mlab does not work 1 2 3 from jasp import * from ase import Atom. The coordinates for the CF3 Br molecule were found at http://cccbdb.plot(energies.pyplot as plt 4 5 6 7 # get the geometry from another calculation with jasp(’molecules/simple-co’) as calc: atoms = calc.8088]).plot(energies. 10.0].plot(dos.3. o_p + 3) plt. Atoms from ase. # a tuple is required for the color color=tuple(cpk_colors[atom.points3d(atom. lvhar=True.positions[[a1. 1]. # We create a bond matrix showing which atoms are connected.. 22 23 24 25 26 lvtot=True. bgcolor=(1. resolution=20.y. [0.x.set_nbands(f=2) calc.a2]. bond_matrix = [[0. [0.plot3d(atoms. scale_factor=vdw_radii[atom. # x-positions atoms. 3].positions[[a1. 1]. 2]. C-F. cd = calc. The total density of states and the s. y.a2]. scale_mode=’none’) # plot the bonds. 2]. z.number]). 0].number]/5.a2]. y. a2 in bond_matrix: mlab. lp = calc. atom. 1)) # make a white figure 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 # plot the atoms as spheres for atom in atoms: mlab. [0. 4]] 49 50 51 52 53 54 for a1. # z-positions [2.get_charge_density() 30 31 mlab.z. etc. atom. atoms=atoms) as calc: calc.Figure 16: Atom-projected DOS for a CO molecule. z. # y-positions atoms. 41 . p and d states on the C and O are shown. 1..calculate() 27 28 29 x.figure(1.. We want a line from C-Br.positions[[a1.get_local_potential() x. 2]. structure import molecule atoms = molecule(’H2O’) atoms. y. lp) mlab.uni-due.3. 42 . 42.contour3d(x.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.png’) mlab.tube_radius=0. z.py). TODO: figure out how to do an isosurface of charge.43 Let us consider a water molecule. colormap=’Reds’) 55 56 57 58 59 60 mlab. 1 2 3 4 from jasp import * from ase. colormapped by the local potential.02.savefig(’images/halogen-ep. The strategy is first to run the calculation.html&dir=vmdplugins for examples of using VMD for visualization.show() Open the python script (dft-scripts/script-33. then run the bader program on the results. The most modern way of calculating the Bader charges is using the bader program from Graeme Henkelmen’s group. See http://www.center(vacuum=6) 5 6 with jasp(’molecules/h2o-bader’. centered in a box.de/~hp0058/?file=manual03. Figure 17: Plot of the electrostatic potential of CF3 Br. 3. 27e 05/09/11) OPEN .calculate() 11 12 os.. atoms=atoms) as calc: calc.py). GRID BASED BADER ANALYSIS (Version 0.74 SECONDS CALCULATING BADER CHARGE DISTRIBUTION 0 10 25 50 75 100 PERCENT DONE: ********************** REFINING AUTOMATICALLY ITERATION: 1 EDGE POINTS: 1400048 REASSIGNED POINTS: 111247 ITERATION: 2 CHECKED POINTS: 913174 REASSIGNED POINTS: 1424 ITERATION: 3 CHECKED POINTS: 15784 REASSIGNED POINTS: 362 ITERATION: 4 CHECKED POINTS: 3190 REASSIGNED POINTS: 176 ITERATION: 5 CHECKED POINTS: 1228 REASSIGNED POINTS: 99 ITERATION: 6 CHECKED POINTS: 688 REASSIGNED POINTS: 21 ITERATION: 7 CHECKED POINTS: 267 REASSIGNED POINTS: 1 ITERATION: 8 CHECKED POINTS: 26 REASSIGNED POINTS: 0 RUN TIME: 26. CHG VASP-STYLE INPUT FILE VASP5 format FFT-grid: 112 x 128 x 120 CLOSE .7 8 9 10 xc=’PBE’.40 SECONDS CALCULATING MINIMUM DISTANCES TO ATOMS 0 10 25 50 75 100 PERCENT DONE: ********************** 43 . encut=350..system(’bader -p all_atom -p atom_index CHG’) Open the python script (dft-scripts/script-34.. CHG RUN TIME: 0.. units import Bohr 4 5 6 with jasp(’molecules/h2o-bader’) as calc: atoms = calc. because the order of atoms in the Atoms object is not the same as in the POSCAR file.0003 1.symbol.29 SECONDS WRITING BADER ATOMIC CHARGES TO ACF.8654 3 6.5265 6.0007 1. positions=pos.sort] * Bohr newatoms = Atoms(symbols.get_chemical_symbols())[calc.1559 -------------------------------------------------------------------------------VACUUM CHARGE: 0. ’ACF.RUN TIME: 1.0000 NUMBER OF ELECTRONS: 8.6422 640. but only if displacement is set to None or we convert the positions to Bohr.sort] pos = atoms.99999 WRITING ATOMIC VOLUMES 0 10 25 50 75 100 PERCENT DONE: ********************** RUN TIME: 3.positions[calc. Otherwise. # X Y Z CHARGE MIN DIST ATOMIC VOL -------------------------------------------------------------------------------1 6.0000 0.96 SECONDS WRITING BADER ATOMIC INDEX TO AtIndex.7632 6.0000 6.0000 7.9990 2.py).bader import attach_charges from ase.dat NUMBER OF BADER MAXIMA FOUND: SIGNIFICANT MAXIMA FOUND: NUMBER OF ELECTRONS: 5407 10 7. 1 2 3 from jasp import * from ase.dat’) 13 14 15 16 17 18 19 print ’#+tblname: bader’ print ’#+caption: Bader charges for a water molecule’ print ’| atom | Bader charge|’ print ’|-’ for atom in newatoms: print ’|{0} | {1} |’.array(atoms.format(atom.dat 1 cat ACF.5831 2 6.0000 0. Note the sorting that has to be done.0000 VACUUM VOLUME: 0.0000 This script should work. cell=atoms.charge) Open the python script (dft-scripts/script-36.io.get_cell()) 11 12 attach_charges(newatoms.0000 6.get_atoms() 7 8 9 10 symbols = np.6422 759. atom.dat WRITING BADER VOLUME CHARGES TO BCF.0000 6.py). 44 .2193 644. the positions do not match because of a Bohr/Angstrom units problem in the code.dat Open the python script (dft-scripts/script-35.5963 7. 6)) 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 with jasp(’molecules/co-{0}’.Table 2: Bader charges for a water molecule atom Bader charge O 0.format(d) print ’energy = {0:1. mod:jasp is set up to automatically handle jobs for you by submitting them to the queue. 0. Here is an example in VASP.001 H 0.2. 1. Atoms 3 4 5 6 bond_lengths = [1. We can find that by computing the total energy as a function of bond length. and noting where the minimum is. 0. [ 14.9993 H 0.05. There are a few features to point out here.append(None) pass 31 32 33 34 35 36 37 if None not in energies: import matplotlib. [0.15. ’bo-’) plt.format(e) print ’forces = (eV/ang)\n {0}’. encut=350.savefig(’images/co-bondlengths.903 0. d = 1.format(co.append(e) print ’d = {0:1. 0]). atoms=co): try: e = co. 0. 6.xlabel(r’Bond length ($\AA$)’) plt. cell=(6.1 Manual determination of a bond length The equilibrium bond length of a CO molecule is approximately the bond length that minimizes the total energy.pyplot as plt plt. [d. 1.4.25] energies = [] 7 8 for d in bond_lengths: # possible bond lengths 9 10 11 12 co = Atoms([Atom(’C’.05 ang energy = -14.py). and each calculation is independent of all the others.215 eV forces = (eV/ang) [[-14. Atom(’O’.png’) Open the python script (dft-scripts/script-37.2f} ang’. We want to compute 5 bond lengths. and you must handle these to control the workflow. 1.get_forces()) print ’’ # blank line except (VaspSubmitted.3f} eV’.01. energies. We will illustrate this by the following examples.ylabel(’Total energy (eV)’) plt.1. 0. # output dir xc=’PBE’. 1 2 from jasp import * from ase import Atom. sigma=0. ] ]] 45 .4 Geometry optimization 3. ismear=1.get_potential_energy() energies. 0])]. It raises a variety of exceptions to let you know what has happened.903 0.plot(bond_lengths. VaspQueued): energies.9997 3.format(d). nbands=6. 1. 10 ang energy = -14.25 ang energy = -14. numpoints=1) 46 .cubic polynomial pp = np. [-5. 1.8 0. 1. minV) 31 32 33 34 # plot the fit x = np. 1. roots = np. energies. ’bo ’) plt. ] ]] d = 1. ’fit’. [-0. ] ]] d = 1. roots) 26 27 28 minV = roots[secd > 0] minE = np.25) fit = np. x) 35 36 37 38 39 plt.linspace(1.polyval(pp.plot(bond_lengths. ’r-’) plt. ’minimum’].d = 1.quadratic 18 19 20 21 # we expect two roots from the quadratic eqn.format(minE. 1.095 0. 0. ] ]] To find the minimum we could run more calculations.roots(dp) 22 23 24 25 # The minimum is where the second derivative is positive.20 ang energy = -14. These are where the # first derivative is equal to zero. suppress=True) 5 6 7 bond_lengths = [1.append(atoms. 0.plot(minV.720 eV forces = (eV/ang) [[-5. 0. minV) 29 30 print ’The minimum energy is {0} eV at V = {1} Ang^3’. 0. 0. 0.838 eV forces = (eV/ang) [[ 0.polyder(pp) # first derivative . and find the analytical minimum.688 eV forces = (eV/ang) [[ 5. fit.05.format(d)) as calc: atoms = calc.set_printoptions(precision=3.1.plot(x.pyplot as plt np.15.get_atoms() energies. 1 2 3 4 from jasp import * import numpy as np import matplotlib.get_potential_energy()) 14 15 16 17 # Now we fit an equation .polyval(pp. [-8. 0.25] energies = [] 8 9 for d in bond_lengths: # possible bond lengths 10 11 12 13 with jasp(’molecules/co-{0}’.141 0.095 0. minE. 1.polyfit(bond_lengths.05.polyder(dp) # second derivative . 0. 3) dp = np.line secd = np. ] [ 5. but a simpler and faster way is to fit a polynomial to the data.polyval(dpp.15 ang energy = -14.2. ’m* ’) plt. ]] d = 1.352 eV forces = (eV/ang) [[ 8.645 0.legend([’DFT’.645 0. energies.8 0. dpp = np.141 0. The results are shown in Figure 18. 2 Automatic geometry optimization with VASP It is generally the case that the equilibrium geometry of a system is the one that minimizes the total energy and forces. IBRION value 1 2 algorithm quasi-Newton (use if initial guess is good) conjugate gradient 47 .xlabel(r’Bond length ($\AA$)’) plt.40 41 42 43 plt.ylabel(’Total energy (eV)’) plt. Here are the most common choices for IBRION. The minimum energy is [-14. Here we compute the bond length for a CO molecule.png’) plt. letting VASP do the geometry optimization for us.savefig(’images/co-bondlengths.843] eV at V = [ 1.py). Since each atom has three degrees of freedom. Luckily. 3.144] Ang^3 Figure 18: Energy vs CO bond length. you can quickly get a high dimensional optimization problem.show() Open the python script (dft-scripts/script-38.4. VASP has built-in geometry optimization using the IBRION and NSW tags. The units of force is eV/Å.0000000. Atom(’H’.get_forces() Open the python script (dft-scripts/script-40.05 eV/Å is usually sufficient.format(d) Open the python script (dft-scripts/script-39. ismear=0. ediff=1e-8.001 eV (or 10*EDIFF). Atom(’O’. the relaxation is stopped. Atom from jasp import * 3 4 5 6 7 atoms = Atoms([Atom(’H’.01.5960812. 1 2 from ase import Atoms. cell=(8. [0. [-0. Here we relax a water molecule which has three atoms.4. 8. i. 6. 1 2 from ase import Atom.001 0. encut=350. [0. For most work.2. 0. 0. set EDIFFG=-0. ] ] ]] 48 . # Gaussian smearing ibrion=2. 0]).get_forces() 21 22 23 24 pos = co.Note: VASP applies a criteria for stopping a geometry optimization. This criteria is controlled by the incar:EDIFFG tag. 0. sigma=0. 0. nbands=6. # this is small for a molecule ibrion=2.pos[1])**2). 0])]. 0. to a negative number.2f} angstroms’. 0. a force tolerance of 0. xc=’PBE’.05.0000000]).py).py). 0. [ 0. 0. 8)) 8 9 10 11 12 13 14 15 16 with jasp(’molecules/h2o_relax’.0000000.7677068. 0. cell=(6. encut=400.3 Relaxation of a water molecule It is not more complicated to relax more atoms. forces ======= [[ 0. 6)) 7 8 9 10 11 12 13 14 15 16 with jasp(’molecules/co-cg’.[0.sum()**0.5960812.7677068. Atom(’O’. 0. 0. 3. If you prefer to stop based on forces. Atoms from jasp import * 3 4 5 6 co = Atoms([Atom(’C’. When the change in energy between two steps is less than 0.0000000]). # conjugate gradient optimizer nsw=5. nsw=10. -0.0000000])].get_positions() d = ((pos[0] . ismear=1. -0.e. atoms=atoms) as calc: 17 18 19 20 print "forces" print ’=======’ print atoms. xc=’PBE’. [0. # do at least 5 steps to relax atoms=co) as calc: 17 18 19 20 print ’Forces’ print ’=======’ print co.5 print ’Bondlength = {0:1. it just may take longer because there are more electrons and degrees of freedom.[1. 2.polyval.data import atomic_masses C_mass = atomic_masses[6] / kg O_mass = atomic_masses[8] / kg 35 36 mu = 1. We only need to fit an equation to the energy vs.units import * 3 4 5 bond_lengths = [1.pi) * np. We will use a cubic polynomial for demonstration here.polyder.linspace(1.15.g.polyval(ddpars.5 Vibrational frequencies 3.get_potential_energy()) 11 12 13 14 15 # fit the data pars = np. ’b-’) plt. find the minimum energy bond-length.5.append(atoms. 1. efit. We actually already have the data to do this from Manual determination. 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.1 Manual calculation of vibrational frequency The principle idea in calculating vibrational frequencies is that we consider a molecular system as masses connected by springs. 1. energies.1. and then evaluate the second derivative of the fitted function at the minimum. 1 2 from jasp import * from ase.25) efit = np. func:numpy. If the springs are Hookean. We will compute the value of k from ν = 2π DFT calculations as follows: 2 k = ∂∂xE2 at the equilibrium bond length. 3) xfit = np. in a simple molecule like CO where there is only one spring. xfit) 16 17 18 19 20 21 # first derivative dpars = np.polyfit(bond_lengths.sqrt(k / mu) print ’The CO vibrational frequency is {0} Hz’. 1.plot(bond_lengths. / (2. the force is proportional to the displacement.25] energies = [] 6 7 8 9 10 for d in bond_lengths: with jasp(’molecules/co-{0}’.xlabel(’Bond length ($\AA$)’) plt. Polynomials are numerically convenient because they are easy to fit.pyplot as plt plt.get_atoms() energies.polyder(pars) # find where the minimum is. For example.format(frequency/3e10) 41 42 43 44 45 46 47 import matplotlib.05. and it is trivial to get the roots and derivatives of the polynomials. chose the second one because it is the # minimum we need. e.polyval(ddpars.3.0 / C_mass + 1. 1.0 / O_mass) 37 38 39 40 frequency = 1.plot(xfit.format(*frequency) print ’The CO vibrational frequency is {0} cm^{{-1}}’. 1.show() Open the python script (dft-scripts/script-41.05. as well as to evaluate them at other points using func:numpy.py).polyder(dpars) 25 26 d_min = droots[np. droots = np.0 / (1.polyfit. d_min) / (J / m**2) 30 31 32 33 34 # mu.polyval(pars. bond-length data. and func:numpy. reduced mass from ase. the frequency is: p 1 k/µ where µ1 = m1C + m1O and k is the spring constant.roots(dpars) 22 23 24 # second derivative ddpars = np.ylabel(’Total energy (eV)’) plt. The CO vibrational frequency is 6. droots) > 0] 27 28 29 # curvature at minimum = force constant in SI units k = np. energies. * np.format(d)) as calc: atoms = calc. ’bo ’) plt.43082289837e+13 Hz 49 . We access the capability by using a new value for incar:IBRION.0000000])].7677068.0000000]).3f} eV’. 12 13 14 15 16 17 18 19 20 21 22 with jasp(’molecules/h2o_vib’. For IBRION=5. The default number of displacements is 2.format(E_zpe) Open the python script (dft-scripts/script-42. If the spring is non-linear.2 Automated vibrational calculations VASP has built-in capability for performing vibrational calculations. only symmetry inequivalent displacements are considered. A final note is that this analysis is in the "harmonic approximation". especially at higher temperatures. 8)) atoms. # finite differences with symmetry nfree=2. 8. 0.get_forces() 50 . # Set to 1 for vibrational calculation atoms=atoms) as calc: 23 24 25 26 print ’Forces’ print ’======’ print atoms. 0. Atom(’O’.0000000]). xc=’PBE’. and h is Planck’s constant (4. cell=(8. Atom from jasp import * import ase.015. [0. and tends to be very important for small atoms.php/H2O_vibration from ase import Atoms. The procedure described above is basically how many vibrational calculations are performed.608] cm^{-1} This result is in good agreement with experiment.0000000. 1 2 3 4 5 # <<water-vib>> # adapted from http://cms. ismear=0. 3.5960812. # default as well ediff=1e-8.units 6 7 8 9 10 11 atoms = Atoms([Atom(’H’. # central differences (default) potim=0.135667516e-15 eV/s). encut=400.The CO vibrational frequency is [ 2143. The frequency equation is the solution to a harmonic oscillator. 1 2 c = 3e10 # speed of light cm/s h = 4. With more atoms. [0.at/wiki/index. We now consider how much energy is in this vibration.6076625*c # 1/s 5 6 E_zpe = 0.133 eV This is a reasonable amount of energy! Zero-point energy increases with increasing vibrational frequency. 0. You can also specify the size of the displacement with incar:POTIM (the default is 0.mpi. then there are anharmonic effects that may become important.0000000. 0. # for vibrations you need precise energies nsw=1. You can specify the number of displacements with incar:NFREE.5960812. you have to determine a force constant matrix and diagonalize it.135667516e-15 # eV*s 3 4 nu = 2143. see.7677068.py).univie. which makes the calculations slightly cheaper.015 Å).center() -0.ac. # Gaussian smearing ibrion=6. For IBRION=6. This is commonly called zero-point energy (ZPE) and it is defined as EZP E = 21 hν for a single mode. [0. 0.5*h*nu 7 8 print ’E_ZPE = {0:1. which we cover in Automated vibrational calculations. all atoms that are not constrained are displaced. E_ZPE = 0. 44 In practice.5. Atom(’H’. we usually allow a packaged code to automate this. The values of 5 and 6 calculated the Hessian matrix using finite differences. For more details. The vibrations are easy to spot. where all atoms move in the same direction (either x. which also do not change the total energy of the molecule.012959493+0j) 08: (0. Water has 3 atoms.032 -0. One way is to visualize the modes. a symmetric stretch at 3657 cm-1 (3723) 2. The modes of water vibration are (with our calculated values in parentheses): 1. Forces ====== [[ 0. The rotations/translations are not always cleanly separable.032 -0. mode 3 is a mixed translation/rotation 5.001]] energies ======== 00: 0. mode 0 is an asymmetric stretch 2.015883929+0j) eV eV eV eV Note we get 9 frequencies here. e) Open the python script (dft-scripts/script-43.018 -0. modes = calc.007093876 eV 04: 0. That leaves 3N-6 = 3 degrees of vibrational freedom where some or all of the bonds are stretched. leading to 9 possible combinations of collective motions. Another three of those motions are rotations. an asymmetric stretch at 3756 cm-1 (3836) 3.012642767+0j) 07: (0.py). with three degrees of freedom each. Three of those collective motions are translations.002459836 eV 05: (0.cgi?ID=C7732185&Mask=800#Electronic-Spec The results are not too far off.27 28 29 30 31 32 print # vibrational energies are in eV energies. e in enumerate(energies): print ’{0:02d}: {1} eV’. y or z) and there is no change in the total energy of the molecule.get_vibrational_modes() print ’energies\n========’ for i. 0. mode 1 is a symmetric stretch 3. or by using IBRION=7 or 8.035 0. i. resulting in a change in the total energy. We usually do not worry about this because these modes are usually not important. and a bending mode at 1595 cm-1 (1583) http://webbook.018 0.19618999 eV 03: 0.e.gov/cgi/cbook.001] [-0. mode 2 is a bending mode 4.nist.475824705 eV 01: 0.format(i.461734211 eV 02: 0. and more accurate frequencies may be possible using tighter tolerance on POTIM. Let us briefly discuss how to determine which vectors are vibrations and which are rotations or translations. 1.000291856+0j) 06: (0.003] [ 0. mode 4 is a rotation 51 . This is an issue of accuracy and convergence. get_vibrational_modes(mode=3. we will relax a water molecule.ac. Zero-point energy for multiple modes For a molecule with lots of vibrational modes the zero-point energy is defined P as the sum over all the vibrational modes: EZP E = i 21 hνi Here is an example for water. 1 2 3 4 from jasp import * import numpy as np c = 3e10 # speed of light cm/s h = 4.htm for a more quantitative discussion of these modes. massweighted=True.sum([0.135667516e-15 # eV/s 5 6 7 8 # first. 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. The ZPE of water is 0. and a method to project the rotations and translations out of the Hessian matrix. 3.univie.572 eV Note the zero-point energy of water is also fairly high (more than 0.format(ZPE) 18 19 20 21 # one liner ZPE = np. Note we do not sum over the imaginary modes. but some are just small). 52 . with jasp(’molecules/h2o_vib’) as calc: freq = calc. show=True) Open the python script (dft-scripts/script-44. mode 5 is a translation 7.at/david.5 * h * nu 16 17 print ’The ZPE of water is {0:1. get the frequencies.com/g_whitepap/vib.py). We should also ignore the rotational and translational modes (some of those are imaginary.html#Entry02 there is a recipe for computing the Infrared vibrational spectroscopy intensities in VASP.py). identifying them. That is because of the high frequency O-H stretches.0 for f in freq: if not isinstance(f.6. float)]) print ’The ZPE of water is {0:1.karhanek/downloads. First. mode 7 is a partial translation 9. See http://www.5 * h * f * c for f in freq if isinstance(f. modes = calc. mode 6 is a rotation 8.get_vibrational_frequencies() 9 10 11 12 13 14 15 ZPE = 0.format(ZPE) Open the python script (dft-scripts/script-45.5 eV).3f} eV’.6 Simulated infrared spectra At http://homepage. We are going to do that for water here.3f} eV’. float): continue # skip complex numbers nu = f * c # convert to frequency ZPE += 0.gaussian. txt 11 53 . lepsilon=True.get_atoms() 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # now define a new calculator with jasp(’molecules/h2o_vib_dfpt’. # Gaussian smearing ibrion=2. this shell script was provided to extract the results. # switches on the DFPT vibrational analysis (with # no symmetry constraints) nfree=2.1 2 from ase import Atoms.5960812. then \ printf " . fi grep "in e.. 8 9 10 11 12 13 14 15 16 17 18 19 with jasp(’molecules/h2o_relax’. 8. Atom(’H’. ICIQ Tarragona. cell=(8. 0. 0. atoms=atoms) as calc: print ’Forces’ print ’===========================’ print atoms.py).es) 4 5 6 7 8 9 10 # extract Born effective charges tensors printf ". exit 1 . Spain (www. Note. FAILED! Born effective charges missing! Bye! \n\n" . Forces =========================== [[ 0. nwrite=3. cummulative" -A $BORN_NROWS OUTCAR > born.5 where finite differences were used. ismear=0. 0.7677068. ] [ 0.0000000. 2011-03-25. -0.py).calculate(atoms) Open the python script (dft-scripts/script-47. 0. 1 2 3 #!/bin/bash # A utility for calculating the vibrational intensities from VASP output (OUTCAR) # (C) David Karhanek.0000000]). 0. To analyze the results. nsw=10. [0. encut=400. 0. # Gaussian smearing ibrion=7.5960812. nsw=1.0000000])].0000000]). [0.015. xc=’PBE’.001 0. ]] Next. 0. encut=400. ediff=1e-8. # enables to calculate and to print the BEC # tensors lreal=False.get_forces() Open the python script (dft-scripts/script-46. 0.0000000. potim=0. # affects OUTCAR verbosity: explicitly forces # SQRT(mass)-divided eigenvectors to be printed atoms=atoms) as calc: calc.. we instruct VASP to compute the vibrational modes using density functional perturbation theory with IBRION=7.iciq. [0. 8)) -0. ] [-0. ismear=0.7677068. 1 from jasp import * 2 3 4 5 # read in relaxed geometry with jasp(’molecules/h2o_relax’) as calc: atoms = calc. this is different than in 3. Atom(’O’. Atom from jasp import * 3 4 5 6 7 atoms = Atoms([Atom(’H’.reading OUTCAR" BORN_NROWS=‘grep NIONS OUTCAR | awk ’{print $12*4+1}’‘ if [ ‘grep ’BORN’ OUTCAR | wc -l‘ = 0 ] . xc=’PBE’. 0. bo..vib..done\n" 42 43 44 45 46 47 48 49 50 51 52 53 54 # parse deviation vectors (eig) printf ".ei.e.pol}’ > matr-vib-${nuu}-alpha-${alpha}-ion-${ss} done sumpol=‘cat matr-vib-${nuu}-alpha-${alpha}-ion-* | awk ’{sum+=$7} END {print sum}’‘ int=‘echo "$int+($sumpol)^2" | sed ’s/[eE]/*10^/g’ | bc -l‘ done freq=‘awk ’(NR==1){print $8}’ temps02/eigens..$bod e.$5.txt printf ".eige.$ss done mkdir temps02 .. do # summing over atoms ss=‘printf "%03u" $s‘ awk -v a="$alpha" ’(NR==a){print}’ bornch.done\n" 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 # parse matrices.$eid eigens.$4}’ borncs.$alpha # summing over beta coordinates and multiplying Z(s. bod=‘printf "%03u" $sd‘ .bo.$nuu‘ echo "$nuu $freq $int">> exact. mv eigens.0 for alpha in 1 2 3 . split -a 3 -d -l $NBORN_STEP temp. mv born.e.vib.alpha.born.allions split -a 3 -d -l 1 e. mv temp.txt mkdir inputs . fi EIG_NVIBS=‘grep -A 2000 ’SQRT(mass)’ OUTCAR | grep ’cm-1’ | wc -l‘ EIG_NIONS=‘grep NIONS OUTCAR | awk ’{print $12}’‘ EIG_NROWS=‘echo "($EIG_NIONS+3)*$EIG_NVIBS+3" | bc‘ grep -A $(($EIG_NROWS+2)) ’SQRT(mass)’ OUTCAR | tail -n $(($EIG_NROWS+1)) | sed ’s/f\/i/fi /g’ > eigenvectors. print $0. do nuu=‘printf "%03u" $nu‘ tail -n $sad eigens.. do nuu=‘printf "%03u" $nu‘ int=0.done\n" 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 # set up a new directory.ion.done\n" 55 56 57 58 59 60 61 62 63 # parse born effective charge matrices (born) printf ".$nuu.txt temp. do ss=‘printf "%03u" $s‘ awk ’{print $2.$bod borncs. ei=‘printf "%03u" $nu‘ .done\n" 87 88 89 # format results.. mv temp.born.$ss | \ awk ’{pol=$1*$4+$2*$5+$3*$6. do let nud=nu-1 . eid=‘printf "%03u" $nud‘ .txt printf " .txt temps01/ for nu in ‘seq 1 $EIG_NVIBS‘ .ion. normalize intensities printf "." done printf " .$nuu.txt eigenvectors..vib.txt eigenvectors. then \ printf " .txt > temp. for s in ‘seq 1 $EIG_NIONS‘ . mkdir temps01 ..splitting files" mkdir intensities .ion.multiplying matrices. multiply them and collect squares (giving intensities) printf ".12 13 14 15 16 17 18 19 # extract Eigenvectors and eigenvalues if [ ‘grep ’SQRT(mass)’ OUTCAR | wc -l‘ != 1 ] .$nuu.$ss | tail -3 > bornch.vib.born.alpha)*e(s) done by the following awk script paste z. bo=‘printf "%03u" $s‘ .charges" for s in ‘seq 1 $EIG_NIONS‘ .txt intensities/ cd intensities/ let NBORN_NROWS=BORN_NROWS-1 let NEIG_NROWS=EIG_NROWS-3 let NBORN_STEP=4 let NEIG_STEP=EIG_NIONS+3 tail -n $NBORN_NROWS born.." ".eige.ion.alpha. summing " for nu in ‘seq 1 $EIG_NVIBS‘ . mv temp.parsing eigenvectors" let sad=$EIG_NIONS+1 for nu in ‘seq 1 $EIG_NVIBS‘ .txt > temp.txt temp. do let sd=s-1 .0 for s in ‘seq 1 $EIG_NIONS‘ . mv temp.$nuu.$3.* temps02/ printf " . mv born.$ei done for s in ‘seq 1 $EIG_NIONS‘ .txt inputs/ split -a 3 -d -l $NEIG_STEP temp.$nuu.ion.vib. do # summing over alpha coordinates sumpol=0. exit 1 .parsing eff.vib. FAILED! Restart VASP with NWRITE=3! Bye! \n\n" .$alpha e.vib.$bo done done printf " .* borncs.txt temp. do let sd=s-1.vib.$ss. bod=‘printf "%03u" $sd‘..$ss.$6}’ > e.$ss > z.prepare for parsing printf ". split files .eige.ei.normalizing intensities" 54 .vib.txt tail -n $NEIG_NROWS eigenvectors. bo=‘printf "%03u" $s‘..res.$bo done printf " .allions temp.$nuu | head -n $EIG_NIONS | awk ’{print $4.$nuu.ion. 000 005 19..done ...done .6 0.txt Open the python script (dft-scripts/script-48.* e.$1.txt > temp.txt > results.res.. 1 2 3 4 5 6 7 8 9 10 11 12 13 #!/bin/bash # reformat intensities..parsing eigenvectors .$2.726 002 3713.txt cat reform... mv *res*txt results/ let NMATRIX=$EIG_NVIBS**2 printf "%5u atoms found\n%5u vibrations found\n%5u matrices evaluated" \ $EIG_NIONS $EIG_NVIBS $NMATRIX > results/statistics.txt # fast switch to clean up all temporary files rm -r temps* cat results/results. It is not obvious that will always be the right way to do it as the order of the eigenvectors is not guaranteed.charges .reform.3 0.1 0.1f %5.$2..019 003 1587..1f %5.reform.345 Note that the results above include the rotational and translational modes (modes 4-9)..2 0.90 91 92 max=‘awk ’(NR==1){max=$3} $3>=max {max=$3} END {print max}’ exact.reformatting and normalizing intensities .txt | awk ’{print $1}’ ‘. .allions temps03/ mkdir temps04.000 007 16..006 003 1587.reformatting and normalizing intensities" cd intensities/results/ nlns=‘wc -l exact.3f\n".txt‘ awk -v max="$max" ’{print $1.done\n.reform.5 1./.normalizing intensities .done .$3/max}’ temp.. and recalculates the intensities. Open the python script (dft-scripts/script-49...done .txt max=‘awk ’(NR==1){max=$3} $3>=max {max=$3} END {print max}’ temp..reform.$3/max}’ exact.3 0.3 0.reform..py).$3/max}’ temp.txt > exact..000 55 .res.005 008 45.res.res.ion.done ..2 1.reform.$2..txt cd . let bodylns=nlns-6 head -n $bodylns exact.done\n" 93 94 95 96 97 98 99 100 101 102 103 104 105 # clean up. The following shell script removes those.done .. .res.finalizing: 001 3827.*.res.227 002 3713.. just normal modes: 3N -> (3N-6) printf ".res..0 0. display results printf ". mv bornch.txt printf " .parsing eff.normal modes:\n" rm temp. summing .$1.0 0..000 009 136. Note that it appears to just remove the last 6 modes and req compute the intensities..312 004 235.0 0..reading OUTCAR .finalizing:\n" mkdir temps03.1 0.txt awk -v max="$max" ’{printf "%03u %6.006 006 2.res.txt printf " ...txt > reform.*.res.res.res..3f\n"..done .res.vib.normal modes: 001 3827. mv matr-* temps05/ mkdir results.multiplying matrices. mv z..txt‘ awk -v max="$max" ’{printf "%03u %6. .* temps04/ mkdir temps05.ion* e.py).vib..splitting files . 000 0.006 0. We first consider an N2 molecule.005 0. the total energy.7 Thermochemical properties of molecules mod:ase. there is only a small change in the molecule dipole moment. The symmetry numbers are determined by the molecular point group.thermochemistry can be used to estimate thermodynamic properties of gases in the ideal gas limit. intensity in enumerate(calc.000 0. and some information about the molecular symmetry. mode 00 01 02 03 04 05 06 07 08 Relative intensity 0. H2 D3d 6 Td 12 CH4 Oh 24 1 2 3 from ase. See also.get_infrared_intensities()): print ’{0:02d} {1:1.345 3. The module needs as input the geometry. intensity) Open the python script (dft-scripts/script-50. 45 For HREELS simulations see. Earlier we interpreted that as the symmetric stretch.The interpretation of these results is that the mode at 3713 cm-1 would be nearly invisible in the IR spectrum.py). the vibrational energies. Table 3: Symmetry numbers for common point groups point group σ examples C1 1 Cs 1 C2 2 C2v 2 H2 O C3v 3 NH3 C∞v 1 CO D2h 4 D3h 6 D5h 10 D∞h 2 CO2 .thermochemistry import IdealGasThermo from jasp import * 4 5 atoms = molecule(’N2’) 56 .312 1. 1 2 3 4 5 from jasp import * with jasp(’molecules/h2o_vib_dfpt’) as calc: print ’mode Relative intensity’ for i.format(i.006 0. 47 Here is a table of the most common ones. In this mode.227 0.structure import molecule from ase.3f}’.000 0. so there is a small IR intensity. 46 The shell script above has been translated to a convenient python function in mod:jasp. pressure=101325.0169775241059 eV 02: 0.0 Pa: ================================================= S T*S 57 .15 K: =============================== E_elec -16.039 eV Cv_rot (0->T) 0.py).10).853610575e-09 eV 04: 8.1356675e-15 # eV*s c = 3. thermo = IdealGasThermo(vib_energies=vib_energies[0:0]. spin=0) 43 44 45 # temperature in K. ibrion=6.68490175e-10 eV 05: 0.format(i.15.478 eV E_ZPE 0.29159234324 eV 01: 0.e) 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.set_cell((10. symmetrynumber=2. atoms=atoms) as calc: calc.get_free_energy(temperature=298.15. xc=’PBE’.6 atoms. atoms=atoms. xc=’PBE’. atoms=atoms) as calc: electronicenergy = atoms.0169775241059 eV 03: 2. This example does not work if # you give all the energies because one energy is zero. nsw=5. nsw=1.calculate() vib_freq = calc. ibrion=2. potim=0.) Open the python script (dft-scripts/script-51. vibrational energies ==================== 00: 0.e in enumerate(vib_energies): print ’{0:02d}: {1} eV’. we get vibrational modes with jasp(’molecules/n2-vib’. nfree=2. encut=300.get_potential_energy() 16 17 18 19 20 21 22 23 24 25 26 27 # next.15 K and P = 101325.get_vibrational_frequencies() # in cm^1 28 29 30 31 32 33 34 35 #convert wavenumbers to energy h = 4.10.000 eV (C_v -> C_p) 0.0 eV Enthalpy components at T = 298. G in eV G = thermo.0e10 #cm/s vib_energies = [h*c*nu for nu in vib_freq] print ’vibrational energies\n====================’ for i. encut=300. geometry=’linear’. pressure in Pa.000 eV Cv_trans (0->T) 0. electronicenergy=electronicenergy. scale_atoms=False) 7 8 9 10 11 12 13 14 15 # first we relax a molecule with jasp(’molecules/n2-relax’.388 eV =============================== Entropy components at T = 298.026 eV ------------------------------H -16.026 eV Cv_vib (0->T) 0. format(-T*S/1000/96.4168 H = 0.0000000 eV/K 0.464 eV S_rot 0.388 eV -T*S -0. 58 .087 eV ======================= Let us compare this to what is in the Nist webbook via the Shomate equations.8 3. 10.0000000 eV/K -0. [5. D = 2 ∗ EO − EO2 . 5])]. Simple estimate of O2 dissociation energy 1 2 from jasp import * from ase import Atom.15 t = T/1000.E/(2*t**2) + G print ’-T*S = {0:1.235 eV S_elec 0.0015579 eV/K 0. Atoms 3 4 5 atoms = Atoms([Atom(’O’. -T*S = -0. 1 2 3 4 5 6 7 8 9 import numpy as np A = 28.699 eV ================================================= Free energy components at T = 298.63537 E = 0.3f} eV’. Let us do that. The dissociation energy is pretty straightforward to define: it is the energy of the products minus the energy of the reactant.000 eV ------------------------------------------------S 0.8.000 eV S (1 atm -> P) -0. 10)) 6 7 8 with jasp(’molecules/O’. 13 14 15 S = A*np.592 eV This is reasonable agreement for the entropy.853978 C = -9. It would appear that we simply calculate the energy of an oxygen atom.0000000 eV/K 0.0023449 eV/K 0.699 eV ----------------------G -17.647459 D = 16.0 Pa: ======================= H -16.98641 B = 1. xc=’PBE’.1 Molecular reaction energies O2 dissociation The first reaction we consider is a simple dissociation of oxygen molecule into two oxygen atoms: O2 → 2O.15 K and P = 101325. cell=(10.4853) Open the python script (dft-scripts/script-52.000 eV S_vib 0.0007870 eV/K 0.log(t) + B*t + C*t**2/2 + D*t**3/3 .S_trans (1 atm) 0.py). You will get different results if you use different exchange correlation functionals. 5.671914 G = 226.000117 F = -8. 3. and the energy of an oxygen molecule and evaluate the formula.0 10 11 12 T = 298. and these would have different energies. VaspQueued): E_O = None 14 15 16 17 18 19 20 # now relaxed O2 dimer atoms = Atoms([Atom(’O’. Atom(’O’.22. We implicitly neglected spin-polarization in the example above. cell=(10. 5. 10)) 21 22 23 24 25 26 27 28 29 30 31 32 with jasp(’molecules/O2’. cell=(10. encut=400. Atoms 3 4 5 atoms = Atoms([Atom(’O’. [6. we have to tell VASP to use spin-polarization. To account for spin polarization. 1 2 from jasp import * from ase import Atom. and these should have different energies.format(2 * E_O . 5]. encut=400.py). ismear=0. 5]. which is very different than what we calculated! Let us consider some factors that contribute to this error. In a triplet state there are two electrons with spins of the same sign. 10. 5. [5. cell=(10. [5.get_potential_energy() except (VaspSubmitted. 5]. 10)) 6 7 8 9 10 11 12 13 14 15 16 with jasp(’molecules/O-sp-triplet’. xc=’PBE’. 5])]. atoms=atoms) as calc: try: E_O2 = atoms. xc=’PBE’.format(atoms. magmom=1)]. ismear=0. [5. Atom(’O’. 5. Furthermore. and give initial guesses for the magnetic moments of the atoms. the oxygen atom can be a singlet or a triplet. E_O2): print ’O2 -> 2O D = {0:1.get_potential_energy() except (VaspSubmitted. [6. VaspQueued): E_O = None 17 18 print ’Magnetic moment on O = {0} Bohr magnetons’. 5. 10)) 59 . VaspQueued): E_O2 = None 33 34 35 if None not in (E_O. since the O2 molecule can be in one of two spin states. ismear=0.3f} eV’. 10.encut=400. nsw=10.521 eV The answer we have obtained is way too high! Experimentally the dissociation energy is about 5. magmom=1). # turn spin-polarization on atoms=atoms) as calc: try: E_O = atoms. magmom=2)].2 eV (need reference). Estimating O2 dissociation energy with spin polarization in triplet ground states To tell VASP to use spin-polarization we use ISPIN=2. ispin=2.get_potential_energy() except (VaspSubmitted. and we set initial guesses for magnetic moments on the atoms with the magmom keyword. a singlet or a triplet. That could be a problem. atoms=atoms) as calc: 9 10 11 12 try: 13 E_O = atoms. Let us try again with spin polarization. 10. ibrion=2.get_magnetic_moment()) 19 20 21 22 23 # now relaxed O2 dimer atoms = Atoms([Atom(’O’. 5.22.E_O2) Open the python script (dft-scripts/script-53. 5]). O2 -> 2O D = 8. xlabel(’energy [eV]’) plt. # turn spin-polarization on ibrion=2.py).dos import * 3 4 5 6 7 8 with jasp(’molecules/O2-sp-triplet’) as calc: dos = DOS(calc.format(np. e.2) d_up = dos. encut=400. TODO: show what "hard or soft" is in the pseudopotential.E_O2) Open the python script (dft-scripts/script-54.95489738902 number of down states = 5. atoms=atoms) as calc: try: E_O2 = atoms. It is still more than 1 eV above an experimental value. 1 2 from jasp import * from ase. One has 7 electrons in it (the blue lines). number of up states = 5.0 # integrate up to 0eV print ’number of up states = {0}’.legend([’up’.get_dos(spin=0) d_down = dos.get_potential_energy() except (VaspSubmitted.3f} eV’. and the other has 5 electrons in it (the green line).format(np. width=0. xc=’PBE’.py).format(2 * E_O . -d_down) plt.trapz(d_up[ind]. Oxygen is a "hard" atom that requires a high cutoff energy to achieve high levels of convergence.0000084 Bohr magnetons O2 -> 2O D = 6.get_magnetic_moment()) 40 41 42 if None not in (E_O. # make sure we relax the geometry nsw=10. We will look at the differences in these two through the density of states.trapz(d_down[ind].format(atoms.dft.00001754136 You can see in Figure 19 that there are two different densities of states for the two spins. e[ind])) 14 15 16 17 18 19 20 21 import pylab as plt plt. VaspQueued): E_O2 = None 37 38 39 # verify magnetic moment print ’Magnetic moment on O2 = {0} Bohr magnetons’. Magnetic moment on O = 2. d_up. E_O2): print ’O2 -> 2O D = {0:1.24 25 26 27 28 29 30 31 32 33 34 35 36 with jasp(’molecules/O2-sp-triplet’. Some additional parameters that might need to be checked for convergence are the SIGMA value (it is probably too high for a molecule). ismear=0.get_energies() 9 10 11 12 13 ind = e <= 0.0000072 Bohr magnetons Magnetic moment on O2 = 2. e[ind])) print ’number of down states = {0}’. but most of that error is due to the GGA exchange correlation functional. Looking at the two spin densities In a spin-polarized calculation there are actually two electron densities: one for spin-up and one for spin-down.savefig(’images/O2-sp-dos.ylabel(’DOS’) plt.668 eV This is much closer to accepted literature values for the DFT-GGA O2 dissociation energy. The difference of 60 .png’) Open the python script (dft-scripts/script-55. ’down’]) plt. as well as the cutoff energy.plot(e. ispin=2.get_dos(spin=1) e = dos. get_potential_energy() except (VaspSubmitted. 350. 61 . Atom(’O’. 400. 5]. ispin=2. For example. 10.format(encut). atoms=atoms) as calc: try: E_O = atoms. cell=(10. Atoms encuts = [250. 500. xc=’PBE’. the blue peak between -25 and -30 eV corresponds to one electron. ismear=0. It is customary to set the Fermi level to 0 eV in DOS plots. Remember that only peaks in the DOS below the Fermi level are occupied. 5. 300. magmom=2)]. 450. 5. magmom=1)]. [5. encut=encut. where as the blue peak between -5 and -10 eV corresponds to three electrons. 5. in a 1s orbital. magmom=1).22. 550] 4 5 6 7 8 D = [] for encut in encuts: atoms = Atoms([Atom(’O’. The peaks roughly correspond to electrons. [6. two electrons leads to the magnetic moment of 2 which we calculated earlier. 5]. [5. 10)) 9 10 11 12 13 14 15 16 17 18 19 with jasp(’molecules/O-sp-triplet-{0}’. 5]. Convergence study of the O2 dissociation energy 1 2 3 from jasp import * from ase import Atom.Figure 19: Spin-polarized DOS for the O2 molecule. VaspQueued): E_O = None 20 21 22 23 # now relaxed O2 dimer atoms = Atoms([Atom(’O’. Note that increasing the planewave cutoff significantly increases the computational time.650 eV eV eV eV eV eV eV Based on these results (Figure 20).668 6.cell=(10.pyplot as plt plt. 10)) 24 25 with jasp(’molecules/O2-sp-triplet-{0}’. 350.format(encut). VaspQueued): E_O2 = None 26 27 28 29 30 31 32 33 34 35 36 37 38 if None not in (E_O.format(encut.708 6.get_potential_energy() except (VaspSubmitted. E_O2): d = 2*E_O . ismear=0. encut=encut. 550] print ’encut (eV) Total CPU time’ print ’--------------------------------------------------------’ 4 5 6 7 8 9 10 11 for encut in encuts: OUTCAR = ’molecules/O2-sp-triplet-{0}/OUTCAR’.savefig(’images/O2-dissociation-convergence.648 6. 400.650 6. O2 O2 O2 O2 O2 O2 O2 -> -> -> -> -> -> -> 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.808 62 . 500. 1 2 3 encuts = [250. d) 43 44 45 46 47 48 import matplotlib. ’r’) for line in f: if ’Total CPU time used (sec)’ in line: print ’{0} eV: {1}’. 450. 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.format(encut) f = open(OUTCAR.format(encut. line) f.ylabel(’O$_2$ dissociation energy (eV)’) plt.727 6. ispin=2.E_O2 D. D) plt. # this turns relaxation on nsw=10.py).696 6. and within 50 meV at 350 eV cutoff. encut (eV) Total CPU time -------------------------------------------------------250 eV: Total CPU time used (sec): 67. 10. xc=’PBE’.296 350 eV: Total CPU time used (sec): 150.append(d) print ’O2 -> 2O encut = {0} 39 40 41 42 D = {1:1. You have to decide what an appropriate level of convergence is. 300.close() Open the python script (dft-scripts/script-57.3f} eV’. you could argue the dissociation energy is converged to about 2 meV at a planewave cutoff of 450 eV.plot(encuts.png’) Open the python script (dft-scripts/script-56. atoms=atoms) as calc: try: E_O2 = atoms. # turn spin-polarization on ibrion=2.py).xlabel(’ENCUT (eV)’) plt.926 300 eV: Total CPU time used (sec): 121. A variation of nearly 0. The default value of SIGMA is 0. this means a very small Fermi temperature (SIGMA) should be used.381 500 eV: Total CPU time used (sec): 240. SIGMA is the broadening factor used to smear the electronic density of states at the Fermi level. However.2 eV is seen from the default Fermi temperature of kb T = 0.705 550 eV: Total CPU time used (sec): 266. We were not careful in selecting a good value for SIGMA in the calculations above. virtually no change was observed for a hydrogen atom or molecule or for an oxygen molecule as a function of the Fermi temperature. which may be fine for metals.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. We are somewhat forced to use the machinery designed for metals on molecules.Figure 20: Convergence study of the O2 dissociation energy as a function of ENCUT. For a metal with a continuous density of states this is appropriate. The O2 dissociation energy as a function of SIGMA is shown in Figure 21.2 eV and the value of kb T = 0. but it is not correct for molecules. 400 eV: Total CPU time used (sec): 307. The solution is to use a 63 . it should not be used for semiconductors. 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. 12 Consequently.2.465 450 eV: Total CPU time used (sec): 199. but for molecules with discrete energy states it does not make sense. In VASP.0001 eV. molecules or atoms. 0. but that is not practical for convergence reasons. sigma=sigma.append(d) print ’O2 -> 2O sigma = {0} D = {1:1. Ideally you would use SIGMA=0.E_O2 D.xlabel(’SIGMA (eV)’) plt.get_potential_energy() except (VaspSubmitted.format(sigma). 5. 0.py).[5.png’) Open the python script (dft-scripts/script-58.get_potential_energy() except (VaspSubmitted. 10.plot(sigmas.format(sigma.magmom=1)]. 1 2 from jasp import * from ase import Atom. 5. [5. 10)) 6 7 8 9 with jasp(’molecules/O-sp-singlet’. 5].[5. atoms=atoms) as calc: try: E_O = atoms. Let us examine the effect of SIGMA on the dissociation energy here.2. ismear=0.05. 0. cell=(10. 10)) 27 28 29 30 31 32 33 34 35 36 37 38 39 40 with jasp(’molecules/O2-sp-triplet-sigma-{0}’. 5. 0. sigma=sigma.01. d) 46 47 48 49 50 51 import matplotlib. Atom(’O’. ismear=0.savefig(’images/O2-dissociation-sigma-convergence. 1 2 from jasp import * from ase import Atom.22. 10. 5. let us consider the case where each species is in the singlet state. ispin=2. 64 .[6. cell=(10. 10. 10)) 10 11 12 13 14 15 16 17 18 19 20 21 with jasp(’molecules/O-sp-triplet-sigma-{0}’. # turn spin-polarization on ibrion=2. # make sure we relax the geometry nsw=10.02.1. D. Clearly SIGMA has an effect. xc=’PBE’. magmom=2)]. E_O2): d = 2 * E_O . ispin=2. but it does not move the dissociation energy closer to the literature values! Estimating singlet oxygen dissociation energy Finally. xc=’PBE’. VaspQueued): E_O2 = None 41 42 43 44 45 if None not in (E_O.magmom=1). xc=’PBE’.very small SIGMA. 0. Atoms 3 4 sigmas = [0. magmom=0)]. ’bo-’) plt.3f} eV’. 5]. encut=400.pyplot as plt plt. 5].ylabel(’O$_2$ dissociation energy (eV)’) plt. so we try to find what is small enough. encut=400. 5].format(sigma). VaspQueued): E_O = None 22 23 24 25 26 # now relaxed O2 dimer atoms = Atoms([Atom(’O’.001] 5 6 7 8 9 D = [] for sigma in sigmas: atoms = Atoms([Atom(’O’. atoms=atoms) as calc: try: E_O2 = atoms. cell=(10. Atoms 3 4 5 atoms = Atoms([Atom(’O’. encut=400. atoms=atoms) as calc: try: E_O2 = atoms. encut=400.Figure 21: Effect of SIGMA on the oxygen dissociation energy.get_magnetic_moment()) 19 20 21 22 23 # now relaxed O2 dimer atoms = Atoms([Atom(’O’.format(atoms. 5]. 10)) 24 25 26 27 28 29 30 31 32 33 34 35 36 with jasp(’molecules/O2-sp-singlet’.get_magnetic_moment() 40 41 42 if None not in (E_O.22. ismear=0.get_potential_energy() except (VaspSubmitted. 5]. atoms. Atom(’O’. # make sure we relax the geometry nsw=10. xc=’PBE’.E_O2) 65 . magmom=-1)].get_potential_energy() except (VaspSubmitted.format(2*E_O . atoms=atoms) as calc: 10 11 12 13 try: 14 E_O = atoms. ismear=0. cell=(10. 5. magmom=1). [5. ispin=2. 10. E_O2): print ’O2 -> 2O D = {0:1. 5. [6. # turn spin-polarization on ibrion=2. VaspQueued): E_O = None 15 16 17 18 print ’Magnetic moment on O = {0} Bohr magnetons’.3f} eV’. ispin=2. VaspQueued): E_O2 = None 37 38 39 # verify magnetic moment print ’O2 molecule magnetic moment = ’. Also interesting is that the dissociation energy is almost equal to the experimental value.get_potential_energy()) Open the python script (dft-scripts/script-60. so the molecule is correct.format(atoms. This highlights a difficulty in computing magnetic moments: you provide an initial guess and a solution is found.01.py).9998232 Bohr magnetons O2 molecule magnetic moment = 0.get_potential_energy()) except (VaspSubmitted. Magnetic moment on O = 1.830101 eV triplet: -9. ismear=0. [0. even though we guessed an initial magnetic moment of 0.format(calc. encut=400. 10)) 23 24 25 26 27 28 29 30 31 32 33 with jasp(’molecules/O-square-box-center’. let us consider variations of a square box.Open the python script (dft-scripts/script-59.get_potential_energy()) 5 6 7 with jasp(’molecules/O2-sp-triplet’) as calc: print ’triplet: {0} eV’.01.0 O2 -> 2O D = 5.get_atoms(). and may reflect the fact that the singlet oxygen state is less stable than the triplet state. VaspQueued): 66 . atoms=atoms) as calc: try: print ’Square box (center): E = {0} eV’. magmom=2)].format(atoms. sigma=0. VASP still found a triplet spin state on the oxygen atom. Atoms 3 4 5 6 # square box origin atoms = Atoms([Atom(’O’.get_atoms(). 1 2 from jasp import * from ase import Atom. ispin=2. The magnetic moment of a singlet state is zero. ismear=0. We will examine the total energy of an oxygen atom in a few geometries. 10)) 7 8 9 10 11 12 13 14 15 16 17 18 with jasp(’molecules/O-square-box-origin’. 5. singlet: -8. 10. xc=’PBE’.get_potential_energy()) except (VaspSubmitted. 0. atoms=atoms) as calc: try: print ’Square box (origin): E = {0} eV’. xc=’PBE’. ispin=2. Estimating triplet oxygen dissociation energy with low symmetry It has been suggested that breaking spherical symmetry of the atom can result in lower energy of the atom. [5. 5]. encut=400. 10. 0]. cell=(10. First. Let us directly compare their total energies: 1 from jasp import * 2 3 4 with jasp(’molecules/O2-sp-singlet’) as calc: print ’singlet: {0} eV’. The symmetry is broken by putting the atom off-center in a box. magmom=2)]. sigma=0.848238 eV You can see here the triplet state has an energy that is 1 eV more stable than the singlet state. This is probably a coincidence. VaspQueued): pass 19 20 21 22 # square box center atoms = Atoms([Atom(’O’.py).650 eV Interestingly. cell=(10.format(calc. get_potential_energy()) except (VaspSubmitted.32. 10)) 24 25 26 27 28 29 30 31 32 33 34 35 with jasp(’molecules/O-orthorhombic-box-center’. 9. encut=400. The origin and center calculations are identical in energy. atoms=atoms) as calc: try: print ’Square box (random): E = {0} eV’. magmom=2)].format(atoms. Square box (origin): E = -1.01. atoms=atoms) as calc: try: print ’Orthorhombic box (center): E = {0} eV’. xc=’PBE’. magmom=2)]. encut=400.516623 eV Square box (center): E = -1.py). cell=(8.get_potential_energy()) except (VaspSubmitted. ismear=0.32. sigma=0.5. [0.11]. magmom=2)].get_potential_energy()) except (VaspSubmitted. ismear=0. 0]. cell=(8.format(atoms. sigma=0. Atoms 4 5 6 7 # orthorhombic box origin atoms = Atoms([Atom(’O’. VaspQueued): pass 20 21 22 23 # orthrhombic box center atoms = Atoms([Atom(’O’. VaspQueued): pass 36 37 38 39 # orthorhombic box random atoms = Atoms([Atom(’O’.01. 10.516623 eV Square box (random): E = -1. cell=(8. xc=’PBE’. 10)) 39 40 41 42 43 44 45 46 47 48 49 50 with jasp(’molecules/O-square-box-random’. magmom=2)]. 10)) 8 9 10 11 12 13 14 15 16 17 18 19 with jasp(’molecules/O-orthorhombic-box-origin’.13.515359 eV There is no significant difference in these energies. encut=400. ispin=2. sigma=0. let us consider some non-square boxes. xc=’PBE’.01. [4. 7. 0. atoms=atoms) as calc: try: print ’Orthorhombic box (origin): E = {0} eV’. sigma=0. The meV variation in the random calculation is negligible. 1. ispin=2. ismear=0. 10)) 40 41 42 43 44 45 with jasp(’molecules/O-orthorhombic-box-random’. 4. [2. [2. ispin=2.01. ismear=0. Now.34 pass 35 36 37 38 # square box random atoms = Atoms([Atom(’O’. 1. 67 . 9. 1 2 3 # calculate O atom energy in orthorhombic boxes from jasp import * from ase import Atom.11].13. xc=’PBE’. encut=400. 7. 5]. cell=(10. VaspQueued): pass Open the python script (dft-scripts/script-61.format(atoms. 9. 9. Magnetic moment on O = 2.01. Surprisingly.22. ispin=2.894124 eV Orthorhombic box (random): E = -1. 10. # make sure we relax the geometry nsw=10.get_potential_energy() print ’Magnetic moment on O = {0} Bohr except (VaspSubmitted. xc=’PBE’.py).4 eV. the "random" position is higher in energy. 5. sigma=0.get_magnetic_moment()) 19 20 21 22 23 # now relaxed O2 dimer atoms = Atoms([Atom(’O’.3f} eV’. VaspQueued): pass 50 51 Open the python script (dft-scripts/script-62.2. xc=’PBE’.get_potential_energy() # verify magnetic moment print ’Magnetic moment on O2 = {0} Bohr magnetons’.494285 eV This is a surprisingly large difference in energy! Nearly 0. magmom=2)]. encut=400. 5]. ismear=0.01. cell=(10. Atoms 3 4 5 atoms = Atoms([Atom(’O’. This is precisely the amount of energy we were in disagreement with the literature values. E_O print ’O2 -> 2O D = {0:1. We use a non-symmetric box for the O-atom. 10)) 24 25 26 27 28 29 30 31 32 33 34 35 36 37 with jasp(’molecules/O2-sp-triplet’. we put this all together. 4. 5. [6.format(atoms. [5.893571 O2 -> 2O D = 6. atoms=atoms) as calc: try: E_O = atoms.1. sigma=0. VaspQueued): E_O2 = None 41 42 43 44 if None not in (E_O.format(atoms.E_O2) Open the python script (dft-scripts/script-63.get_potential_energy()) except (VaspSubmitted. Finally. 6. magmom=1).8941 eV Orthorhombic box (center): E = -1.get_magnetic_moment()) 38 39 40 except (VaspSubmitted. atoms=atoms) as calc: try: E_O2 = atoms. Atom(’O’. similar to the cubic boxes.0000016 Bohr magnetons Magnetic moment on O2 = 2. encut=400.format(atoms. ismear=0.1]. 5].py). atoms=atoms) as calc: 46 47 48 try: 49 print ’Orthorhombic box (random): E = {0} eV’. [5. 1 2 from jasp import * from ase import Atom.0000084 Bohr magnetons E_O: -1.format(2 * E_O .ispin=2. # turn spin-polarization on ibrion=2.061 eV 68 . Orthorhombic box (origin): E = -1. cell=(8. E_O2): print ’E_O: ’. ispin=2. VaspQueued): E_O = None magnetons’. magmom=1)]. 10)) 6 7 8 9 10 11 12 13 14 15 16 17 18 with jasp(’molecules/O-sp-triplet-lowsym’. we get the lower energy for the O atom. Also note that this error is specific to there being a spherical atom in a symmetric cell.get_magnetic_moment() Open the python script (dft-scripts/script-64. 5]. atom in enumerate(atoms): print ’atom {0}: magmom = {1}’.5.119 eV In the following calculation. 10)) 6 7 with jasp(’molecules/O-sp-triplet-lowsym-sv’. the ENMIN in the POTCAR is very high! 1 grep ENMIN $VASP_PP_PATH/potpaw_PBE/O_sv/POTCAR Open the python script (dft-scripts/script-65. Note however. ENMIN = 1066. Verifying the magnetic moments on each atom It is one thing to see the total magnetic moment of a singlet state.get_magnetic_moments() 10 11 12 13 14 print ’singlet ground state’ for i. although still nearly an eV greater than the experimental dissociation energy. This is not a problem for most molecules. atom in enumerate(atoms): print ’atom {0}: magmom = {1}’.get_atoms() magmoms = atoms.clone(’molecules/O2-sp-triplet-magmoms’) 18 19 20 21 22 23 24 25 26 27 with jasp(’molecules/O2-sp-triplet-magmoms’) as calc: calc.get_atoms() magmoms = atoms. Here we try the O_sv potential. ENMAX = 1421. cell=(8. The moments are determined by a projection method that probably involves a spherical orbital.clone(’molecules/O2-sp-singlet-magmoms’) 5 6 7 8 9 with jasp(’molecules/O2-sp-singlet-magmoms’) as calc: calc. you will not see the error. 1 2 from jasp import * from ase import Atom. Note the atomic magnetic moments do not add up to the total magnetic moment. Note that with a different "random" position.get_magnetic_moments() print print ’triplet ground state’ for i. 69 .This actually agrees within 30-50 meV of reported literature values. if you do not need the dissociation energy in your analysis.format(i. magmoms[i]) print atoms. magmom=2)]. So. which treats the 1s electrons as valence electrons.get_magnetic_moment() 15 16 17 with jasp(’molecules/O2-sp-triplet’) as calc: calc. 9.py).493. magmoms[i]) print atoms. All the disagreement we had been seeing was apparently in the O atom energy.py). In VASP you must use LORBIT=11 to get the magnetic moments of the atoms written out. we let VASP select an appropriate ENCUT value. which are generally non-spherical. and another to ask what are the magnetic moments on each atom. so the moments may be over or underestimated. Atoms 3 4 5 atoms = Atoms([Atom(’O’.set(lorbit=11) atoms = calc. 4. Using a different potential It is possible we need a higher quality potential to get the 6.set(lorbit=11) atoms = calc.format(i. [4.02 eV value quoted by many in the literature. 1 from jasp import * 2 3 4 with jasp(’molecules/O2-sp-singlet’) as calc: calc. The atomic magnetic moments are not really true observable properties. Atom(’O’.get_magnetic_moment()) 20 21 22 23 24 # now relaxed O2 dimer atoms = Atoms([Atom(’O’. # make sure we relax the geometry nsw=10. ismear=0. we simply need to compute the total energy of each molecule in its equilibrium geometry. [5. [6.0000001 Bohr magnetons Magnetic moment on O2 = 1. 10)) 25 26 27 28 29 30 31 32 33 34 35 36 37 38 with jasp(’molecules/O2-sp-triplet-sv’. VaspQueued): E_O = None 16 17 18 19 print ’Magnetic moment on O = {0} Bohr magnetons’. since we let VASP choose the ENCUT value. Magnetic moment on O = 2.xc=’PBE’. It is possibly not converged.set_cell([8.3f} eV’. ∆E = ECO2 + EH2 − ECO − EH2 O For now. 8.299 eV This result is close to other reported values. In the next section we will add zero-point energies and compute the energy difference as a function of temperature. the point is that a harder potential does not fix the problem of overbinding in the O2 molecule. magmom=1)]. 8]. 3. sigma=0. These will automatically be at the coordinates from the G2 database. 10.get_potential_energy() except (VaspSubmitted. ispin=2. setups={’O’: ’_sv’}. 5].01. 5. xc=’PBE’.22. atoms=atoms) as calc: 8 9 10 11 12 13 14 try: 15 E_O = atoms.2 Water gas shift example We consider calculating the reaction energy of the water-gas shift reaction in this example.format(atoms. sigma=0. cell=(10.get_potential_energy() except (VaspSubmitted. we compute this energy simply as the difference in DFT energies. 1 2 from ase. and that value is the ENMIN value in the POTCAR.structure import molecule from jasp import * 3 4 # first we define our molecules. setups={’O’: ’_sv’}.E_O2) Open the python script (dft-scripts/script-66. magmom=1). CO + H2 O CO2 + H2 We define the reaction energy as the difference in energy between the products and reactants. 5].py).format(atoms.8. 5 6 7 CO = molecule(’CO’) CO. That is a fundamental flaw in the GGA exchange-correlation functional. ispin=2. atoms=atoms) as calc: try: E_O2 = atoms. # turn spin-polarization on ibrion=2. E_O2): print ’O2 -> 2O D = {0:1. 5.format(2*E_O . Nevertheless. ismear=0.01. scale_atoms=False) 8 9 H2O = molecule(’H2O’) 70 . For now. VaspQueued): E_O2 = None 39 40 41 # verify magnetic moment print ’Magnetic moment on O2 = {0} Bohr magnetons’.get_magnetic_moment()) 42 43 44 if None not in (E_O.9999996 Bohr magnetons O2 -> 2O D = 6. 8. ismear=0. VaspQueued): eH2 = None 54 55 56 57 58 59 60 61 62 63 64 65 with jasp(’molecules/wgs/H2O’. atoms=H2) as calc: try: eH2 = H2. Delta E = -0. nsw=10. scale_atoms=False) 14 15 16 H2 = molecule(’H2’) H2.3f} kcal/mol’.get_potential_energy() except (VaspSubmitted. ismear=0. 8.set_cell([8. atoms=CO) as calc: try: eCO = CO. such as zero-point and temperature corrections. In the next section we will examine whether additional corrections are needed. 71 . nsw=10.get_potential_energy() except (VaspSubmitted. scale_atoms=False) 11 12 13 CO2 = molecule(’CO2’) CO2.eH2O print ’Delta E = {0:1. ibrion=2.06035) print ’Delta E = {0:1. xc=’PBE’. ismear=0.eCO .get_potential_energy() except (VaspSubmitted. 8].py). ismear=0. eCO. xc=’PBE’. atoms=CO2) as calc: try: eCO2 = CO2. eH2. encut=350. eH2O): pass else: dE = eCO2 + eH2 . VaspQueued): eH2O = None 66 67 68 69 70 71 72 73 if None in (eCO2. which is a fair bit lower than we calculated here. ibrion=2. encut=350.format(dE * 96. nsw=10.514 kJ/mol We estimated the enthalpy of this reaction at standard conditions to be -41 kJ/mol using data from the NIST webbook.set_cell([8. 8].get_potential_energy() except (VaspSubmitted. scale_atoms=False) 17 18 19 20 21 22 23 24 25 26 27 28 29 # now the calculators to get the energies with jasp(’molecules/wgs/CO’.614 kcal/mol Delta E = -69. VaspQueued): eCO2 = None 42 43 44 45 46 47 48 49 50 51 52 53 with jasp(’molecules/wgs/H2’. ibrion=2. 8. 8]. xc=’PBE’. encut=350. encut=350.10 H2O.720 eV Delta E = -16.485) Open the python script (dft-scripts/script-67. xc=’PBE’.3f} eV’. atoms=H2O) as calc: try: eH2O = H2O.set_cell([8. nsw=10.format(dE) print ’Delta E = {0:1.3f} kJ/mol’. ibrion=2. VaspQueued): eCO = None 30 31 32 33 34 35 36 37 38 39 40 41 with jasp(’molecules/wgs/CO2’.format(dE * 23. Inspection of these results shows the geometries were all relaxed.beta.alpha.000 a.e.000 8.000 -0.000] 8.0 90.789536 eV Unit cell vectors (angstroms) x y z length a0 [ 8.It is a good idea to verify your calculations and structures are what you expected..y.000 0.z]tag rmsForce constraints 0 O [0.000 Ang^3 Stress (GPa):xx.05 eV/Å.000 8.000 0. 1 from jasp import * 2 3 4 5 6 7 8 print ’**** Calculation summaries’ print ’***** CO’ with jasp(’molecules/wgs/CO’) as calc: print ’#+begin_example’ print calc print ’#+end_example’ 9 10 11 12 13 14 print ’***** CO2’ with jasp(’molecules/wgs/CO2’) as calc: print ’#+begin_example’ print calc print ’#+end_example’ 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 print ’***** H2O’ with jasp(’molecules/wgs/H2O’) as calc: print ’#+begin_example’ print calc print ’#+end_example’ Open the python script (dft-scripts/script-68.gamma (deg):8. yz.346] 0 0.0 90.000 a2 [ 0.000] 8.000 0. Let us print them here. xy 0.000 8.005 0.01 T T T 1 C [0.490] 0 0.py).0 Unit cell volume = 512. i.000] 8.000 90.000 a1 [ 0.c. yy.000 0.000 7. Calculation summaries CO : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/molecules/wgs/CO converged: True Energy = -14.000 -0.000 8.01 T T T -------------------------------------------------INCAR Parameters: ----------------nbands: 9 ismear: 0 nsw: 10 72 .000 Atom# sym position [x. zz.000 0.000 0.005 0.000 0. xz.005-0.b. the forces on each atom are less than 0. z]tag rmsForce constraints 0 C [0.gamma (deg):8. 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.alpha.0 Unit cell volume = 512.959572 eV Unit cell vectors (angstroms) x y z length a0 [ 8.000 8. 1.000 Atom# sym position [x.823] 0 0.009 0. zz.000 0. xy 0.01 T T T -------------------------------------------------INCAR Parameters: ----------------nbands: 12 ismear: 0 nsw: 10 ibrion: 2 encut: 350.000 -0.y.000] 8.000 0.000 8.000 8.b.000 8.beta.000] 0 0.000 -0.0 None Normal [1.000 0.000 90.01 T T T 2 O [0.0 magmom: None prec: Normal kpts: [1.000 Ang^3 Stress (GPa):xx.000 0.0 90.000 a.000] 8. xz.000 0.0 90.000 6.000 0.00 T T T 1 O [0.009 0.000 0.000 0.c.ibrion: encut: magmom: prec: kpts: reciprocal: xc: txt: gamma: 2 350.008-0. yz. 1] reciprocal: False xc: PBE txt: gamma: False Pseudopotentials used: 73 .000 1.000 a2 [ 0. yy.000] 8. 1.000 a1 [ 0.177] 0 0. 0 magmom: None prec: Normal kpts: [1.000 8.000 90.000 0.00 T T T 1 H [0. 1.000 8. yy.0 90.00 T T T -------------------------------------------------INCAR Parameters: ----------------nbands: 5 ismear: 0 nsw: 10 ibrion: 2 encut: 350.beta.0 90.000-0.alpha.000] 8.000] 8.744001 eV Unit cell vectors (angstroms) x y z length a0 [ 8.000 0.y.000 8.000 0.0 Unit cell volume = 512. 1] reciprocal: False xc: PBE txt: gamma: False Pseudopotentials used: ---------------------H: potpaw_PBE/H/POTCAR (git-hash: fbc0773b08b32f553234b0b50cc6ad6f5085c816) H2O : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/molecules/wgs/H2O converged: True Energy = -14. xz.000 7.c.000 8.000 Ang^3 Stress (GPa):xx.000 Atom# sym position [x.624] 0 0.000 a1 [ 0.b. zz.000 0.000 0.000 a2 [ 0.gamma (deg):8.000 a.000 0. xy 0.000] 8.z]tag rmsForce constraints 0 H [0.193569 eV Unit cell vectors (angstroms) x y z length 74 .000 0.000 0.000 -0.376] 0 0.---------------------C: potpaw_PBE/C/POTCAR (git-hash: 2272d6745da89a3d872983542cef1d18750fc952) O: potpaw_PBE/O/POTCAR (git-hash: 9a0489b46120b0cad515d935f44b5fbe3a3b1dfa) H2 : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/molecules/wgs/H2 converged: True Energy = -6. yz.000 -0.000 0. First we do each vibrational calculation.000 Atom# sym position [x.000 8. encut=350. We will break these calculations into several pieces.234 7. After those are done. 1.0 Unit cell volume = 512.c.000 Ang^3 Stress (GPa):xx.000 -0.004 0.8. CO vibrations 1 from jasp import * 2 3 4 5 # get relaxed geometry with jasp(’molecules/wgs/CO’) as calc: CO = calc. yz.000 0.000 8. potim=0.y.005 0.000 7.z]tag rmsForce constraints 0 O [0. 1] reciprocal: False xc: PBE txt: gamma: False Pseudopotentials used: ---------------------H: potpaw_PBE/H/POTCAR (git-hash: fbc0773b08b32f553234b0b50cc6ad6f5085c816) O: potpaw_PBE/O/POTCAR (git-hash: 9a0489b46120b0cad515d935f44b5fbe3a3b1dfa) 3.000 90.0 90. xz. 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). xy 0.000] 8.000 a2 [ 0.0 90.000 -0. nfree=2.000 8.000 a1 [ 0. nsw=1.000 8.b.06 T T T 1 H [0.gamma (deg):8. yy.alpha.000] 8.000 0.000 0. and estimate the temperature dependent contributions to vibrational energy and entropy.02.522] 0 0. ibrion=6.766 7.522] 0 0.000 0.122] 0 0.000 0. xc=’PBE’.3 Temperature dependent water gas shift equilibrium constant To correct the reaction energy for temperature effects.04 T T T 2 H [0. ismear=0. we must compute the vibrational frequencies of each species.0 magmom: None prec: Normal kpts: [1.beta. zz.000 0.000] 8.005-0.get_atoms() 6 7 8 9 10 11 12 13 14 15 # now do the vibrations with jasp(’molecules/wgs/CO-vib’.000 a.a0 [ 8.000 0. 75 .04 T T T -------------------------------------------------INCAR Parameters: ----------------nbands: 8 ismear: 0 nsw: 10 ibrion: 2 encut: 350. 594878 cm^(-1) (0. H2 vibrations 1 from jasp import * 2 3 4 # get relaxed geometry with jasp(’molecules/wgs/H2’) as calc: 76 .987178+0j) cm^(-1) (17.5 = 1). 00: 01: 02: 03: 04: 05: 2115.700411+0j) cm^(-1) CO2 is a linear molecule with 3N-5 = 4 vibrational modes.calculate() vib_freq = calc.344306+0j) cm^(-1) (1. nfree=2. potim=0. The other 5 modes are 3 translations and 2 rotations.594878 cm^(-1) 60.16 17 18 19 20 atoms=CO) as calc: calc. encut=350. ismear=0.format(i.py).689504 cm^(-1) 635. 00: 01: 02: 03: 04: 05: 06: 07: 08: 2352.calculate() vib_freq = calc.015913 cm^(-1) 635.763867+0j) cm^(-1) (1.py). f in enumerate(vib_freq): print ’{0:02d}: {1} cm^(-1)’. nsw=1.700411+0j) cm^(-1) (62.get_atoms() 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # now do the vibrations with jasp(’molecules/wgs/CO2-vib’. ibrion=6.get_vibrational_frequencies() for i. atoms=CO2) as calc: calc.get_vibrational_frequencies() for i. They are the first four frequencies in the output above.958586+0j) cm^(-1) (17. xc=’PBE’.format(i.02.958586+0j) cm^(-1) CO has only one vibrational mode (3N-5 = 6 .763867+0j) cm^(-1) (62.901285 cm^(-1) 1316. f in enumerate(vib_freq): print ’{0:02d}: {1} cm^(-1)’. CO2 vibrations 1 from jasp import * 2 3 4 5 # get relaxed geometry with jasp(’molecules/wgs/CO2’) as calc: CO2 = calc.528894 cm^(-1) 60.015913 cm^(-1) (0.f) Open the python script (dft-scripts/script-69. f) Open the python script (dft-scripts/script-70. 0 cm^(-1) 0.286732+0j) cm^(-1) Water has 3N-6 = 3 vibrational modes. encut=350. nsw=1. ismear=0. f) Open the python script (dft-scripts/script-72.23055 cm^(-1) 135.get_vibrational_frequencies() for i.5 H2 = calc.0 cm^(-1) (1e-05+0j) cm^(-1) There is only one frequency of importance (the one at 4281 cm−1 ) for the linear H2 molecule.format(i.280411 cm^(-1) (0.format(i.062213 cm^(-1) 3672.146855 cm^(-1) 0.get_atoms() 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # now do the vibrations with jasp(’molecules/wgs/H2-vib’.1246 cm^(-1) 1586.calculate() vib_freq = calc.py).869518+0j) cm^(-1) (131. f in enumerate(vib_freq): print ’{0:02d}: {1} cm^(-1)’. xc=’PBE’.get_atoms() 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # now do the vibrations with jasp(’molecules/wgs/H2O-vib’. atoms=H2O) as calc: calc. nfree=2. atoms=H2) as calc: calc. 00: 01: 02: 03: 04: 05: 06: 07: 08: 3782.208582+0j) cm^(-1) (26. encut=350. potim=0.py).calculate() vib_freq = calc. nsw=1.02. ibrion=6. xc=’PBE’. ibrion=6.get_vibrational_frequencies() for i. H2 O vibrations 1 from jasp import * 2 3 4 5 # get relaxed geometry with jasp(’molecules/wgs/H2O’) as calc: H2O = calc. f in enumerate(vib_freq): print ’{0:02d}: {1} cm^(-1)’.917749 cm^(-1) 129.82763 cm^(-1) 16.02.146855 cm^(-1) 129. 77 . ismear=0. potim=0.297061+0j) cm^(-1) (106. nfree=2. f) Open the python script (dft-scripts/script-71. 00: 01: 02: 03: 04: 05: 4281. get_vibrational_frequencies() CO2_vib_energies = [h * c * nu for nu in vib_freq] 34 35 36 37 with jasp(’molecules/wgs/H2-vib’) as calc: vib_freq = calc. geometry=’linear’.get_atoms() E_CO2 = CO2.get_potential_energy() 10 11 12 13 with jasp(’molecules/wgs/CO2’) as calc: CO2 = calc. electronicenergy=E_H2O.get_vibrational_frequencies() H2O_vib_energies = [h * c * nu for nu in vib_freq] 42 43 44 45 46 47 # now we make a thermo object for each molecule CO_t = IdealGasThermo(vib_energies=CO_vib_energies[0:0]. spin=0) 48 49 50 51 52 CO2_t = IdealGasThermo(vib_energies=CO2_vib_energies[0:4]. atoms=H2.get_free_energy(temperature=T. electronicenergy=E_H2.get_vibrational_frequencies() CO_vib_energies = [h * c * nu for nu in vib_freq] 30 31 32 33 with jasp(’molecules/wgs/CO2-vib’) as calc: vib_freq = calc. geometry=’linear’. 20) # K P = 101325.pyplot as plt 5 6 7 8 9 # first we get the electronic energies with jasp(’molecules/wgs/CO’) as calc: CO = calc.CO_t. pressure=P) . pressure=P) + H2_t.thermochemistry import IdealGasThermo from jasp import * import numpy as np import matplotlib. 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. electronicenergy=E_CO. atoms=CO2. symmetrynumber=2.linspace(298. 1 2 3 4 from ase.H2O_t. geometry=’linear’.Thermochemistry Now we are ready.1356675e-15 # eV * s c = 3. electronicenergy=E_CO2. spin=0) 58 59 60 61 62 H2O_t = IdealGasThermo(vib_energies=H2O_vib_energies[0:3].0e10 # cm / s 26 27 28 29 with jasp(’molecules/wgs/CO-vib’) as calc: vib_freq = calc. symmetrynumber=1.get_free_energy(temperature=T.get_vibrational_frequencies() H2_vib_energies = [h * c * nu for nu in vib_freq] 38 39 40 41 with jasp(’molecules/wgs/H2O-vib’) as calc: vib_freq = calc. 1000.get_free_energy(temperature=T. atoms=CO. atoms=H2O.get_potential_energy() 14 15 16 17 with jasp(’molecules/wgs/H2’) as calc: H2 = calc. symmetrynumber=2.get_enthalpy(temperature=T) + H2_t. # Pa Grxn = np.get_atoms() E_H2 = H2. pressure=P)) * 96.485 for T in Trange]) 71 72 73 74 Hrxn = np.get_free_energy(temperature=T. pressure=P) .get_potential_energy() 18 19 20 21 with jasp(’molecules/wgs/H2O’) as calc: H2O = calc. geometry=’nonlinear’.get_enthalpy(temperature=T) .get_atoms() E_CO = CO. We have the electronic energies and vibrational frequencies of each species in the reaction.get_potential_energy() 22 23 24 25 # now we get the vibrational energies h = 4. symmetrynumber=2.get_enthalpy(temperature=T) 78 . spin=0) 53 54 55 56 57 H2_t = IdealGasThermo(vib_energies=H2_vib_energies[0:0].array([(CO2_t.array([(CO2_t.H2O_t.get_atoms() E_H2O = H2O. the Gibbs free energy is about -75 kJ/mol. You can see a few things here.plot(Trange. significantly overestimating it. This is too negative compared to the experimental standard free energy.savefig(’images/wgs-dG-T. label=’$\Delta G_{rxn}$’) plt. 100]) plt.png’) 84 85 86 plt.485 for T in Trange]) 75 76 77 78 79 80 81 82 83 plt.314e-3 # gas constant in kJ/mol/K 87 88 89 90 91 92 93 94 Keq = np.figure() R = 8.show() Open the python script (dft-scripts/script-73. but the most likely one is errors in the exchange-correlation functional.xlabel(’Temperature (K)’) plt.xlabel(’Temperature (K)’) plt. Keq) plt. 79 .ylim([0. ’bo-’.plot(Trange.CO_t. ’ro:’. label=’$\Delta H_{rxn}$’) plt.savefig(’images/wgs-Keq.ylabel(’$K_{eq}$’) plt. which we estimated to be about -29 kJ/mol from the NIST webbook.png’) plt.plot(Trange.ylabel(r’$\Delta G_{rxn}$ (kJ/mol)’) plt.legend(loc=’best’) plt. The error in energy has a significant effect on the calculated equilibrium constant. Figure 22: Thermodynamic energies of the water gas shift reaction as a function of temperature. Hrxn.exp(-Grxn/R/Trange) plt. There could be several reasons for this disagreement.get_enthalpy(temperature=T)) * 96. Grxn. One is that at near 298K..py). positions[0] 13 14 15 16 # move N to origin atoms.data. but other algorithms for finding barriers (saddle-points) exist that may be relevant. The NEB class of methods are pretty standard.atom in enumerate(atoms2): if atom. we use the NEB method 48 to compute the barrier to inversion.constraints import FixAtoms 7 8 9 10 atoms = molecule(’NH3’) constraint = FixAtoms(mask=[atom. 3.molecules import molecule import numpy as np from jasp import * from ase.1 1 2 3 4 5 6 Get initial and final states # compute initial and final states from ase import Atoms from ase.set_cell((10.9. Then. We have to create an NH3 molecule in the initial and inverted state (these have exactly the same energy).symbol == ’N’ for atom in atoms]) atoms. 10.symbol == ’H’: 80 .positions 20 21 22 for i.Figure 23: Temperature dependence of the equilibrium constant.9 Molecular reaction barriers We will consider a simple example of the barrier for NH3 inversion. 10).translate(-Npos) atoms. scale_atoms=False) 17 18 19 atoms2 = atoms.set_constraint(constraint) 11 12 Npos = atoms.copy() pos2 = atoms2. 49 3. and then interpolate a band of images. 1 2 3 # Run NH3 NEB calculations from jasp import * from ase. VaspQueued): pass Open the python script (dft-scripts/script-74. encut=350.neb import NEB 4 5 6 with jasp(’molecules/nh3-initial’) as calc: atoms = calc.9.2 Run band calculation Now we do the band calculation.DEBUG. VaspQueued): pass 41 42 43 44 45 46 47 48 49 50 51 with jasp(’molecules/nh3-final’.get_atoms() 10 11 12 13 14 # 5 images including endpoints images = [atoms] images += [atoms. atoms=images) as calc: images.get_neb() 26 27 28 29 30 calc.get_atoms() 7 8 9 with jasp(’molecules/nh3-final’) as calc: atoms2 = calc. nsw=90.py).array([1.png’) plt.23 24 25 # reflect through z pos2[i] *= np. debug=logging. xc=’PBE’.translate([5. 5. atoms=atoms2) as calc: try: calc. 3.positions = pos2 26 27 28 29 #now move N to center of box atoms. 81 . nsw=10.calculate() except (VaspSubmitted. encut=350. ibrion=1.savefig(’images/nh3-neb. -1]) atoms2. atoms=atoms) as calc: try: calc. 5]) atoms2.calculate() except (VaspSubmitted. nsw=10. ibrion=1. 5]) 30 31 32 33 34 35 36 37 38 39 40 with jasp(’molecules/nh3-initial’.show() Open the python script (dft-scripts/script-75. xc=’PBE’.interpolate() 18 19 20 21 22 23 24 25 with jasp(’molecules/nh3-neb’.pyplot as plt plt. spring=-5. xc=’PBE’. energies = calc.translate([5.py).copy() for i in range(3)] images += [atoms2] 15 16 17 neb = NEB(images) neb.plot_neb(show=False) import matplotlib. 1. ibrion=1. 5. Here.pdf for a very informative comparison of DFT codes for computing different bulk properties. fcc Ag.lattice.Figure 24: Nudged elastic band results for ammonia flipping. 82 .lattice.1 Defining and visualizing bulk systems Built-in functions in ase As with molecules.Graphite • mod:ase.dtu.BodyCenteredCubic • mod:ase.org/pdf/1204.lattice.1. mod:ase knows Ag is an fcc metal.cubic.2733.compounds. By default. 4 Bulk systems See http://arxiv. We have to specify the directions (vectors along each axis) to get something other than the default output. mod:ase provides several helper functions to create bulk structures. see https://wiki.html We start with a simple example.lattice. We highlight a few of them here. and knows the experimental lattice constant.1 4.fysik.dk/ase/ase/lattice.NaCl For others. Particularly common ones are: • mod:ase.cubic. the default fcc cell contains four atoms. 4.FaceCenteredCubic • mod:ase.hexagonal. show_unit_cell=2) Open the python script (dft-scripts/script-78. 1]. atoms. 0.png’.io import write from ase. 0]]) 7 8 write(’images/Ag-fcc-primitive.lattice. Lattice(symbols=’Ag’. 0.symbol = ’Pd’ write(’images/AgPd-bulk.4460333675264898. Here we examine an Ag3 Pd alloy structure. 1 2 from ase. The basic strategy is to create the base unit cell in one element and then selectively change some atoms to different chemical symbols.0]. 0].5046 We can use these modules to build alloy unit cells.atoms. 1. [0. 1 2 from ase.lattice. 4.892066735052979. Here we specify the primitive unit cell.png’. 1.py).. [1. atoms. show_unit_cell=2) 7 8 print atoms Open the python script (dft-scripts/script-76.09. directions=[[0. 0].0..cubic import FaceCenteredCubic 3 4 5 6 7 8 9 atoms = FaceCenteredCubic(directions=[[1. 1].bravais.png’. [0. True]) Note: A mod:ase.cubic import FaceCenteredCubic 3 4 atoms = FaceCenteredCubic(’Ag’) 5 6 write(’images/Ag-fcc. True.1 2 from ase. Lattice(symbols=’Ag4’.png’. 1]].lattice. which only has one atom in it.io import write from ase. 1. 1). 0. show_unit_cell=2) 9 10 print atoms Open the python script (dft-scripts/script-77. 83 .Atoms object.09].. show_unit_cell=2) 12 13 14 15 # to make an alloy.Lattice object is returned! This is practically the same as as an mod:ase.lattice. cell=[4. atoms.io import write from ase. size=(1. symbol=’Ag’..py).cubic import FaceCenteredCubic 3 4 5 6 atoms = FaceCenteredCubic(’Ag’.. [1.0) 10 11 write(’images/Ag-bulk. 1. 2. pbc=[True. [1. 4.. positions=. we can replace one atom with another kind atoms[0]. cell=[[2.09. latticeconstant=4. 0.py). atoms. 0. positions=. Figure 25: A simple fcc Ag bulk structure in the primitive unit cell. 84 . Figure 27: A simple fcc Ag bulk structure in the traditional unit cell. To create a graphite structure we use the following code.png’. show_unit_cell=2) 85 . 2. atoms.7079}) write(’images/graphite.png’.Figure 26: A simple fcc Ag bulk structure in the primitive unit cell. Figure 28: A simple Ag3 Pd bulk structure.edu/~asmith/NewATOMS/HOPG. 2.ohiou.io import write 3 4 5 6 7 8 atoms = Graphite(’C’. 1 2 from ase.repeat((2.phy. 1)).lattice. ’c’: 6.pdf) because mod:ase has C in the diamond structure by default. because the top view does not show the spacing between the layers. latticeconstant={’a’: 2.repeat((2.hexagonal import Graphite from ase. atoms. 1)). rotation=’115x’.4612. show_unit_cell=2) 9 10 11 12 write(’images/graphite-top. Note that we have to specify the lattice constants (taken from http://www. We show two views. 65) write(’images/NaCl. To get a compound.05 al = crystal(’Al’.py).org/wiki/Sodium_chloride). b. beta.45z’) Open the python script (dft-scripts/script-80. alpha.Open the python script (dft-scripts/script-79.io import write 3 4 5 atoms = NaCl([’Na’. 90. atoms. a. 90]) print(al) 86 . Chemical symbols 2. ’Cl’].png’. we use the following code. c. 90. Coordinates of the non-equivalent sites in the unit cell 3. spacegroup=225. 0)]. latticeconstant=5. [(0.wikipedia.compounds import NaCl from ase. rotation=’45x. mod:ase. gamma) 1 2 3 4 5 6 7 from ase.lattice. Figure 29: A top view of graphite. This is a concise way to setup structures if you know the following properties of the crystal structure: 1. show_unit_cell=2. For NaCl we use the lattice constant at (http: //en. cellpar=[a. 0. the spacegroup 4. a. and the lattice constant.45y.py). We have to specify the basis atoms to the function generating the compound. 1 2 from ase. the cell parameters (a.spacegroup import crystal # FCC aluminum a = 4.lattice.spacegroup.spacegroup A final alternative to setting up bulk structures is mod:ase. 6. cell=[[4. (0.4 Here is rutile TiO2 . [2.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 . .spacegroup import crystal 2 3 4 5 6 7 a = 4. unit cell formula. Atoms(symbols=’Al4’. 90.. 0.0]. For example.0].80 4. You can search for materials with lots of different criteria including formula. 0..py). positions=. z’ ’P 1’ 3. 1 2 3 4 5 6 7 8 9 10 11 12 #\#CIF1.6 c = 2. [2.0 ’Generated by pymatgen’ 1 RuO2 ’Ru2 O4’ 64. basis=[(0. 4. The website allows you to download the VASP files used to create the calculations. [1. You must sign up for an account at the website. cell=[[4.0 90. CIF has been adopted by the International # Union of Crystallography as the standard for data archiving and # transmission. 90.1 ########################################################################## # Crystallographic Information Format file # Produced by PyCifRW module # # This is a CIF file. by structure. I downloaded this cif file for a RuO2 structure (Material ID 825).0].05. 0.0.05. 0).0.0]. 0. They also develop the pymatgen project (which requires python 2. positions=.org The Materials Project offers web access to a pretty large number of materials (over 21..6. 0. follow the CIF links at # http://www.13970109 4. 0. 0..2 Using http://materialsproject. etc...0)]. spacegroup=136.5436378 90.py).7+).4799097682733903e-16.3. c. 90]) print rutile Open the python script (dft-scripts/script-82.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.5436378 4.1. 0. # # For information on this file format.000 at the time of this writing). 4. [2. a. and then you can access the information. by elements. including structure and other computed properties.0 90.95 rutile = crystal([’Ti’.lattice. .816687638038912e-16. cellpar=[a. Atoms(symbols=’Ti2O4’.iucr.Open the python script (dft-scripts/script-81. y.3. 0. 1 from ase. ’O’]. 000000 0. 1 Ru Ru6 1 0. 1 O O2 1 0.000000 0.b.io import read.000 0.194330 0 .py). atoms.137 a1 [ 0. and now we can run a calculation like this: 1 from jasp import * 2 3 4 5 6 7 with jasp(’bulk/Ru2O4’. Figure 32: An RuO2 unit cell prepared from a cif file.137 0.000 0.io. setups={’Ru’: ’_pv’}) as calc: calc. POSCAR. : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/bulk/Ru2O4 converged: True Energy = -44.000000 0 .beta.137 4.000] 4.500000 0.305670 0 . 1 O O3 1 0. 1 from ase.694330 0. write 2 3 atoms = read(’bulk/Ru2O4_1.541 90.500000 0.py).194330 0. That function automatically recognizes the file type by the extension. show_unit_cell=2) Open the python script (dft-scripts/script-84.0 88 . We can read this file in with func:ase.0 90.541 a2 [ 0.541 a. I have copied these files (INCAR. 1 Open the python script (dft-scripts/script-83.541 0. 1 O O4 1 0.0 90.gamma (deg):3. KPOINTS) to a directory (bulk/Ru2O4).541] 4.305670 0.500000 0.000 4. xc=’PBE’.000] 3.000000 0.c.42 43 44 45 46 47 48 _atom_site_occupancy O O1 1 0.000000 0.805670 0.500000 0 .alpha. 1 Ru Ru5 1 0. You can also download the VASP files.000 4.500000 0.png’.read.302690 eV Unit cell vectors (angstroms) x y z length a0 [ 3.694330 0 .541 4.cif’) 4 5 write(’images/Ru2O4.calculate() print calc Open the python script (dft-scripts/script-85.805670 0 .py). 569 0.388 1. since those were not defaults either.882] 0 0.569 3.0003 lwave: True magmom: [0.002 -0. Or we can gain a little confidence that our version of VASP is working like the one they used.00 T T 1 Ru [0.00 T T -------------------------------------------------- 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. or to plot some interesting electronic structure. we could use this as a starting point to look at an equation of state.00 T T 4 O [0. yz.00 T T 5 O [1. 0.z]tag rmsForce constraints 0 Ru [1.153 3.0 sigma: 0. We also had to specify the special setups used.6. We get exactly the same result as the website! Why is this helpful then? Well. That is good habit.6] prec: Normal algo: Fast lreal: Auto kpts: [8. xy -0. 0.000 0.000 -0.000 -0.153] 0 0.388] 0 0.y.000 Atom# sym position [x. 0.694 Ang^3 Stress (GPa):xx. . .000-0. yy.270 2.6.6.6.569 2.Unit cell volume = 64. 6. zz.659] 0 0.000 3.2 ediff: 0.000 -0. since the default may be something else. 89 .659 0.00 T T 2 O [0.000] 0 0.000 0. 0.270] 0 0. etc.6.882 3.000 1. 0.00 T T 3 O [1. 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. xz. Hence. the number of k-points required becomes smaller. we learned that the total energy is a function of the planewave cutoff energy (ENCUT) used.xlabel(’number of k-points in each dimension’) plt. Another less commonly used scheme is the Chadi-Cohen k-point grid. For example. and the k-point grid is where the property is sampled for the integration. and dense (high numbers of k-points) otherwise. We will typically use a Monkhorst-Pack 28 k-point grid.py). the k-point grid.show() Open the python script (dft-scripts/script-86.pyplot as plt 26 27 28 29 # consider the change in energy from lowest energy state TE = np. if a 1 × 1 × 1 fcc unit cell shows converged energies in a 12 × 12 × 12 k-point grid.get_potential_energy()) except (VaspSubmitted. There is also another calculation parameter you must consider. It is important to check for convergence in these cases. Below we consider the k-point convergence of fcc Ag. the electron density. we need at least a 6 × 6 × 6 k-point grid to achieve a convergence level of at least 50 meV. In bulk systems that is true also. 4. # specifies the Monkhorst-Pack grid encut=300. Note: the k-point convergence is not always monotonic like it is in this example.2 4. VaspQueued): ready = False 21 22 23 if not ready: import sys.array(TE) TE -= TE.plot(KPTS.1 Computational parameters that are important for bulk structures k-point convergence In the section on molecules. xc=’PBE’. 8. so a calculation on a 4 × 4 × 4 grid will be roughly 8 times more expensive than on a 2 × 2 × 2 grid.g.format(k). and it can be difficult to get high levels of convergence. up to 20 × 20 × 20) are needed for highly converged properties such as the density of states in smaller unit cells. 5.exit() 24 25 import matplotlib.ylabel(’Total Energy (eV)’) plt. 27 The Monkhorst-Pack grids are specified as n1 × n2 × n3 grids. The computational cost is linear in the total number of k-points. The higher the number of sampled points.lattice. 3. k.4. kpts=(k. Based on this figure.2. one seeks again to balance convergence with computational tractability.e. then a 2 × 2 × 2 fcc unit cell would 90 . the more accurately the integrals are approximated.cubic import FaceCenteredCubic from jasp import * 3 4 atoms = FaceCenteredCubic(’Ag’) 5 6 KPTS = [2. 6.png’) plt. and the total number of k-points is n1 · n2 · n3. The integration is performed in reciprocal space (i. sys. The k-point grid is a computational tool used to approximate integrals of some property. 10] 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}’. The best practices are to use the same k-point sampling grid in energy differences where possible.g.savefig(’images/Ag-kpt-convergence. 1 2 from ase.min() 30 31 32 33 34 35 plt. and sometimes very dense grids (e. in the Brillouin zone) for convenience and efficiency. over the entire unit cell. k). TE) plt. Oscillations in the total energy are typical. atoms=atoms) as calc: try: TE.append(atoms. As unit cells get larger. e. which is essentially a uniformly spaced grid in the Brillouin zone. 0. It is preferable that the occupancy of several of the highest bands be zero (or at least of order 1 × 10−8 ) to ensure enough variational freedom was available in the calculation.format(sigma). A 2 × 2 × 2 fcc unit cell has eight atoms in it. as if they were occupied at a higher temperature where partial occupation is possible. 1 2 3 from jasp import * from ase import Atom. we would need either a 9 × 9 × 9 or 10 × 10 × 10 k-point grid to get a similar level of accuracy. 0. we used a 6 × 6 × 6 k-point grid on a unit cell with four atoms in it. If we had instead used the primitive unit cell.pyplot as plt 4 5 6 7 8 9 a = 3.2. 1.0]. ismear=-1. Obviously. 4.show the same level of convergence with a 6 × 6 × 6 k-point grid. kpts=(4. 0))].5 * a * np.125 reciprocal atoms.2.0. xc=’PBE’.1. 1. 0. as this will add computational time. In this case. a band is either occupied or empty.0. 4).05. sigma=sigma. 0. 0. Standard values for metallic systems is SIGMA=0.0. 0. In other words. or 216/0. and dramatically increases the rate of convergence. Below we show the effect of SIGMA on the band occupancies.61 atoms = Atoms([Atom(’Cu’. so a 6 × 6 × 6 k-point grid has 216 k-points in it.0. the number of extra bands depends on the temperature used. 2. nbands=9 * 8.001. encut=350.0. The smearing methods were designed for metals.array([[1. In the k-point convergence example above. For molecules.2 Effect of SIGMA In the self-consistent cycle of a DFT calculation. atoms=atoms) as calc: e = atoms. (0. but the best SIGMA may be material specific.repeat((2. it should be determined that enough bands were used by examination of the occupancies. An example of the maximum occupancies of the bands for an Cu bulk as a function of SIGMA is shown in Figure 34. cell=0. or 0. SIGMA and ISMEAR affect how the partial occupancies of the bands are determined. [1. In any case. Atoms import matplotlib.01).get_potential_energy() 24 91 . leading to 864 k-points per reciprocal atom. 0.5] 12 13 for sigma in SIGMA: 14 15 16 17 18 19 20 21 22 23 with jasp(’bulk/Cu-sigma-{0}’.1. which makes it difficult to converge. This results in a continuous dependence of energy on the partial occupancy. semiconductors and insulators you should use a very small SIGMA (e. One solution is to artificially broaden the band occupancies.0]. Consequently. the same as we discussed before. there is no exact matching of k-point grids due to the difference in shape of the cells.20. the occupancy approaches a step function. At absolute zero.0]])). 0. a 12×12×12 k-point grid for a primitive fcc unit cell would be 1728 k-points per reciprocal atom. This discrete occupation results in discontinuous changes in energy with changes in occupation. 1. 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. it is suggested that fifteen to twenty extra bands be used for a SIGMA of 0. 4. 0. 2. [0.g. 2)) 10 11 SIGMA = [0. 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. as SIGMA approaches 0.125 = 1728 k-points per reciprocal atom. the total energy is minimized with respect to occupation of the Kohn-Sham orbitals. Some rules to keep in mind: 1. 1. For example. It is undesirable to have too many extra bands. ylabel(’maximum occupancy (electrons)’) plt.nbands nkpts = len(calc. so the minimum number of bands is int(ceil(nelectrons/2)).:] = calc. | | | ----------------------------------------------------------------------------We tell VASP the number of bands to use with the incar:NBANDS keyword. 4.get_ibz_k_points()) 25 26 27 occ = np. 2. There absolutely must be enough bands to accommodate all the electrons.01733) | | 14 (-0..01838) | | | | The total occupancy of band no... 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. 49 is -0. but this is in general bad practice (even though it is often done in this book!).py). and the higher the incar:SIGMA value is.format(sigma)) 34 35 36 37 38 39 40 41 plt.axis=0) #axis 0 is columns 32 33 plt.3 The number of bands In the last figure. 92 ...get_occupation_numbers(kpt=i) 28 29 30 31 max_occ = np. the more bands you need.legend(loc=’best’) plt. nbands)) for i in range(nkpts): occ[i. without | | unoccupied bands.max(occ. and helps to suppress ’band-crossings. You need enough bands so that the highest energy bands are unoccupied.01413) | | 13 (-0. and VASP will give you a warning that looks like this: ----------------------------------------------------------------------------| | | ADVICE TO THIS USER RUNNING ’VASP/VAMP’ (HEAR YOUR MASTER’S VOICE . label=’$\sigma = {0}$’.zeros((nkpts. | | Because the presence of unoccupied bands improves wavefunction | | prediction.png’) plt.savefig(’images/occ-sigma. or one electron per band for a spin-polarized calculation (note that spin-polarization doubles the number of bands).01472) | | 8 (-0.00932 electrons .xlabel(’band number’) plt.plot(range(nbands). : | | | | 6 (-0.show() Open the python script (dft-scripts/script-87. 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 one spin down) in an calculation without spin-polarization.): | | | | Your highest band is occupied at some k-points! Unless you are | | performing a calculation for an insulator or semiconductor. It is always recommended to | | include a few unoccupied bands to accelerate the convergence of | | molecular dynamics runs (even for insulators or semiconductors).1]) plt..1.ylim([-0. 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.2. max_occ. VASP will set the NBANDS automatically if you do not provide a value.nbands = calc.’ | | Following all k-points will be listed (with the Fermi weights of | | the highest band given in paranthesis) . especially for small molecular systems where NIONS/2 may be only 1. [0.000. Alternatively. 1 import numpy as np 2 3 4 print int(np. or an argument f to set the NBANDS according to the formula nbands = int(nelectrons/2 + len(atoms) ∗ f ). Here is an example of using func:jasp.set_nbands to automatically set the number of bands. We add three additional bands.0 For this calculation we need at least 6 bands (11/2=5.818.set_nbands. The func:jasp. nbands=9. 25 26 However.818]. The default behavior in VASP is: non-spin polarized spin-polarized NELECT/2 + NIONS/2 0. atoms=atoms) as calc: print calc. 1. 11. Atoms 3 93 . 13. 13).py).818.get_valence_electrons provides this for you. The default value of f is 1. the minimum number of bands is almost never enough.py). To figure out how many bands you need.000. 1 2 from jasp import * from ase import Atom.818.818. 1. xc=’PBE’. The default rule would only add half a band. and we always add more bands. 0.5 which is rounded up to 6) and we need to include some extra bands. 1. set f=0. [1. 1 2 from jasp import * from ase import Atom. For transition metals. you can look in the Appendix for a table listing the number of valence electrons for each POTCAR file. isif=4. ibrion=2.)) Open the python script (dft-scripts/script-88.ceil(50 / 2. nsw=10. cell= [[1.000])]. This system is so small it does not substantially increase the computational cost. you can use the func:jasp. it may be required that f=2.ceil(51 / 2. If you are too trifling to do that much work. 0.000. 1. it is necessary to know how many electrons are in your calculation.6*NELECT + NMAGIONS These do not always work.000]. 0.)) print int(np.000. 0. encut=350. Atoms 3 4 5 6 7 atoms = Atoms([Atom(’Cu’.5. kpts=(13. which is not enough. If you want the default VASP behavior. due to the smearing.Here is an example of what this equation does. This function takes an argument N to set the number of bands to N. Armed with this information you can set NBANDS the way you want.5. [0.818]]) 8 9 10 11 12 13 14 15 16 17 18 with jasp(’bulk/alloy/cu’. or transition metals where it may be necessary to add up to 2*NIONS extra bands.get_valence_electrons() Open the python script (dft-scripts/script-89. This function does not consider whether the calculation is spin-polarized or not. 571 a2 [ 0. 1. 13.818] 2.00 T T T -------------------------------------------------INCAR Parameters: ----------------nbands: 9 nsw: 10 ibrion: 2 isif: 4 encut: 350.000 -0. 1.723306 eV Unit cell vectors (angstroms) x y z length a0 [ 1.818 1. xy 0. zz. xc=’PBE’.000 1.000.000 -0. encut=350. nsw=10. 0. : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/bulk/alloy/cu converged: True Energy = -3.000]. Atoms 3 94 .000] 2.818].818] 2.py).4 5 6 7 atoms = Atoms([Atom(’Cu’.818 0. atoms=atoms) as calc: calc.006 0. kpts=(13.set_nbands(9) print calc Open the python script (dft-scripts/script-90.006 0.000 0.beta.006-0.0 magmom: None prec: Normal kpts: (13.alpha.000 1. ibrion=2. isif=4.571 2.000])].b.z]tag rmsForce constraints 0 Cu [0. 0. [1. 1. 1. [0. 13) reciprocal: False xc: PBE txt: gamma: False Pseudopotentials used: ---------------------Cu: potpaw_PBE/Cu/POTCAR (git-hash: a44c591415026f53deb16a99ca3f06b1e69be10b) 1 2 from jasp import * from ase import Atom. 13.y. cell=[[1.000] 0 0. 0.000.818 0. 0.571 60.571 a.818.0 60. xz. 13).000 Atom# sym position [x.000.c.818 1. yz.000 0.017 Ang^3 Stress (GPa):xx.571 2.818]]) 8 9 10 11 12 13 14 15 16 17 18 with jasp(’bulk/alloy/cu’.818. yy.571 a1 [ 1. [0.0 Unit cell volume = 12.gamma (deg):2.818.0 60.000.818. Some formulas I have used in the past include: 95 .b. 13.0 60.818 1. encut=350.000]. atoms=atoms) as calc: calc.000 1.818] 2. 0.000.571 a2 [ 0. 0.set_nbands(f=3) print calc Open the python script (dft-scripts/script-91. kpts=(13. 0.000])].818 1.000] 2. 13).beta. isif=4. 1. 0.571 a1 [ 1.571 2.y. 1.818.818. [0.818]]) 8 9 10 11 12 13 14 15 16 17 18 with jasp(’bulk/alloy/cu-setnbands’.818].c.818.000. 1. False : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/bulk/alloy/cu-setnbands converged: None Energy = nan eV Unit cell vectors (angstroms) x y z length a0 [ 1.818] 2.4 5 6 7 atoms = Atoms([Atom(’Cu’.alpha. free to use any formula you want to set the number of bands. 13. of course. 1.818 0.571 2. ibrion=2.000.818.gamma (deg):2.py).000.z]tag rmsForce constraints 0 Cu [0.818 0.571 60. nsw=10.000] 0 nan T T T -------------------------------------------------INCAR Parameters: ----------------nbands: 9 nsw: 10 ibrion: 2 isif: 4 encut: 350 magmom: None prec: Normal kpts: (13.571 a. xc=’PBE’.0 Unit cell volume = 12.000 1.000 0.017 Ang^3 Stress was not computed Atom# sym position [x. cell=[[1.000 0. 13) reciprocal: False xc: PBE txt: gamma: False Pseudopotentials used: ---------------------None: None (git-hash: None) You are. [0.0 60. [1. 0]. VaspQueued): ready = False 22 23 24 25 26 27 if not ready: import sys.0. 0. [1. NBANDS = 0. e in zip(LC. 1.pyplot as plt plt. 3.ylabel(’Total energy (eV)’) plt. encut=350. kpts=(8. fcc_energies): print ’| {0} | {1} |’. cell=0. 96 .0].6. In this section we show how to calculate the equilibrium volume of each structure.py).5.5*NELECT + 15 3. At higher temperatures. 3.1 fcc/bcc crystal structures The fcc and bcc structures are simple. They only have one degree of freedom: the lattice constant.3 Determining bulk structures What we typically mean by determining bulk structures includes the following: • What is the most stable crystal structure for a material? • What is the lattice constant of fcc Cu? • What are the lattice parameters and internal atom parameters for TiO2 ? All of these questions can often be addressed by finding the volume.png’) 34 35 36 37 38 print ’#+tblname: cu-fcc-energies’ print r’| lattice constant ($\AA$) | Total Energy (eV) |’ for lc.5 * a * np.get_potential_energy() fcc_energies.0.0.0.75] fcc_energies = [] ready = True for a in LC: atoms = Atoms([Atom(’Cu’. fcc_energies) plt. 0. sys.format(lc.65. xc=’PBE’. NBANDS = 0. 4. atoms=atoms) as calc: 19 20 try: 21 e = atoms. one must consider minimizing the free energy.append(e) except (VaspSubmitted. 1. Atoms 3 4 5 6 7 8 9 10 11 12 # fcc LC = [3. This is true at 0K.format(a).65*NELECT + 10 2.xlabel(’Lattice constant ($\AA$)’) plt. 1. 0))].55.0. 3. 1 2 from jasp import * from ase import Atom. e) Open the python script (dft-scripts/script-92. etc.exit() 28 29 30 31 32 33 import matplotlib. and determine which one is more stable. 3.array([[1. 0. We will manually define the crystal structure based on the definitions in Kittel 4 (Chapter 1). 8. shape and atomic positions that minimize the total energy of a bulk system. We start with the fcc crystal structure of Cu. .0. (0.plot(LC.3. 8). 3.1. rather than the internal energy.savefig(’images/Cu-fcc.7. [0. 1. 4.0]])) 13 14 15 16 17 18 with jasp(’bulk/Cu-{0}’. . Fit a cubic polynomial to the data. We will make a bcc crystal at the fcc lattice constant. and then compute the scaling factor needed to make it the right volume. 1. [-1.65 3.plot(’images/Cu-fcc-eos. e0.0]])) 9 10 print ’BCC lattice constant = {0} Ang’. Atoms import numpy as np a = 3./3. B) 19 20 eos.0].55 3.0.0. 1 2 3 from ase import Atom. cell=0.75 Total Energy (eV) -3.format(a * (11.utils.68426 Exercise 4.lattice constant (Å) 3.75] energies = [] volumes = [] for a in LC: with jasp(’bulk/Cu-{0}’.6. 3.get_potential_energy()) 11 12 13 eos = EquationOfState(volumes. 3.eos import EquationOfState LC = [3.append(atoms.7 3. The fcc lattice is close-packed.55. e0.7.utils.get_atoms() volumes.65.63585568663 Before we jump into the bcc calculations. Here is an example using mod:ase.0])].get_volume())**(1.0167118546 A^3 E0 = -3.6 3.get_volume()) energies.711284 -3.696204 -3.)) 97 .7246811445 eV B = 0.format(v0. The question is: what bcc lattice constant gives that volume? The simplest way to answer this is to compute the answer.859009528171 eV/A^3 3. The volume of the equilibrium bcc primitive cell will probably be similar to that.0.723951 -3.0.py). you would fit an equation of state to the data. 1.0. See also the appendix equations of state.61 # lattice constant 4 5 6 7 8 atoms = Atoms([Atom(’Cu’. [0. 3.append(atoms. energies) v0.eos. 3.5. 1 2 3 4 5 6 7 8 9 10 from jasp import * from ase.fit() 14 15 16 17 18 print ’’’ v0 = {0} A^3 E0 = {1} eV B = {2} eV/A^3’’’.2 Use the data in the table above to plot the total energy as a function of the lattice constant.5 * a*np. and the volume of the primitive cell is V = 1/4a3 or about 11.array([[ 1. 1. [ 1. -1.8 Å3 /atom. and find the volume that minimizes the total energy. v0 = 12.png’) Open the python script (dft-scripts/script-93.0. -1.8 / atoms.719946 -3.5 3.649238 -3. If you want to know the lattice constant that gives the lowest energy.0]. let us consider what range of lattice constants we should choose. B = eos. 1.format(a)) as calc: atoms = calc. 3.0. [ 1.get_potential_energy()) 12 13 14 15 16 17 18 19 20 21 # fcc energies and volumes fcc_LC = [3.savefig(’images/Cu-bcc-fcc.array([[ 1. xc=’PBE’.format(a)) as calc: atoms = calc.format(a)) as calc: atoms = calc.pyplot as plt plt.0.py). 2.format(a). 1 2 from jasp import * from ase import Atom.legend() plt. bcc_energies. label=’fcc’) plt.calculate() Open the python script (dft-scripts/script-95.7.get_potential_energy()) 22 23 24 25 import matplotlib.’ print ’| Lattice constant (\AA$^3$) | Total energy (eV) |’ print ’|-’ for lc. 3. encut=350.get_atoms() fcc_volumes.95. -1.0. 1. Exercise 4.0].append(atoms.get_atoms() bcc_volumes.5 * a * np. 1.9. 3. we will compare the two crystal structures. [-1.0]. 3.55. 2.get_volume()) fcc_energies. atoms=atoms) as calc: calc.86838428403 Ang Now we run the equation of state calculations.0.append(atoms. e) Open the python script (dft-scripts/script-96. 0])]. 2.Open the python script (dft-scripts/script-94.py).get_volume()) bcc_energies. 2.6.format(lc.8.85. 3. 8).plot(fcc_volumes.xlabel(’Atomic volume ($\AA^3$/atom)’) plt.65.py).0] 5 6 7 8 9 10 for a in LC: atoms = Atoms([Atom(’Cu’.75] fcc_volumes = [] fcc_energies =[] for a in fcc_LC: with jasp(’bulk/Cu-{0}’. [0. 2.0. -1. 98 . 1. BCC lattice constant = 2. e in zip(bcc_LC.png’) 31 32 33 34 35 36 37 38 # print table of data print ’#+tblname: bcc-data’ print ’#+caption: Total energy vs.append(atoms. fcc_energies. bcc_energies): print ’| {0} | {1} |’.append(atoms. kpts=(8.75. 3. 1.85. Finally. label=’bcc’) 26 27 28 29 30 plt.9.3 Use the data for FCC and BCC Cu to plot the total energy as a function of the lattice constant. 3. 2. Atoms 3 4 LC = [2.95.ylabel(’Total energy (eV)’) plt.0. 2.0. 0.0]])) 11 12 13 14 15 16 17 with jasp(’bulk/Cu-bcc-{0}’.75.0] bcc_volumes = [] bcc_energies = [] for a in bcc_LC: with jasp(’bulk/Cu-bcc-{0}’. 8.5. 1 from jasp import * 2 3 4 5 6 7 8 9 10 11 # bcc energies and volumes bcc_LC = [2.plot(bcc_volumes. 2. 3.8. cell=0. lattice constant for BCC Cu. 8] 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’: 2.657913 Note we plot the energy vs. the fcc structure is the experimentally found structure for Cu. ’c/a’: covera}) 19 20 wd = ’bulk/Ru/{0:1.8. the bcc structure is more stable because the results are not converged! Exercise 4. 4). See Figure 38.6. covera) 21 22 23 24 25 26 27 28 29 30 31 32 33 with jasp(wd.7. 6.7.get_potential_energy()) except (VaspSubmitted. so we use # fewer kpoints.4.5. if you run these calculations at a 4 × 4 × 4 k-point grid.plot(covera_list. # the c-axis is longer than the a-axis.format(a. label=r’a={0} $\AA$’. latticeconstant={’a’: a.2f}-{1:1.0 -3.7. until we calculate the hcp equation of state.584}) 8 9 10 a_list = [2. 1. 1.format(a)) 34 99 . volume for fcc and bcc Cu for different k-point grids. so we can conclude the fcc structure is more favorable.587523 2.716496 2. What can we say here? The fcc structure has a lower energy than the bcc structure.8 -3. 2.2 Optimizing the hcp lattice constant 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. 2.5. 4.95 -3.Table 4: Total energy vs. 1. What can we say about the relative stability of fcc to hcp? Nothing.append(atoms.pyplot as plt 4 5 6 7 atoms = HexagonalClosedPacked(symbol=’Ru’. xc=’PBE’.4 Compute the energy vs. 1 2 3 from ase.lattice.668112 2. encut=350. ’c/a’: 1. atomic volume. It also shows that the atomic volumes in the two structures are similar.hexagonal import HexagonalClosedPacked from jasp import * import matplotlib. kpts=(6.85 -3.2f}’.9 -3. atoms=atoms) as calc: try: energies. In fact. Some caution is in order.9] covera_list = [1. lattice constant for BCC Cu. That is because the lattice constants of the two crystal structures are very different.697781 3.3. Determine when each result has converged. and which structure is more stable. 2.6. 2.75 -3. 1. Lattice constant (Å3 ) Total energy (eV) 2. VaspQueued): pass plt.708699 2. energies. We will start by making a grid of values and find the set of parameters that minimizes the energy. zeros(X.cm.Y = np.5. y) Z = np.show() Open the python script (dft-scripts/script-97.pyplot as plt 3 4 5 x = [2. We can look at the same data in a contour plot which shows more clearly there is minimum in all directions near that point (Figure 39). It is usually not efficient to make a wild guess of the geometry and then turn VASP loose on to optimize it.ylabel(’Energy (eV)’) plt. VaspQueued): pass 15 16 17 18 19 20 21 22 23 cf = plt. 3. It is impractical to try the approach used for the hcp Ru on anything complicated.2f}-{1:1.6. at a c/a ratio of about 1.show() Open the python script (dft-scripts/script-98. There may additionally be internal degrees of freedom for the atoms.7.png’) plt.legend() plt. 2. 1. 1.3 Complex structures with internal degrees of freedom A unit cell has six degrees of freedom: the lengths of each unit cell vector. volume and internal degrees of freedom. 1.meshgrid(x. It looks like there is a minimum in the a=2.8. cmap=plt. Z. Using the results from step 1 as a starting point. but the shape and internal atom positions are allowed to change (ISIF=4).xlabel(’$c/a$’) plt. Find the volume (at constant shape.legend() plt. we rely again on algorithms to optimize the unit cell shape.6. (ISIF=3).6.shape) 9 10 11 for i.a in enumerate(x): for j. 4.covera) 13 14 with jasp(wd) as calc: atoms = calc.py).35 36 37 38 39 plt. do a final calculation near the minimum energy allowing the volume to also change.7 Å curve.get_atoms() try: Z[i][j] = atoms.xlabel(’$a$ ($\AA$)’) plt. Y.contourf(X. 1 2 from jasp import * import matplotlib. The goal here is to just get an idea of where the right volume is.ax.py). 1. Instead.8] 6 7 8 X.savefig(’images/Ru-covera-scan.colorbar(cf) cbar. with relaxed ions) that minimizes the total energy (ISIF=2). the following algorithm works pretty well. 2. 2.ylabel(’$c/a$’) 30 31 32 33 plt. perform a set of calculations at constant volume around the minimum from step 1. 2. 20.format(a.9] y = [1.png’) plt.savefig(’images/ru-contourf. Finally. and the angle between each vector.covera in enumerate(y): 12 wd = ’bulk/Ru/{0:1.5. Instead.set_ylabel(’Energy (eV)’) 27 28 29 plt.7. 2.3.2f}’. 100 . 1.jet) 24 25 26 cbar = plt.get_potential_energy() except (VaspSubmitted.4. 0..mil/lattice/struk/c4.0]) a3 = c * np. Atom(’O’. Atom(’O’. ENMIN 400. c = 2. We will illustrate the process on a well-behaved system (rutile TiO2 ) which has two lattice parameters and one internal degree of freedom.5 * a2 + 0.000. 1 2 3 4 5 # step 1 frozen atoms and shape at different volumes from ase import Atom. Atom(’O’. Atom(’Ti’. Now we consider the k-point convergence. however. k.0. [0. 7.This multistep process is pretty reasonable to get a converged structure pretty quickly. 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. Hence. xc=’PBE’. 1 2 grep ENMAX $VASP_PP_PATH/POTPAW_PBE/Ti/POTCAR grep ENMAX $VASP_PP_PATH/POTPAW_PBE/O/POTCAR Open the python script (dft-scripts/script-99.5 + u) * a1 + (0. 1.5 * a3). the sheets may just move apart until they do not interact any more. 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.0]) a2 = a * np. we should use ENCUT = 1.0. atoms=atoms) as calc: 101 . ENMIN = = 133. 0.u) * a1 + (0..array([1.96 u = 0. however. 8] energies = [] 31 32 33 34 35 36 37 38 39 ready = True for k in KPOINTS: with jasp(’bulk/tio2/kpts-{0}’. (0.nrl. It is not foolproof. encut=520.pyplot as plt 6 7 8 9 10 11 12 13 14 ’’’ create a TiO2 structure from the lattice vectors at http://cst-www.py). cell=[a1. a2.5 * a1 + 0.747 eV 300. u * a1 + u * a2). This is necessary to avoid problems caused by small basis sets when the volume changes.0.u * a2). 4. 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 .5 * a3)]. and that ENCUT be set to 1. 1. and if you have materials such as graphite it may not work well.0.array([0. 0. The VASP manual recommends that you set incar:PREC to ’high’.59 # experimental degrees of freedom.5 .3*400 = 520 eV for good results.0. k). Atom(’O’.5 * a3).000 eV According to the manual.html This site does not exist anymore.navy. ENMAX ENMAX = = 178. -u * a1 . 0. 6. Atoms import numpy as np from jasp import * import matplotlib.5 . 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. 0. 0. 5.]). ’’’ a = 4.format(k). a3]) 28 29 30 KPOINTS = [2.array([0.u) * a2 + 0. 3. kpts=(k. (0. With a typical GGA. sigma=0.5 + u) * a2 + 0. we do that here. 0.3 # internal degree of freedom! 15 16 17 18 19 #primitive vectors a1 = a * np. and Pulay stress.0]) 20 21 22 23 24 25 26 27 atoms = Atoms([Atom(’Ti’.05. There are a few subtle points to mention in doing these calculations.330. For simplicity. 0. It is important to ensure that the energies are reasonably converged with respect to k-point grids.3*max(ENMAX) of the pseudopotentials. savefig(’images/tio2-kpt-convergence.html ’’’ a = 4.array([1. -u * a1 . 1.5 * a2 + 0.u) * a2 + 0. u * a1 + u * a2).. a2. Atom(’Ti’.append(atoms. energies) plt..5. (0.u) * a1 + (0. 1 2 3 4 5 # step 1 frozen atoms and shape at different volumes from ase import Atom. Atom(’O’.append(atoms.]).exit() 47 48 49 50 51 52 plt.5 * a1 + 0. [0. sigma=0.5).0. but keeping a constant cell shape. VaspQueued): ready = False 56 102 . A k-point grid of 5 × 5 × 5 appears suitable for reasonably converged results. 1.append(atoms.nrl.1] #to change volume by 32 33 energies. 1. kpts=(5. / 3. a3]) 27 28 29 v0 = atoms.pyplot as plt 6 7 8 9 10 11 12 13 ’’’ create a TiO2 structure from the lattice vectors at http://cst-www.array([0. 1. 0.0.ylabel(’Total energy (eV)’) plt.59 # experimental degrees of freedom.0.png’) plt. sys. Atoms import numpy as np from jasp import * import matplotlib.40 try: 41 energies. 1. cell=[a1.get_potential_energy()) volumes. 0. scale_atoms=True) 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 with jasp(’bulk/tio2/step1-{0:1.05.get_volume()) except (VaspSubmitted. 0. (0.5 * a3)].5 * a3).format(f).) 39 40 atoms.plot(KPOINTS. 0. Now we proceed with step 1: Compute the total energy of the unit cell allowing internal degrees of freedom to relax. # relax internal degrees of freedom ibrion=1.9. encut=520.0.xlabel(’number of k-points in each vector’) plt. 0.95.get_volume() cell0 = atoms. isif=2.u * a2).0.05. Atom(’O’.show() Open the python script (dft-scripts/script-100.0]) a3 = c * np.3 # internal degree of freedom! 14 15 16 17 18 #primitive vectors a1 = a * np. c = 2.array([0.5 . VaspQueued): ready = False 42 43 44 45 46 if not ready: import sys.5 . xc=’PBE’.0]) a2 = a * np. atoms=atoms) as calc: try: energies.get_cell() 30 31 factors = [0.0]) 19 20 21 22 23 24 25 26 atoms = Atoms([Atom(’Ti’. nsw=50.mil/lattice/struk/c4.get_potential_energy()) except (VaspSubmitted. Atom(’O’. [] 34 35 36 37 38 ready = True for f in factors: v1 = f * v0 cell_factor = (v1 / v0)**(1.0.5 + u) * a1 + (0. 0.5 + u) * a2 + 0.96 u = 0.navy.py). Atom(’O’. 0.0.2f}’. 0.set_cell(cell0 * cell_factor. volumes = [].5 * a3). [] # from step 1 energies. volumes1 = []. This has little effect on the minimum 103 . ’step 2’]. volumes = [].format(f)) as calc: atoms = calc.get_atoms() energies1.1] # to change volume by 4 5 6 7 8 9 10 11 12 13 energies1. However. energies1.plot(volumes. 1.xlabel(’Vol. Table 5: Total energy of TiO2 vs.05. ($\AA^3)$’) plt.png’) 64 65 66 67 68 69 70 print ’#+tblname: tio2-vol-ene’ print ’#+caption: Total energy of TiO_{2} vs.2f}’. volumes.get_potential_energy()) volumes1.ylabel(’Total energy (eV)’) plt. we know the minimum energy volume is near 64 ň3.clone(’bulk/tio2/step2-{0:1.9.361576 -52.append(atoms. loc=’best’) plt.py).append(atoms.format(v. isif=4) as calc: atoms = calc.py).2f}’.2434972 -52. VaspQueued): ready = False 24 25 26 if not ready: import sys.get_atoms() try: energies.4796548 -52.ylabel(’Total energy (eV)’) plt. at constant volume: ISIF=4. sys. energies): print ’| {0} | {1} |’.show() Open the python script (dft-scripts/script-102. 1 from jasp import * 2 3 factors = [0.png’) plt.5977336 -52. we now want to use these initial starting points for a second round of optimization where we allow the unit cell shape to change.legend([’step 1’.64715 Now. sys.exit() 59 60 61 62 63 plt.801329 68. 1.plot(volumes1. You could at this point fit an equation of state to find that minimum. especially for the larger unit cell deformation. energies) plt.1254184 -51.exit() 27 28 29 30 31 32 33 34 import matplotlib.2f}’. Volume (Å3 ) Energy (eV) 56.462241 62.’ print ’| Volume ($\AA^3$) | Energy (eV) |’ print ’|-’ for v.append(atoms. energies) plt.57 58 if not ready: import sys. ($\AA^3)$’) plt. volume.format(f).get_potential_energy()) volumes. 0.format(f)) 14 15 16 17 18 19 20 21 22 23 # now set ISIF=4 and run with jasp(’bulk/tio2/step2-{0:1.pyplot as plt plt.get_volume()) calc.get_volume()) except (VaspSubmitted. 1.savefig(’images/tio2-step1.0.820427 59. [] # for step 2 ready = True for f in factors: with jasp(’bulk/tio2/step1-{0:1. volume.95.761097 65.xlabel(’Vol.append(atoms. e in zip(volumes.savefig(’images/tio2-step2. The take away message here is that the total energy slightly decreases when we allow the unit cell shape to change. e) Open the python script (dft-scripts/script-101. 818610 eV Unit cell vectors (angstroms) x y z length a0 [ 4.00 T T T -------------------------------------------------INCAR Parameters: ----------------nbands: 20 nsw: 50 ibrion: 1 isif: 3 encut: 520.000] 0 0.661 0.485] 0 0. At this point.clone(’bulk/tio2/step3’) 5 6 7 8 9 10 with jasp(’bulk/tio2/step3’.format(spglib.000 0.beta.000 0. and recalculate the total energy at that volume. xz.alpha. zz.420 1.000-0.py).calculate() atoms = calc.00 T T T 3 O [3.00 T T T 2 O [1.970 90.00 T T T 4 O [3.000 2. It looks like the calculation at bulk/tio2/step2-1.751 0. : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/bulk/tio2/step3 converged: True Energy = -52.751 1. and estimate the volume at the minimum volume.000] 4. yz.910 1.241 0. 5.0 sigma: 0.00 T T T 5 O [0.910 3.420 0.000 Atom# sym position [x.485] 0 0. shape and internal coordinates.485] 0 0. isif=3) as calc: calc. xy -0.000 4.get_spacegroup(atoms)) Open the python script (dft-scripts/script-103.0 90.y.05’) as calc: calc.000 0.000 -0. which is related to the curvature of the equation of state.970 a. but would have an effect on the bulk modulus.331 1.661 a2 [ 0.661 4. yy. 1 from jasp import * 2 3 4 with jasp(’bulk/tio2/step2-1.241 3.515 Ang^3 Stress (GPa):xx.661 2.000] 0 0. you could fit an equation of state to the step 2 data. An alternative is a final calculation with ISIF=3.000 -0.volume.b.661 a1 [ 0.000 0.000 -0.000] 0 0. 5] 104 .05 is close to the minimum. which optimizes the unit cell volume.970] 2.661 0. so we will use that as a starting point for the final calculation.000 -0.gamma (deg):4.0 90.z]tag rmsForce constraints 0 Ti [0.0 Unit cell volume = 64.331 2.c.000] 4.get_atoms() print calc 11 12 13 from pyspglib import spglib print ’\nThe spacegroup is {0}’.00 T T T 1 Ti [2.05 magmom: None prec: Normal kpts: [5. 05. (0. The space group is still correct. energies = []. Looks good! As a final note. 4. default ismear: ismear=-5: -52.817345 The difference here is on the order of a meV. we examine the effect on the bulk lattice constant of Pd (exp.881). An excellent review of this can be found in. Atoms from ase. ’PW91’ or ’PBE’. The value of xc can be ’LDA’. 1 from jasp import * 2 3 4 5 6 with jasp(’bulk/tio2/step3’) as calc: atoms = calc. 1. atoms. 1. cell=0.eos import EquationOfState 4 5 LC = [3. 0. The lattice vectors are close in length to the experimentally known values. 3. 0. [] for a in LC: atoms = Atoms([Atom(’Pd’.75. 3.85.clone(’bulk/tio2/step4’) 7 8 9 10 11 12 with jasp(’bulk/tio2/step4’.81861 -52. 1.get_atoms() print ’ismear=-5: ’.01 eV/Å.0. 50 We examine several functionals.0]. 3.0].90. [1.80.array([[1.utils. 3.get_atoms() print ’default ismear: ’. Here we examine the effect. the VASP manual recommends you do not use the final energy directly from the calculation. The xc keyword in jasp is used to select the POTCARs. but rather run a final calculation with incar:ISMEAR set to -5. 1. 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. and the angles between the vectors has not changed much.0. 4. ismear=-5. 0))].0.4 Effect of XC on bulk properties The exchange correlation functional can significantly affect computed bulk properties. That does not seem significant here. 3. [0.0. 0. 105 .0]])) with jasp(’bulk/Pd-LDA-{0}’. and the stress is also very small.get_potential_energy() Open the python script (dft-scripts/script-104.95.get_potential_energy() calc. The final volume is close to where we expect it to be based on steps 1 and 2. 1 2 3 from jasp import * from ase import Atom.py). 4. nsw=0) as calc: atoms = calc.0.1] 6 7 8 9 10 11 12 13 volumes. Here.3.0. Let us consider the LDA functional first.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. atoms. You can see that the forces on all the atoms are less than 0.format(a).5 * a * np.0. VaspQueued): pass 20 21 22 23 24 25 26 27 28 if len(energies) == len(LC): eos = EquationOfState(volumes. 3. 0.0]. ’PBEsol’. 12. We will consider four different functionals here.append(e) volumes. energies) v0. ’PBE’. [] for a in LC: atoms = Atoms([Atom(’Pd’. 1.get_potential_energy() energies. 0.get_volume()) except (VaspSubmitted. kpts=(12. atoms=atoms): 14 15 16 17 18 try: 19 e = atoms. xc=’LDA’. B = eos. 4.encut=350.0.format((4*v0)**(1. 3.format((4*v0)**(1.fit() print ’{1:6s} lattice constant is {0:1.0.952 Ang^3 Ang^3 Ang^3 Ang^3 106 . 1.array([[1. LDA lattice constant is 3.append(atoms. [0./3. 1.0]. This tag was designed to use the LDA POTCAR files. GGA[key]) else: print energies. 0.)) Open the python script (dft-scripts/script-105.0]])) with jasp(’bulk/Pd-GGA-{1}-{0}’. 1 2 3 from jasp import * from ase import Atom.3f} Ang^3’.0.85. B = eos. 3. ’RPBE’} 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 for key in GGA: volumes.3f} Ang^3’. 0))].80. 12).py). 4. encut=350.utils.75. cell=0. energies = []. (0.90.882 3.).append(atoms.0.py).append(e) volumes.855 Ang^3 For a GGA calculation. key). LC print ’{0} is not ready’. 12).0.05. e0. e0. xc=’LDA’.format(a. atoms=atoms): try: e = atoms. energies) v0.1] 6 7 8 9 10 GGA = {’AM’: ’PE’: ’PS’: ’RP’: ’AM05’. 3. kpts=(12. Atoms from ase.0.get_volume()) except (VaspSubmitted. VaspQueued): pass 31 32 33 34 35 36 37 38 39 if len(energies) == len(LC): eos = EquationOfState(volumes.get_potential_energy() energies.fit() print ’LDA lattice constant is {0:1. 1./3.885 3. PBEsol AM05 RPBE PBE lattice lattice lattice lattice constant constant constant constant is is is is 3.95. but with a GGA functional.990 3.format(GGA[key]) Open the python script (dft-scripts/script-106.0. 12. 4. gga=key.eos import EquationOfState 4 5 LC = [3. [1. it is possible to specify which functional you want via the incar:GGA tag.5 * a * np. you can see below that the total energy is pretty converged by a 6 × 6 × 6 k-point grid.187 eV According to Kittel. size=(1. encut=350. [1. Atom 4 5 6 7 8 9 10 # bulk system atoms = FaceCenteredCubic(directions=[[0. 1. 50 It is typical that LDA functionals underestimate the lattice constants. atoms=atoms) as calc: bulk_energy = atoms. but it has been reported to be a superior functional for reactivity.bulk_energy print ’The cohesive energy is {0:1. There are a few reasons we may have discrepancy here: 1. 1. so we will use that structure and let VASP find the equilibrium volume for us. We did not check for convergence with the planewave cutoff. and for Pd. 5. 3. RPBE is particularly bad at the lattice constant. kpts=(4. 1].[5. 1]. encut=350.cubic import FaceCenteredCubic from ase import Atoms.py). 1). PBEsol and AM05 were designed specifically for solids.get_potential_energy() 21 22 23 24 # atomic system atoms = Atoms([Atom(’Rh’. 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. The k-point grid used in the bulk state is not very dense. 0. xc=’PBE’.75 eV. We will compute this for rhodium. 25 4. 1. The cohesive energy is 6. 107 . 4 the cohesive energy of Rh is 5. 9)) 25 26 27 28 29 30 31 with jasp(’bulk/atomic-rh’. [1. 8. nsw=10. Rh is normally an fcc metal. 1). 2. We neglected spin on the atomic state. symbol=’Rh’) 11 12 13 14 15 16 17 18 19 20 with jasp(’bulk/bulk-rh’.format(cohesive_energy) Open the python script (dft-scripts/script-107. 1 2 3 from jasp import * from ase. xc=’PBE’. 4. Rh in the atomic state has this electronic structure: [Kr] 4d8 5s1 and is a doublet.get_potential_energy() 32 33 34 cohesive_energy = atomic_energy . First we consider the k-point convergence. cell=(7. 1.lattice. these functionals do an exceptional job of reproducing the lattice constants. isif=3. ibrion=2. and that GGAs tend to overestimate the lattice constants. atoms=atoms) as calc: atomic_energy = atoms. However. 0]].These results compare very favorably to those in.3f} eV’. kpts=(1. 5])]. e-atomic_energy) Open the python script (dft-scripts/script-108. 8.format(k. Note we do not need to check the k-point convergence of the atomic state because it is surrounded by vacuum on all sides. 1]. {0:2d}. 6.get_potential_energy() 19 20 print ’({0:2d}. 9)) 24 25 26 27 28 29 30 31 with jasp(’bulk/atomic-rh-sp’. ispin=2. 3. Atom # bulk system atoms = FaceCenteredCubic(directions=[[0.837472 -6. 1). kpts=(k.format(k). 9. 12): cohesive (15. 9.215367 -6. xc=’PBE’. 18] 11 12 13 14 15 16 17 18 for k in kpts: with jasp(’bulk/bulk-rh-kpts-{0}’. atoms=atoms) as calc: bulk_energy = atoms. 4. 1. 6): cohesive ( 9. 3): cohesive ( 4.[5. 1. 15): cohesive (18.208576 -6.lattice. atoms=atoms) as calc: atomic_energy = atoms. cell=(7. {0:2d}): cohesive energy = {1} eV’. nsw=10.get_potential_energy() 32 108 . 1 2 3 4 5 6 7 8 9 from jasp import * from ase. 12. encut=350.215319 -6. 5. 12. kpts=(1.1 from jasp import * 2 3 4 5 with jasp(’bulk/atomic-rh’) as calc: atoms = calc. magmom=1)].189573 -6. 15. 4). k. k).get_potential_energy() 6 7 8 with jasp(’bulk/bulk-rh’) as calc: atoms = calc. 0]]. 18): cohesive energy energy energy energy energy energy energy = = = = = = = -4. ibrion=2. ( 3. 15.cubic import FaceCenteredCubic from ase import Atoms. kpts=(4. encut=350.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. xc=’PBE’. [1. 4. 18. 0. 1.get_potential_energy() 20 21 22 23 # atomic system atoms = Atoms([Atom(’Rh’. 4.get_atoms() atomic_energy = atoms.py). 1]. atoms=atoms) as calc: e = atoms. 1.210668 -6. size=(1. encut=350. 6. [1. xc=’PBE’.get_atoms() 9 10 kpts = [3. 5]. isif=3. 4): cohesive ( 6. We will examine the magnetic state next. 9): cohesive (12. 1). and so there should not be any dispersion in the bands. symbol=’Rh’) 10 11 12 13 14 15 16 17 18 19 with jasp(’bulk/bulk-rh’. The stress and strain are six component vectors.py). Phys. 12). now with a relaxed geometry at hand. kpts=(12. Finally. isif=3.33 34 cohesive_energy = atomic_energy . 1 2 from jasp import * from jasp. 4. we did not check that at all (see Estimating triplet oxygen dissociation energy with low symmetry). 12.1 1 2 Al elastic properties from jasp import * from ase. The cohesive energy is 5. Saxe. 1. # displacements nsw=1.elastic_moduli import * 3 4 5 with jasp(’bulk/Al-bulk’) as calc: calc. 104104 (2002).0 print B 109 .get_potential_energy() print atoms. ibrion=1.015.get_potential_energy() EM = calc. it is also possible there is a lower energy non-spherical atom energy.get_elastic_moduli() print EM 17 18 19 20 21 c11 = EM[0.get_atoms() print atoms.127 -0.5. This is accomplished with IBRION=6 and ISIF ≥ 3 in VASP. xc=’PBE’. B 65. we proceed with the elastic constants.clone(’bulk/Al-elastic’) 6 7 8 9 10 11 12 13 14 15 16 with jasp(’bulk/Al-elastic’. 51 We seek the elastic constant tensor that relates stress (σ) and strain () via σ = c.127 0. atoms=atoms) as calc: print atoms.75 eV which is very close to this value. Rev. See this reference (from the VASP page).lattice. # gets elastic constants potim=0.5 See this reference.bulk_energy print ’The cohesive energy is {0:1. 0. TODO Elastic properties 4.887 eV Again. -14. 0.get_stress() Open the python script (dft-scripts/script-110.cubic import FaceCenteredCubic 3 4 atoms = FaceCenteredCubic(symbol=’Al’) 5 6 7 8 9 10 11 12 13 14 15 16 with jasp(’bulk/Al-bulk’. nsw=30.127 -0. nfree=2) as calc: atoms = calc. so c will be a 6 × 6 symmetric matrix. # isif=3. ] Ok. prec=’High’. the value in Kittel 4 is 5. Le Page and P.96989 [-0.3f} eV’. ibrion=6.0] c12 = EM[0. encut=350.format(cohesive_energy) Open the python script (dft-scripts/script-109.py).1] B = (c11 + 2 * c12) / 3. 0. -14. 0.944 66.5. 0. The C44 constant above is too low.592189 110 . kpts=(6.687 0. This is accomplished with IBRION=6 and ISIF ≥ 3 in VASP.153 [ 66.969509 [[ 98. and probably we need to check these constants for convergence with respect to kpoints.cubic import BodyCenteredCubic 3 4 5 6 atoms = BodyCenteredCubic(symbol=’Fe’) for atom in atoms: atom. -0. 0.Open the python script (dft-scripts/script-111. 0. 1.0 7 8 9 10 11 12 13 14 15 16 17 18 with jasp(’bulk/Fe-bulk’. 77. Phys. we proceed with the elastic constants. 104104 (2002).687]] This example shows the basic mechanics of getting the elastic constants. Saxe. ] 0. 0. 0. # gets elastic constants potim=0. -0. and maybe the value of POTIM. # isif=3. ispin=2.08309 66.153 66.153 98. 4. ] 1. 1.944 [ 66. xc=’PBE’. -16.get_potential_energy() print atoms. ibrion=6.get_stress() Open the python script (dft-scripts/script-112.153 98. 0. ] Ok. 0. 0.153 66. 0. ] 0.py). 6). ] 0.2 1 2 Fe elastic properties from jasp import * from ase.magmom = 3.944 0.687 0. [ 0. 0. 6. nfree=2) as calc: atoms = calc. 0. ] 0.153 [ 0.get_atoms() print atoms. [ 0.py). encut=350.05. 1. atoms=atoms) as calc: print atoms. B 65. See this reference (from the VASP page). # displacements nsw=1.001 -0. Rev. -16.001 -0.001 -0. ibrion=1. now with a relaxed geometry at hand. nsw=30.py).clone(’bulk/Fe-elastic’) 5 6 7 8 9 10 11 12 13 with jasp(’bulk/Fe-elastic’.lattice. Le Page and P. planewave cutoff.604623 [-0. isif=3.get_potential_energy() Open the python script (dft-scripts/script-113. 0. 1 from jasp import * 2 3 4 with jasp(’bulk/Fe-bulk’) as calc: calc. 0000 0.0000 0.0000 0.6085 2803.0000 0.0000 0.0000 0.0000 YY 1622.0000 0.0000 0.8792 0.0000 0.0000 0.0000 0.0000 0.0000 ZZ 0.0000 0. and 3) the total elastic modulus.0000 XY 0.0000 0.0000 0.0000 0. the results are written out to the OUTCAR file.0000 0.0000 YY 1622.5081 1622.0000 866.0000 0.0000 866.6085 0.0000 866.6085 2803.6085 1622.0000 0.0000 YZ 0.0000 0.0000 0.0000 0.0000 0.0000 ZZ 1622.0000 0.0000 0.0000 0.0000 0.5081 1622.0000 0.0000 0.8792 0.0000 0.6085 0.0000 0.5081 0.0000 0.0000 866.0000 0.6085 1622.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0. three sets of moduli are written out 1) the elastic tensor for rigid ions.0000 0.8792 0.0000 0.0000 ZX 0.0000 0. line in enumerate(lines): if line.0000 XY 0.startswith(’ TOTAL ELASTIC MODULI (kBar)’): j = i + 3 data = lines[j:j+6] break 11 12 13 for line in data: EM += [[float(x) for x in line.0000 0.0000 ZX 0.0000 0.0000 0.0000 866.0000 0.6085 0.0000 0.0000 0.5081 1622.0000 0. Finally we parse out the matrix elements and cast them as floats. then take the six lines that start three lines after that.0000 0.0000 0.0000 ZX 0. First we get the line where the total elastic moduli start. Actually.0000 -------------------------------------------------------------------------------- TOTAL ELASTIC MODULI (kBar) Direction XX YY ZZ XY YZ ZX -------------------------------------------------------------------------------XX 2803.readlines() for i.0000 0.0000 0.6085 1622.0000 866. SYMMETRIZED ELASTIC MODULI (kBar) Direction XX YY ZZ XY YZ ZX -------------------------------------------------------------------------------XX 2803.6085 0.0000 0.0000 YY 0.0000 0.0000 0.8792 0.5081 1622.6085 2803.0000 XY 0.8792 -------------------------------------------------------------------------------Let us write a small code here to extract the Total elastic moduli from the OUTCAR file.0000 YZ 0.split()[1:]]] 14 15 print np.0000 ZZ 1622.0000 0. all in kBar.0000 0.array(EM) 111 .6085 2803.0000 0.0000 0. 1 2 import numpy as np EM = [] 3 4 5 6 7 8 9 10 with open(’bulk/Fe-elastic/OUTCAR’) as f: lines = f.8792 -------------------------------------------------------------------------------and ELASTIC MODULI CONTR FROM IONIC RELAXATION (kBar) Direction XX YY ZZ XY YZ ZX -------------------------------------------------------------------------------XX 0.5081 0.0000 0. 2) the contribution from allowing the atoms to relax.Now.6085 1622.0000 YZ 0.0000 0. energies = []. 3. 3.gov/data/PDFfiles/jpcrd34. 0. 0. 1622.6085 [ 0. 3.6085 0. 0. 0). we must use some simple models that we parameterize by DFT.0. ispin=2. Fe is in a BCC crystal structure. 1.5)]. ] 0.5081 [ 1622.append(e) volumes. which is high in symmetry.0]])) 12 13 14 15 16 17 18 19 20 21 22 23 24 with jasp(’bulk/Ni-{0}’.55. 0.0.savefig(’images/Ni-fcc. see http://www. 0.75] volumes.7. 3. We start by computing the equation of state for fcc Ni. atoms=atoms) as calc: try: e = atoms.pyplot as plt plt. 1622.5081 0.65. 0.py).6.nist. 866. Further discussion of symmetry.png’) Open the python script (dft-scripts/script-115. 0. fcc_energies) plt.exit() 28 29 30 31 32 33 import matplotlib. 0.0].5.5 * a * np. and maybe literature. 1.0. [0.0. 1. ] 0.12). 0. magmom=2. Consequently. xc=’PBE’.Open the python script (dft-scripts/script-114. ] 0. Atoms 3 4 5 6 7 8 9 10 11 # fcc LC = [3.6 Bulk thermodynamics We can predict temperature dependent thermodynamic properties of bulk materials without too much effort. [[ 2803. kpts=(12.ylabel(’Total energy (eV)’) plt.6085 [ 1622. ] 866.array([[1. [] for a in LC: atoms = Atoms([Atom(’Ni’.8792 0.xlabel(’Lattice constant ($\AA$)’) plt. Here we follow the example in Reference 52 for computing the thermal coefficient of expansion.py).8792 0. heat capacity. [ 0. 0.get_volume()) except: pass 25 26 27 if len(energies) != len(LC): import sys.pdf for a lot of detail 4. encut=350. 0. 0. ] 0. 0. 112 .6085 2803. 0.12. 0. 0. 3.append(atoms.5081 1622.get_potential_energy() energies. 866. enthalpy and entropy for Ni as a function of temperature.plot(LC. As with the thermochemical properties of ideal gases.6085 1622. [1.0. [ 0.0. 1. sys.8792]] TODO: compare to a normal EOS. cell=0.format(a). 1 2 from jasp import * from ase import Atom.6085 2803.0]. many of the elements in the matrix are equal to zero. (0. 5*a3). 0. cell=[a1.0. so that one may become stable under pressure.get_cell() 27 28 volumes = [28.nrl. 0.array([0. 30.0]) 15 16 17 18 19 20 21 22 atoms = Atoms([Atom(B. 0. or alternatively.0. Atom(X. To show this. 34.0.get_volume() cell0 = atoms. 36. a2. ’’’ create a rutile structure from the lattice vectors at http://cst-www.5+u)*a1 + (0. a3]) 23 24 25 26 nTiO2 = len(atoms) / 3.5-u)*a1 + (0. (0.5*a1 + 0. u = 0. The condition where a phase transition occurs is when the pressure in the two phases is the same. a = 4. (0. 1.0.958. 0. we need Erutile (V ) and Eanatase (V ).0. Atom(X.5-u)*a2 + 0.59.html 9 10 11 12 13 14 spacegroup: 136 P4_2/mnm ’’’ a1 = a * np. We now consider the relative stability of two phases under pressure.7 Effect of pressure on phase stability So far we have only considered relative stability at a pressure of 0 Pa. Atom(X. Atoms 4 5 6 7 8 B = ’Ti’.navy... 0.array([0..5*a2 + 0. u*a1 + u*a2).5*a3)].4. Atom(X. 1 2 3 # run the rutile calculations from jasp import * from ase import Atom.5*a3). ∂E The pressure is defined by: P = − ∂V .] #vol of one TiO2 113 . 32. which occurs at a common tangent. Wewill consider TiO2 in the rutile and anatase phases. Atom(B. 1. v0 = atoms. 0..5+u)*a2 + 0.0]) a3 = c * np.array([1..u*a2). -u*a1 . c = 2.mil/lattice/struk/c4. X = ’O’. compute the volume. 0..0. Pressure can affect the energy of two phases differently.0]) a2 = a * np. So if we have an equation of state E(V ) we can calculate T the pressure at any volume.]).305. given a pressure. [0. Atom(X.calculate() except (VaspSubmitted.navy. z*a1 . kpts=(6. cell=[a1.5 * a./3. 1..0.calculate() except (VaspSubmitted. / 3. 0.5 * c]) 11 12 13 14 15 16 17 18 atoms = Atoms([Atom(B.7573.375 * a2 + 0. Now we will fit cubic polynomials to the data. -(0.array([0. 0. 1 2 3 4 # fit cubic polynomials to E(V) for rutile and anatase from jasp import * import matplotlib. v0 = atoms. 0.array([1.. sigma=0..0. VaspQueued): pass Open the python script (dft-scripts/script-116.5+2*z)*a3). 0. ismear=0.5-z)*a2 + (0.0]) a3 = np.py). a = 3.py). VaspQueued): pass Open the python script (dft-scripts/script-117.25 * a3).125 * a1 + 0.0831. 6). isif=2. encut=350.5 * a.html 5 6 B = ’Ti’.a2. Atoms # http://cst-www.)).25 . 33.25-z)*a2 + 2. Atom(X. z = 0.get_cell() 23 24 volumes = [30. 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}’.75 * a3). 1 2 3 4 # run the anatase calculations from jasp import * from ase import Atom. ibrion=2. 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}’. 6). isif=2. Atom(B. 0.001. ismear=0.array([0.7842.nrl. 39.0. -0. atoms=atoms) as calc: try: calc.29 30 31 32 for v in volumes: atoms.] #vol of one TiO2 25 26 27 28 for v in volumes: atoms. encut=350..5 + z)*a2 + (0.*z*a3).)).0]) a2 = a * np.format(v).5-2*z)*a3)].get_volume() cell0 = atoms. X = ’O’.001. 6. sigma=0.a3]) 19 20 21 22 nTiO2 = len(atoms) / 3.25+z)*a1 + (0.set_cell(cell0 * ((nTiO2*v/v0)**(1. -z*a1 + (0. 0. 35. c = 2*4. 7 8 9 10 a1 = a * np. xc=’PBE’.z)*a2 + (1-2*z)*a3). xc=’PBE’. ibrion=2. Atom(X. (0.0.25 + z)*a1 + (0. kpts=(6. atoms=atoms) as calc: try: calc. nsw=20.mil/lattice/struk/c5.(0. 6.625 * a2 + 0.set_cell(cell0 * ((nTiO2 * v / v0)**(1.format(v). 37.125 * a1 + 0.pyplot as plt import numpy as np 114 . nsw=20. Atom(X. 37.u. -0.polyder(rpars) 38 39 40 print ’anatase ppars: {0!r}’.47]) rutile epars: array([ -0. [] for v in volumes: with jasp(’bulk/TiO2/rutile/rutile-{0}’. 33.format(rpars) # get pressure parameters P(V) = -dE/dV dapars = -np.33. np.xlim([25.get_volume() / nTiO2) a_energies. 3) 30 31 32 33 34 35 36 37 print ’E_anatase(V) = {0:1. np.2f}*V^3 + {1:1.get_potential_energy() / nTiO2) 16 17 18 19 20 21 22 23 24 25 # rutile equation of state volumes = [28.plot(vfit.0 a_volumes. r_energies.polyfit(a_volumes. ’g-’) 54 55 56 57 58 59 60 plt.append(atoms.append(atoms.2f}*V^3 + {1:1.format(v)) as calc: atoms = calc.2f}’. 5. 0.2f}*V + {2:1. 40]) plt..)’) plt.2f}*V + {2:1. r_energies = [].2f}*V + {3:1. label=’Rutile’) plt.format(*apars) print ’E_rutile(V) = {0:1.26.get_atoms() nTiO2 = len(atoms) / 3.2f}*V^2 + {1:1. -26]) plt.33*V + 38.xlabel(’Volume ($\AA^3$/f.14*V^2 + -5. 32. a_energies..59 anatase epars: array([ -0. . r_energies. 5.linspace(28.00*V^2 + -0.polyval(apars. label=’Anatase’) plt.format(drpars) 41 42 43 44 print print ’P_anatase(V) = {0:1. 42.format(dapars) print ’rutile ppars: {0!r}’. 3) rpars = np. vfit).2f}’.29. 30.legend() plt.] # vol of one TiO2 r_volumes..get_potential_energy() / nTiO2) 26 27 28 29 # cubic polynomial fit to equation of state E(V) = pars*[V^3 V^2 V^1 V^0] apars = np. -5.)’) plt. -0. In other words we have to solve these two equations: 115 ..polyval(rpars.00*V^3 + 0. ’b-’) 51 52 53 plt. a_energies. 35. -5.polyder(apars) drpars = -np.ylabel(’Total energy (eV/f.2f}*V^2 + {2:1. 34. vfit).format(*rpars) print ’anatase epars: {0!r}’. 39.. E_anatase(V) = -0.append(atoms.format(*drpars) 45 46 vfit = np. .13*V^2 + -5.plot(r_volumes.plot(vfit.append(atoms.33 To find the conditions where a phase transition occurs. 0. ..00*V^3 + 0.23 P_rutile(V) = 0. a_energies = []. 38.’bo ’.23]) rutile ppars: array([ 0.23*V + 42.29*V + 5. [] for v in volumes: with jasp(’bulk/TiO2/anatase/anatase-{0}’.2f}*V^2 + {1:1.py).polyfit(r_volumes.get_volume() / nTiO2) r_energies.2f}’.5 np.33]) P_anatase(V) = 0.14.plot(a_volumes.13.0 r_volumes.2f}*V^2 + {2:1.format(v)) as calc: atoms = calc.format(apars) print ’rutile epars: {0!r}’. we have to find the common tangent line between the rutile and anatase phases. .u.format(*dapars) print ’P_rutile(V) = {0:1..26*V + 5. 40) 47 48 49 50 # plot the equations of state plt.2f}’.59]) anatase ppars: array([ 0.set_printoptions(precision=2) 6 7 8 9 10 11 12 13 14 15 # anatase equation of state volumes = [30.2f}*V + {3:1.47 E_rutile(V) = -0.png’) Open the python script (dft-scripts/script-118.get_atoms() nTiO2 = len(atoms) / 3.’gs ’. 36..23.savefig(’images/rutile-anatase-eos.] # vol of one TiO2 formula unit a_volumes.ylim([-27.00*V^2 + -0. V2) 24 25 26 return [(E_anatase .23520055e+00.vfit). label=’rutile’) plt. we expect that anatase will start converting into rutile. (E_anatase . polyval(anatase_epars.plot(vfit. x0[0]) / GPa) 33 34 35 # illustrate the common tangent import matplotlib. 1 2 from ase.format(polyval(rutile_ppars.67490656 Anatase pressure: 4. [28.V2) .png’) Open the python script (dft-scripts/script-119. We use the func:scipy.1 Bulk reaction energies Alloy formation energies 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.pyplot as plt 36 37 38 39 40 41 42 43 44 45 vfit = linspace(28.savefig(’images/eos-common-tangent.x0[1])].vfit). V1) E_anatase = polyval(anatase_epars.E_rutile) / (V1 .fsolve to solve this problem.E_rutile) / (V1 .8 4. Along this common tangent.74040625e-03.25202869e+01]) rutile_epars = array([-1.23520055e+00]) 5.60558808e-01.(Eanatase (V 1) − Erutile (V 2))/(V 1 − V 2) = Panatase (V 1) (Eanatase (V 1) − Erutile (V 2))/(V 1 − V 2) = Prutile (V 2) This is a nonlinear algebra problem.5 GPa. rutile_ppars = array([3. 40) plt.)’) plt. -5.60893508] At a pressure of 4.)’) plt.85933071e-01. -5. 9 10 11 12 # polynomial fits for pressures anatase_ppars = array([3.optimize.42966536e-01. 4.V2) .52495142656 GPa Rutile pressure: 4. linspace. x0[1]) / GPa) print ’Rutile pressure: {0} GPa’. label=’common tangent’) plt. 4. The solutions are at V = [ 31.24680208e-03.legend() plt. 5.optimize import fsolve x0 = fsolve(func.33239733e+00. V2) 21 22 23 P_rutile = polyval(rutile_ppars. The kinds of questions we can easily answer are: 116 . polyval 3 4 5 6 7 8 # copied from polynomial fit above anatase_epars = array([-1.18147737e-03.P_anatase.P_rutile] 27 28 29 30 31 32 from scipy.33239733e+00]) 13 14 15 16 17 def func(V): V1 = V[0] # rutile volume V2 = V[1] # anatase volume 18 19 20 E_rutile = polyval(rutile_epars.plot(vfit. label=’anatase’) plt. 1.ylabel(’Total energy (eV/f.format(polyval(anatase_ppars.plot(x0.85903670e+01]) 1. a mixture of the two phases will be more stable than either pure phase.u.5249514267 GPa 34.py). ’ko-’. [polyval(rutile_epars.8.u. 3. polyval(rutile_epars.format(x0) print ’Anatase pressure: {0} GPa’. polyval(anatase_epars. V1) P_anatase = polyval(anatase_ppars.x0[0]).30279404e-01. 34]) print ’The solutions are at V = {0}’.xlabel(’Volume ($\AA^3$/f. TODO add literature discussion there is some controversy about the most stable phase. -2. add discussion here. -2.units import GPa from numpy import array.06049246e-03. get_potential_energy() 36 37 38 print ’Cu energy = {0} eV’.000. Given two alloy structures at the same composition.978.000. we will need the total energies of fcc Cu and fcc Pd. 1. 0. 0. We consider two structures with composition CuPd.py). ibrion=2. 1. encut=350. 13. The approach is pretty general. We cannot say Pd is more stable than Cu. cell= [[ 1. Basic alloy formation energy 1 2 3 # get bulk Cu and Pd energies. [ 1. it is not like Cu could transmutate into Pd! Next. [ 0.000. we will rely on the built in unit cell optimization algorithm in VASP (ISIF=3). [0.000. as previously described in the multistep process for optimizing a bulk system. 1.723352 eV Pd energy = -5. [ 1. kpts=(13.000]. To get started. Given a set of alloy structures at different compositions.978.18438 eV Note that the Pd energy is more negative than the Cu energy. and then run a calculation to find the optimized geometry and unit cell.1. which one is more stable? 3. isif=3. 0. 13. nbands=9. 25 26 27 28 29 30 31 32 33 34 35 with jasp(’bulk/alloy/pd’. nbands=9. This may take some work.978. nsw=10.818.000.818. ibrion=2. These coordinates for these structures came from research of the author.000. atoms=atoms) as calc: cu = atoms.818.818.978].818]]) 0.978]]) 0. 0. 0.format(pd) Open the python script (dft-scripts/script-120. kpts=(13.000])]. so we can use the VASP optimization routines.get_potential_energy() 20 21 22 23 24 atoms = Atoms([Atom(’Pd’. xc=’PBE’.818]. you must identify the coordinates and unit cell of the candidate structure. 13).000])].000. Cu energy = -3. cell=[[ 1. Rather than compute a full equation of state for these. 1. nsw=10. 1. 9 10 11 12 13 14 15 16 17 18 19 with jasp(’bulk/alloy/cu’. we will consider a question like which of two structures with composition of CuPd is more stable. [0. 13). 1. which ones are stable with respect to phase separation? Each of these questions is answered by calculating the formation energy of the alloy from the parent metals. <<pure-metal-components>> from jasp import * from ase import Atom. Thus. We get those first. 0.000]. 1. This does not mean anything significant. xc=’PBE’. Is the formation of an alloy at a particular composition and structure energetically favorable? 2.000. atoms=atoms) as calc: pd = atoms. 117 . 1. isif=3.format(cu) print ’Pd energy = {0} eV’.978. encut=350. Atoms 4 5 6 7 8 atoms = Atoms([Atom(’Cu’. [0. Here the geometry is pretty close to optimized. 12. kpts=(12. 8). 7.format(e1) print ’cupd-2: {0} eV/atom’.039]. Atoms 3 4 5 6 7 8 atoms = Atoms([Atom(’Cu’. kpts=(8. 28 29 30 31 32 33 34 35 36 37 38 with jasp(’bulk/alloy/cupd-2’. Atom(’Pd’. isif=3. 7. 5. [-1. atoms=atoms) as calc: cupd2 = atoms. because cupd-2 has twice as many atoms as cupd-1. 3.get_atoms() e1 = atoms.701. 0.629.701. nsw=10. encut=350. 5.format(cupd2) Open the python script (dft-scripts/script-121. Atom(’Cu’. 11.039])].629 ].415.8. cell= [[0. that is the energy normalized per CuPd formula unit. as long as we normalize consistently. xc=’PBE’.415. ibrion=2.804 .get_atoms() e2 = atoms. 2.000. We should compare the normalized total energies.629. This is wrong.get_potential_energy() 39 40 41 print ’cupd-1 = {0} eV’. xc=’PBE’.8).1 2 from jasp import * from ase import Atom.000]). encut=350.979436 eV Looking at these energies. [-0. nsw=10. -2. 2. [-3.629 ].629.format(cupd1) print ’cupd-2 = {0} eV’.804])]. nbands=34.049]).170. 3. 0.303. [-11. 3. 2. It is conventional in alloy calculation to normalize by the number of atoms in the unit cell.804. 5. nbands=17.get_potential_energy() 20 21 22 23 24 25 26 27 atoms = Atoms([Atom(’Cu’.652.get_potential_energy()/len(atoms) 6 7 8 9 with jasp(’bulk/alloy/cupd-2’) as calc: atoms = calc.039.000. isif=3. 9 10 11 12 13 14 15 16 17 18 19 with jasp(’bulk/alloy/cupd-1’. 2. atoms=atoms) as calc: cupd1 = atoms.039. [0. [0.5742045 eV/atom cupd-2: -4. 1 from jasp import * 2 3 4 5 with jasp(’bulk/alloy/cupd-1’) as calc: atoms = calc.format(e2) Open the python script (dft-scripts/script-122.000. ibrion=2.148409 eV cupd-2 = -17. It does not matter which.049.py).000. 0. cell=[[-5. 3.170.039].get_potential_energy()/len(atoms) 10 11 12 print ’cupd-1: {0} eV/atom’. [-3. [-7. Atom(’Pd’.629. you could be tempted to say cupd-2 is more stable than cupd-1 because its energy is much lower. [-3. 0. however. cupd-1: -4. cupd-1 = -9.py). Atom(’Pd’. 5. or as an alternative the number of atoms in the unit cell.701 ]]) 0.000.000.170]). [-5.494859 eV/atom 118 .049.000]]) 0.415]). 0. 11. we show some pretty general code that computes these formation energies. [-3. 0.format(e1) print ’Delta Hf cupd-2 = {0:1. Atom(’Cu’.get_atoms() pd = atoms. but the cupd-1 structure is more stable than the cupd-2 structure. This is shown conceptually in Figure 45.py).246.get_atoms() e1 = atoms. 10.000.get_potential_energy() # subtract bulk energies off of each atom in cell for atom in atoms: if atom. Both structures are energetically more favorable than an equal composition mixture of the parent metals.2f} eV/atom’.821.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. [0.get_potential_energy() for atom in atoms: if atom.get_potential_energy()/len(atoms) 12 13 14 15 16 atoms = Atoms([Atom(’Cu’. Delta Hf cupd-1 = -0. 1 2 from jasp import * from ase import Atom.000]).get_potential_energy()/len(atoms) 8 9 10 11 with jasp(’bulk/alloy/pd’) as calc: atoms = calc.12 eV/atom Delta Hf cupd-2 = -0.2f} eV/atom’.get_atoms() e2 = atoms. is the following reaction exothermic: Cu + Pd → CuPd for the two configurations we examined? Below. 3. Atoms 3 4 5 6 7 # parent metals with jasp(’bulk/alloy/cu’) as calc: atoms = calc. However. [-10. we are looking at total energies. The heat of formation for both structures is exothermic.672. 0. 1 from jasp import * 2 3 4 5 6 # bulk energy 1 with jasp(’bulk/alloy/cu’) as calc: atoms = calc.After normalizing by number of atoms. we can see that cupd-1 is a more stable structure. We will now examine another structure at another composition and its stability. 7. and normalizes them by the number of atoms in the unit cell.821.246.get_atoms() cu = atoms.246])]. 7. Atom(’Pd’. Atom(’Cu’. [-7.672]).symbol == ’Cu’: e1 -= cu else: e1 -= pd e1 /= len(atoms) # normalize by number of atoms in cell 23 24 25 26 27 28 29 30 31 32 with jasp(’bulk/alloy/cupd-2’) as calc: atoms = calc.821]). 3.get_potential_energy()/len(atoms) 12 13 14 15 16 17 18 19 20 21 22 with jasp(’bulk/alloy/cupd-1’) as calc: atoms = calc.672.000.symbol == ’Cu’: e2 -= cu else: e2 -= pd e2 /= len(atoms) 33 34 35 print ’Delta Hf cupd-1 = {0:1. 10.format(e2) Open the python script (dft-scripts/script-123. fcc Cu and Pd? In other words.get_atoms() pd = atoms. and we might ask: is cupd-1 more stable than an unreacted mixture of the parent compounds.04 eV/atom The answer is yes. 119 . ibrion=2.symbol == ’Cu’: e3 -= cu else: e3 -= pd e3 /= len(atoms) print ’Delta Hf cu3pd-1 = {0:1. atoms=atoms) as calc: e3 = atoms.format(Hf1 + (x0 .0.735. 0. Atom(’Pd’. 8).Cu + x0−x3 (Hf.565.000]). [0.get_atoms() pd = atoms. Hf.get_atoms() cu = atoms. 3.000]).86])].25 is: x0−x Hf = Hf.867.x3) * (Hf3 .Hf1)) Open the python script (dft-scripts/script-125.000. Atom(’Cu’.25. nsw=10. 0. 5.5. [-5. let us consider one more structure with the Cu3 Pd stoichiometry.464. cell=[[-3. x = 0.000. Atom(’Cu’.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’. 1 2 from jasp import * from ase import Atom.get_potential_energy() for atom in atoms: if atom. kpts=(8.5. 0.000. 1. [-1. xc=’PBE’.cupd−1 − Hf.12. Atoms 3 4 5 6 7 # parent metals with jasp(’bulk/alloy/cu’) as calc: atoms = calc. 1.464]. Schematically what we are seeing is shown in Figure ??fig:alloy-phase-separation. Finally. We define the following quantities: Hf. 1.000]. However. 5. The composition weighted average at xP d = 0. Hf3 = -0.464]. [-1.py).Cu = 0. Therefore.464. Composition weighted average = -0. 5.2f} eV/atom’. isif=3. encut=350.02 eV/atom The formation energy is slightly exothermic. 3.format(e3) Open the python script (dft-scripts/script-124. Delta Hf cu3pd-1 = -0. nbands=34. [-3. 5. 8. 120 .867.12 eV/atom.get_potential_energy()/len(atoms) 12 13 14 15 16 17 atoms = Atoms([Atom(’Cu’.py).0. 0.464.x) / (x0 .0 eV/atom. Hf1 = 0. which means the structure is more stable than a mixture of the parent metals.464. we could expect that structure to phase separate into a mixture of pure Cu and cupd-1.17 18 19 cell=[[-5.Cu ) 1 2 x0 = 0. 0.get_potential_energy()/len(atoms) 8 9 10 11 with jasp(’bulk/alloy/pd’) as calc: atoms = calc.000.cupd−1 = -0. x3 = 0.867. [0.867]).565.867. x3 = 0. x0 = 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. 1. let us consider whether the structure is stable with respect to phase separation into pure Cu and the cupd-1 structure.000. 0. 3 4 print ’Composition weighted average 5 6 7 = {0} eV’. We did not calculate that structure. isif=3. 0. 3.735. 8). encut=400.54 which uses a cluster expansion methodology.5. Atom(’Cu’. encut=350. 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’. it is known that the CuPd alloy forms a bcc structure.06 eV/atom. We cannot say. Atoms 4 5 6 # http://phycomp.27 7 8 9 10 11 12 13 atoms = Atoms([Atom(’Cu’. 4.000.5. 0. nsw=10.get_potential_energy() for atom in atoms: if atom.html#Cu2O a = 4.2f} eV/atom’. We also note here that we have ignored a few other contributions to alloy stability. 3. One approach is to use a tool that automates the discovery of relevant structures such as the Alloy Theoretic Automated Toolkit (ATAT) 53. 0. 18 19 0. 8. 0.2 Metal oxide oxidation energies We will consider here the reaction 2 Cu2 O + O2 4 CuO. We need to compute the energy of each species.0. atoms=atoms) as calc: e4 = atoms. 0. 0. Cu2 O calculation 1 2 3 # run Cu2O calculation from jasp import * from ase import Atom.py). We have only considered the electronic energy contributions to the formation energy.000.000. and it is below the composition weighted formation energy of -0.5. so we can not say if it is more or less stable than the obvious fcc structure we found.75.[0.symbol == ’Cu’: e4 -= cu else: e4 -= pd e4 /= len(atoms) print ’Delta Hf cu3pd-2 = {0:1.set_cell((a. 0. nbands=34. Atom(’Cu’. a). we conclude that this structure will not phase separate into a mixture of Cu and CuPd. Atom(’O’.il/~ira/types.5.25]).5]). 121 . 0.0]). 0. Atom(’O’.25. 0. Delta Hf cu3pd-2 = -0. The construction of alloy phase diagrams is difficult. scale_atoms=True) 16 17 18 with jasp(’bulk/Cu2O’. or if it might phase separate into two other phases. however. [0. 0]). Atom(’Cu’. [0. kpts=(8. ibrion=2. our analysis is limited to comparisons of the structures computed on the fcc lattice.75. which may stabilize some structures more than others.ac. The reaction energy is: ∆E = 4ECuO − 2ECu2 O − EO2 . if there is a more stable phase not yet considered. [0. At temperatures above absolute zero there are additional contributions including configurational and vibrational entropy.format(e4) Open the python script (dft-scripts/script-126.735].5]). You are always faced with the possibility that there is a phase that you have not calculated that is more stable than the ones you did calculate. [0. Consequently. In fact. a.10 eV/atom This looks promising: the formation energy is much more favorable than cu3pd-1.8.technion. [0. [0.0. xc=’PBE’. Finally. 0. [0.75])]) 14 15 atoms.25. 000 -0. : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/bulk/Cu2O converged: True Energy = -27.135 2.270 4.alpha.270 0. 8). xz.135] 0 0.000 4. yy.000 0.000] 0 0.00 T T T 1 Cu [2. yz.19 20 21 22 23 24 25 26 27 kpts=(8.270 a.0 magmom: None prec: Normal kpts: (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) CuO calculation 122 .00 T T T 2 Cu [2.py).000 2.270 90.000] 0 0.b.000] 4.gamma (deg):4.270 4.000 0.000 2.y.202] 0 0.c.0 90.set_nbands() calc.270 a1 [ 0.calculate() print calc Open the python script (dft-scripts/script-127.000 0. 8. xy 0.854 Ang^3 Stress (GPa):xx.beta.000-0.z]tag rmsForce constraints 0 Cu [0. nsw=30. xc=’PBE’.135 0.000 Atom# sym position [x.000 -0.000 0. atoms=atoms) as calc: calc.067 1.135 0.000] 4.202 3.00 T T T 4 O [1. isif=3.00 T T T 5 O [3.270 0. zz.270] 4.202 3.067] 0 0.0 Unit cell volume = 77.204590 eV Unit cell vectors (angstroms) x y z length a0 [ 4.000 0. 8.000 4.270 a2 [ 0.135] 0 0. ibrion=2.067 1.00 T T T -------------------------------------------------INCAR Parameters: ----------------nbands: 37 nsw: 30 ibrion: 2 isif: 3 encut: 400.0 90.135 2.00 T T T 3 Cu [0.000 0. 5*a2).beta.4226 c = 5.navy.5819 13 14 15 16 a1 = np.6837 b = 3.array([c*np.1 2 3 # run CuO calculation from jasp import * from ase import Atom.008 0.5*b.5*a.776 0. a2.046] 2. yy.000 5.151 0.cos(beta). Atom(’O’.b.54/180*np. Atom(’O’.908 a1 [ 2.776 0.770 -0.03 T T T -------------------------------------------------INCAR Parameters: ----------------nbands: 23 nsw: 30 ibrion: 2 123 .000 Atom# sym position [x. Atoms 4 5 6 7 8 9 10 11 12 # CuO # http://cst-www.25*a3)].5*a3).5*a1 + 0.set_nbands() calc.0.0]) a2 = np. c*np. 0.566] 0 0. nsw=30.alpha.html a = 4. cell=(a1.013 0.8 95. zz.00 T T T 1 Cu [0.html # http://www.com/docs/info/10681727_51. -y*a1 + y*a2 + 0.302 1. 8.908 2. 8).1288 beta = 99.z]tag rmsForce constraints 0 Cu [1. xc=’PBE’.03 T T T 3 O [1.y*a2 .888 0.8 95. ibrion=2. 0.array([0.25*a3). atoms=atoms) as calc: calc.gamma (deg):2.111 -0.0.8 Unit cell volume = 41. 0.000 0.00 T T T 2 O [2.302 -1.009-0. : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/bulk/CuO converged: True Energy = -19. 0.023] 0 0.762 0. xy 0.861] 0 0. 0.087] 5.046] 2.5*a.0]) a3 = np.144 95.908 5.730 Ang^3 Stress (GPa):xx.5*b.168 1.888 2.168 3. yz. y*a1 .sin(beta)]) 17 18 19 20 21 22 atoms = Atoms([Atom(’Cu’.springermaterials.000 -0.calculate() print calc Open the python script (dft-scripts/script-128. xz.144 a. kpts=(8.730 0.nrl.mil/lattice/struk/b26.c. 0.array([0. Atom(’Cu’.318] 0 0.509498 eV Unit cell vectors (angstroms) x y z length a0 [ 2. a3)) 23 24 25 26 27 28 29 30 31 32 33 34 with jasp(’bulk/CuO’.y.908 a2 [-0.py).pi y = 0. encut=400. -0. isif=3. so the number of formula units in an atoms is # len(atoms)/3.wiley.966119 eV This is the reaction energy for 2 Cu2 O → 4 CuO.get_masses().0*cuo_energy . 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 from jasp import * 2 3 4 5 6 7 8 # don’t forget to normalize your total energy to a formula unit. In. One reason is related to errors in the O2 dissociation energy. 8.py).2. There are a few reasons why our number does not agree with the experimental reaction energy.format(rxn_energy) Open the python script (dft-scripts/script-129.get_potential_energy() 18 19 20 rxn_energy = 4. 1 2 3 from ase import Atoms atoms = Atoms(’Cu2O’) MW = atoms. # kJ/g print ’rxn energy = {0:1.14 eV.com/doi/ 10. Cu2O # has 3 atoms.isif: encut: magmom: prec: kpts: reciprocal: xc: txt: gamma: 3 400.4) # convert to eV Open the python script (dft-scripts/script-130. and another reason is related to localization of electrons in the Cu 3d orbitals.get_atoms() o2_energy = atoms.py). Reaction energy = -1. 55 Fixing the second error requires the application of DFT+U (see DFT+U).4440130107/pdf for the reaction 2CuO Cu2 O + 1/2 O2 .get_potential_energy()/(len(atoms)/2) 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.o2_energy . The heat of reaction is reported to be 1000 J/g product at http://onlinelibrary.get_potential_energy()/(len(atoms)/3) 9 10 11 12 with jasp(’bulk/CuO’) as calc: atoms = calc.format(-2 * H * MW / 96.sum() 4 5 6 H = 1.1f} eV’. with jasp(’bulk/Cu2O’) as calc: atoms = calc. 55 The first error of incorrect O2 dissociation error is a systematic error that can be corrected empirically. 55 the experimental reaction is estimated to be about -3. 124 .0*cu2o_energy print ’Reaction energy = {0} eV’.get_atoms() cuo_energy = atoms.get_atoms() cu2o_energy = atoms.1002/er.0 None Normal (8. 24 A highly technical discussion of this issue can be found in Ref. B]. and β is a broadening function. (2.calc. 1 from jasp import * 2 3 4 npoints = 200 width = 0.get_fermi_level() 22 23 24 # these are the energies we want to evaluate the dos at energies = np.1)).1 5 6 7 8 def gaussian(energies. (2. VI. k in enumerate(wk): e_kn. showed that the highest occupied eigenvalue is equal to the ionization energy of a system within an exact density functional theory. npoints) 25 26 27 # this is where we build up the dos dos = np. which can be measured with photoelectron spectroscopy. 56–58 and is only true for the exact exchange/correlation functional.array(e_kn) .pi) / width 9 10 with jasp(’bulk/pd-dos’) as calc: 11 12 13 # kpt weights wk = calc.9 Bulk density of states The density of states refers to the number of electronic states in a particular energy range.1) yields a set of Kohn-Sham (K-S) orbitals and an associated set of eigenvalues that correspond to the energies of these orbitals. 18 The sum of the squared K-S orbitals. to account for the finite number of k-points used in the calculations. and the sum of the eigenvalues is a significant part of the total energy (Eq. and should tend to zero as the number of k-points approaches infinity.rxn energy = -3.linspace(e_kn. it seems reasonable to suppose these quantities have other significant relationships to physical observables. to use them to calculate the density of states (DOS) 61 [Sec.min(). The amount of broadening is arbitrary. The solution to Eq. 62 . 3 Stowasser and Hoffmann discussed an approach to using the K-S orbitals in more traditional molecular orbital interpretations. e_kn. is equal to the electron density (Eq.0 eV This is pretty close to the value in 55 and might need a temperature correction to get agreement at 298K. but poor results for tightly bound orbitals and band gaps. eik): x = ((energies .1)). but the results were primarily qualitative. however. Perdew et al. it has become fairly standard.get_eigenvalues(kpt=i)) 20 21 e_kn = np. 59 More recently. 4. typically a gaussian function.append(calc. a DFT analog of Koopmans’ theorem has been developed that formally identifies the eigenvalues with vertical ionization potentials. neither of which have any known directly observable meaning. not the approximate ones used in practice. 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.zeros(npoints) 125 . This has been found to yield reasonable results for the valence bands in metals.exp(-x**2) / np. 60 Despite the arguments against ascribing physical meaning to the K-S orbitals and eigenvalues. Thus. 24 but their interpretation has been vigorously debated in the literature.eik) / width) return np. (2.max(). especially for solids.sqrt(np.get_k_point_weights() 14 15 16 17 18 19 # for each k-point there are a series of eigenvalues # here we get all the eigenvalues for each k-point e_kn = [] for i. pyplot as plt from ase.savefig(’images/pd-dos. e_kn[k][i]) 33 34 35 36 37 import matplotlib.py).png’) Open the python script (dft-scripts/script-132.png’) plt.pyplot as plt plt.py). The peak between -5 to 0 eV is the Pd d-band.ylabel(’DOS’) plt.2) d = dos.get_energies() 9 10 11 12 13 14 import pylab as plt plt. This DOS looks roughly like you would expect.plot(e.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].show() Open the python script (dft-scripts/script-131. width=0. The VASP manual recommends a final run be made with ISMEAR=-5. Here is a more convenient way to compute the DOS using mod:ase.xlabel(’energy (eV)’) plt.plot(energies. 126 .get_dos() e = dos.dft. dos) plt.savefig(’images/manual-dos. which uses the tetrahedron method with Bl\"ochl corrections. d) plt. 1 2 3 from jasp import * import matplotlib.dft import DOS 4 5 6 7 8 with jasp(’bulk/pd-dos’) as calc: dos = DOS(calc. encut=300. d) plt. b.get_atoms() calc.png’) plt.ylabel(’DOS’) plt. 0. kpts=(k. We can test for convergence of the DOS.2) d = dos. xc=’PBE’. 16.format(k).get_dos() + k / 4.0))]. 12.xlabel(’energy [eV]’) plt. b. Atom from jasp import * import sys 4 5 6 7 8 import matplotlib. 1 2 3 from ase import Atoms.9 # approximate lattice constant b = a / 2.py). 14. Much insight into bonding has been gained by 127 . 18. (b.1 2 3 4 from jasp import * from ase. b). k).plot(e.show() Open the python script (dft-scripts/script-134.savefig(’images/pd-dos-ismear-5.dft import DOS import pylab as plt 9 10 11 12 13 14 15 a = 3.0 e = dos.get_energies() 14 15 16 17 18 19 import pylab as plt plt. label=’k={0}’.py).0.xlabel(’energy (eV)’) plt. k. cell=[(0. (0. 0. atoms=bulk) as calc: 25 # this runs the calculation try: bulk.d. width=0.png’) Open the python script (dft-scripts/script-133.plot(e. 4.legend() plt.2) d = dos.ylabel(’DOS’) plt. 0.dft import DOS with jasp(’bulk/pd-dos’) as calc: calc. 10.get_dos() e = dos.10 Atom projected density of states 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. 0)]) 16 17 kpts = [8.0.get_potential_energy() dos = DOS(calc. (b.clone(’bulk/pd-dos-ismear-5’) 5 6 7 8 with jasp(’bulk/pd-dos-ismear-5’) as calc: bulk = calc.format(k)) except: pass plt. This not notably different to me. 20] 18 19 20 21 22 23 24 for k in kpts: with jasp(’bulk/pd-dos-k{0}-ismear-5’. bulk = Atoms([Atom(’Pd’. width=0.pyplot as plt import numpy as np from ase.get_energies() 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 plt. The k-points are most important.get_potential_energy() dos = DOS(calc. b).savefig(’images/pd-dos-k-convergence-ismear-5.set(ismear=-5) 9 10 11 12 13 bulk. 9 # approximate lattice constant b = a / 2. we consider how to get the atom-projected density of states (ADOS). the one electron wave functions can be projected onto spherical harmonic orbitals. However. The first moment is the average energy of distribution. beyond which no contributions are included. however. the d-band filling can be determined. This difficulty arises because the orbital-band occupations are not observable. the d-orbital electron count is well defined. if it is too large. the remaining discussion will be focused on the properties of the projected d-states. 66 Consequently. 7 and linear muffin tin orbital theory. you can see very different ADOS. In a solid. 7 Consequently. a cutoff radius was introduced.g. The s and p states in a metal are typically delocalized in space and more like free-electrons. analogous to the center of mass for a mass density distribution. such as the d-band center and d-band width. The nth order moment. 67 and Chapter 6 in Refs. this means that the projection on one atom may overlap with the projection on a neighboring atom. several schemes have been developed to project the one-electron Kohn-Sham wave functions onto atomic wave functions. 68 and 69 ). as will be seen later. It is not obvious what the electron count in the d-band should be for an atom in a metal. is sensitive to the cutoff radius (and in other DFT implementations. We are interested in properties of the d-band on Pd. 1 2 3 from ase import Atoms. in contrast.0))]. so it will be used as an initial reference point for comparison. it may include electrons from neighboring atoms. and only the first and second moments are considered in this work. 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. which have different sizes. One might want to use different cutoff radii for different atoms. resulting in double counting of electrons. the d orbitals are fairly localized and reasonably approximated by atomic orbitals. The zeroth moment is just the total number of states. The second moment is the mean squared width of the distribution. and these are the Wigner-Seitz radii for each atom. but these moments are rarely used.vasp import VaspDos 4 5 6 import matplotlib. and that is precisely what these quantities are used for here. e. Thus. it might not capture all of the electrons associated with the atom. (0. Mulliken orbital populations have been used successfully for many years to examine the qualitative differences between similar systems.0. It is not obvious what the best cutoff radius is. 63–65 In VASP.0. You must set the RWIGS tag to get ADOS.pyplot as plt import numpy as np 7 8 9 10 a = 3. 4 A powerful method for characterizing distributions is to examine various moments of the distribution (see Chapter 4 in Ref. which has carried over to the solid-state arena. In this example. If the radius is too small. 0. a discussion of the analysis and results is warranted. 128 . Atom from jasp import * from ase. The radial component of the atomic orbitals extends to infinity. in this case it will be normalized to unity. Depending on the cutoff radius (RWIGS) you choose. The s valence orbitals in a metal.atomic/molecular orbital theory. thus it would require an iterative procedure to determine it. µn .calculators. For a gas-phase. The third moment is a measure of skewness and the fourth moment is related to kurtosis. They are the wavefunctions projected onto atomic orbitals. bulk = Atoms([Atom(’Pd’. By integrating the projected d-band up to the Fermi level. neutral metal atom in the ground state. Furthermore. It is important to note that these projected density of states are not physical observables. However. the reference energy is always the Fermi level. thus how the electrons are divided up between atoms is arbitrary and. the ideal cutoff radius for an atom may change in different environments. For some situations this makes sense. 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. are almost totally delocalized. 0. Consequently. the basis set). trapz(dos.trapz(dos.25) 60 61 62 plt.ylabel(’DOS (arbitrary units)’) 63 64 65 plt. 8.shape). 5 ind = (energies < 5) & (energies > -10) 34 35 36 energies = energies[ind] dos = dos[ind] 37 38 39 40 41 42 Nstates = np.xlabel(’$E . energies) / np.18 d-band center = -2.zeros(dos[occupied].calculators.fill_between(x=energies[occupied]. 0. label=’$d$-orbitals’) 54 55 56 57 58 59 # plot the occupied states in shaded gray plt. (b. energies) 46 47 48 49 50 print print print print ’Total # states = {0:1.trapz(energies**2 * dos.py). get d-orbitals on atom 0 31 32 33 # we will select energies in the range of -10.72 eV 4. energies) occupied = energies <= 0.0 N_occupied_states = np. xc=’PBE’.savefig(’images/pd-ados.2f}’.10. y1=dos[occupied]. # wigner-seitz radii for ados kpts=(8. 1 2 3 from ase import Atoms. encut=300.format(np. energies) 43 44 45 # second moment wd2 = np. color=’gray’.2f} eV’.get_potential_energy() 25 26 27 # now get results ados = VaspDos(efermi=calc. energies) / np. Total # states = 9.1 Effect of RWIGS on ADOS Here we examine the effect of changing RWIGS on the number of counted electrons.29 number of occupied states = 8. lreal=False. 0)]) 11 12 13 14 15 16 17 18 19 20 21 with jasp(’bulk/pd-ados’. b).format(N_occupied_states) ’d-band center = {0:1.png’) plt. dos.show() Open the python script (dft-scripts/script-135. and properties of the d-band moments.00 eV d-band width = 2.energy dos = ados. b. (b. energies[occupied]) # first moment ed = np. y2=np.2f} eV’.cell=[(0.trapz(energies * dos.sqrt(wd2)) 51 52 53 # plot the d-band plt. b). ’d’) # energy is an attribute. Atom from jasp import * from ase.site_dos(0.get_fermi_level()) 28 29 30 energies = ados.E_f$ (eV)’) plt.format(Nstates) ’number of occupied states = {0:1.trapz(dos.5].format(ed) ’d-band width = {0:1. atoms=bulk) as calc: 22 23 24 # this runs the calculation bulk.plot(energies. rwigs=[1. 8). not a function # this is a function.trapz(dos[occupied].2f}’. b. alpha=0.vasp import VaspDos 129 . energy dos = ados.trapz(energies**2 * dos. 5.append(N_occupied_states) ED. 0.1.py).ylabel(’# occupied states’) plt. energies) / np. 2.trapz(dos. energies) / np. b. label=’d-band width (eV)’) ax2. b).trapz(dos.5) 53 54 55 56 57 58 plt.0 N_occupied_states = np. 5 ind = (energies < 5) & (energies > -10) 40 41 42 energies = energies[ind] dos = dos[ind] 43 44 45 46 47 48 Nstates = np. energies) 49 50 51 52 N. (0.0 ] 17 18 ED.clone(’bulk/pd-ados-rwigs-{0}’.25.0. label=’N. (b.0))]. energies) occupied = energies <= 0.0.5.get_yticklabels(): tl.set_xlabel(’RWIGS ($\AA$)’) ax1.format(rwigs)) as calc: calc.show() Open the python script (dft-scripts/script-136.set_ylabel(’d-band center (eV)’. N = [].twinx() ax2.get_fermi_level()) 34 35 36 energies = ados. VaspQueued): continue 29 30 31 32 33 # now get results ados = VaspDos(efermi=calc. color=’b’) for tl in ax1. 0.5. 1. 1. cell=[(0. (b. energies[occupied]) ed = np.plot(RWIGS.append(wd2**0.4 import sys 5 6 7 import matplotlib. b. ED. ’gs’.get_yticklabels(): tl.set_color(’b’) 67 68 69 70 71 72 ax2 = ax1.set_ylabel(’d-band width (eV)’.pyplot as plt import numpy as np 8 9 10 11 12 13 14 a = 3. ax1 = plt.set(rwigs=[rwigs]) 26 27 try: 28 calc. 3.trapz(dos[occupied].savefig(’images/ados-rwigs-occupation. WD.format(rwigs)) 23 24 25 with jasp(’bulk/pd-ados-rwigs-{0}’. ’bo’. 2. [] 19 20 21 22 for rwigs in RWIGS: with jasp(’bulk/pd-ados’) as calc: calc. energies) wd2 = np. bulk = Atoms([Atom(’Pd’.0.0.trapz(energies * dos. color=’g’) for tl in ax2.plot(RWIGS.9 # approximate lattice constant b = a / 2. 0)]) 15 16 RWIGS = [1.set_color(’g’) 73 74 75 plt. 0.trapz(dos. b).append(ed) WD.subplots() ax1.legend(loc=’best’) plt. WD. 4.site_dos(0.calculate() except (VaspSubmitted. 1.savefig(’images/ados-rwigs-moments. label=’d-band center (eV)’) ax1.0. ’bo’. 130 . ’d’) 37 38 39 #we will select energies in the range of -10.plot(RWIGS. occupied states’) plt.png’) plt. []. N.0.png’) 59 60 61 62 63 64 65 66 fig.xlabel(’RWIGS ($\AA$)’) plt. a / 2.DEBUG. xc=’PBE’. 1 2 3 from jasp import * from ase import Atom.beta.0].. 0.0 60.799983 eV Unit cell vectors (angstroms) x y z length a0 [ 2.]].026-0.695] 3. [0. xy -0. Atom(’Si’.get_potential_energy() print calc Open the python script (dft-scripts/script-137. scale_atoms=True) 12 13 14 15 16 17 18 19 20 21 22 with jasp(’bulk/Si-selfconsistent’.25. 4).sciencenet.0.0.y.000] 3.000 -0. [0. [0.1e-03.0 60.25. a / 2.00 T T T -------------------------------------------------INCAR Parameters: ----------------nbands: 8 istart: 0 icharg: 2 131 .000 2. 4. First. We will use Si as an example (adapted from http://bbs.c. The d-band center and width also change. 0. yz.026 -0.000] 0 0. yy.z]tag rmsForce constraints 0 Si [0.000 2. kpts=(4.811 3. 4.026 -0.347] 0 0.. : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/bulk/Si-selfconsistent converged: True Energy = -10.695 0..695] 3. [a / 2.cn/bbs/upload/20083418325986.000 Atom# sym position [x.000 0.811 a1 [ 0.347 1. Atoms from ase.]. First. xz. we compute the self-consistent band structure. 0.11 Band structures To compute a band structure we do two things.134 Ang^3 Stress (GPa):xx. we get the self-consistent electron density in a calculation. atoms=atoms) as calc: atoms. This is due to overcounting of neighboring electrons.811 a2 [ 2.25])]) 8 9 10 11 atoms.695 2.38936 atoms = Atoms([Atom(’Si’. Then we compute the band structure at the desired k-points. 0.695 2.. debug=logging. a / 2.695 0.b. 0]).811 60.pdf).00 T T T 1 Si [1. 0. zz.gamma (deg):3.0 Unit cell volume = 39. prec=’Medium’. istart=0.000 0.visualize import view 4 5 6 7 a = 5. ediff=0. icharg=2.py).347 1.You can see the number of occupied states increases approximately linearly here with RWIGS.000 -0.set_cell([[a / 2. a / 2.811 a.811 3.alpha. 205 -0.c. kpts=kpts.z]tag rmsForce constraints 0 Si [0. reciprocal=True.347 1.5. 0. 0].ediff: magmom: prec: kpts: reciprocal: xc: txt: gamma: 0.134 Ang^3 Stress (GPa):xx.gamma (deg):3.000 2. icharg=11) as calc: calc. zz. yy. we run a new calculation along the k-point path desired. 0].811 3.000 0.000 2. [0.000 Atom# sym position [x. Doing that results in some lost information if you overwrite the old files.811 a1 [ 0.b.000 0.clone(wd) 7 8 9 10 11 kpts = [[0.811 a2 [ 2.00 T T T -------------------------------------------------- 132 . 0. xy -0. yz. using code to ensure this only happens one time. : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/bulk/Si-bandstructure converged: True Energy = -3.5.000 -0.811 60.alpha.695 0.0 60.0 60. 4) False PBE False Pseudopotentials used: ---------------------Si: potpaw_PBE/Si/POTCAR (git-hash: ae2291fdf186a34272463039fb5a87cde0e50174) Now. 1 from jasp import * 2 3 wd = ’bulk/Si-bandstructure’ 4 5 6 with jasp(’bulk/Si-selfconsistent’) as calc: calc.205 -0.0001 None Medium (4. [0.620909 eV Unit cell vectors (angstroms) x y z length a0 [ 2. 0. We will copy the old directory to a new directory.811 a.00 T T T 1 Si [1.calculate() print(calc) Open the python script (dft-scripts/script-138. The standard VASP way of doing this is to modify the INCAR and KPOINTS file and rerun VASP. 0.695] 3.000] 3.5.695 0.347 1.811 3.0].695] 3.695 2. 4. kpts_nintersections=10.205-0. xz.py).beta.000] 0 0. We will not do that.5]] # L # Gamma # X 12 13 14 15 16 17 18 19 with jasp(wd.347] 0 0.0 Unit cell volume = 39. 0.y.000 -0.695 2.5. [0. 0. 000000000000000E-004 CAR unknown system 8 20 8 0.0].5000000E+00 1 -1.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.5000000E-01 0.4444444E+00 0. [0.INCAR Parameters: ----------------nbands: 8 istart: 0 icharg: 11 ediff: 0.py).392989 8 16.5. 0. 0. 0].826306 3 3. 1 f = open(’bulk/Si-bandstructure/EIGENVAL’.5000000E-15 . 0]. 0.readline() f.3810853E-09 1. 0. ’r’) 2 3 4 5 6 line1 line2 line3 line4 = = = = f.3810853E-09 0.5.readline() f.4444444E+00 1 -2.826311 2 -1. [0.0001 magmom: None prec: Medium kpts: [[0.1956688E+02 0.0000000E+00 0.744294 6 6. [0.3810853E-09 0.5.669062 2 -0.153716 5 6.918013 0. 2 2 1 1 0. 0.5000000E-01 We can ignore the first five lines.5.405965 0.0000000E+00 0.readline() 133 0.744321 7 16. The structure of the EIGENVAL file looks like this: 1 head -n 20 bulk/Si-bandstructure/EIGENVAL Open the python script (dft-scripts/script-139.readline() f.5000000E+00 0. 0.153690 4 3. [0.savefig(’images/Si-bandstructure. energy = int(fields[0]). 0. 0. 0.]. 0. Atom(’Si’. a/2. (’$\Gamma$’. [0. (’X’.readline(). Since the lattice constant affects the overlap of neighboring atoms. weight = [float(x) for x in f. [0.. nbands = [int(x) for x in f. we expect that smaller lattice constants will show more dispersion.split()] 9 10 blankline = f. broader bands. 0.7 8 comment = f. ’$\Gamma$’. bands. 1 2 from jasp import * from jasp. we examine the effect of the lattice constant on the band structure.1 create example showing band dispersion with change in lattice constant In this section.set_cell([[a/2. 0. a/2.. 0.close() 23 24 import matplotlib.38936.0. [0.append(energy) blankline = f. Next we will examine the connection between band structures and density of states. Larger lattice constants.readline() unknown. 0. [0. p = calc. 0.5. 19]) ax.1].e. nkpoints.5.set_xticks([0. 1 2 from jasp import * from jasp. 0]). [0.jasp_bandstructure import * 3 4 5 6 from ase import Atom.5.0.png’) Open the python script (dft-scripts/script-140. 4. 134 .. 6. 0.0.0.readline(). ’$X$’]) plt.5]).ylabel(’Energy (eV)’) ax.set_xticklabels([’$L$’.0.split()] 16 17 18 19 20 21 22 for j in range(nbands): fields = f.0]).0]. band_energies[i]) 28 29 30 31 32 33 34 35 ax = plt. 0.5. (’M’.readline() 11 12 band_energies = [[] for i in range(nbands)] 13 14 15 for i in range(nkpoints): x.11.0]).png’) Open the python script (dft-scripts/script-141.readline().0.plot(range(nkpoints). 10. 0.split() id.xlabel(’k-vector’) plt. In this example.25. (’X’. 0.gca() ax.get_bandstructure(kpts_path=[(’$\Gamma$’.5.py).set_xticks([]) # no tick marks plt.savefig(’images/tio2-bandstructure-dos.py). z.25])]) 10 11 12 atoms. 0.25. i. 0. we will compute the band structure of TiO2 using a function built into mod:jasp to do the analysis described above.pyplot as plt 25 26 27 for i in range(nbands): plt.0]): 7 8 9 atoms = Atoms([Atom(’Si’. 0. Atoms ready = True for i.5. y.jasp_bandstructure import * 3 4 5 6 7 8 9 10 with jasp(’bulk/tio2/step3’) as calc: n.0]). should show narrower bands. (’M’. in contrast. [0.7.readline() f.5]). We examine this in silicon. a/2. [0.0.0])]) 11 12 p. float(fields[1]) band_energies[id . [0. 5.a in enumerate([4. 8.format(i) ready = False 32 33 34 if not ready: import sys. (’$\Gamma$’.. You cannot set it to be an arbitrary float. 6.png’. [0. energies) 135 .5. 4).5.0.]]. encut=300. 0. 1.[a/2.savefig(’images/Si-bs-{0}. then we know there is a lower energy magnetic solution than a non-magnetic solution. Note that NUPDOWN can only be an integer. kpts=(4.12.plot(NUPDOWNS.bands. 5. kpts=(4. (’$\Gamma$’. 0]). nupdown=B.lattice. 1 2 from jasp import * from ase.get_potential_energy() energies.0. If there is a minimum in the energy.exit() 35 36 37 38 p. VaspQueued): pass 25 26 27 import matplotlib. 0. 4. ediff=0.1 Determining if a magnetic solution is energetically favorable We can force a total magnetic moment onto a unit cell and compute the total energy as function of the total magnetic moment.12 Magnetism 4. atoms=atoms) as calc: try: n.0.0]). 0].format(B). scale_atoms=True) 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}’. ispin=2. [0. symbol=’Fe’) 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 NUPDOWNS energies for B in with = [0. [0. istart=0. [0. a/2. 0.py). 1]].p = calc.0.cubic import BodyCenteredCubic 3 4 5 6 7 8 atoms = BodyCenteredCubic(directions=[[1. xc=’PBE’. 4. 1).append(e) except (VaspSubmitted.0. 4. (’X’.5.0. 0]).0.1e-03.pyplot as plt plt. prec=’Medium’. 0.5])].0 is notably sharper than the band structure for a=4. 2. 0]. xc=’PBE’. 4. kpts_nintersections=10) except (VaspSubmitted. We use incar:NUPDOWN to enforce the magnetic moment in the cell. icharg=2.0.format(i)) p.format(i). not ready 0 You can see the band structure for a=6. sys. 0. 0.0. 0.2f}’. size=(1. 1. [0.5.show() Open the python script (dft-scripts/script-142. atoms=atoms) as calc: try: e = atoms. [0.0] = [] NUPDOWNS: jasp(’bulk/Fe-bcc-fixedmagmom-{0:1. VaspQueued): print ’not ready {0}’.get_bandstructure(kpts_path=[(’L’. 4). 25 Bohr-magnetons Individual moments are [ 2.5 Bohr-magnetons.3. prec=’Normal’. 1).15.00. 1.magmom = 2.py). Magnetic moments = [ 2. 0.get_magnetic_moments() print ’Total magnetic moment = ’.lattice. # you need this for individual magnetic moments atoms=atoms) as calc: try: e = atoms.3.3]]) 11 12 13 14 15 16 17 18 19 20 21 with jasp(’bulk/afm-feo’.Atom object.3. It is possible to model this by setting the magnetic moments on each mod:ase. 4. [0. 4. 1 2 from jasp import * from ase import Atom. we must set the magnetic moment on the atoms. Note that VASP recommends you overestimate the magnetic moment guesses if you are looking for ferromagnetic solutions. 2. magmom=5). 0.xlabel(’Total Magnetic Moment’) plt.00. lorbit=11. 1]]. [2. kpts=(4.3.28 29 30 31 plt. 4. VaspQueued): pass 27 28 29 print ’Total magnetic moment is {0:1. This is a good guess for a real calculation.00]. 2. there are equal numbers of spin up and down electrons that align in a regular pattern. magmom=0). 0]. 2.45.15.png’) plt.15. encut=300. but pointing in opposite directions so that there is no net magnetism.get_potential_energy() B = atoms.15]. In the example after this. [0. [6. [2. 0]. Atom(’O’. atoms. 2. ] .get_magnetic_moment() Open the python script (dft-scripts/script-145.get_magnetic_moment() magmoms = atoms. To run a spin-polarized calculation with initial guesses on each atom. [2.py). [0.cubic import BodyCenteredCubic 3 4 5 6 7 8 atoms = BodyCenteredCubic(directions=[[1. You can see here there is a minimum in energy at a total magnetic moment somewhere between 4 and 5. 0. [4. 6. 4. 1. Here we set it through the magmom attribute on the atom. 4).15]. # this forces a non-magnetic solution lorbit=11. Atom(’O’.format(magmoms) Open the python script (dft-scripts/script-144.652 0. 0. magmom=-5). atoms. we set it in the Atoms object. encut=350. 6. cell=[[4.show() Open the python script (dft-scripts/script-143. Atom(’Fe’.652 -2.2f} Bohr-magnetons’.15. 2. Total magnetic moment is 4. ispin=2. 4. symbol=’Fe’) 9 10 11 12 # set magnetic moments on each atom for atom in atoms: atom.savefig(’images/Fe-fixedmagmom.45].format(B) print ’Individual moments are {0} Bohr-magnetons’. which means the magnetic moment on each atom must be about 2. Atoms 3 4 5 6 7 8 9 10 atoms = Atoms([Atom(’Fe’.12.ylabel(’Energy (eV)’) plt.45.134] Bohr-magnetons 4. 1 2 from jasp import * from ase.2 Antiferromagnetic spin states In an antiferromagnetic material.get_magnetic_moments() except (VaspSubmitted.15. # to get individual moments lreal=False.15.15].3].134 2. size=(1. xc=’PBE’. ispin=2.py). There are two Fe atoms in the unit cell. magmom=0)]. 0. nupdown=0. 136 atoms=atoms) as calc: print ’Magnetic moments = ’. 2.5 13 14 15 16 17 18 19 20 21 22 23 24 25 26 with jasp(’bulk/Fe-bcc-sp-1’. Figure 30: A side view of graphite. 137 . 138 .Figure 31: A view of a NaCl crystal structure. 139 .Figure 33: k-point convergence of the total energy of fcc Ag. Figure 34: Effects of SIGMA on the occupancies of the Cu system. 140 . volume for fcc Cu with fitted cubic polynomial equation of state. 141 . fcc lattice contant for Cu.Figure 35: Total energy vs. Figure 36: Total energy vs.65 Å. It appears the minimum is near 3. 142 .Figure 37: Comparison of energies between fcc and bcc Cu. The fcc structure is lower in energy. c/a for different values of a.Figure 38: Total energy vs. 143 . 144 .Figure 39: Contour plot of the total energy of hcp Ru for different values of a and c/a. Figure 40: k-point convergence of rutile TiO2 . 145 . volume for rutile TiO2 in step 1 of the optimization.Figure 41: Total energy vs. 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 . 149 .Figure 44: Illustration of the common tangent that shows the pressure where anatase and rutile coexist before anatase converts to rutile. 150 .Figure 45: Conceptual picture of two alloys with exothermic formation energies. E4 and E3 are energies associated with two different alloy structures at the same composition. The dashed line represents a composition weighted average energy of the parent metals. Both structures are more stable than a mixture of pure metals with the same composition. but E3 is more stable than E4. Since the energy of cu3pd-1 is above the solid line. 151 . The solid line shows the composition weighted average energy of a mixture of Cu and cupd-2. it is less favorable than a mixture of Cu and cupd-2 with the same composition.Figure 46: Illustration of of an alloy structure with an exothermic formation energy that is not stable with respect to phase separation. Since cu3pd-2 is below the dotted line. 152 .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. it is more stable than the phase-separated mixture. Figure 48: Total DOS for bulk Pd. 153 . bcc111. slab. 154 . hcp001 and diamond111.1 Simple surfaces ase provides many utility functions to setup surfaces.1. show_unit_cell=2) Open the python script (dft-scripts/script-146. size=(2.5 Surfaces 5. 1 2 from ase.1 Surface structures As with molecules and bulk systems mod:ase provides several convenience functions for making surfaces. vacuum=10. rotation=’90x’.py).png’. There are built in functions for fcc111. bcc110.surface import fcc111 from ase.io import write 3 4 slab = fcc111(’Al’.0) 5 6 write(’images/Al-slab. 2. 5. 3). Here is a simple example of an fcc111 Al surface.lattice. also have small unit cells. which tends to make them computationally affordable. however.2 Vicinal surfaces The vast majority of surface calculations are performed on flat surfaces. many reasons to model the properties of surfaces 155 . 5. The flat surfaces.1. also known as low Miller index surfaces.Figure 60: An Al(111) slab with three layers and 20 Å of vacuum. This is partially because these surfaces tend to have the lowest surface energies. There are. and thus are likely to be experimentally observed. 1. Here is an example of a (211) surface. You may be interested in the reactivity of a step edge.py). mod:ase provides a general function for making vicinal surfaces. Many stepped surfaces are not that difficult to make now. or you may use the lower cooridnation of steps as a proxy for nanoparticle reactivity.repeat((3. 1)).center(vacuum=10. The main idea in generating them is described here. axis=2) 7 8 9 10 11 write(’images/Au-211. 1). (2. 1 2 from ase. s1. 3.lattice.surface import surface from ase. # change the orientation for viewing show_unit_cell=2) Open the python script (dft-scripts/script-147. 156 . rotation=’-30z.io import write 3 4 5 6 # Au(211) with 9 layers s1 = surface(’Au’. for example.90x’.that are not flat. 9) s1.png’. 157 .Figure 61: An Au(211) surface constructed with ase. p = calc.5.0 90.864 27. 0. bands.0])]. the k-point grids for slab calculations always have the form of M × N × 1.177069 eV Unit cell vectors (angstroms) x y z length a0 [ 2.get_bandstructure(kpts_path=[(r’$\Gamma$’. (r’$\Gamma$’. the k-point grid.py). 6). kpts=(6. 0.beta. To illustrate why. [0.surface import fcc111 3 4 atoms = fcc111(’Al’.864 a1 [ 1. (’$K1$’.5. 0. [0. encut=300.015 a.0 90.015] 27. 1 2 from jasp import * from ase.savefig(’images/Al-slab-bandstructure. 5. 0. we show there are forces on the slab atoms.0. First. 0. [0. 1. 0. (’$K3$’. 6. size=(1. (’$K2$’. 0]).png’) p. 0]). xc=’PBE’.2 Surface calculation parameters There is one important parameter that is different for surfaces than for bulk calculations. [0. (’$K2$’.0.jasp_bandstructure import * = fcc111(’Al’.gamma (deg):2.864 0.0]).c. (r’$\Gamma$’.surface import fcc111 ase.000 27.lattice. consider this example: 1 2 3 4 5 from from from from slab ase. encut=350. Assuming you have followed the convention that the z-axis is normal to the surface.480 0. [0.py). 0.0) 5 6 7 8 9 10 11 12 with jasp(’surfaces/Al-slab-unrelaxed’. 0. atoms=atoms) as calc: atoms.show() Open the python script (dft-scripts/script-148. 0. vacuum=10.get_forces() print calc Open the python script (dft-scripts/script-149.0. vacuum=10.0 158 . 0. 0.3 Surface relaxation When a surface is created. 4). xc=’PBE’. 0]).864 2.5.0]).015 90. [0.000] 2. 4).000 0.000] 2.432 2.000 0. kpts_nintersections=10) 21 22 23 p.5.alpha. We will examine some consequences of this with a simple Al slab. [0.0]).5. 1). kpts=(6.io import write jasp import * jasp. 1.0) 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 with jasp(’surfaces/Al-bandstructure’. 1. : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/surfaces/Al-slab-unrelaxed converged: True Energy = -14. (’$K1$’.864 a2 [ 0. size=(1.0. 6. the bulk symmetry is broken and consequently there will be forces on the surface atoms.5. [0. atoms=slab) as calc: n. 0.b.5.lattice.0]). 007 0.01 T T -------------------------------------------------INCAR Parameters: ----------------nbands: 10 encut: 350.000 -0.677] 0 0.0 magmom: None prec: Normal kpts: (6.000 0.653 14.000 10.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).y.872 Ang^3 Stress (GPa):xx.015] 0 0. xy 0.007 0. xz.18 T T 3 Al [0.000] 0 0.z]tag rmsForce constraints 0 Al [0. 6.18 T T 2 Al [2.000 Atom# sym position [x.000 17. 1) reciprocal: False xc: PBE txt: gamma: False 159 T T T T .432 0.827 12. Unit cell volume = 191. yz.000 0. Note the bands are flat in the direction normal to the surface. hence only one k-point is needed in this direction.338] 0 0.01 T T 1 Al [1. yy.864 1. zz.000 -0.002-0. 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 from jasp import * 2 3 4 5 with jasp(’surfaces/Al-slab-unrelaxed’) as calc: atoms = calc.get_atoms() print ’Total energy: {0:1.3f} eV’.format(atoms.get_potential_energy()) 6 7 8 for i in range(1, len(atoms)): print ’{0} deltaz = {1:1.3f} angstroms’.format(i, atoms[i].z - atoms[i-1].z) Open the python script (dft-scripts/script-150.py). Total energy: -14.177 eV 1 deltaz = 2.338 angstroms 2 deltaz = 2.338 angstroms 3 deltaz = 2.338 angstroms To reduce the forces, we can let VASP relax the geometry. We have to make some decisions about how to relax the slab. One choice would be to relax all the atoms in the slab. If we do that, then there will be no atoms with bulk like spacing unless we increase the slab thickness pretty dramatically. It is pretty common to freeze some atoms at the bulk coordinates, and let the others relax. We will freeze the bottom two layers (defined by tags 3 and 4) and let the first two layers relax. To do that we add constraints to the slab. Note: the ase constraints are only partially used by jasp. The mod:ase.constraints.FixAtoms constraint gets written to the POSCAR file, and is then used internally in VASP. The only other constraint that VASP can use internally is mod:ase.constraints.FixScaled. The other constraints are not written to the POSCAR and are not used by VASP. 1 2 3 from jasp import * from ase.lattice.surface import fcc111 from ase.constraints import FixAtoms 4 5 atoms = fcc111(’Al’, size=(1, 1, 4), vacuum=10.0) 6 7 8 constraint = FixAtoms(mask=[atom.tag >= 3 for atom in atoms]) atoms.set_constraint(constraint) 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 Open the python script (dft-scripts/script-151.py). : ----------------------------VASP calculation from /home-research/jkitchin/dft-book2/surfaces/Al-slab-relaxed converged: True 160 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 from jasp import * 2 3 4 with jasp(’surfaces/Al-slab-relaxed’) as calc: atoms = calc.get_atoms() 5 6 print ’Constraints = True: ’, atoms.get_forces(apply_constraint=True) 7 8 print ’Constraints = False: ’, atoms.get_forces(apply_constraint=False) Open the python script (dft-scripts/script-152.py). Constraints = True: [[ 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] from jasp import * from ase.lattice.surface import fcc111 3 4 5 6 with jasp(’surfaces/Al-slab-relaxed’) as calc: atoms = calc.get_atoms() print ’Total energy: {0:1.3f}’.format(atoms.get_potential_energy()) 7 8 9 10 for i in range(1, len(atoms)): print ’d_({0},{1}) = {2:1.3f} angstroms’.format(i, i-1, atoms[i].z - atoms[i-1].z) Open the python script (dft-scripts/script-153.py). Total energy: -14.181 d_(1,0) = 2.338 angstroms d_(2,1) = 2.299 angstroms d_(3,2) = 2.345 angstroms Depending on the layer there is either slight contraction or expansion. These quantities are small, and careful convergence studies should be performed. Note the total energy change from unrelaxed to relaxed is not that large in this case (e.g., it is about 5 meV). This is usually the case for metals, where the relaxation effects are relatively small. In oxides and semiconductors, the effects can be large, and when there are adsorbates, the effects can be large also. 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 √ √surface structure that may have a lower surface energy. Some famous reconstructions include: Si- 7 × 7, Pt(100) hex reconstruction, 73,74 and the Au(111) herringbone reconstruction. We will consider the (110) missing row reconstruction. 75 For some metals, especially Pt and Au, it is energetically favorable to form the so-called missing row reconstruction where every other row in the surface is "missing". It is favorable because it lowers the surface energy. Let us consider how we might calculate and predict that. It is straightforward to compute the energy of a (110) slab, and of a (110) slab with one row missing. However, these slabs contain different numbers of atoms, so we cannot directly compare the total energies to determine which energy is lower. We have to consider where the missing row atoms have gone, so we can account for their energy. We will consider that they have gone into the bulk, and so we to consider the energy associated with the following transformation: slab110 → slabmissing row + bulk Thus, if this change in energy: Ebulk + Eslabmissingrow − Eslab110 is negative, then the formation of the missing row is expected to be favorable. 5.4.1 Au(110) missing row reconstruction We first consider the Au(110) case, where the reconstruction is known to be favorable. 162 Clean Au(110) slab 1 2 3 4 from from from from jasp import * ase.lattice.surface import fcc110 ase.io import write ase.constraints import FixAtoms 5 6 7 8 atoms = fcc110(’Au’, size=(2, 1, 6), vacuum=10.0) constraint = FixAtoms(mask=[atom.tag > 2 for atom in atoms]) atoms.set_constraint(constraint) 9 10 write(’images/Au-110.png’, atoms.repeat((2, 2, 1)), rotation=’-90x’, show_unit_cell=2) 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() Open the python script (dft-scripts/script-154.py). Missing row in Au(110) 1 2 3 4 from from from from jasp import * ase.lattice.surface import fcc110 ase.io import write ase.constraints import FixAtoms 5 6 7 atoms = fcc110(’Au’, size=(2, 1, 6), vacuum=10.0) del atoms[11] # delete surface row 8 9 10 constraint = FixAtoms(mask=[atom.tag > 2 for atom in atoms]) atoms.set_constraint(constraint) 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() Open the python script (dft-scripts/script-155.py). Bulk Au 1 2 3 from jasp import * from ase.visualize import view from ase.lattice.cubic import FaceCenteredCubic 4 5 6 7 8 9 atoms = FaceCenteredCubic(directions=[[0, 1, 1], [1, 0, 1], [1, 1, 0]], size=(1, 1, 1), symbol=’Au’) 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 Open the python script (dft-scripts/script-156.py). Analysis of energies 1 from jasp import * 2 3 4 5 with jasp(’surfaces/Au-110’) as calc: slab = calc.get_atoms() eslab = slab.get_potential_energy() 6 7 8 9 with jasp(’surfaces/Au-110-missing-row’) as calc: missingrow = calc.get_atoms() emissingrow = missingrow.get_potential_energy() 10 11 12 13 with jasp(’bulk/Au-fcc’) as calc: bulk = calc.get_atoms() ebulk = bulk.get_potential_energy() 14 15 16 17 print ’natoms slab = {0}’.format(len(slab)) print ’natoms missing row = {0}’.format(len(missingrow)) print ’natoms bulk = {0}’.format(len(bulk)) 18 19 print ’dE = {0:1.3f} eV’.format(emissingrow + ebulk - eslab) Open the python script (dft-scripts/script-157.py). natoms slab = 12 natoms missing row = 11 natoms bulk = 1 dE = -0.070 eV The missing row formation energy is slightly negative. The magnitude of the formation energy is pretty small, but just slightly bigger than the typical convergence errors observed, so we should cautiously conclude that the reconstruction if favorable for Au(110). We made a lot of shortcuts in computing this quantity, including using the experimental lattice constant of Au, not checking for convergence in kpoints or planewave cutoff, and not checking for convergence with respect to slab thickness or number of relaxed layers. 5.4.2 Ag(110) missing row reconstruction Clean Ag(110) slab 1 2 3 4 from from from from jasp import * ase.lattice.surface import fcc110 ase.io import write ase.constraints import FixAtoms 5 6 7 8 atoms = fcc110(’Ag’, size=(2, 1, 6), vacuum=10.0) constraint = FixAtoms(mask=[atom.tag > 2 for atom in atoms]) atoms.set_constraint(constraint) 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() Open the python script (dft-scripts/script-158.py). 164 1.tag > 2 for atom in atoms]) atoms. Bulk Ag 1 2 3 from jasp import * from ase.get_atoms() emissingrow = missingrow. 1.constraints import FixAtoms 5 6 7 atoms = fcc110(’Ag’. 6).Missing row in Ag(110) 1 2 3 4 from from from from jasp import * ase. 12).get_atoms() eslab = slab. 1]. encut=350. 12.calculate() Open the python script (dft-scripts/script-159. isif=2.lattice. atoms=atoms) as calc: calc. symbol=’Ag’) 10 11 12 13 14 15 16 with jasp(’bulk/Ag-fcc’.get_potential_energy() 14 15 16 17 print ’natoms slab = {0}’. xc=’PBE’.calculate() Open the python script (dft-scripts/script-160. kpts=(6.py). 165 . size=(2. size=(1.0) del atoms[11] # delete surface row 8 9 10 constraint = FixAtoms(mask=[atom.lattice.format(emissingrow + ebulk . 0]].get_potential_energy() 10 11 12 13 with jasp(’bulk/Ag-fcc’) as calc: bulk = calc.set_constraint(constraint) 11 12 13 14 15 16 17 18 19 20 with jasp(’surfaces/Ag-110-missing-row’. Analysis of energies 1 from jasp import * 2 3 4 5 with jasp(’surfaces/Ag-110’) as calc: slab = calc.py).visualize import view from ase.format(len(bulk)) 18 19 print ’dE = {0:1.format(len(missingrow)) print ’natoms bulk = {0}’. 1]. xc=’PBE’. nsw=10. ibrion=2. 1.3f} eV’. [1. kpts=(12. 0. 1). encut=350.format(len(slab)) print ’natoms missing row = {0}’. 1).cubic import FaceCenteredCubic 4 5 6 7 8 9 atoms = FaceCenteredCubic(directions=[[0.io import write ase. atoms=atoms) as calc: calc.py). vacuum=10. 1. [1.surface import fcc110 ase.get_potential_energy() 6 7 8 9 with jasp(’surfaces/Ag-110-missing-row’) as calc: missingrow = calc.eslab) Open the python script (dft-scripts/script-161.get_atoms() ebulk = bulk. 6. nsw=10. 166 . 76 5.set_constraint(constraint) 8 9 10 11 12 13 14 15 16 17 with jasp(’surfaces/Cu-110’. xc=’PBE’. 6). 1].py).py). size=(2.e.constraints import FixAtoms 4 5 6 7 atoms = fcc110(’Cu’.0) constraint = FixAtoms(mask=[atom.cubic import FaceCenteredCubic 4 5 6 7 atoms = FaceCenteredCubic(directions=[[0. 6.constraints import FixAtoms 4 5 6 atoms = fcc110(’Cu’. 1).008 eV For Ag(110). xc=’PBE’. vacuum=10.3 Cu(110) missing row reconstruction Clean Cu(110) slab 1 2 3 from jasp import * from ase. kpts=(6. ibrion=2. Bulk Cu 1 2 3 from jasp import * from ase. encut=350.4.calculate() Open the python script (dft-scripts/script-163. ibrion=2.surface import fcc110 from ase. Experimentally.tag > 2 for atom in atoms]) atoms. 0]]. the reconstruction is not seen on very clean Ag(110) although it is reported that some adsorbates may induce the reconstruction. 6. atoms=atoms) as calc: calc.surface import fcc110 from ase.calculate() Open the python script (dft-scripts/script-162. [1. that we cannot confidently say whether the reconstruction is favorable or not. 1.lattice. 1. isif=2.tag > 2 for atom in atoms]) atoms. Missing row in Cu(110) 1 2 3 from jasp import * from ase. the missing row formation energy is practically thermoneutral. kpts=(6. 6). This energy is so close to 0eV. 1.0) del atoms[11] # delete surface row 7 8 9 10 11 12 13 14 15 16 17 18 constraint = FixAtoms(mask=[atom.natoms slab = 12 natoms missing row = 11 natoms bulk = 1 dE = -0. i. encut=350.lattice.set_constraint(constraint) with jasp(’surfaces/Cu-110-missing-row’.visualize import view from ase. size=(2. vacuum=10.lattice. [1. isif=2. nsw=10. atoms=atoms) as calc: calc. not that favorable. 1). 1]. 1. 0. xc=’PBE’.format(len(missingrow)) print ’natoms bulk = {0}’. 12). This is not written by default in VASP.get_potential_energy() 10 11 12 13 with jasp(’bulk/Cu-fcc’) as calc: bulk = calc.get_potential_energy() 6 7 8 9 with jasp(’surfaces/Cu-110-missing-row’) as calc: missingrow = calc. # write out only electrostatic potential.get_fermi_level() 17 167 . not xc pot atoms=atoms) as calc: 14 15 16 calc.calculate() ef = calc.py).5 Work function To get the work function.pyplot as plt 3 4 5 with jasp(’surfaces/Al-slab-relaxed’) as calc: atoms = calc. kpts=(6. we need to have the local potential.format(emissingrow + ebulk . kpts=(12. # write out local potential lvhar=True. natoms slab = 12 natoms missing row = 11 natoms bulk = 1 dE = -0.get_potential_energy() 14 15 16 17 print ’natoms slab = {0}’. 12. 1). encut=350. and we have to tell it to do that with the LVTOT and LVHAR keywords.calculate() Open the python script (dft-scripts/script-164.get_atoms() eslab = slab. Analysis 1 from jasp import * 2 3 4 5 with jasp(’surfaces/Cu-110’) as calc: slab = calc. lvtot=True. symbol=’Cu’) 8 9 10 11 12 13 14 15 16 with jasp(’bulk/Cu-fcc’. atoms=atoms) as calc: calc. but it could mean it is very easy to lift.size=(1.format(len(bulk)) 18 19 print ’dE = {0:1. encut=350.get_atoms() ebulk = bulk.get_atoms() 6 7 8 9 10 11 12 13 with jasp(’surfaces/Al-slab-locpot’. 1 2 from jasp import * import matplotlib.get_atoms() emissingrow = missingrow. 1).eslab) Open the python script (dft-scripts/script-165. That does not mean the reconstruction will not happen.3f} eV’. 1. xc=’PBE’.011 eV It is questionable whether we should consider this evidence of a missing row reconstruction because the number is small. 6.format(len(slab)) print ’natoms missing row = {0}’. 5.py). average(lp[:. the k-point sampling is not equivalent in the two systems. Nslab Eslab ≈ 2σ + N Ebulk bulk Then. Unfortunately. one with inversion symmetry.linspace(0.04 eV The workfunction of Al is listed as 4. but with increased k-points in the z-direction. and one can in general expect some errors due to this. and that the slab energy is also converged with respect to k-points. one of the methods described above is likely sufficient.e.get_atoms() 19 20 x. An alternative method for calculating surface energies that does not involve an explicit bulk calculation follows Ref. z]) for z in range(nz)]) # setup the x-axis in realspace uc = atoms. nz = lp. In the worst case.edu/hbase/tables/ photoelec. max(xaxis)]. nz) 28 29 30 31 32 33 plt.08 at http://hyperphysics. 168 . The advantage of these methods is the small number of calculations required to obtain the estimate. y. 77. we can estimate Ebulk by plotting the total energy of the slab as a function of the slab thickness.2f} eV’. and a slab calculation that is sufficiently thick to get the estimate.6 Surface energy The easiest way to calculate surface energies is from this equation: Nslab Ebulk ) σ = 12 (Eslab − N bulk where Eslab is the total energy of a symmetric slab (i.array([np.png’) 34 35 36 37 ind = (xaxis > 0) & (xaxis < 5) wf = np. particularly in the z-direction where the vacuum is (where typically only one k-point is used in slabs). z. Consequently. The bulk system is treated subtly different than the slab system. The idea is then to increase the thickness of the slab until the surface energy σ converges.gsu. :.ylabel(’x-y averaged electrostatic potential’) plt.18 atoms = calc.ef print ’ The workfunction is {0:1. one needs only a bulk calculation (which must be done anyhow to get the bulk lattice constant to create the slab). ef].html. Additional calculations are only required to test the convergence of the surface energy. ’k:’) plt. uc[2][2]. This maximizes the cancellation of k-point errors. Ebulk is the total energy of a bulk unit cell. axy) plt. as discussed in. and where both sides of the slab have been relaxed).average(axy[ind]) .plot(xaxis.plot([min(xaxis). in the limit of N → ∞.format(wf) Open the python script (dft-scripts/script-166.get_cell() xaxis = np.phy-astr.savefig(’images/Al-wf. with the best case being cancellation of the errors due to total k-point convergence.xlabel(’Position along z-axis’) plt. Nslab is the number of atoms in the slab. 5. this approach does not always work.py). Thus. 77 A variation of this method that usually results in better k-point error cancellation is to calculate the bulk unit cell energy using the slab unit cell with no vacuum space. 78 The method follows from equation (ref{eq:se}) where for a N-atom slab. lp = calc. One should be sure that the bulk energy is fully converged with respect to k-points. [ef. and Nbulk is the number of atoms in the bulk unit cell. but still does not guarantee convergence of the surface energy. ny.get_local_potential() 21 22 nx. the bulk system and slab system have the same Brillouin zone in at least two dimensions. with the same k-point mesh in the x and y directions. The energies should be compared at the same cutoff energies.shape 23 24 25 26 27 axy = np. one can get a linear divergence in the surface energy with slab thickness. The workfunction is 4.78 For quick estimates of the surface energy. append(slab.578 0. n).5 * (-N * energies[i + 1] + (N + 1) * energies[i]) sigmas. 6. nlayers nlayers nlayers nlayers nlayers nlayers nlayers nlayers = 3 = 4 = 5 = 6 = 7 = 8 = 9 = 10 sigma sigma sigma sigma sigma sigma sigma sigma = = = = = = = = 0.append(sigma) print ’nlayers = {1:2d} sigma = {0:1. Here is an example showing a conversion between these two units.48 eV/atom. size=(1.energies[i] sigma = 0. size=(1. sigmas.322 0. 9. atoms=slab) as calc: calc. 8.plot(Nlayers[0:-1].pyplot as plt 4 5 6 7 Nlayers = [3.1): N = Nlayers[i] DeltaE_N = energies[i + 1] .center() 13 14 15 16 17 18 19 20 21 22 23 with jasp(’bulk/Cu-layers/{0}’.png’) Open the python script (dft-scripts/script-167. m import numpy as np 4 5 6 slab = fcc111(’Cu’.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. 1. 1). vacuum=10.592 0. kpts=(8.399 0.0) cell = slab.0) slab.lattice. N) 31 32 33 34 35 plt. encut=350.48 # eV/atom 11 12 print ’sigma = {0} J/m^2’.surface import fcc111 import matplotlib. xc=’PBE’.format(sigma. We will use unrelaxed slabs for computational efficiency. 11] energies = [] sigmas = [] 8 9 for n in Nlayers: 10 11 12 slab = fcc111(’Cu’.set_nbands(f=2) # the default nbands in VASP is too low for Al try: energies. vacuum=10.units import J.savefig(’images/Cu-unrelaxed-surface-energy. 3). cell[1])) 9 10 sigma = 0.format(n).319 0.ylabel(’Surface energy (eV/atom)’) plt. 1 2 3 from ase. VaspQueued): pass 24 25 26 27 28 29 30 for i in range(len(Nlayers) . 5. ’bo-’) plt. 7. 10. 1.551 0.3f} eV/atom’.surface import fcc111 from ase.format(sigma / area / (J / m**2)) 169 .get_cell() 7 8 area = np.linalg.N σ = limN →∞ 12 (Eslab − N ∆EN ) N −1 N where ∆EN = Eslab − Eslab .cross(cell[0]. or 1.lattice. We will examine this approach here.xlabel(’Number of layers’) plt. 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.36 J/m2 .590 0. 4.get_potential_energy()) except (VaspSubmitted. 1 2 3 from jasp import * from ase.norm(np. 79 In 80 the surface energy of Cu(111) is reported as 0.py). 8. An alternative solution. Here we will just illustrate the effect. For a classic paper on trends in surface energies see. 2.2 Slab with a dipole correction 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.2. size=(2. and it is typical to at least consider the correction. You can use the IDIPOL tag to turn it on. encut=340. 5. The problem is that this gives the slab a dipole moment. 3=z.3628146074 J/m^2 5.7. but then very thick (eight to ten layers) slabs must be used to ensure the adsorbates do not interact through the slab. and specify which direction to apply it in (1=x. 83 5. z)). sigma = 1. thus the work function is not well-defined.py). add_adsorbate from jasp import * import matplotlib.py). slab. # write out only electrostatic potential. 85 In this technique. the dipole correction scheme. not xc pot atoms=slab) as calc: calc. was developed by Neugebauer and Scheffler 84 and later corrected by Bengtsson. 2. # write out local potential lvhar=True. xc=’PBE’. 2).6. kpts=(2. The advantage of this approach is that thinner slabs with adsorbates on only one side can be used. rotation=’-90x’.7 Dipole correction A subtle problem can arise when an adsorbate is placed on one side of a slab with periodic boundary conditions. and compare the results later. and 82 for an example of the influence of adsorbates on surface energies and particle shapes of Cu. 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.1 Slab with no dipole correction We simply run the calculation here. position=’fcc’) 9 10 11 slab. lvtot=True. show_unit_cell=2) 12 13 14 15 16 17 18 19 20 with jasp(’surfaces/Al-Na-nodip’. There are also literature reports that the correction is small.surface import fcc111. This simply corrects the total energy and forces.lattice.calculate() Open the python script (dft-scripts/script-169.0) add_adsorbate(slab. See 81 for an example of computing Mo2 C surface energies and particle shapes. ’Na’. height=1. One solution to this problem is to use slabs with adsorbates on both sides.center() write(’images/Na-Al-slab. It 170 .io import write 6 7 8 slab = fcc111(’Al’. 1). in the literature the use of this correction is fairly standard.Open the python script (dft-scripts/script-168. vacuum=10.png’. 5.pyplot as plt from ase. 1 2 3 4 5 # compute local potential of slab with no dipole from ase.1 Advanced topics in surface energy The surface energies can be used to estimate the shapes of nanoparticles using a Wulff construction. 86 Nevertheless. an external field is imposed in the vacuum region that exactly cancels the artificial field caused by the slab dipole moment. The existence of this field in the vacuum also makes the zero-potential in the vacuum ill-defined. y. 2=y. which is currently the common practice. 4=(x.7. 657] Comparing no dipole correction with a dipole correction To see the difference in what the dipole correction does. y.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’.calculate() Open the python script (dft-scripts/script-170. For that.surface import fcc111.does not change the contents of LOCPOT. you have to also set the LDIPOL and DIPOL tags.shape nelements = n0 * n1 * n2 voxel_volume = slab. lp = calc. sedc = np. (cd * y). 2). # write out only electrostatic potential.T). idipol=3.212 2. # write out local potential lvhar=True.array([(cd * x). dipol=sedc) as calc: calc. 4) 41 42 calc. nz = lp. ldipol=True. size=(2. n1. cd = calc. vacuum=10. The VASP manual recommends you first set IDIPOL to get a converged electronic structure.get_atoms() 6 7 8 x.sum(). 1 2 from jasp import * import matplotlib. and then set LDIPOL to True. (cd * z).T). y. # only along z-axis lvtot=True. add_adsorbate from jasp import * 4 5 6 slab = fcc111(’Al’.inv(uc.center() 9 10 11 12 13 14 15 16 17 with jasp(’surfaces/Al-Na-dip’. we now plot the potentials from each calculation. encut=340. z.shape 9 171 . 2. analyze the charge density to get the center of charge.get_charge_density() n0. ny.round(sedc.get_volume() / nelements total_electron_charge = cd.pyplot as plt 3 4 5 with jasp(’surfaces/Al-Na-nodip’) as calc: atoms = calc. not xc pot atoms=slab) as calc: 18 19 calc. and set the center of electron density in DIPOL.linalg.lattice. and then run a second calculation.T 38 39 40 # we only write 4 decimal places out to the INCAR file. That makes these calculations a multistep process.sum() * voxel_volume 26 27 28 29 30 31 electron_density_center = np.2. xc=’PBE’. so we round here. z. 1). 2.7.py). height=1. position=’fcc’) 7 8 slab.get_cell() 35 36 37 # get scaled electron charge density center sedc = np.calculate() 20 21 22 23 24 25 x.sum().sum()]) electron_density_center *= voxel_volume electron_density_center /= total_electron_charge 32 33 34 print ’electron-density center = {0}’.0) add_adsorbate(slab. because we must run a calculation.get_local_potential() nx.419 10. 1 2 3 # compute local potential with dipole calculation on from ase. electron_density_center.3 4.format(electron_density_center) uc = slab.dot(np. n2 = cd. ’Na’. kpts=(2. electron-density center = [ 5. It is not efficient to set all three at the same time for some reason. 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. and that the atoms have moved far apart.25 ML.get_fermi_level() e2 = atoms.linspace(0. the electrostatic potential never flattens out. the slab may reconstruct on adsorption.plot(xaxis_1. uc[2][2]. and the products may or may not stick to the surface. except for the step jump near 23 Å. With a dipole correction the potential is flat in the vacuum region. axy_2.py).plot([min(xaxis_2). We have to decide where to put the adsorbates. nz) 27 28 29 ef2 = calc. For computational speed. label=’Fermi level’) plt. nz = lp. but allow the adsorbate to relax.e. :. The two deep dips are where the atoms are. [ef2.get_cell() xaxis_2 = np. The difference in energy with and without the dipole correction here is small. the gas-phase molecule may or may not dissociate. there is near constant slope in the vacuum region.get_local_potential() nx. max(xaxis_2)].format(e2-e1) 32 33 34 35 36 37 38 39 plt. nz) 14 15 e1 = atoms.10 11 12 13 axy_1 = [np.ylabel(’xy-averaged electrostatic potential’) plt. y.5 ∗ EO2 172 .’. The difference between the Fermi level and the flat vacuum potential is the work function.png’) Open the python script (dft-scripts/script-171. 2. 4. 3. ny. and some sites will be more stable than others. ’k:’. The key points to notice in this figure are: 1.legend(loc=’best’) plt.get_atoms() 19 20 21 x. z]) for z in range(nz)] # setup the x-axis in realspace uc = atoms. :. what site to put them on. uc[2][2]. which means there is an electric field there. ∆Hads (eV /O) = Eslab+O − Eslab − 0.average(lp[:.8 5. 5. label=’dipole correction’) plt.8. z]) for z in range(nz)] # setup the x-axis in realspace uc = atoms.get_potential_energy() 30 31 print ’The difference in energy is {0} eV. We will model the oxygen coverage at 0. label=’no dipole correction’) plt.plot(xaxis_2. axy_1. We will assume the oxygen molecule has split in half. 5. we will freeze the slab.xlabel(’z ($\AA$)’) plt. lp = calc.867888 eV. The difference in energy is 3. z.get_potential_energy() 16 17 18 with jasp(’surfaces/Al-Na-dip-step2’) as calc: atoms = calc. i.get_cell() xaxis_1 = np.shape 22 23 24 25 26 axy_2 = [np. The slab may already have some adsorbates on it.savefig(’images/dip-vs-nodip-esp. Without a dipole correction. We will consider the dissociative adsorption of O2 on three sites of a Pt(111) slab.linspace(0. which means we need to use a 2 × 2 surface unit cell. ef2].average(lp[:. kpts=(4. vacuum=10.get_potential_energy() Open the python script (dft-scripts/script-172.lattice.py). xc=’PBE’. add_adsorbate from ase. size=(2. ibrion=2.surface import fcc111.py). atoms.png’.constraints import FixAtoms 5 6 atoms = fcc111(’Pt’. show_unit_cell=2) 11 12 13 14 15 16 17 with jasp(’surfaces/Pt-slab’. kpts=[4.0) 7 8 9 # note this function only works when atoms are created by the surface module.get_potential_energy() Open the python script (dft-scripts/script-173. 2.png’. 1). vacuum=10. atoms=atoms) as calc: 24 25 print atoms.set_constraint(constraint) 13 14 15 from ase. atoms. -67. atoms=atoms) as calc: print atoms.io import write write(’images/Pt-fcc-ori. height=1. encut=350.constraints import FixAtoms 4 5 6 7 atoms = fcc111(’Pt’. 2. xc=’PBE’. ’O’.set_constraint(constraint) 8 9 10 from ase. position=’fcc’) 10 11 12 constraint = FixAtoms(mask=[atom. show_unit_cell=2) 16 17 18 19 20 21 22 23 with jasp(’surfaces/Pt-slab-O-fcc’.663924 173 . encut=350.2. -73. add_adsorbate(atoms.lattice.0) constraint = FixAtoms(mask=[True for atom in atoms]) atoms. 4. 3).io import write write(’images/Pt-fcc-site.711178 fcc site 1 from jasp import * 2 3 4 from ase. 4. 1]. 3).Calculations clean slab calculation 1 2 3 from jasp import * from ase.surface import fcc111 from ase.symbol != ’O’ for atom in atoms]) atoms. size=(2. nsw=25. O atom on the bridge site 1 2 3 from jasp import * from ase. kpts=(4.lattice. nsw=25. xc=’PBE’. add_adsorbate(atoms. position=’bridge’) 9 10 11 constraint = FixAtoms(mask=[atom.py). vacuum=10. 4. 1). add_adsorbate from ase.constraints import FixAtoms 4 5 atoms = fcc111(’Pt’.663615 174 .surface import fcc111. -73. size=(2.2.set_constraint(constraint) 12 13 14 15 16 17 18 19 with jasp(’surfaces/Pt-slab-O-bridge’. atoms=atoms) as calc: 20 21 22 calc. height=1. encut=350.0) 6 7 8 # note this function only works when atoms are created by the surface module. 2.symbol != ’O’ for atom in atoms]) atoms. 3). ’O’. ibrion=2.calculate() print atoms.get_potential_energy() Open the python script (dft-scripts/script-174. 1). 2.lattice.Figure 72: Initial geometry of the bridge site. position=’hcp’) 9 10 11 constraint = FixAtoms(mask=[atom. height=1.symbol != ’O’ for atom in atoms]) atoms.set_constraint(constraint) 12 13 14 from ase. kpts=(4. vacuum=10. ’O’. 175 .constraints import FixAtoms 4 5 atoms = fcc111(’Pt’. nsw=25.calculate() Open the python script (dft-scripts/script-175. add_adsorbate(atoms. xc=’PBE’. 3). atoms=atoms) as calc: calc. encut=350.0) 6 7 8 # note this function only works when atoms are created by the surface module. atoms.surface import fcc111.io import write write(’images/Pt-hcp-o-site. 4.png’. ibrion=2. show_unit_cell=2) 15 16 17 18 19 20 21 22 23 with jasp(’surfaces/Pt-slab-O-hcp’.py). add_adsorbate from ase. size=(2. It is definitely on the bridge.2. hcp site 1 2 3 from jasp import * from ase. show_unit_cell=2) 23 24 25 26 with jasp(’molecules/O2-sp-triplet-350’) as calc: atoms = calc.0. atoms.get_atoms() e_slab_o_bridge = atoms.get_atoms() e_slab = atoms.show_unit_cell=2) 8 9 10 11 12 with jasp(’surfaces/Pt-slab-O-fcc’) as calc: atoms = calc.0. atoms.png’.Analysis of adsorption energies 1 2 from jasp import * from ase.png’.get_potential_energy() write(’images/pt-slab-hcp-o.5 * e_O2 Hads_bridge = e_slab_o_bridge .e_slab .format(Hads_hcp) print ’Hads (bridge) = {0} eV/O’.get_potential_energy() write(’images/pt-slab-bridge-o.get_atoms() e_slab_o_fcc = atoms.png’. Hads (fcc) = -1.0384925 eV/O 176 .0.show_unit_cell=2) 18 19 20 21 22 with jasp(’surfaces/Pt-slab-O-bridge’) as calc: atoms = calc.get_potential_energy() write(’images/pt-slab-fcc-o.5 * e_O2 31 32 33 34 print ’Hads (fcc) = {0} eV/O’.e_slab .io import write 3 4 5 6 7 with jasp(’surfaces/Pt-slab’) as calc: atoms = calc.format(Hads_bridge) Open the python script (dft-scripts/script-176.png’.get_potential_energy() 27 28 29 30 Hads_fcc = e_slab_o_fcc .get_atoms() e_slab_o_hcp = atoms.5 * e_O2 Hads_hcp = e_slab_o_hcp .py). atoms.e_slab .show_unit_cell=2) 13 14 15 16 17 with jasp(’surfaces/Pt-slab-O-hcp’) as calc: atoms = calc.format(Hads_fcc) print ’Hads (hcp) = {0} eV/O’. atoms.get_atoms() e_O2 = atoms.get_potential_energy() write(’images/pt-slab. 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. Figure 73: Final geometry of the fcc site. Figure 74: Final geometry of the hcp site. The bridge site (Figure 75, however, is clearly not at a bridge site! 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 haven’t copied CONTCAR to POSCAR), and the CONTCAR contains the final geometry. 1 from ase.io import read, write 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) Open the python script (dft-scripts/script-177.py). 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 from jasp import * 2 3 4 5 from ase.lattice.surface import fcc111, add_adsorbate from ase.constraints import FixAtoms, FixScaled from ase.io import write 6 7 atoms = fcc111(’Pt’, size=(2, 2, 3), vacuum=10.0) 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 write(’images/Pt-O-bridge-constrained-final.png’, atoms, show_unit_cell=2) print ’Final O position : {0}’.format(atoms.positions[-1]) 31 32 33 34 35 # now compute Hads with jasp(’surfaces/Pt-slab’) as calc: atoms = calc.get_atoms() e_slab = atoms.get_potential_energy() 36 37 38 39 40 with jasp(’molecules/O2-sp-triplet-350’) as calc: atoms = calc.get_atoms() e_O2 = atoms.get_potential_energy() 41 42 Hads_bridge = e_bridge - e_slab - 0.5*e_O2 43 44 print ’Hads (bridge) = {0:1.3f} eV/O’.format(Hads_bridge) Open the python script (dft-scripts/script-178.py). Initial O position: [ 1.386 Final O position : [ 1.386 Hads (bridge) = -0.488 eV/O 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. Figure 78: Initial state of the O atom on the bridge site. 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 from jasp import * from ase.lattice.surface import fcc111 from ase.constraints import FixAtoms 4 5 6 7 atoms = fcc111(’Pt’, size=(1, 1, 3), vacuum=10.0) constraint = FixAtoms(mask=[True for atom in atoms]) atoms.set_constraint(constraint) 8 9 write(’images/Pt-fcc-1ML.png’, atoms, show_unit_cell=2) 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 Open the python script (dft-scripts/script-179.py). -16.927696 181 ibrion=2. encut=350.png’.constraints import FixAtoms from ase.fcc site at 1 ML coverage 1 from jasp import * 2 3 4 5 from ase. 1). show_unit_cell=2) 17 18 19 20 21 22 23 24 25 26 with jasp(’surfaces/Pt-slab-1x1-O-fcc’. add_adsorbate(atoms.2.get_potential_energy() Open the python script (dft-scripts/script-180. -21. atoms=atoms) as calc: print atoms. atoms.941003 182 .lattice. size=(1.surface import fcc111.py). xc=’PBE’.0) 8 9 10 # note this function only works when atoms are created by the surface module. nsw=25. 1. position=’fcc’) 11 12 13 constraint = FixAtoms(mask=[atom. 3).set_constraint(constraint) 14 15 16 write(’images/Pt-o-fcc-1ML. 8. vacuum=10. height=1. kpts=(8. ’O’.symbol != ’O’ for atom in atoms]) atoms. add_adsorbate from ase.io import write 6 7 atoms = fcc111(’Pt’. get_potential_energy() 15 16 17 hads = e_slab_o .25 ML coverage! We will return what this means in Atomistic thermodynamics effect on adsorption. Let us define a general surface formation energy scheme like this: 183 .3f} eV’.get_atoms() e_slab_o = atoms.get_atoms() e_O2 = atoms.5 * e_O2 print ’Hads (1ML) = {0:1.e_slab .get_potential_energy() 6 7 8 9 10 # clean slab with jasp(’surfaces/Pt-slab-1x1’) as calc: atoms = calc.format(hads) Open the python script (dft-scripts/script-181.Adsorption energy at 1ML 1 from jasp import * 2 3 4 5 with jasp(’surfaces/Pt-slab-1x1-O-fcc’) as calc: atoms = calc.get_potential_energy() 11 12 13 14 with jasp(’molecules/O2-sp-triplet-350’) as calc: atoms = calc.8.0.3 Effect of adsorption on the surface energy There is a small point to make here about what adsorption does to surface energies. 5.py).get_atoms() e_slab = atoms. Hads (1ML) = -0.099 eV The adsorption energy is much less favorable at 1ML coverage than at 0. Appropriate normalization factors must be included if that is not true.9 Adsorbate vibrations Adsorbates also have vibrational modes.set(ibrion=5. the area for both sides of the slab. provided that the adsorption energy is negative.ads − Eslab − Eads for adsorption We defined γclean = 2A on a single side of a slab. we get Hads ∆E 2A = γ = γclean + A You can see here that the adsorption energy serves to stabilize. 184 .format(calc.get_vibrational_modes(0) print ’Elapsed time = {0} seconds’.135667516e-15 # eV*s 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’. and that each surface contributes half of the energy change. The overall change in energy: ∆E = Eslab.FixAtoms or func:ase.format(f/(h*c)) ’All energies = ’. or reduce the surface energy. ∆E = Eslab.format(f/h) cm^{{-1}}’. Below we consider the vibrational modes of an oxygen atom in an fcc site on Pt(111). so Eslab. nsw=1) atoms = calc.format(f/meV) 1/s’. 7. • 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. v = calc. If we normalize by 2A.constraints. For metal surfaces with adsorbates.get_atoms() f. 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. it is common to only compute vibrational modes of the adsorbate on a frozen metal slab.ads − Eslab − Eads = 2∆Hads . it is assumed there are the same number of atoms (not including the adsorbates) in the slabs and bulk. 1 from jasp import * 2 3 4 with jasp(’surfaces/Pt-slab-O-fcc’) as calc: calc.get_elapsed_time()) allfreq = calc.ads − Eslab − Eads − Ebulk + Eslab 1 (Eslab − Ebulk ).clone(’surfaces/Pt-slab-O-fcc-vib’) 5 6 7 8 9 10 11 12 13 14 15 with jasp(’surfaces/Pt-slab-O-fcc-vib’) as calc: calc. and add and subtract a constant term Eslab . # default as well ediff=1e-8.units import meV c = 3e10 # cm/s h = 4. In this case.ads − Eads − Ebulk where the the energies are appropriately normalized for the stoichiometry. allfreq Open the python script (dft-scripts/script-182. Unlike a free molecule. the translational and rotational modes of an adsorbate may actually have real frequencies.py). there are adsorbates on both sides of the slab.Let us presume the surfaces are symmetric. Let us rearrange the terms.constraints.FixScaled) if you use IBRION=5.015. The other IBRION settings (6. and the same number of adsorbate atoms in the slab and Eads .format(f) meV’.get_vibrational_modes()[0] 16 17 18 19 from ase. and we defined Hads = Eslab. As written. # finite differences with selective dynamics nfree=2. You can limit the number of modes calculated with constraints (func:ase. Some final notes about the equations above: • We were not careful about stoichiometry. # central differences (default) potim=0. 8) do not respect the selective dynamics constraints. Sometimes they are called frustrated translations or rotations. 537929 meV vibrational freq = 1. nsw=1) atoms = calc. 185 .044346362.get_vibrational_modes(0) allfreq = calc. 0. This is why it is common to keep the slab atoms frozen.547387346 cm^{-1} All energies = [0. The other two are called frustrated translations. It is typical to neglect this coupling because of the large difference in mass between O and Pt.061606647 eV vibrational energy = 61. # finite differences with symmetry nfree=2. # central differences (default) potim=0.format(f / h) cm^{{-1}}’.113451691 cm^{-1} All energies = [0. 0.045628623.044344470000000004] There are three modes for the free oxygen atom.023701702.53634035507e+13 1/s vibrational freq = 512.set(ibrion=6. 0.06353792899999999.format(f) meV’.py).format(f / meV) 1/s’.023223747 Note that now there are 39 modes.format(calc. and this will have an effect on the result because the O atom could be coupled to the surface modes. 1 from jasp import * 2 3 4 with jasp(’surfaces/Pt-slab-O-fcc’) as calc: calc.48964216204e+13 1/s vibrational freq = 496.063537929 eV vibrational energy = 63.clone(’Pt-slab-O-fcc-vib-ibrion=6’) 5 6 7 8 9 10 11 12 13 with jasp(’surfaces/Pt-slab-O-fcc-vib-ibrion=6’) as calc: calc.023701702.345 seconds vibrational energy = 0. The O frequencies are not that different from the previous calculation (497 vs 512 cm−1 .015 seconds For mode 0: vibrational energy = 0.get_vibrational_modes()[0] 17 18 19 20 from ase. 0.format(f / (h * c)) ’All energies = ’.045628623. allfreq Open the python script (dft-scripts/script-183. 0.get_elapsed_time()) 14 15 16 f. Note that we did not include the surface Pt atoms in the calculation. which is 3*N where N=13 atoms in the unit cell.get_atoms() print ’Elapsed time = {0} seconds’. which correspond to slab modes that are essentially phonons. # default as well ediff=1e-8. It pays to use constraints to minimize the number of these calculations.units import meV c = 3e10 # cm/s h = 4. 0. m = calc. Calculating these results took 39*2 finite differences.061606647. One of them is a mode normal to the surface (the one with highest frequency.Elapsed time = 14269. It took about a day to get these results on a single CPU. Elapsed time = 77121.606647 meV vibrational freq = 1.135667516e-15 # eV*s 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’. Next we look at the difference in results when we calculate all the modes.015. 0. Many of the modes are low in frequency. get_vibrational_modes(2) print calc.10.1 Vibrations of the bridge site Here we consider the vibrations of an O atom in a bridge site.clone(’surfaces/Pt-slab-O-bridge-vib’) 7 8 9 10 11 12 13 14 15 16 17 with jasp(’surfaces/Pt-slab-O-bridge-vib’) as calc: calc.020649715+0j) eV vibrational energy = (20.10 Surface Diffusion barrier See this review 92 of diffusion on transition metal surfaces.pyplot as plt 4 5 6 with jasp(’surfaces/Pt-slab-O-fcc’) as calc: initial_atoms = calc.5.get_atoms() 7 186 . Finally.set(ibrion=5.format(f/(h*c)) Open the python script (dft-scripts/script-184.06691932. This corresponds to the motion of the O atom falling into one of the neighboring 3-fold sites.135667516e-15 # eV*s 25 26 27 28 29 print print print print ’vibrational ’vibrational ’vibrational ’vibrational energy energy freq freq = = = = {0} {0} {0} {0} eV’. We will use the results from previous calculations of oxygen atoms in an fcc and hcp site.047345270999999994. 5. 0.units import meV c = 3e10 # cm/s h = 4. # finite differences with selective dynamics nfree=2. then we will construct a band of images connecting these two sites.format(f/meV) 1/s’.constraints import FixAtoms 3 4 5 6 # clone calculation so we do not overwrite previous results with jasp(’surfaces/Pt-slab-O-bridge-xy-constrained’) as calc: calc. This position is a transition state for hopping between the fcc and hcp sites. [0. 1 2 from jasp import * from ase. v = calc.set_constraint([constraint]) 18 19 20 f. (0.py).symbol != ’O’ for atom in atoms]) atoms.99307909065e+12+0j) 1/s vibrational freq = (166.9. nsw=1) atoms = calc. we let VASP optimize the band and analyze the results to get the barrier.format(f) meV’.020649715000000003+0j)] vibrational energy = (0.649715+0j) meV vibrational freq = (4. which we saw earlier is a metastable saddle point. # central differences (default) potim=0. but rather a saddle point.neb import NEB import matplotlib. # default as well ediff=1e-8.015.get_vibrational_modes()[0] 21 22 23 24 from ase.1 Standard nudged elastic band method Here we illustrate a standard NEB method. It also indicates this position is not a stable minimum. 1 2 3 from jasp import * from ase.435969688+0j) cm^(-1) Note that we have one imaginary mode. You need an initial and final state to start with. 5.constraints constraint = FixAtoms(mask=[atom.format(f/h) cm^(-1)’.get_atoms() del atoms. The climbing image NEB method 93 solves that problem by making one image climb to the top./images/pt-o-fcc-hcp-neb.copy()] # this is the TS 22 23 24 25 neb = NEB(images) # Interpolate linearly the positions of these images: neb.plot_neb(show=False) 45 46 47 48 49 50 51 52 53 # remember you are in surfaces/Pt-O-fcc-hcp-neb.g.575224 Iterations: 12 Function evaluations: 24 We should compare this barrier to what we could estimate from the simple adsorption energies in the fcc and bridge sites../. e. This is not usually possible though. by symmetry.49 eV. or other means. 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’. 5.451 Ang to z based on our # previous bridge calculation.positions[-1] = 0. spring=-5. and add 1. and in the bridge site was -0. Optimization terminated successfully. 0.. VaspQueued): pass Open the python script (dft-scripts/script-185.positions[10]) + [0.5 * (ts. ibrion=1.copy() ts. which is very close to the calculated barrier from the NEB calculation.451] 17 18 19 20 21 # construct the band images = [initial_atoms] images += [initial_atoms. 1. atoms=final_images) as calc: 43 44 try: images.interpolate() 26 27 28 29 30 # now add the second half images2 = [ts. so to save in # the images directory you need .55 eV.copy()] images2 += [ts. ts = initial_atoms.png’) except (VaspSubmitted.interpolate() 34 35 36 # collect final band.04 eV.2 Climbing image NEB One issue with the standard NEB method is there is no image that is exactly at the transition state. it is much faster to directly compute the energy of the initial and transition states for barrier determinations. The bridge position is half way between # atoms 9 and 10. energies = calc.positions[9] + ts./.. The adsorption energy in the fcc site was -1. Current function value: -0. Here we use the previous calculation as a starting point and turn on the climbing image method.py).copy()] images2 += [final_atoms] 31 32 33 neb2 = NEB(images2) neb2.. nsw=90. 187 . In cases where you can determine what the transition state is. and there is no way to verify the transition state by vibrational analysis.savefig(’.get_neb() p = calc.8 9 with jasp(’surfaces/Pt-slab-O-hcp’) as calc: final_atoms = calc. we use vector geometry to # define the bridge position.get_atoms() 10 11 12 13 14 15 16 # here is our estimated transition state. The difference between these two is 0. That means there is some uncertainty of the true energy of the transition state. You set LCLIMB==True= in jasp to turn on the climbing image method.10. plt.copy()] images += [ts./ in the path to get you # back up. plot_neb(show=False) import matplotlib. lclimb=True) 9 10 11 12 13 14 images. 0.lattice. efield=field. xc=’PBE’. I thought there would be an image that had climbed to the top.pyplot as plt plt. 0. 2. atoms[-1].y.11 TODO Diffusion rates with transition state theory 5.1 2 3 4 # perform a climbing image NEB calculation from jasp import * with jasp(’surfaces/Pt-O-fcc-hcp-neb’) as calc: calc. encut=350.z + 1. 5. incar:IDIPOL will be set to 3 for surfaces so it points in the direction of the third lattice vector. [atoms[-1]. 0. vacuum=10. More band points would probably clarify that.py).format(field. 4). we will use a frozen slab. TODO This did not do exactly what I expected. which is conventionally in the z-direction and normal to the surface. For simplicity. We have to set the incar:EFIELD parameter to specify the field strength (in V/Å).svg’) plt.25 ML. [atoms[12]. shift their electron density around.append(Atom(’C’.0. VaspQueued): pass Open the python script (dft-scripts/script-187. Usually.savefig(’images/pt-o-cineb. 6. debug=logging.0. # set field in z-direction atoms=atoms) as calc: try: print ’{0}: {1:1.y. with the CO molecule in the geometry reported in that reference.append(Atom(’O’.x. See Vibrations of the bridge site for an example.10.format(field).0: -108.set(ichain=0.show() Open the python script (dft-scripts/script-186.5]: with jasp(’surfaces/Pt-co-field-{0}’. 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.surface import fcc111 3 4 5 6 atoms = fcc111(’Pt’. # turn dipole correction on idipol=3. 1 2 from jasp import * from ase.3 Using vibrations to confirm a transition state A transition state should have exactly one imaginary degree of freedom which corresponds to the mode that takes reactants to products. Maybe this is an artifact of the spline fitting. a=3. We can model this to some extent in VASP.851])) atoms. 5. atoms[12]. which changes their stability . atoms. Climbing image NEB.e.3f}’.get_potential_energy()) except (VaspSubmitted.157])) 7 8 9 10 11 12 13 14 15 16 17 18 19 20 for field in [-0.clone(’surfaces/Pt-O-fcc-hcp-cineb’) 5 6 7 8 with jasp(’surfaces/Pt-O-fcc-hcp-cineb’.z + 1.py). 1). energies = calc.get_neb() calc.986) atoms. size=(2.DEBUG) as calc: calc. i. atoms[12]. # set the field ldipol=True. and incar:LDIPOL to True. atoms[-1].x. and finally specify which lattice vector the field should be applied to with incar:IDIPOL.12 TODO Effects of electric fields on adsorbates Electric fields can polarize adsorbates. kpts=(6.077 188 .5. or the top is within the tolerance of the top two points. These energies are crazy different.nrl.13 TODO Simulating STM images http://cst-www. 5.html 189 . and the forces on the atoms with the field on are insanely high.mil/users/sullivan/stm_backup/stm2.navy. This section is on hold until I figure that out. 190 .Figure 63: The unreconstructed Au(110) surface viewed from the side. Figure 64: Au(110) with the missing row reconstruction. 191 . 192 .Figure 65: xy averaged local electrostatic potential of an Al(111) slab. Figure 66: Schematic figure illustrating the calculation of a surface energy. Figure 67: Surface energy of a Cu(111) slab as a function of thickness. 193 . 194 . Figure 69: Comparison of the electrostatic potentials with a dipole correction and without it. 195 . Figure 70: Schematic of an adsorption process. 196 . Figure 71: Pt(111) fcc surface Figure 80: Schematic of forming a surface with adsorbates. 197 . then allow adsorption to occur on the surfaces. First we form two clean surfaces by cleaving the bulk. 198 .Figure 81: Energy pathway for O diffusion from an fcc to hcp site with a spline fit to determine the barrier. 903471 = 246. F = -8.32234. K 5 6 print 0.H(298. This is clearly a big effect! Between 500-600K.log(t) + B * t + C * (t**2) / 2.units! 5 6 7 8 9 # A D G Shomate parameters = 31.linspace(10. the energy has dropped by nearly 1 eV.0 3 4 print J. and use the parameters from the NIST Webbook for O2 .E / (2. h = (A * t + B * (t**2) / 2.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. In the ideal gas limit. E = -0.pyplot as plt from ase. C = 57. Let us see how this affects the free energy at different temperatures. H = 0.23531. 1 2 3 import matplotlib.xlabel(’Temperature (K)’) plt.007374.7945.00103642721413 96.savefig(’images/O2-mu.6 Atomistic thermodynamics Let us consider how much the Gibbs free energy of an O2 molecule changes as a function of temperature.86644 = -36. + D * (t**3) / 3. the pressure changes the free energy by kT ln P/P0 where P0 is the standard state pressure (1 atm or 1 bar depending on the convention chosen). # Kelvin not defined in ase. + D * (t**4) / 4. . mol.50624. 700) 30 31 G = enthalpy(T) .png’) Open the python script (dft-scripts/script-189.plot(T. Pressure also affects the free energy.ylabel(r’$\Delta G^\circ$ (eV)’) plt.H) return h * kJ / mol 28 29 T = np.0221367e+23 1. * t**2) + G) return s * J / mol / K 20 21 22 23 24 25 26 27 def enthalpy(T): ’’’ H .E / t + F .485308989 1 2 3 4 import numpy as np import matplotlib.units import * 199 . 6.24150636309e+18 6.15) returned as eV/molecule’’’ t = T / 1000. We use the Shomate polynomials to approximate the temperature dependent entropy and enthalpy.pyplot as plt import numpy as np from ase. . at 1 atm. 1 2 from ase. B = -20.py).units import * K = 1.py).100 * kJ / mol / K 7 8 print 1 * eV / (kJ / mol) Open the python script (dft-scripts/script-188.units import * K = 1. + C * (t**3) / 3. G) plt.0 0.T * entropy(T) 32 33 34 35 36 plt. Figure 82: Effect of temperature on the Gibbs free energy of an O_2 molecule at standard state (1 atm). 4 5 6 atm = 101325 * Pascal #atm is not defined in units K = 1 # Kelvin 7 8 9 # examine range over 10^-10 to 10^10 atm P = np.logspace(-10, 10) * atm 10 11 12 13 14 15 16 plt.semilogx(P / atm, kB * (300 * K) * np.log(P / (1 * atm)), label=’300K’) plt.semilogx(P / atm, kB * (600 * K) * np.log(P / (1 * atm)), label=’600K’) plt.xlabel(’Pressure (atm)’) plt.ylabel(r’$\Delta G$ (eV)’) plt.legend(loc=’best’) plt.savefig(’images/O2-g-p.png’) Open the python script (dft-scripts/script-190.py). None Similarly, you can see that simply changing the pressure has a large effect on the Gibbs free energy of an ideal gas through the term: kT ln(P/P0 ), and that this effect is also temperature dependent. This leads us to the final formula we will use for the chemical potential of oxgyen: DF T ZP E µO2 = EO + EO + ∆µ(T ) + kT ln(P/P0 ) 2 2 We can use µO2 in place of EO2 everywhere to include the effects of pressure and temperature on the gas phase energy. If T=0K, and P=1 bar, we are at standard state, and this equation reduces to the DFT energy (+ the ZPE). 200 Figure 83: Effects of pressure on the ideal gas Gibbs free energy of O2 . 6.1 Bulk phase stability of oxides 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 p∆V ≈ 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 1×10−10 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 K = 1. #not defined in ase.units! atm = 101325 * Pascal 8 9 10 11 12 # A D G Shomate parameters valid from 100-700K = 31.32234; B = -20.23531; C = 57.86644 = -36.50624; E = -0.007374; F = -8.903471 = 246.7945; H = 0.0 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 def DeltaMu(T, P): ’’’ returns delta chemical potential of oxygen at T and P T in K P in atm ’’’ return enthalpy(T) - T * entropy(T) + kB * T * np.log(P / atm) 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 print ’Cu2O decomposition temperature is {0:1.0f} K’.format(fsolve(func, 900)[0]) 50 51 52 53 def func(T): ’Ag2O’ return -0.99 - 0.5 * DeltaMu(T, P) 54 55 56 print ’Ag2O decomposition temperature is {0:1.0f} K’.format(fsolve(func, 470)[0]) 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=r’1$\times 10^{10}$ atm’) plt.plot(T, DeltaMu(T, 1e5*atm), label=r’1$\times 10^5$ atm’) plt.plot(T, DeltaMu(T, 1*atm), label=’1 atm’) 202 65 66 plt.plot(T, DeltaMu(T, 1e-5*atm), label=r’1$\times 10^{-5}$ atm’) plt.plot(T, DeltaMu(T, 1e-10*atm), label=r’1$\times 10^{-10}$ atm’) 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’) Open the python script (dft-scripts/script-191.py). Cu2O decomposition temperature is 917 K Ag2O decomposition temperature is 478 K Figure 84: ∆ µO2 (T,p) at different pressures and temperatures. Now, let us make a phase diagram that shows the boundary between silver oxide, and silver metal in P and T space. 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 K = 1. #not defined in ase.units! atm = 101325*Pascal 8 9 10 11 12 # A D G Shomate parameters valid from 100-700K = 31.32234; B = -20.23531; C = 57.86644 = -36.50624; E = -0.007374; F = -8.903471 = 246.7945; H = 0.0 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 def DeltaMu(T, P): ’’’ T in K P in atm ’’’ return enthalpy(T) - T * entropy(T) + kB * T * np.log(P / atm) 39 40 41 42 P = np.logspace(-11, 1, 10) * atm T = [] for p in P: 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’) Open the python script (dft-scripts/script-192.py). This shows that at high temperature and low pO2 metallic silver is stable, but if the pO2 gets high enough, the oxide becomes thermodynamically favorable. Here is another way to look at it. 1 2 3 import numpy as np import matplotlib.pyplot as plt from ase.units import * 4 5 6 7 K = 1. # not defined in ase.units! atm = 101325*Pascal Hf = -0.99 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 plt.plot(Dmu, Hf, label=’Ag$_2$O’) plt.plot(Dmu, np.zeros(Hf.shape), label=’Ag’) plt.xlabel(r’$\Delta \mu_{O_2}$ (eV)’) plt.ylabel(’$H_f$ (eV)’) plt.savefig(’images/atomistic-thermo-hf-mu.png’) Open the python script (dft-scripts/script-193.py). None This graph shows graphically the ∆µO2 required to make the metal more stable than the oxide. Anything less than about -2 eV will have the metal more stable. That can be achieved by any one of the following combinations (graphically estimated from Figure 84): About 500K at 1×10−10 atm, 600K at 1×10−5 atm, 900K at 1atm, etc. . . 204 desorption occurs. Now we can examine the effect of ∆µ(T. and below some pressure adsorption will not be favorable. We will use the adsorption energies for the oxygen on Pt(111) system we computed earlier: 1 2 import numpy as np import matplotlib. We expand µads as Eads + ∆µ(T. We lso know the coverage depends on the pressure and temperature. That leaves only the pressure and temperature dependence of the adsorbate. and thus: ∆Gads ≈ Eslab. p) where ∆Hads is the adsorption energy we defined earlier. Above some temperature.49 205 . what coverage would you expect on a surface? We saw earlier that adsorption energies depend on the site and coverage.2 Effect on adsorption We now consider the question: Given a pressure and temperature.ads − Eslab − Eads − ∆µ(T. which we treat in the ideal gas limit.60 bridge25 = -0.04 hcp25 = -0. p) on the adsorption energies. p) or ∆Gads ≈ ∆Hads − ∆µ(T.Figure 85: Temperature dependent decomposition pressure for Ag2 O. 6. We seek to develop a quantitative method to determine those conditions. as well as configurational entropy if that is relevant. We redefine the adsorption energy as: ∆Gads ≈ Eslab.pyplot as plt 3 4 5 6 fcc25 = -1.ads − Eslab − µads where again we neglect all contributions to the free energy of the slabs from vibrational energy and entropy. p). 10 8 9 Dmu = np.png’) plt.60 bridge (0.25 ML’) 0.5*Dmu). plt.py).49 fcc(1ML) -0.0. np.25 ML) -0.plot(Dmu. Table 6: Adsorption site dependence of adsorption energies of oxygen on Pt(111).show() Open the python script (dft-scripts/script-194.0.25 ML) -1. plt.savefig(’images/atomistic-thermo-adsorption.Figure 86: Dependence of the formation energy on the oxygen chemical potential. label=’fcc . label=’Pt(111)’) 0.04 hcp (0.plot(Dmu. label=’fcc .legend(loc=’best’) plt.5*Dmu).ylabel(r’$\Delta G_{ads}$ (eV/O)’) plt.0 ML’) 16 17 18 19 20 21 plt. label=’bridge .linspace(-4.5*Dmu).25 * (fcc25 .1.0.25 ML’) 1. plt.shape).plot(Dmu. plt. 2) 10 11 12 13 14 15 plt.25 ML) -0.0.0. 206 . system ∆H(eV /O) fcc (0.xlabel(r’$\Delta \mu O_2$ (eV)’) plt.25 * (hcp25 .5*Dmu).10 7 fcc1 = -0. label=’hcp .0.plot(Dmu.plot(Dmu.0 * (fcc1 .zeros(Dmu.0.25 * (bridge25 .25 ML’) 0. By equilibrium arguments we can say that µH∗ = 12 µH2 . so that only simple DFT calculations are needed to estimate them. Let us consider these three reactions of dissociative adsorption of hydrogen and hydrogen disulfide.Figure 87: Effect of oxygen chemical potential on the adsorption energy. 207 . p) = Egas (0K) + δµ + kT ln p/p0 . SH ∗ +∗ S ∗ +H∗ The reaction energy of interest is Erxn = µS∗ +µH∗−µSH∗ The question is. H2 S + 2∗ H ∗ +SH∗ 3. 1. 6. and consider how to compute the reaction energy for the third reaction. as we have defined before. the chemical potentials of all these three adsorbed species depend on the chemical potentials of two gas-phase species. Thus. preferrably of molecules that can be approximated as ideal gases. what are these chemical potentials? We would like them in terms of pressures and temperature. It follows that at equilibrium: µH∗ + µSH∗ = µH2 S and µH∗ + µS∗ = µSH∗ . The chemical potentials  of each of these gases can be defined as: µgas (T. From the first equation we have: µSH∗ = µH2 S − 12 µH2 and from the second equation we have: µS∗ = µSH∗ − µH∗ = µH2 S − µH2 . H2 + 2∗ 2H∗ 2.3 Atomistic therodynamics and multiple reactions In 82 we considered multiple reactions in an atomistic thermodynamic framework. c.270 90.135 0. ’U’:4. In 55 they use a U parameter of 4 eV for Cu which gave the best agreement with the experimental value.00 T T T 5 O [3. now with DFT+U.000 0.000 Atom# sym position [x.270] 4. ibrion=-1.clone(’bulk/Cu2O-U=4. Atoms 3 4 5 with jasp(’bulk/Cu2O’) as calc: calc.0 90.1.000 2.202 3.135 2.270 0.1 DFT+U VASP manual on DFT+U It can be difficult to find the lowest energy solutions with DFT+U. zz. : ----------------------------VASP calculation from /home/jkitchin/dft-org/bulk/Cu2O-U=4. yy.018 0.067 1.135 2. ’J’:0.1 Metal oxide oxidation energies with DFT+U We will reconsider here the reaction (see Metal oxide oxidation energies) 2 Cu2 O + O2 4 CuO.000] 0 0.py). We will also try that. yz.202 3.270 0.000] 4.135] 0 0. Some strategies for improving this are discussed in.000 0.00 T T T 1 Cu [2.854 Ang^3 Stress (GPa):xx.set(ldau=True. #do not rerelax nsw=0) calc.0 90.270 a.135] 0 0.0’) 6 7 8 9 10 11 12 13 14 15 16 with jasp(’bulk/Cu2O-U=4.0 converged: True Energy = -22.0.b. ’O’:{’L’:-1.0}}.270 4. xy 0.270 4. # select simplified rotationally invariant option ldau_luj={’Cu’:{’L’:2.000 0.7 Advanced electronic structure methods 7. # turn DFT+U on ldautype=2.018 0.270 a2 [ 0.0 1 2 from jasp import * from ase import Atom.000 -0.0}.228203 eV Unit cell vectors (angstroms) x y z length a0 [ 4. ’U’:0.00 T T T -------------------------------------------------INCAR Parameters: 208 .000 4.00 T T T 4 O [1. xz.beta.0 Unit cell volume = 77.067 1. Cu2 O calculation with U=4. 95 7. ldauprint=1.000 0.067] 0 0.00 T T T 2 Cu [2.000 4.000] 0 0.z] tag rmsForce constraints 0 Cu [0.0.calculate() print calc Open the python script (dft-scripts/script-195.gamma (deg): 4.000] 4.135 0.202] 0 0.000 2.0’) as calc: calc.00 T T T 3 Cu [0.018 -0.y.000 -0.270 a1 [ 0. We need to compute the energy of each species.alpha. ’J’:0. ’O’:{’L’:-1.clone(’bulk/CuO-U=4. type is set to LDAUTYPE" bulk/Cu2O-U=4. ’U’:4.0 ldau: True magmom: None ldaul: [-1.py). ldauprint=1. 0.0}.0 2 4. 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 grep -A 3 "LDA+U is selected. #do not rerelax nsw=0) calc.0] ldauj: [0. ’U’: 4. ’Cu’: {’J’: 0.0.0.0.0.0] ldau_luj: {’O’: {’J’: 0. # select simplified rotationally invariant option ldau_luj={’Cu’:{’L’:2. 8.0] ldauu: [0. ’J’:0.----------------nbands: 37 nsw: 0 ibrion: -1 ldautype: 2 isif: 3 ldauprint: 1 encut: 400.0’) 6 7 8 9 10 11 12 13 14 15 16 with jasp(’bulk/CuO-U=4. # turn DFT+U on ldautype=2. LDA+U is selected. 209 . ’L’: -1}.calculate() print calc Open the python script (dft-scripts/script-197.0. ’U’: 0.0/OUTCAR Open the python script (dft-scripts/script-196. ’J’:0. Atoms 3 4 5 with jasp(’bulk/CuO’) as calc: calc.0}}.0’) as calc: calc.0 CuO calculation with U=4.0 1 2 from jasp import * from ase import Atom.py). ’L’: 2}} prec: Normal kpts: [8.0 0. ibrion=-1. 4.0 0.0.0. 2. ’U’:0.set(ldau=True. angular momentum U (eV) J (eV) type is set to LDAUTYPE = for each species LDAUL = for each species LDAUU = for each species LDAUJ = 2 -1 0.0.0. 0 converged: True Energy = -16.0] ldau_luj: {’O’: {’J’: 0.beta.302 1. 8.027 -0. xy 0.908 a2 [-0.00 T T T 1 Cu [0.908 2. ’L’: 2}} prec: Normal kpts: [8.730 Ang^3 Stress (GPa):xx. ’U’: 4.030 0. ’U’: 0.888 0.908 5.566] 0 0.0.z] tag rmsForce constraints 0 Cu [1.8 95.0] ldauj: [0. 2. 4.046] 2.007 -0. ’Cu’: {’J’: 0.302 -1. 0. yz.0.gamma (deg): 2.0.000 -0.144 95.0] ldauu: [0.04 T T T -------------------------------------------------INCAR Parameters: ----------------nbands: 23 nsw: 0 ibrion: -1 ldautype: 2 isif: 3 ldauprint: 1 encut: 400.762 0. zz.y.151 0.b.018 0.0.0.8 95.04 T T T 3 O [1. xz.000 5.776 0.888 2.770 -0.046] 2.0.c.144 a.908 a1 [ 2.023] 0 0. yy.0 ldau: True magmom: None ldaul: [-1.870130 eV Unit cell vectors (angstroms) x y z length a0 [ 2.0.318] 0 0. ’L’: -1}.111 -0.8 Unit cell volume = 41.861] 0 0.alpha.: ----------------------------VASP calculation from /home/jkitchin/dft-org/bulk/CuO-U=4.168 3.00 T T T 2 O [2. 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) Reaction energy calculation with DFT+U 1 from jasp import * 2 210 .168 1.730 0.776 0.087] 5.000 Atom# sym position [x. # turn DFT+U on ldautype=2. ’O’:{’L’:-1. so the number of formula units in an atoms is # len(atoms)/3.format(U)) 6 7 8 9 10 11 12 13 14 15 16 with jasp(’bulk/Cu2O-U={0}’. ibrion=-1. ’U’:0.get_potential_energy()/(len(atoms)/2) 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. Cu2O # has 3 atoms. 55 which at U=4 eV is about -3. ’U’:U. ’U’:U.0. # select simplified rotationally invariant option ldau_luj={’Cu’:{’L’:2.0.clone(’bulk/Cu2O-U={0}’.0}. How much does U affect the reaction energy? results are to the U parameter.get_atoms() o2_energy = atoms.get_potential_energy()/(len(atoms)/3) 9 10 11 12 with jasp(’bulk/CuO-U=4.o2_energy . ’O’:{’L’:-1.get_potential_energy()/(len(atoms)/2) 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_potential_energy() 18 19 20 21 rxn_energy = 4.clone(’bulk/CuO-U={0}’.0*cuo_energy . In that paper.format(U)) as calc: calc. We do that here. #do not rerelax nsw=0) atoms = calc. Reaction energy = -1.0*cu2o_energy print ’Reaction energy = {0} eV’. 6.set(ldau=True. which is pretty good considering we have not checked for convergence.get_atoms() cuo_energy = atoms.36 eV per O2 .0’) as calc: atoms = calc.0}}.py).get_potential_energy() 38 211 .0}. ’J’:0. #do not rerelax nsw=0) atoms = calc. they apply a constant shift of -1.get_potential_energy()/(len(atoms)/3) 17 18 19 20 ## CuO ######################################## with jasp(’bulk/CuO’) as calc: calc. We have not applied the O2 correction here yet. we agree within 0.get_atoms() cu2o_energy = atoms.0’) as calc: atoms = calc. ’J’:0.12 eV.format(rxn_energy .2.set(ldau=True.0]: ## Cu2O ######################################## with jasp(’bulk/Cu2O’) as calc: calc.023819 eV This is still not in quantitative agreement with the result in.36) Open the python script (dft-scripts/script-198.get_atoms() o2_energy = atoms. ’U’:0. ldauprint=1.1.format(rxn_energy) print ’Corrected energy = {0} eV’.get_atoms() cuo_energy = atoms.format(U)) as calc: calc. ’J’:0.0. ldauprint=1.3 4 5 6 7 8 # don’t forget to normalize your total energy to a formula unit. ’J’:0. with jasp(’bulk/Cu2O-U=4. # select simplified rotationally invariant option ldau_luj={’Cu’:{’L’:2.14 eV (estimated from a graph). After we apply that correction. 1 2 3 4 5 It is reasonable to consider how sensitive our from jasp import * for U in [2. # turn DFT+U on ldautype=2.format(U)) 21 22 23 24 25 26 27 28 29 30 31 with jasp(’bulk/CuO-U={0}’. 4.663819 eV Corrected energy = -3.get_atoms() cu2o_energy = atoms.0.0}}. ibrion=-1. set(lhfcalc=True.rxn_energy .2) e_pbe0 = dos.mpi. On one hand. algo=’D’. 55 the difference in reaction energy from U=2 eV to U=4 eV was about 0.py). This example highlights the challenge of using an approach like DFT+U.4) atoms = calc.at/wiki/index. algo=’D’.2.cubic import FaceCenteredCubic from ase.set(lhfcalc=True. symbol=’Ni’) atoms[0].2.5 eV (estimated from graph). Note that for U=0 eV.1. atoms.96 eV). [1.1]. 7.0*cu2o_energy print ’U = {0} reaction energy = {1}’.876906 reaction energy = -3. so that it is decoupled from the non-cancelling errors that U fixes. the effect of adding U decreases this reaction energy.653819 reaction energy = -3.lattice. See 96 for additional discussion of how to mix GGA and GGA+U results.ac. size=(1. [1.5).2 7.get_energies() d_pbe = dos.1]. atoms=atoms) as calc: print ’PBE energy: ’. width=0.get_potential_energy() dos = DOS(calc.get_potential_energy() dos = DOS(calc.atoms. ismear=-5.397605 In.0]]. U = 2. width=0.get_energies() d_pbe0 = dos. On the other hand. U has a clear effect of changing the reaction energy. so does the correction factor for the O2 binding energy.get_potential_energy() 212 . ispin=2.magmom = 1 11 12 13 14 15 16 17 18 19 20 21 with jasp(’bulk/Ni-PBE’. In any case.0 U = 6.2) e_pbe = dos.o2_energy .php/FccNi_DOS 1 2 3 from jasp import * from ase.get_atoms() print ’HSE06 energy: ’.48 eV from U=2 eV to U=4 eV.1.get_dos() 35 36 37 38 39 40 41 with jasp(’bulk/Ni-HSE06’) as calc: calc.lorbit=11.atoms. time=0. you should be careful to use well converged results to avoid compensating for convergence errors with U. In 55 the authors tried to get the O2 binding energy correction from oxide calculations where U is not important. time=0. Overall.get_atoms() print ’PBE0 energy: ’. we had a (corrected reaction energy of -3.5.1.0 U = 4.univie.4) atoms = calc.get_dos() 22 23 24 calc.0 reaction energy = -3.clone(’bulk/Ni-PBE0’) calc.0*cuo_energy . Here we see a range of 0.99) Open the python script (dft-scripts/script-199.39 40 rxn_energy = 4.1.1 Hybrid functionals FCC Ni DOS This example is adapted from http://cms. hfscreen=0.format(U.clone(’bulk/Ni-HSE06’) 25 26 27 28 29 30 31 32 33 34 with jasp(’bulk/Ni-PBE0’) as calc: calc.dft import DOS 4 5 6 7 8 9 10 atoms = FaceCenteredCubic(directions=[[0. xc=’PBE’. kpts=(5.2.0.1). we consider the regular PBE functional.ylabel(’DOS’) plt. d_pbe0.get_dos() 42 43 44 45 46 47 48 49 50 51 52 53 import pylab as plt plt.dos = DOS(calc.py).plot(e_hse06.3 TODO DFT+D http://cms. d_hse06.530247 -6.plot(e_pbe.univie. label=’HSE06’) plt. d_pbe. PBE energy: PBE0 energy: HSE06 energy: -5.at/vasp/vasp/DFT_D2_method_Grimme.848931 -6.get_energies() d_hse06 = dos. width=0. and two hybrid GGAs (PBE0 ad HSE06).ac.html 97 Van der Waal forces can play a considerable role in binding of aromatic molecules to metal surfaces (ref). 7.First.plot(e_pbe0. label=’PBE0’) plt. Here we consider the effects of these forces on the adsorption energy of benzene on an Au(111) surface.png’) Open the python script (dft-scripts/script-200.293369 Figure 88: Comparison of DOS from GGA.savefig(’images/ni-dos-pbe-pbe0-hse06.xlabel(’energy [eV]’) plt. label=’PBE’) plt.legend() plt. 213 .mpi.2) e_hse06 = dos. size=(3. encut=350.0 + [0. 3.05] 17 214 . atoms=atoms) as calc: print atoms.surface import fcc111.get_potential_energy() Open the python script (dft-scripts/script-201.lattice. nsw=100.1 PBE gas-phase benzene 1 2 from jasp import * from ase. xc=’PBE’. encut=350.py). 23 and 25 p = (atoms.positions[22] + atoms.419513 benzene on Au(111) 1 2 3 4 5 # Benzene on the slab from jasp import * from ase. -82. add_adsorbate from ase. nsw=100. -76. add_adsorbate from ase.011625 clean slab 1 2 3 4 # the clean gold slab from jasp import * from ase.data.data.4.0. ibrion=1.positions[20] + atoms.lattice. xc=’PBE’. size=(3. 22.positions[23] + atoms. ibrion=1.surface import fcc111.py).molecules import molecule 3 4 5 benzene = molecule(’C6H6’) benzene. 0.constraints import FixAtoms 5 6 atoms = fcc111(’Au’.0.translate(-benzene.center(vacuum=5) 6 7 8 9 10 11 12 13 14 with jasp(’molecules/benzene-pbe’.get_potential_energy() Open the python script (dft-scripts/script-202.3).visualize import view.3). kpts=(1.get_center_of_mass()) 10 11 12 13 14 15 16 # I want the benzene centered on the position in the middle of atoms # 20.1). kpts=(4. view(atoms) 13 14 15 16 17 18 19 20 21 with jasp(’surfaces/Au-pbe’. vacuum=10) benzene = molecule(’C6H6’) benzene.3.positions[25])/4.3.1).symbol==’Au’ for atom in atoms]) atoms.molecules import molecule from ase. atoms=benzene) as calc: print benzene.1.constraints import FixAtoms 6 7 8 9 atoms = fcc111(’Au’.7.3. vacuum=10) 7 8 9 10 # now we constrain the slab c = FixAtoms(mask=[atom.set_constraint(c) 11 12 #from ase. nsw=100. view(atoms) 26 27 28 29 30 31 32 33 34 with jasp(’surfaces/Au-benzene-pbe’.get_potential_energy() Open the python script (dft-scripts/script-205. ibrion=1. size=(3.3).get_potential_energy() Open the python script (dft-scripts/script-204. add_adsorbate from ase.symbol==’Au’ for atom in atoms]) atoms.surface import fcc111.1).symbol==’Au’ for atom in atoms]) atoms. view(atoms) 13 14 15 16 17 18 19 20 21 22 with jasp(’surfaces/Au-pbe-d2’. xc=’PBE’. clean slab 1 2 3 4 # the clean gold slab from jasp import * from ase. ibrion=1.center(vacuum=5) 6 7 8 9 10 11 12 13 14 15 with jasp(’molecules/benzene-pbe-d2’.constraints import FixAtoms 5 6 atoms = fcc111(’Au’.4.translate(p) atoms += benzene 20 21 22 23 # now we constrain the slab c = FixAtoms(mask=[atom.lattice.set_constraint(c) 24 25 #from ase. nsw=100.1.4.py).py).molecules import molecule 3 4 5 benzene = molecule(’C6H6’) benzene. xc=’PBE’. atoms=atoms) as calc: print atoms. xc=’PBE’. kpts=(4. encut=350.3. nsw=100.visualize import view.visualize import view. gas-phase benzene 1 2 from jasp import * from ase. kpts=(4. atoms=atoms) as calc: print atoms. encut=350. lvdw=True. encut=350. atoms=benzene) as calc: print benzene. lvdw=True.py).1). kpts=(1.3.set_constraint(c) 11 12 #from ase.18 19 benzene.data.2 DFT-D2 To turn on the van der Waals corrections 98 we set incar:LVDW to True.1). vacuum=10) 7 8 9 10 # now we constrain the slab c = FixAtoms(mask=[atom. ibrion=1.get_potential_energy() Open the python script (dft-scripts/script-203. 7. 215 . contours=[0. y./.translate(p) atoms += benzene 20 21 22 23 # now we constrain the slab c = FixAtoms(mask=[atom.mpi.visualize import view. ismear=0. size=(3.positions[25])/4. atoms=atoms) as calc: print atoms. encut=350..3.lattice. more parameters) treatment of van der Waal forces in VASP (http: //cms.data. y.3). 22.0.molecules import molecule from ase. 7. prec=’high’. add_adsorbate from ase.01.symbol==’Au’ for atom in atoms]) atoms.0. elf = calc. 7./images/cf4-elf-3.constraints import FixAtoms 6 7 8 9 atoms = fcc111(’Au’.center(vacuum=5) 8 9 10 11 12 13 14 15 16 17 with jasp(’molecules/cf4-elf’. lvdw=True.e.contour3d(x. z. xc=’PBE’.ac.structure import molecule from enthought.3]) mlab. kpts=(4. z.1).figure() 216 . vacuum=10) benzene = molecule(’C6H6’) benzene.calculate() 18 19 20 21 x.positions[22] + atoms.positions[23] + atoms. atoms=atoms) as calc: calc. encut=350.05] 17 18 19 benzene.savefig(’. ibrion=1.3 Advanced vdW-DF functionals There is a more sophisticated (i.get_center_of_mass()) 10 11 12 13 14 15 16 # I want the benzene centered on the position in the middle of atoms # 20.4.at/vasp/vasp/vdW_DF_functional_Langreth_Lundqvist_et_al. 3. 0.py).positions[20] + atoms. lelf=True.4 ELF Need better intro here.translate(-benzene. elf. nsw=100.set_constraint(c) 24 25 #from ase.3.surface import fcc111.html).mayavi import mlab 5 6 7 atoms = molecule(’CF4’) atoms. 1 2 3 4 # compute ELF for CF4 from jasp import * from ase.0 + [0. xc=’PBE’..get_potential_energy() Open the python script (dft-scripts/script-206. sigma=0. view(atoms) 26 27 28 29 30 31 32 33 34 35 with jasp(’surfaces/Au-benzene-pbe-d2’.get_elf() mlab. 23 and 25 p = (atoms.univie.benzene on Au(111) 1 2 3 4 5 # Benzene on the slab from jasp import * from ase.png’) 22 23 mlab. 24 25 mlab.contour3d(x, y, z, elf,contours=[0.75]) mlab.savefig(’../../images/cf4-elf-75.png’) Open the python script (dft-scripts/script-207.py). None ./images/mlab-test.png These images (Figure 89 and 90) are basically consistent with those in Reference. 99 7.5 TODO Charge partitioning schemes 7.6 TODO Modeling Core level shifts 217 Figure 89: ELF for an isosurface of 0.3 for CF4 . 218 Figure 90: ELF for an isosurface of 0.75 for CF4 . 219 8 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. 9 Appendices 9.1 Recipes 9.1.1 Modifying Atoms by deleting atoms 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 #delete all the hydrogens ind2del = [atom.index for atom in atoms if atom.symbol==’H’] print ’Indices to delete: ’,ind2del 10 11 del atoms[ind2del] 12 13 14 # now print what is left print atoms Open the python script (dft-scripts/script-208.py). Atoms(symbols=’C2OH6’, positions=..., cell=[1.0, 1.0, 1.0], pbc=[False, False, False]) Indices to delete: [3, 4, 5, 6, 7, 8] Atoms(symbols=’C2O’, positions=..., cell=[1.0, 1.0, 1.0], pbc=[False, False, False]) 9.1.2 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 ’’’ adapted from https://listserv.fysik.dtu.dk/pipermail/campos/2004-September/001155.html ’’’ 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 # the bcc111 function automatically tags atoms slab = bcc111(’W’, a=3.92, # W lattice constant size=(2,2,6), # 6-layer slab in 2x2 configuration vacuum=10.0) 15 16 17 #reset tags to be powers of two so we can use binary math slab.set_tags([2**a.get_tag() for a in slab]) 18 19 20 21 22 23 24 # we had 6 layers, so we create new tags starting at 7 # Note you must use powers of two for all the tags! LAYER1 = 2 ADSORBATE = 2**7 FREE = 2**8 NEARADSORBATE = 2**9 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 #the adsorbate is centered between atoms 20, 21 and 22 (use #view(slab)) and over atom12 let us label those atoms, so it is easy to #do electronic structure analysis on them later. tags = slab.get_tags() # len(tags) changed, so we reget them. tags[12]+=NEARADSORBATE tags[20]+=NEARADSORBATE tags[21]+=NEARADSORBATE tags[22]+=NEARADSORBATE slab.set_tags(tags) #update the tags slab.set_tags(tags) 50 51 52 53 #extract pieces of the slab based on tags #atoms in the adsorbate ads = slab[(slab.get_tags() & ADSORBATE) == ADSORBATE] 54 55 56 #atoms in LAYER1 layer1 = slab[(slab.get_tags() & LAYER1) == LAYER1] 57 58 59 #atoms defined as near the adsorbate nearads = slab[(slab.get_tags() & NEARADSORBATE) == NEARADSORBATE] 60 61 62 #atoms that are free free = slab[(slab.get_tags() & FREE) == FREE] 63 64 65 #atoms that are FREE and part of the ADSORBATE freeads = slab[(slab.get_tags() & FREE+ADSORBATE) == FREE+ADSORBATE] 66 67 68 #atoms that are NOT FREE notfree = slab[(slab.get_tags() & FREE) != FREE] 69 70 71 72 73 constraint = FixAtoms(mask = (slab.get_tags() & FREE) != FREE) slab.set_constraint(constraint) write(’images/tagged-bcc111.png’, slab, rotation=’-90x’, show_unit_cell=2) from ase.visualize import view; view(slab) Open the python script (dft-scripts/script-209.py). 221 9. Unfortunately. Other units are defined in terms of those units.1. Å for distance. and amu for mass.Figure 91: The tagged bcc(111) structure created above.3 Using units in ase mod:ase uses a base set of atomic units. the frozen atoms do not show up in the figure. and you can easily convert to alternative 222 . seconds for time.These are eV for energy. ’kJ’. ’alpha’.485309 kJ/mol 1 eV = 23.100) y = np. No units algebra is enforced (i.units by dividing your quantity in atomic units by the units you want. ’C’. ’Angstrom’. ’Ry’. ’fs’. (x=time.036749 Hartrees 1 eV = 0.numpoints’] = 1 #default is 2 import matplotlib. suppose you have x and y data.format(eV/(kJ/mol)) kcal/mol’.605698 eV 10 hours = 600. and the corresponding y-data. We also show some customization of matplotlib. We have x data in the range of 0 to 6. y=signal) and you want to integrate the date between a particular time interval.4 Extracting parts of an array See http://www. ’GPa’.scipy.format(1*Rydberg/eV) 13 14 15 16 # derived units minute = 60*s hour = 60*minute 17 18 19 #convert 10 hours to minutes print ’10 hours = {0} minutes’. When analyzing numerical data you may often want to analyze only a part of the data. You can slice a numpy array to extract parts of it. For example. ’Bohr’.060542 kcal/mol 1 Hartree = 627.py). ’kg’.0 minutes 9.e. ’Hartree’.linspace(0.y.net/users/customizing. See http://www.1. ’Rydberg’. ’mol’. We want to extract the x and y data for 2 < x < 4. Note these are only conversion factors. ’nm’. d = 0.plot(x. ’eV’.509541 kcal/mol 1 Rydberg = 13.rcParams[’legend.format(10*hour/minute) Open the python script (dft-scripts/script-210. To do this. ’second’] It is not that hard to define your own derived units though. 1 2 3 4 5 import numpy as np import matplotlib as mpl #http://matplotlib.format(1*Hartree/(kcal/mol)) print ’1 Rydberg = {0} eV’. In this example we show how to extract the data in an interval.sourceforge. ’cm’. and y data that is the cos(x). ’Pascal’. ’s’. ’AUT’.073499 Rydbergs 1 eV = 96. org/Cookbook/Indexing for several examples of this. ’Debye’.format(eV/Rydberg) kJ/mol’.scipy.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’.label=’full’) 11 12 ind = (x>2) & (x<4) 13 223 .pyplot as plt 6 7 8 x = np. Not too many units are defined: [’A’. ’meV’. ’Ang’.units import * 2 3 4 d = 1*Angstrom print ’ d = {0} nm’. ’m’. ’kB’.6. we utilize the numpy capability of slicing with a boolean array. it will be ok to add a m and a kg)! 1 from ase. ’erg’.1 nm 1 eV = 0. ’J’. ’kcal’.html mpl.format(eV/Hartree) Rydbergs’.format(eV/(kcal/mol)) 10 11 12 print ’1 Hartree = {0} kcal/mol’.org/Cookbook/BuildingArrays for examples of making numpy arrays. ’Ha’.cos(x) 9 10 plt. 9. The expression x > 2 returns an array of booleans (True where the element of x is greater than 2. The solid line represents the whole array.legend(loc=’lower right’) plt. x < 2 and x > 4).png’) Open the python script (dft-scripts/script-211. 224 . Here is an example of computing a 95% confidence interval on an average. and the symbols are the array between 2 < x < 4. We take the logical and of these two boolean arrays to get another boolean array where both conditions are True (i. Similarly x < 4 returns a boolean array where x is less than 4.5 Statistics Confidence intervals mod:scipy has a statistical package available for getting statistical distributions. and False where it is not) equal in size to x. This final boolean array is True for the part of the arrays we are interested in.e. This is useful for computing confidence intervals using the student-t tables.plot(subx.1.py).savefig(’images/np-array-slice.suby.’bo’.label=’sliced’) xlabel(’x’) ylabel(’cos(x)’) plt.14 15 subx = x[ind] suby = y[ind] 16 17 18 19 20 21 plt. None Figure 92: Example of slicing out part of an array. and we can use it to extract the subarrays we want. sqrt(1.A)).png’) Open the python script (dft-scripts/script-213..dot(Aexp. avg_x + pred_interval) Open the python script (dft-scripts/script-212.float)]) 17 18 19 pars_np. dof) * std_x * np. 4.dot(np.3) print ’pars from polyfit: {0}’.+1. savefig pars = polyfit(xdata.3f} and {1:1.5.array([0.linalg. it is easy to fit an exponential function to it! # y = a*exp(x)+b Aexp = np.exp(xdata).03.ydata)) print ’pars from linear algebra: {0}’..resids.dot(Aexp. xdata**2. ydata)) 37 38 39 40 41 42 43 44 45 plot(xdata.linalg.join(s). ’b-’.1. We are 95% confident the next measurement will be between 16. 25 26 27 28 29 30 31 A^TAx = A^Tb x = (A^TA)^-1 A^T b ’’’ # not as pretty but equivalent! pars_man= np. ylabel. we can left multiply each side by A^T. legend.linalg.1. xdata. np.1. np.format(pars_man) 32 33 34 35 36 #but.]) ydata = np.ones(len(xdata). 37.1 #average measurement std_x = 0.6.95 12 13 pred_interval = t. np.2]) 6 7 8 9 10 #fit a third order polynomial from pylab import polyfit.99.np.format(pars) 11 12 13 14 15 16 ## numpy method returns more data A = np.0.81. np. fity. ydata) print ’pars from np.4.rank.float)]) pars_exp=np. show.dot(A. pars_exp).0 . 0.ydata.ones(len(xdata).inv(np.2.ppf(1-alpha/2.3.1.stats... Aexp)).lstsq: {0}’.format(pars_np) 20 21 22 23 24 ’’’ we are trying to solve Ax = b for x in the least squares sense.T.s = np. xlabel.1 2 import numpy as np from scipy. ’ will be between {0:1.py). pars) plot(xdata. 9.124 9.T. 15. np. 24.column_stack([np. and then solve for x with an inverse..01 #standard deviation of measurements 8 9 #Find 95% prediction interval for next measurement 10 11 alpha = 1. label=’poly fit’) plot(xdata. np.T. plot.2. label=’exp fit’) xlabel(’x’) ylabel(’y’) legend() savefig(’images/curve-fit-1.076 and 16.column_stack([xdata**3.lstsq(A. 225 .3f}’] print ’’.py).dot(Aexp.pred_interval.array([0. ydata. ’k-’.dot(A. ’ro’) fity = np.linalg.format(avg_x .distributions import t 3 4 5 6 7 n = 10 #number of measurements dof = n . There are more rows in A than elements in x so.1 #degrees of freedom avg_x = 16../n) 14 15 16 17 s = [’We are 95% confident the next measurement’.6 Curve fitting Linear fitting 1 2 #examples of linear curve fitting using least squares import numpy as np 3 4 5 xdata = np.dot(A.dot(np.inv(np..T. 463.linalg. -56.61365079 -0.Murnaghan(pars.lstsq: [ 0. 17. -56.1. 2.V0*B0/(BP-1.29.46..x): #we will minimize this function err = y . 16. 14.82. 16.0..61365079 -0.08928571] pars from np.optimize import leastsq import numpy as np 3 4 vols = np.vol): ’From Phys.array([-56.) 16 17 return E 18 19 20 21 22 def objective(pars. 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) .52]) 5 6 energies = np. Rev.7 1 2 Nonlinear curve fitting from scipy.-56.04861111 0.y.63440476 0.54. 9.71.08928571] pars from linear algebra: [ 0.array([13.pars from polyfit: [ 0.23.63440476 0.63440476 0.08928571] Figure 93: Example of linear least-squares curve fitting.41.04861111 0. 18. B 28. -56.41]) 7 8 9 10 11 12 13 def Murnaghan(parameters.61365079 -0.04861111 0. 0.x) return err 23 24 x0 = [ -56.5] #initial guess of parameters 226 . py).x) plt. 0.scipy.format(plsq[0]) 29 30 31 import matplotlib.55905648]).pyplot as plt plt.46839641.org/doc/scipy/reference/tutorial/optimize.xlabel(’Volume’) plt.energies.7407944 .1.plot(x.0.8 1 2 Nonlinear curve fitting by direct least squares minimization from scipy.’k-’) plt.ylabel(’energy’) plt.71.array([13. 17. args=(energies.57233217.plot(vols. See additional examples at http://docs.50) y = Murnaghan(plsq[0]. 1) Figure 94: Example of least-squares non-linear curve fitting. Fitted parameters = (array([-56. 16.savefig(’images/nonlinear-curve-fitting. 18. 2. x0.vols)) 27 28 print ’Fitted parameters = {0}’. 14. 16.25 26 plsq = leastsq(objective. 9.52]) 227 .png’) Open the python script (dft-scripts/script-214.82.optimize import fmin import numpy as np 3 4 volumes = np. html.max(vols).linspace(min(vols).y.’ro’) 32 33 34 35 36 37 38 39 #plot the fitted curve on top x = np.23. y. 2.vol): #we will minimize this function err = energies .pyplot as plt plt.)) #note args is a tuple 27 28 print ’parameters = {0}’. The downside is you need an initial guess.5] #initial guess of parameters 25 26 plsq = fmin(objective.-56.3075 2.’k-’) plt. -56.plot(x.ylabel(’Total energy (eV)’) plt.stats.000020 Iterations: 137 Function evaluations: 240 parameters = [-56. 0. Optimization terminated successfully.py). -56.format(plsq) 29 30 31 import matplotlib.x0.59341303] .x) plt.png’) Open the python script (dft-scripts/script-215.plot(volumes. Current function value: 0.46932645 0.savefig(’images/nonlinear-fitting-lsq.463.7671 23 24 25 5.distributions import t 5 6 7 8 ’’’ fit this equation to data y = c1 exp(-x) + c2*x 9 10 11 12 this is actually a linear regression problem.vol) return np.46.29.9044796 9.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) .optimize import curve_fit from scipy. 16.41]) 7 8 9 10 11 12 13 def Murnaghan(parameters.array([-56.Murnaghan(pars.4528 ’’’ 26 228 16.args=(volumes.9 1 2 3 4 Nonlinear curve fitting with confidence intervals # Nonlinear curve fit with confidence interval import numpy as np from scipy..5 6 energies = np.41.V0*B0/(BP-1. but it is convenient to use the nonlinear fitting routine because it makes it easy to get confidence intervals. 13 14 15 from Matlab b = 16 4.max(volumes).’ro’) 32 33 34 35 36 37 38 39 #plot the fitted curve on top x = np.59141447 1.) 15 16 return E 17 18 19 20 21 22 def objective(pars.energies.vol): ’From PRB 28.xlabel(’Volume ($\AA^3$)’) plt.1100 17 18 19 20 21 bint = 22 4.9671 2.6267 1. -56.1.50) y = Murnaghan(plsq.linspace(min(volumes).54..sum(err**2) #we return the summed squared error directly 23 24 x0 = [ -56. ppf(1. 0.06079909]) 30 31 32 33 # this is the function we want to fit to our data def func(x. x.1) yfit = func(xfit. 0. 3.5.70192769. 229 .46826356. 2. 4.2.format(i. np.88155125. 3. 4. 3.py).array([ 4.’b-’) plt.86379487. dof) # student-t value for the dof and confidence level 45 46 47 48 49 50 for i.’fit’]. pcov = curve_fit(func. 4.loc=’best’) plt.yfit. 4. p.c0. 1..’bo ’) xfit = np. p . ]) y = np.y. 0.78382253.plot(x.Figure 95: Fitting a nonlinear function.3. c1): return c0 * np. 4. 0.96.11]) 36 37 alpha = 0. 0.array([ 0. p. 27 28 29 x = np.1.5 print ’c{0}: {1} [{2} {3}]’.7. pars[1]) plt.pyplot as plt plt.9. 3.8.sigma*tval.57021389.0-alpha/2.plot(xfit.6. 0. p0=[4.29240134. 0. pars[0].var in zip(range(n).exp(-x) + c1*x 34 35 pars.4.65454727. y.legend([’data’. pars.diag(pcov)): sigma = var**0. 0.png’) Open the python script (dft-scripts/script-216.linspace(0. p + sigma*tval) 51 52 53 54 55 56 57 58 import matplotlib.savefig(’images/nonlin-fit-ci.16428541.05 # 95% confidence interval 38 39 40 n = len(y) # number of data points p = len(pars) # number of parameters 41 42 dof = max(0. n-p) # number of degrees of freedom 43 44 tval = t. 5) 17 18 xfit = np. bounds_error=False) 12 13 14 15 16 # to find the maximum. 4 ]) 0. you can still fit/interpolate with splines. 0. f(xfit).’bo’) plt.array([ 0.44 ]) 9 10 11 # create the interpolating function f = interp1d(x. -y. 0. f(xmax). f2 = interp1d(x. so we create a new function here. kind=’cubic’) xmax = fmin(f2.plot(xmax.c0: 4.10995112628 [1.plot(xfit. 1 2 3 4 5 # use splines to fit and interpolate data from scipy.y.96713966439 [4.optimize import fmin import numpy as np import matplotlib.. 2. We # cannot just multiply f by -1. 1.4) 19 20 21 22 plt.’g*’) 230 . 0. y = np. 9.30753456558] 2. kind=’cubic’.linspace(0.’r-’) plt.308. 2.pyplot as plt 6 7 8 x = np.546. we minimize the negative of the function.plot(x.55. 3.76711622067 5.45278603188] Figure 96: Nonlinear fit to data.10 Interpolation with splines When you do not know the functional form of data to fit an equation.1.62674476321 c1: 2. y.array([ 0.interpolate import interp1d from scipy. legend([’data’. What are you to do? Interpolate.title(’Max point = ({0:1. this solution only applies to rectangular grids. Figure 97: Illustration of a spline fit to data and finding the maximum point. float(f(xmax)))) plt.xlabel(’x data’) plt.1. Later we will generalize the approach. where we use multiple linear 1D interpolations to compute the value of a point inside a cube. numpoints=1) plt. html 9.b.savefig(’images/splinefit. The principle we will use to develop an interpolation function in 3D is called trilinear interpolation.png’) Open the python script (dft-scripts/script-217. loc=’best’.11 Interpolation in 3D You might ask.2f})’. {1:1.ylabel(’y data’) plt.c).format(float(xmax).23 24 25 26 27 28 plt. We state the problem as follows: We know a scalar field inside a unit cell on a regularly spaced grid.2f}.org/doc/scipy/reference/tutorial/interpolate. and they are known on the fft grids. 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. I could not find any standard library methods for 3D interpolation. As developed here.’fit’. In contrast to an abundance of methods for 1D and 2D interpolation. say P=(a. In VASP these fields may be the charge density or electrostatic potential for example. We want to estimate the value of the scalar field at a point not on the grid.’max’].scipy.py). 231 . There are other good examples at http://docs. and the value of the scalar field at I2 by interpolating between P3 and P4. In these points the only variable changing is x.zi): ’’’ interpolate a cubic 3D grid defined by x. so it is a simple 1D interpolation.z2).cd. Note that the point I5 has coordinates (a.cd at the point (xi. to obtain points I3.z1) and I6 is at (a. I4 and I5. 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. y.xi. Finally. We repeat the process on the top of the cube.zi) 232 .z.c).b.get_atoms() x. and is defined by points P1-P8 as shown in Figure ??. 1 2 from jasp import jasp import numpy as np 3 4 5 6 with jasp(’molecules/co-centered’) as calc: atoms = calc. We can then compute the value of the scalar field at I5 by interpolating between I1 and I2.y.z. we compute the value of the scalar field at point P by interpolating between points I5 and I6.b.Solution: Find the cube that contains the point. cd = calc.get_charge_density() 7 8 9 10 11 def interp3d(x. We use 1D interpolation formulas to compute the value of the scalar field at points I1 by interpolating between P1 and P2.y.b.yi.yi. z. val in enumerate(vector): if val > value: return i-1 return None 23 24 25 26 xv = x[:. A bisection search would be faster.:. 5.0. yi.plot(R. 8].j.j+1.linalg. icd) cR = np.0.p[2]) for p in points] 74 75 import matplotlib.0. 5. ’r-’) #markers for where the nuclei are plt.xv) j = get_index(b. j+1.plot([cR. k] cd[i. k] cd[i.P1) plt. 2]. j. [0.norm(pos[0] .z.k] y[i.get_positions() 62 63 64 P1 = np.j. oR].0.c = xi.py).linalg. k+1] cd[i+1.k] z[i.0]) P2 = np.savefig(’images/CO-charge-density. cR].xlabel(’|R| ($\AA$)’) plt.0. zi 29 30 31 32 i = get_index(a.j.k] z[i.plot([oR.pyplot as plt 76 77 78 79 80 81 82 83 84 85 plt. j. j+1.12 ’’’ 13 14 15 16 17 18 19 20 21 22 def get_index(value. 5. k+1] cd[i.j.norm(pos[1] .yv) k = get_index(c.y.show() Open the python script (dft-scripts/script-218.zv) 33 34 35 36 37 38 39 x1 x2 y1 y2 z1 z2 = = = = = = x[i.png’) plt. j+1.k+1] u1 u2 u3 u4 u5 u6 u7 u8 = = = = = = = = cd[i.ylabel(’Charge density (e/$\AA^3$)’) plt. j.cd. [0.0] yv = y[0. 5.array([9. ’r-’) plt. k+1] cd[i+1.P1) oR = np. ’’’ for i.0] zv = z[0.k] x[i+1.vector): ’’’ assumes vector ordered decreasing to increasing.0. 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.:] 27 28 a.p[1]. j. k] cd[i+1.array([0. None 233 .norm(p-P1) for p in points] 71 72 73 # interpolated line icd = [interp3d(x.k] y[i.p[0]. k] cd[i+1.0]) 65 66 npoints = 60 67 68 points = [P1 + n*(P2-P1)/npoints for n in range(npoints)] 69 70 R = [np. j+1.j.linalg.b. get_atoms() x.zi]) 19 20 21 22 23 #1D arrays of cooridinates xv = x[:. Do the interpolations along the basis vectors.cd = calc.z2) where (P2-P1) is a cell basis vector a. savefig.:] 24 234 .sb.yi.array([xi.0. 1 2 3 ’’’ 3D vector interpolation in non-cubic unit cells with vector interpolation.yi.y2. ’’’ from jasp import * import bisect import numpy as np from pylab import plot. Below is an example of this code.0. Given u1 at P1(x1. ylabel.z. using a the python library bisect to find the cell. show 11 12 13 14 with jasp(’molecules/co-centered’) as calc: atoms = calc.u. u = u1 + sa*(u2-u1).0] yv = y[0. The overall strategy is the same: Find the cell that contains the point (a.c). we need to do interpolation along arbitrary vectors.0] zv = z[0. 4 5 6 7 8 9 10 This function should work for any shape unit cell.xi.Figure 98: An example of interpolated charge density of a CO molecule along the axis of molecule. compute the scaled coordinates (sa.b. To generalize this to non-cubic cells.y.z1) and u2 at P2(x2.zi): 17 18 p = np.:.sc) of the point inside the cell.y1. xlabel.get_charge_density() 15 16 def vinterp3d(x.y. There are still 7 interpolations to do.z. yi) .0. P3-P1.bisect_right(yv.k] u2 = u[i+1.array([x[i+1.’r-’) xlabel(’|R| ($\AA$)’) ylabel(’Charge density (e/$\AA^3$)’) savefig(’images/interpolated-charge-density.z[i.k].j.k+1] 47 48 49 50 51 #cell basis vectors. P5-P1]) 52 53 54 #now get interpolated point in terms of the cell basis s = np.z[i+1.1 = bisect.k] u4 = u[i+1.array([x[i.k]]) P3 = np.[0.j.k].j+1.j.T).j.y[i.y[i.0.array([x[i.k]]) P2 = np. None 9.array([x[i. We only need P1.linalg.8].linalg.k+1].j.k].0]) P2 = np.1.p[0].j.j+1.k].0.array([0.1 = bisect.linalg.array([P2-P1.inv(cbasis.k+1] u8 = u[i+1. so we want the index to the left of that point = bisect. and P5 P1 = np. P2.j.’r-’) #markers for where the nuclei are plot([oR.k]]) P5 = np.25 26 27 28 29 30 # # # i j k we subtract 1 because bisect tells us where to insert the element to maintain an ordered list.z[i.j. but the voxel cell containing the point cbasis = np.j. P3.k+1]]) 37 38 39 40 41 42 43 44 45 46 #values of u at edge of cell u1 = u[i.icd) pos = atoms.np.k].k].norm(p-P1) for p in points] 81 82 icd = [vinterp3d(x.2].y[i.k+1] u6 = u[i+1. sb.p[1].z.j.dot(np.norm(pos[0]-P1) oR = np.yi.bisect_right(xv.1 31 32 33 34 35 36 #points at edge of cell.array([xi.0.j+1.z[i.p[2]) for p in points] 83 84 85 86 87 88 89 90 91 92 93 plot(R.[0.norm(pos[1]-P1) plot([cR. 5.k+1] u7 = u[i.oR]. 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 ui5 = ui1 + s[1]*(ui2-ui1) ui6 = ui3 + s[1]*(ui4-ui3) 66 67 ui7 = ui5 + s[2]*(ui6-ui5) 68 69 return ui7 70 71 72 73 # compute a line with 60 points in it through these two points P1 = np.j+1. 5.j.array([10.zi])-P1) 55 56 57 58 59 #now s = #next we ui1 = u1 ui2 = u3 (sa.cd.linalg.png’) show() Open the python script (dft-scripts/script-219. 5.k] u3 = u[i.j+1.j+1.12 Reading and writing data 235 .cR].py).y[i+1.xi) .j.zi) .get_positions() cR = np.bisect_right(zv. not the unit cell.j.y. 5.j+1.k] u5 = u[i.0]) 74 75 npoints = 60 76 77 points = [P1 + n*(P2-P1)/npoints for n in range(npoints)] 78 79 80 # compute the distance along the line R = [np.k+1]. dat’) Open the python script (dft-scripts/script-221.dat’.csv2rec and func:pylab.py).org/Cookbook/InputOutput for examples of numpy io. see also func:pylab. and later you can read these arrays back in with: 1 x.save(’pdat. 1 pylab.scipy.load. func:pylab. Likewise.savetxt.load(’pdat. Basically. any datafile that has some structure to it can probably be read by python. 4 robert.save and func:pylab.y = pylab. just open a file and write data to it. 5 terry.y)) Open the python script (dft-scripts/script-220.py).Figure 99: Interpolated charge density for a CO molecule. Let us consider a datafile with these contents: #header #ignore these lines john. From scratch You can save data in many ways from scratch.loadtxt and func:pylab. See http://www. 5 236 . Built-in io modules pylab has two convenient and powerful functions for saving and reading data.(x. The average energy of distribution is: R ρEdE Eavg = R ρdE or.format(a.E)/np. Note that y comes first. skip the first two lines.trapz() method.’. in python: 1 e_avg = np.write(’#ignore these lines\n’) for a. ’w’) #note ’w’ = write mode f.6] f = open(’somefile’.trapz(y.py). and append the second field to another variable as an integer. We can integrate the density of states to find the total R number of states: Nstates = ρdE or. {1}\n’. Suppose for example.append(int(fields[1])) #number Open the python script (dft-scripts/script-222.E) 237 .x).readlines() 4 5 6 7 8 for line in lines[2:]: #skip the first two lines fields = line.’r’). Integration can be used to calculate average properties of continuous distributions. ρ as a function of energy E. opening a file in ’w’ mode clobbers any existing file.close() Open the python script (dft-scripts/script-223. Use it like this: func:numpy.b)) f. Manually writing and reading files is pretty tedious.py).13 Integration Numerical integrations is easy with the numpy.E) Open the python script (dft-scripts/script-224. in python: 1 Nstates = np.v2): f. Writing datafiles is easy too.1. 1 2 3 4 5 6 7 8 v1 = [’john’.trapz(rho.split(’.write(’{0}. when writing to a file you have to add a carriage return to each line. 9. Some notes: 1. 2. ’terry’] v2 = [4. we have a density of states.py). y and x must be the same length. and append the first field to one variable.b in zip(v1. where rho is a vector that contains the density of states at each energy in the vector E (vector here means a list of numbers).5. ’robert’.A standard approach would be to read in all the lines.’) v1.append(fields[0]) #names v2.trapz(rho. so do that with care! 1.trapz(rho*E. split each line (remember each line is a string) at the ’. Whenever possible you should use the built-in methods of mod:numpy or mod:pylab. For example: 1 2 3 v1 = [] v2 = [] lines = open(’somefile’.write(’#header\n’) f. tb1) 38 39 40 41 42 43 ’’’and now.E)/np. 9.0]*len(x) dyc[0] = (y[0] .0]*len(x) for i in range(len(y)-1): dyf[i] = (y[i+1] .time() .len(y)): dyb[i] = (y[i] . we use:: 1 2 n = 2 mom_2 = np. It calculates the differences between the elements in your list.79 y = np.time() dyb = [0.py).78.linspace(0.1f} seconds’. where there is not a forward difference to use.79. they are surprisingly fast even up to 10000 points in the vector.1f} seconds’.sin(x) dy_analytical = np. 100) # 100 points between 0. These last two examples are the zeroth and first moments of the density of states. a centered formula’’’ tc1 = time. and the third and fourth moements are related to skewness and kurtosis of the distribution. which makes it unsuitable for plotting the derivative of a function.time() dyc = [0.1.x[1]) for i in range(1.tf1) 28 29 30 31 32 33 34 35 ’’’and now a backwards difference’’’ tb1 = time. 0.format(time.format(time.Open the python script (dft-scripts/script-225.0]*len(x) #set first element by forward difference dyb[0] = (y[0] .time() dyf = [0. It is implied in these formulas that the data points are equally spaced. and returns a list that is one element shorter.x[1]) for i in range(1.E) Open the python script (dft-scripts/script-226.cos(x) ’’’ let us use a forward difference method: that works up until the last point.y[1])/(x[0] .trapz(rho.78 and 0. ’’’ 19 20 21 22 23 24 25 tf1 = time.y[i])/(x[i+1]-x[i]) #set last element by backwards difference dyf[-1] = (y[-1] .y[1])/(x[0] .py).len(y)-1): 238 .14 Numerical differentiation numpy has a function called func:numpy. there.y[-2])/(x[-1] .x[-2]) 26 27 print ’ Forward difference took {0:1.trapz(rho*E**n. The second moment is related to the width squared of the distribution. They work well for very smooth data.pyplot as plt import time 4 5 6 7 8 9 ’’’ These are the brainless way to calculate numerical derivatives.y[i-1])/(x[i]-x[i-1]) 36 37 print ’ Backward difference took {0:1. The nth is defined by: R moment ρ∗E n dE mn = R ρdE To get the second moment of the density of states in python. 1 2 3 import numpy as np import matplotlib. Simple loops to define finite difference derivatives Loops in python are pretty slow (relatively speaking) but they are usually trivial to understand. we use a backward difference.time() . ’’’ 10 11 12 13 14 15 16 17 18 x = np. In this script we show some simple ways to construct derivative vectors using loops.diff that is similar to the one found in Matlab. savefig(’images/simple-diffs.format(time.0 seconds Backward difference took 0.dyf.0 seconds Obviously.plot(x.y[-2])/(x[-1] . Numpy offers some vectorized methods that allow us to compute derivatives without loops.’--’.plot(x.legend(loc=’lower left’) plt.plot(x. Figure 100: Comparison of different numerical derivatives.44 45 dyc[i] = (y[i+1] .y[i-1])/(x[i+1]-x[i-1]) dyc[-1] = (y[-1] . Loops are usually not great for performance.label=’analytical derivative’) plt.plot(x.’--’.1f} seconds’.x[-2]) 46 47 print ’ Centered difference took {0:1.label=’centered’) 57 58 59 plt.’--’.py).dyc.0 seconds Centered difference took 0.dyb. although this comes at the mental cost of harder to understand syntax: 239 . all of these evaluations are very fast.tc1) 48 49 50 51 ’’’ the centered formula is the most accurate formula here ’’’ 52 53 54 55 56 plt.time() .png’) Open the python script (dft-scripts/script-227.label=’backward’) plt. Forward difference took 0.label=’forward’) plt.dy_analytical. x[-2]) 32 33 plt.x[-2]) 13 14 15 16 17 ’’’ calculate dy by center differencing using array slices ’’’ 18 19 20 21 22 dy2 = np.plot(x. derivatives tend to magnify noise.pi.y[0:-2])/(x[2:] .plot(x. None If your data is very noisy. you will have a hard time getting good derivatives.py).zeros(y.diff(x) dy[-1] = (y[-1] .plot(x.plot(x.sin(x) dy_analytical = np.y[i])/(x[i+1]-x[i]) #set last element by backwards difference dyf[-1] = (y[-1] .lw=2. you have to employ smoothing techniques.y[-3])/(x[-2] .’k--’.dy2.*h) 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] .pi.2*np.float) #we know it will be this size h = x[1]-x[0] #this assumes the points are evenely spaced! dy[2:-2] = (y[0:-4] .2*np.0]*len(x) for i in range(len(y)-1): dyf[i] = (y[i+1] .diff(y)/np.cos(x) 7 8 9 10 11 12 13 #2-point formula dyf = [0.8y[i-1] + 8[i+1] .x[-2]) 23 24 25 26 27 28 29 plt.1*np.linspace(0. or explicitly by smoothing the data yourself.shape.label=’centered diff’) plt.float) #we know it will be this size dy2[1:-1] = (y[2:] .y[-2])/(x[-1] .linspace(0.x[0:-2]) dy2[0] = (y[1]-y[0])/(x[1]-x[0]) dy2[-1] = (y[-1] .dy_analytical.1 2 import numpy as np import matplotlib.shape) dy_analytical = np.x[-3]) dy[-1] = (y[-1] .pyplot as plt 3 4 5 6 x = np.random(size=x.100) y = np. or taking the derivative of a function that has been fit to the data in the neighborhood you are interested in.label=’forward diff’) plt.dy.np.x[-2]) 14 15 16 ’’’ calculate dy by 4-point center differencing using array slices 17 18 \frac{y[i-2] .y[4:])/(12.pyplot as plt 3 4 5 6 x = np.shape.cos(x) 7 8 9 10 11 12 # we need to specify the size of dy ahead because diff returns #an array of n-1 elements dy = np.np.label=’analytical derivative’) plt.8*y[1:-3] + 8*y[3:-1] .float) #we know it will be this size dy[0:-1] = np.zeros(y.savefig(’images/vectorized-diffs.y) plt. In these cases.zeros(y.plot(x.y[-2])/(x[-1] .y[-2])/(x[-1] .shape.random. either implicitly by using a multipoint derivative formula.y[i+2]}{12h} 19 20 21 22 y[0] and y[1] must be defined by lower order methods and y[-1] and y[-2] must be defined by lower order methods ’’’ 23 24 25 26 dy = np.sin(x) + 0. Here is an example of a 4-point centered difference of some noisy data: 1 2 import numpy as np import matplotlib.legend(loc=’lower left’) plt.np.100) y = np.y[-2])/(x[-1] .y) 240 .png’) Open the python script (dft-scripts/script-228. cos(x) 12 13 14 ’’’ http://sci.math/2008-05/msg00401.png’) Open the python script (dft-scripts/script-229.py).label=’analytical derivative’) plt.dy. but the four-point derivative is a little better than the two-pt formula.legend(loc=’lower left’) plt.arange(0.random.label=’4pt-centered diff’) plt.sin(x) + 0.lw=2.random(size=x.plot(x.pyplot as plt 3 4 5 N = 101 #number of points L = 2*np.’k--’.shape) dy_analytical = np. FFT derivatives 1 2 It is possible to perform derivatives using fast fourier transforms (FFT): import numpy as np import matplotlib. 34 35 36 37 38 plt.0. None The derivative is still noisy.html 15 16 you can use fft to calculate derivatives! 241 .dyf.plot(x.05*np.dy_analytical.tech-archive.pi #interval of data 6 7 x = np.net/Archive/sci.’r-’.Figure 101: Comparison of different numerical derivatives.savefig(’images/multipt-diff.L.plot(x.label=’2pt-forward diff’) plt.L/float(N)) #this does not include the endpoint 8 9 10 11 #add some random noise y = np. plot(x.fft(y)) 27 28 29 30 31 plt.fft.fft.15 NetCDF files NetCDF is a binary.dy_analytical.ifft(1.label=’analytical der’) plt.0)) 23 24 k *= 2*np.fr/plone/software/scientificpython/) 242 .y) plt. This example does not show any major advantage in the quality of the derivative.Figure 102: Comparison of 2 point and 4 point numerical derivatives. 9.plot(x. The input file and output file for Dacapo is the NetCDF format. but cross-platform structured data format.plot(x.fd.label=’fft der’) plt.j*k * np.png’) Open the python script (dft-scripts/script-230. On creating a NetCDF file you must define the dimensions and variables before you can store data in them.(N-1)/2) +[0] + range(-(N-1)/2.pi/L 25 26 fd = np. 17 ’’’ 18 19 20 21 22 if N % 2 == 0: k = np.legend(loc=’lower left’) 32 33 plt.asarray(range(0.1.NetCDF (http://dirac.cnrs-orleans.IO. and it is almost certain I would never remember how to do this off the top of my head.savefig(’images/fft-der.N/2)+[0] + range(-N/2+1. You can create and read NetCDF files in python using one of the following modules: mod:Scientific.0)) else: k = np.asarray(range(0.py). y)) Open the python script (dft-scripts/script-231.y = [].’r’). csv reading: 1 2 import csv reader = csv.0.6. mod:netCDF3 (http://netcdf4-python.reader(open("some.sourceforge. "w")) writer.100) y = np.csv".delimiter=’. so you must turn the strings back into floats (or whatever other format they should be).writerows(zip(x.16 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.1.writer(open("some.0.html) mod:pycdf (http://pysclint.Figure 103: Comparison of FFT numerical derivatives.cos(x) 5 6 7 8 import csv writer = csv.py).[] for row in reader: 243 .’) 3 4 5 x.googlecode.linspace(0.net/pycdf/) this is a very low level module modelled after the C-api. I am not sure it is completely bug-free (I have problems with character variables) 9. It is not so easy to read the data back in though because the module only returns strings.csv".com/svn/trunk/docs/netCDF3-module. energy) wbk. so one day checkout pydoc csv.py). using swftools (png2swf.append(a) y. 17.1.23. -56. Check them out some day too. -56. energies)): vol = pair[0] energy = pair[1] sheet. 16. -56.sheet_by_name(’sheet 1’) print sheet1.46. pair in enumerate(zip(volumes.83.46. 18. -56.83.add_sheet(’sheet 1’) 6 7 8 volumes = np.72. [13.28_Current_Stable_Version_.py).18 TODO making movies 1. 1 2 import numpy as np import xlwt 3 4 5 wbk = xlwt.52] [-56. using animate 2.append(b) Open the python script (dft-scripts/script-232. 16. -56.save(’images/test-write.array([13. The mod:pickle and mod:shelve modules of python also offer some data storage functionality. We can create Excel files in python with mod:xlwt. 1 2 3 4 5 import xlrd wbk = xlrd.col_values(0) print sheet1.23.write(i. Let us read in the data we just wrote.41.42]) 9 10 11 12 13 14 15 for i.46. -56. 9.6 7 8 9 #csv returns strings that must be cast as floats a.29. We wrote 5 volumes to column 0.1.xls’) Open the python script (dft-scripts/script-233. Reading Excel files We can also read Excel files (even on Linux!) with mod:xlrd.py).swftools. 14.46.b = [float(z) for z in row] x.array([-56. The module is more powerful than I have shown here.1.41.42] 9. -56. 17.xls’) sheet1 = wbk.0.9. Google this module if you need to do this a lot.72.org/wiki/Main_Page#SWF_Tools_0. 14. 18.2_.52]) energies = np.Workbook() sheet = wbk. -56.0. This is almost as much work as manually reading the data though.29.29_ Documentation 244 .vol) sheet.0. and 5 energies to column 1.17 Writing and reading Excel files Writing Excel files It is sometimes convenient to do some analysis in Excel.col_values(1) Open the python script (dft-scripts/script-234.write(i. pdf2swf) #http://wiki.open_workbook(’images/test-write. so we will have to transpose the positions provided by the atoms class. and then transpose the final result to get the positions back into row-vector form: s = ((AT )−1 pT )T Here we implement that in code: 1 2 3 from ase.408] [ 0.lattice.667 0.y.167 0.92.2. in standard form: AT s = p and we need to solve for s as: s = (AT )−1 · p p must be a column vector.1 Changing coordinate systems Let A.167 0.get_cell() 14 15 16 s = np. C be the unit cell vectors A = A1x + A2y + A3z (9) B = B1x + B2y + B3z (10) C = C1x + C2y + C3z (11) and we want to find the vector [s1.set_printoptions(precision=3.3).2. we get: s1A1x + s1A2y + s1A3z + s2B1x + s2B2y + s2B3z + s3C1x + s3C2y + s3C3z = p1x + p2y + p3z If we now match coefficients on x. #3-layer slab in 1x1 configuration vacuum=10.408] 245 .slab. Coordinates in new basis are: [[ 0.get_positions() #these positions use x. we can  B1 C1 B2 C2   B3 C3 write a set of linear equations as:    p1 s1 s2  =  p2  p3 s3 (12) or.T).inv(newbasis. s2.  A1  A2 A3 and z.dot(np.167 0.408] [ 0.667 0.T print ’Coordinates in new basis are: \n’. y. # Pd lattice constant size=(2. B.surface import fcc111 import numpy as np np.2 Computational geometry 9.suppress=True) 4 5 6 7 8 slab = fcc111(’Pd’.linalg.pos.get_scaled_positions() Open the python script (dft-scripts/script-235. a=3.9.py).T).167 0.z vectors as a basis 11 12 13 # we want to see the atoms in terms of the unitcell vectors newbasis = slab. s3] so that P = s1A + s2B + s3C if we expand this.s 17 18 19 # what we just did is equivalent to the following atoms method print ’Scaled coordinates from ase are: \n’.0) 9 10 pos = slab. pos.333 0.408] [ 0. 0.bulk. 1. Sometimes it is nice if all the coordinates are integers.833 0.get_cell(). [0. -0. 0.167 0. symbol=’Fe’) 9 10 11 12 13 newbasis = 2. 1. and assuming one atom is at the origin.167 0.1]]. 0.lattice.0].667 0.get_positions() 16 17 18 19 s = np.2.592] [ 0.5 ] [ 0. 0.5. 0. 1. 0. 2.5 ] [ 0.T).5.592]] The method shown above is general to all basis set transformations.0. we will use the bcc primitive lattice vectors and express the positions of each atom in terms of them.333 0.5 0. 0. 0. -0.667 0. [0.inv(newbasis.833 0.167 0.408] [ 0.833 0.5 ] [ 0.408] [ 0.5 0.667 0.5.5.592] [ 0.167 0.5 ] [ 0.linalg.5 0.833 0.py).408] [ 0.592] [ 0. For this example.5 ] [-0.667 0.5].5 0.333 0.167 0.5 0.333 0.5 0.333 0.1.cubic import BodyCenteredCubic import numpy as np bulk = BodyCenteredCubic(directions=[[1.5].667 0.5]]) 14 15 pos = bulk.87*np.667 0. 2.[ 0.linalg. We examine another case next. latticeconstant=2.333 0.592] [ 0.833 0.5. 0. By definition each atomic position should be an integer combination of the primitive lattice vectors (before relaxation.333 0.T).T).0. 0.87. 0.5 ] [ 0.dot(np. size=(2.] [ 1.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. and the unit cell is aligned with the primitive basis!) 1 2 3 4 5 6 7 8 from ase.167 0.592]] Scaled coordinates from ase are: [[ 0.592] [ 0. atom positions in primitive basis [[ 0. 0.T Open the python script (dft-scripts/script-236. 0. [0.2). [0. 1.333 0.5 ] [ 0. 0.5 0.dot(np.] 246 .5.0].array([[-0.] [ 1.T).] [ 0.inv(newbasis.5 0.5 ] [ 0.408] [-0.833 0.592] [ 0. A. If they are right-handed the determinant will be positive. 0.dot(a/np. 1.1]) #numpy 6 7 B = Vector([0. 3. 1. 2. 0. Switching any two rows will change the sign of the determinant and the handedness.angle(B) #in radians print ’numpy angle = ’. and if they are left-handed the determinant will be negative. 2. 2. 2. B = ’. 2. 2.0]) 8 9 10 11 print ’|A| = ’.2.cross(B) print ’numpy A .] [ 1.1. 2. 0. 2.] [ 1.cross.]] unit cell in terms of the primitive basis [[ 0. 2.] [ 2. 0] 247 .5 #numpy way print ’|a| = ’.cross(A.] [ 2.py).np.] [ 3.1. 1. 2. 2.2.] [ 2.] [ 2. 1.get_volume.] [ 2.length() #Scientific Python way print ’|a| = ’.] [ 3.0.linalg.] [ 1. 2.np. a2 and a3 are the unit cell vectors. 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. 1. 1.]] 9.Geometry import Vector 3 4 5 A = Vector([1.A.1]) #Scientfic a = np. angles Scientific.] [ 2. 1. 1 import numpy as np 2 3 a1 = [2.np. 9. 3.np. however.] [ 2.norm(a). Here are three equivalent ways to compute the unit cell volume. to simply evaluate that equation as the determinant of the matrix describing the unit cell.1.norm(B))) 15 16 17 18 #cross products print ’Scientific A .linalg. 0.2 Simple distances. where each row of the matrix is a unit cell vector.norm(a) #numpy way 2 12 13 14 print ’ScientificPython angle = ’.Geometry contains several useful functions for performing vector algebra including computing lengths and angles.B) #you can use Vectors in numpy Open the python script (dft-scripts/script-237. mod:ase implements a convenient function to get the volume of an mod:Atoms object: func:ase. It is more convenient.linalg.A.cross.array([1.0. 1 2 import numpy as np from Scientific. 1.Atoms.[ 1. 3. 3.] [ 2.arccos(np. B = ’. 2.sum(a**2)**0. 2.0.B/np. 0.3 Unit cell properties The volume of a unit cell can be calculated from V = (a1 × a2 ) · a3 where a1 . cell=uc) #empty list of atoms print ’V = {0} ang^3 from get_volume’.array([h. The script below shows several ways to accomplish that.array([a1.get_cell()) 13 14 15 ’’’ g(111) = 1*b1 + 1*b2 + 1*b3 16 17 18 19 20 and |g(111)| = 1/d_111 ’’’ h.1) d = 1.a2).1.3f} Angstroms’.0) 10 11 12 # these are the reciprocal lattice vectors b1.format(d) 23 24 25 26 #method #2 hkl = np.0].array([b1.b3).google. hkl ’’’ 40 41 Gstar = np. dot(b1. 0] a3 = [0.format(np.2. a2. [0. 1. 1 2 import numpy as np from ase.b2.b2.dot. size=(1.linalg. a3]) 8 9 10 print ’V = {0} ang^3 from dot/cross’.1.b3]) #reciprocal unit cell 27 28 29 ’’’ Gstar is usually defined as this matrix of dot products: 30 31 32 33 Gstar = np.T) 42 43 id2 = np. 1/d_hkl^2 = hkl .b3)].b2).b3)]]) 34 35 36 but I prefer the notationally more compact: Gstar = G .com/books?id=nJHSqEseuIUC&lpg=PA118&ots=YA9TBldoVH 248 .G.b3).0. you need to calculate the d-spacing (which is the spacing between parallel planes of atoms) for the hkl plane you are using.1]].0 ang^3 from det V = 20.b2).np.format(np.dot(hkl.b2)./np.linalg. latticeconstant=4. Gstar .cubic import FaceCenteredCubic 3 4 5 6 7 8 9 ag = FaceCenteredCubic(directions=[[1.dot(G. transpose(G) 37 38 39 then.get_volume()) Open the python script (dft-scripts/script-238.dot.0.inv(ag.1).array([[dot(b1.4 5 a2 = [1.4 d-spacing If you like to set up the vacuum in your slab calculations in terms of equivalent layers of atoms.hkl)) 44 45 print ’d_111 spacing (method 2) =’.a3)) print ’V = {0} ang^3 from det’.sqrt(1/id2) 46 47 # http://books.dot(Gstar.b3)]. dot(b1. dot(b2.det(uc)) 11 12 from ase import Atoms 13 14 15 atoms = Atoms([].b1).0 ang^3 from get_volume 9.norm(h*b1 + k*b2 + l*b3) 21 22 print ’d_111 spacing (method 1) = {0:1.py).linalg. V = 20 ang^3 from dot/cross V = 20.b3 = np.0].cross(a1. [0. [dot(b1.l = (1. symbol=’Ag’.k.k. 10] 6 7 uc = np. dot(b3. dot(b2.dot(np.format(atoms. 0. [dot(b1.lattice.l]) G = np.np.1.dot. dot(b2. 249 . Below we compute these and use them in the general triclinic structure formula which applies to all the structures.3f} {4:1.angle(C) beta = A. In each of these cases we show equations for the energy as a function of volume.format(d) Open the python script (dft-scripts/script-239.3f} {3:1.000 1.3 Equations of State The module mod:ase.000 4. ’’’ from Scientific.format(a.eos uses a simple polynomial equation of state to find bulk unit cell equilibrium volumes and bulk modulus. and angles.length()#*angstroms2bohr 68 69 70 71 72 # angles between the vectors in radians alpha = B. A current description of the equation is in reference.length()#*angstroms2bohr = C.000 4.48 49 # &dq=reciprocal%20metric%20tensor&pg=PA119#v=onepage # &q=reciprocal%20metric%20tensor&f=false 50 51 52 53 54 55 56 57 ’’’Finally. a b c alpha beta gamma 4. alpha.571 1.571 d_111 spacing (method 3) = 2.3.Geometry import Vector import math 58 59 60 61 62 unitcell = ag. Here we summarize them and provide references to the relevant literature.beta.b.1) 80 81 from math import sin.3f} {1:1. 9. vector lengths. cos 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 .571 1.30940107676 9.sqrt(id2) 93 94 print ’d_111 spacing (method 3) = {0}’.angle(B) 73 74 75 76 77 print print ’a b c alpha beta gamma’ print ’{0:1. many text books on crystallography use long algebraic formulas for computing the d-spacing with sin and cos. 100 You can also find the equations for the Vinet and Poirier-Tarantola equations of state in that reference.get_cell() A = Vector(unitcell[0]) B = Vector(unitcell[1]) C = Vector(unitcell[2]) 63 64 65 66 67 # a b c lengths of the vectors = A.3f} {2:1.c.1.angle(C) gamma = A.cos(gamma)**2 +2*cos(alpha)*cos(beta)*cos(gamma))) 91 92 d = 1/math.1 Birch-Murnaghan This is probably the most common equation of state used most often. There are several other choices you could use that are more standard in the literature. although sometimes the volume is transformed or normalized. and is a modification of the original Murnaghan EOS described below.gamma) 78 79 h.3f}\n’.length()#*angstroms2bohr = B.py).utils.3f} {5:1.l = (1.k. 9. B0 and B00 are the bulk modulus and its pressure derivative at the equilibrium volume V0 .3 Birch The original Birch equation 103 is: 2  2 E = E0 + 98 B0 V0 VV0 3 − 1 + 9 0 16 B0 V0 (B0 − 4)  V V0 2/3 3 −1 The Anton-Schmidt Equation of state 104  n+1   BV0 1 V E(V ) = E∞ + n+1 ln VV0 − n+1 V0 where E∞ corresponds to the energy at infinite separation. -56.2 Murnaghan The equation mostoften used inthe Murnaghan 101 equation of state is described in 102 .42]) 10 11 12 #make a vector to evaluate fits on with a lot of points so it looks smooth vfit = np.46.optimize import leastsq 6 7 8 9 # raw data from 2. 9. 17.array([-56. V0 . unit cell volume (V ) data. -56.46.100) 13 14 ### fit a parabola to the data 250 .29. You may find other derivations of this equation in the literature too. The following example illustrates one approach to this problem for the Murnaghan equation of state: 1 ’’’Example of fitting the Birch-Murnaghan EOS to data’’’ 2 3 4 5 import numpy as np import matplotlib. All of these equations of state are non-linear in the cell volume.Birch-Murnaghan EOS: 0 V0 (η 2 − 1)2 (6 + B00 (η 2 − 1) − 4η 2 ) E(η) = E0 + 9B16 where η = (V /V0 )1/3 . n is typically about -2. 18.23. -56.3.72.linspace(min(v).py v = np. When fitting data to this equation a guess of 2-4 for B00 is usually a good start. B0 V0 B0 0 /V ) 0 +1 − B E = ET + BB00V (VB 0 −1 0 −1 0 0 0 where V is the volume. We then fit that data to one of the above equations to extract the parameters we want.3. 16. although the model they use to derive this equation breaks down at large separations so this is usually not a good estimate of the cohesive energy.83. B0 and B00 are the bulk modulus and its pressure derivative at the equilibrium volume V0 . which means you have to provide some initial guesses for the parameters.5 Fitting data to these equations of state 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.41. 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 . 9. B and B00 which are used as initial guess for a non-linear least squares fit of the equation of state to the data.3.4 9.pyplot as plt from scipy.52]) e = np. 14.3-al-analyze-eos.max(v). -56.0.3. All of these are parameters that are fitted to energy vs. 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(η).array([13.2. ’Bulk modulus = {0:1.4.631 0.15 16 # y = ax^2 + bx + c a.format(murnpars[1].x): #we will minimize this function err = y .2f} GPa’.ylabel(’Energy (eV)’) plt.753 251 16. transform = ax.set_printoptions(precision=3) print ’initial guesses : ’.4. np.e. which is just 2a*V0 31 32 33 and from experience we know Bprime_0 is usually a small number like 4 ’’’ 34 35 36 37 38 39 #now v0 = e0 = b0 = bP = here are our initial guesses. b0.472 [-56. v0] #initial guesses in the same order used in the Murnaghan function 63 64 murnpars. but we can use it to get some analytical guesses for other parameters. ’Min volume = {0:1. 0.legend(loc=’best’) 73 74 75 76 77 78 79 80 81 #add some text to the figure in figure coordinates ax = plt.466 0. 21 22 23 24 25 V0 = minimum energy volume.4. bP.label=’parabolic fit’) plt. Murnaghan(murnpars.plot(vfit.’ro’) plt. murnpars[1]*160. args=(e. equation From PRB 28.V0*B0/(BP-1.5. transform = ax.xlabel(’Volume ($\AA^3$)’) plt.21773).b.py).savefig(’images/a-eos. which is: E0 = aV0^2 + bV0 + c 29 30 B is equal to V0*d^2E/dV^2.’--’.polyfit(v. a*vfit**2 + b*vfit + c.transAxes) plt.Murnaghan(pars.2) #this is from pylab 17 18 19 20 ’’’ the parabola does not fit the data very well.2f} eV/$\AA^3$ = {1:1. 0. return a vector of energies.79 ] 16.png’) 82 83 84 85 np.) 53 54 return E 55 56 57 58 59 60 # and we define an objective function that will be minimized def objective(pars. 4.c = np.e.format(murnpars[3]).gca() plt.array(x0) #array for easy printing print ’fitted parameters: ’.v)) #this is from scipy 65 66 67 68 69 70 71 72 #now we make a figure summarizing the results plt. or where dE/dV=0 E = aV^2 + bV + c dE/dV = 2aV + b = 0 V0 = -b/2a 26 27 28 E0 is the minimum energy. x0.text(0. murnpars Open the python script (dft-scripts/script-240.y.2f} $\AA^3$’. initial guesses : fitted parameters: [-56.573] .vfit). ier = leastsq(objective.vol): ’’’ given a vector of parameters and volumes. -b/(2*a) a*v0**2 + b*v0 + c 2*a*v0 4 40 41 42 43 44 45 46 47 48 49 50 #now we have to create the equation of state function def Murnaghan(parameters.plot(v. label=’Murnaghan fit’) plt.transAxes) plt.text(0.plot(vfit.49 4.x) return err 61 62 x0 = [e0.5480 (1983) ’’’ 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) . 9.4.py on your executable path.optimize.parallel_vasp) exitcode = os.4 9. and are the main reason we converged to a solution.1 Miscellaneous jasp/VASP tips Installing jasp You need to create an executable script named runvasp. The initial fitted parabola is shown to illustrate how it is useful for making initial guesses of the minimum and bulk modulus.readlines()) 9 10 11 12 13 14 15 16 17 if NPROCS == 1: print ’NPROCS = ’. You can see our guesses from the parabola were actually pretty good. 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. Here is a comparison of the initial guesses and final parameters.NPROCS parcmd = ’mpirun -np %i %s’ % (NPROCS.Figure 104: Fitted equation of state for bulk data.leastsq function does not converge.environ: NPROCS = len(open(os.environ[’PBS_NODEFILE’]). This script is located in jasp/bin.system(serial_vasp) else: print ’NPROCS = ’. You can see the Murnaghan equation of state fits the data better than the parabola.system(parcmd) else: 252 .NPROCS exitcode = os. Here is an example script that works for both serial and parallel versions of VASP. If you try other guesses you will probably find the scipy. The following guidelines tell you what is in a potential: No extension means the standard potential. extension _h _s _sv _pv _d means the potential is harder than the standard (i. Install the potentials in a directory and name the potential directories like this: my_vasp_potentials potpaw potpaw_GGA potpaw_PBE The potpaw directory contains the LDA potentials. For example: 1 export VASP_PP_PATH=$HOME/vasp/my_vasp_potentials Open the python script (dft-scripts/script-243. You have two options: 1. jasp expects to find the POTCAR potentials in specific directories.py Open the python script (dft-scripts/script-242.system(serial_vasp) 18 19 #end Open the python script (dft-scripts/script-241. Then create an environment variable that points to this script.py). in your . If you already have potential directories setup with different names. Then. For example in .2 Using a special setup VASP provides special setups for some elements.4. needs a higher cutoff energy) means the potential is softer than the standard (i.py).e. potpaw_GGA contains PW91 potentials. 253 .bashrc file set an environment variable that points to this directory. you can always make symlinks with the names above that point to your directories.exitcode = os. and potpaw_PBE contains the PBE potentials. 9.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.py).bashrc: 1 export VASP_SCRIPT=$HOME/kitchinpython/jasp/bin/run_vasp. • 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. The following extensions mean: Table 7: Meaning of extensions on POTCAR files for special setups. 001.py).4. encut=300.[5.py). xc=’PBE’. 5]. None How do you know it ran on four nodes? 1 head molecules/O_sv-4nodes/OUTCAR Open the python script (dft-scripts/script-247. encut=300.3 Running jasp in parallel jasp is smart. # specifies O_sv potential atoms=atoms) as calc: 15 16 print ’Total energy = {0} eV’.[5.format(atoms. cell=(6. 6.6)) 6 7 8 9 10 11 12 13 14 with jasp(’molecules/O_sv-4nodes’.magmom=1)]. magmom=1)]. setups={’O’:’_sv’}. 9. 1 2 3 4 5 from jasp import * JASPRC[’queue. cell=(6. it will automatically try to run in parallel.get_potential_energy()) Open the python script (dft-scripts/script-244. 1 head -n 1 molecules/O_sv/POTCAR Open the python script (dft-scripts/script-245. Atom from jasp import * 3 4 5 atoms = Atoms([Atom(’O’.nodes’]=4 from ase import Atom. sigma=0. ispin=2.6.61345 eV How do you know you got the right special setup? We can look at the first line of the POTCAR file in the calculation directory to see. PAW_PBE O_sv 05Jul2007 This shows we indeed used the O_sv setup. If you ask for more than one node. sigma=0.001. # specifies O_sv potential atoms=atoms) as calc: 15 16 print calc. 5.py). ispin=2. 254 . xc=’PBE’. ismear=0. setups={’O’:’_sv’}.1 2 from ase import Atoms.5]. Total energy = -1578. ismear=0.calculate() Open the python script (dft-scripts/script-246.5. Atoms atoms = Atoms([Atom(’O’.py). 6)) 6 7 8 9 10 11 12 13 14 with jasp(’molecules/O_sv’. This can be achieved using the mod:multiprocessing module in python. e 16 17 18 19 # this only runs in the main script. 1. and a section that only runs in the "main" script.6. 0.(0.get_potential_energy() v = atoms. The challenge is how to tell the computer to run a set of calculations in parallel.0.0. 0. 0.0. and use mod:multiprocessing to handle running them and waiting for you. 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. and construct a script with a function that runs a calculation.6). 0))]. The design uses exceptions to exit the script if the results are not available for subsequent analysis. To do this.vasp. 1. [0.get_volume() return v.set_volume(v0*(1 + f)) label = ’bulk/cu-mp/step1-{0}’. The design expects that you run the script often.08.0.utils.5. it is inconvenient to have to rerun your script again after the first set of calculations is done.get_volume() 28 29 30 31 32 33 34 35 36 37 # Step 1 COUNTER = 0 calculators = [] # list of calculators to be run factors = [-0.4 Running multiple instances of jasp in parallel mod:jasp was designed to enable asynchronous. In this scenario.1] for f in factors: newatoms = atoms.0]. cell=0. you must instruct mod:jasp to use a "run mode". [1. 0.0]. 09:10:10 4 groups ----------------------------------------------------------------------------------------------------9. 0. and wait for the calculations to finish.2.get_atoms() e = atoms.5 * a*np. 1 2 3 4 5 import multiprocessing from jasp import * from ase import Atom. xc=’PBE’.6 atoms = Atoms([Atom(’Cu’. kpts=(6. 1.array([[1. parallel running processes through a queuing system. 0. 1. 0.4.31 1 nodes.format(COUNTER) COUNTER += 1 38 39 40 41 42 calc = jasp(label.copy() newatoms.0. Atoms from ase.05.0.0]])) v0 = atoms.12 11Nov11 complex executed on running on 4 nodes distr: one band on LinuxIFC date 2012. The principle idea is to set up the calculations you want to run. This is ideal for submitting large numbers of independent calculations in one script.eos import EquationOfState import numpy as np 6 7 8 9 10 11 12 13 14 15 # this is the function that runs a calculation def do_calculation(calculator): ’function to run a calculation through multiprocessing’ with calculator as calc: atoms = calc.1.0. encut=350.05. 255 . and the results are analyzed only when they are finally available. 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 # setup an atoms object a = 3. atoms=newatoms) calculators. -0.isym=2. -0.join() # wait here for calculations to finish 91 92 93 94 # proceed with analysis V += [x[0] for x in out] E += [x[1] for x in out] 95 96 97 V = np.90) & (f <= 1.02.04.map(do_calculation.array(E) 98 99 f = np. step1: v1 = 12. isym=2.format(**locals()) 63 64 65 66 67 68 69 ### ################################################################ ## STEP 2. E) v1.02. encut=350.plot(’images/cu-mp-eos. e1. 0.array(V)/v1 100 101 102 # only take points within +. xc=’PBE’.png’) Open the python script (dft-scripts/script-248. E[ind]) v2.py). e2.fit() print ’step2: v2 = {v2}’.04. calculators) pool.Pool(processes=NCORES) 50 51 52 53 54 # get the output from running each calculation out = pool.1) 103 104 105 106 107 eos = EquationOfState(V[ind]. kpts=(6.map(do_calculation. atoms=newatoms) 43 44 45 46 calculators.format(COUNTER) COUNTER += 1 77 78 79 80 81 82 83 84 calc = jasp(label.10% of the minimum ind = (f >=0. 0.format(**locals()) eos.6.array(V) E = np.Pool(processes=NCORES) 87 88 89 90 out = pool.0218897111 step2: v2 = 12.set_volume(v1*(1 + f)) label = ’bulk/cu-mp/step2-{0}’.fit() print ’step1: v1 = {v1}’. 0. B = eos.0216094217 256 .06] 70 71 72 73 74 75 76 calculators = [] # reset list for f in factors: newatoms = atoms.append(calc) 85 86 pool = multiprocessing. 0.copy() newatoms.0.close() pool.close() pool. eos around the minimum ## ################################################################# factors = [-0.06.6).join() # this makes the script wait here until all jobs are done 55 56 57 58 # now proceed with analysis V = [x[0] for x in out] E = [x[1] for x in out] 59 60 61 62 eos = EquationOfState(V. calculators) pool. B = eos.append(calc) 47 48 49 # now we set up the Pool of processes pool = multiprocessing. This is not 100% satisfying. Also. The second time you get the smaller output above. the runjasp. one process on multiple nodes/cores instead of a single job that runs multiple processes simultaneously on multiple nodes/cores.py script which ultimately runs VASP will run VASP in parallel.cores_per_process’] = 2 13 14 15 16 17 18 # to submit this script.py import os if ’PBS_O_WORKDIR’ in os. Here is an example of running this through the queue.utils.py # qsub -l nodes=1:ppn=6. i. JASPRC[’queue. 1 2 3 4 5 6 #!/usr/bin/env python import multiprocessing from jasp import * from ase import Atom. Atoms from ase. save it as cu-mp. but it is the best that I have found for now.nodes’] = 1 9 10 11 12 # Here we will be able to run three MPI jobs on 2 cores at a time.environ: os. and you must save the script and submit manually to the queue with matching parameters.chdir(os. The main variations are you must set several variables in JASPRC that indicate you want to use mod:multiprocessing.environ[’PBS_O_WORKDIR’]) 19 20 21 22 # this is the function that runs a calculation def do_calculation(calculator): ’function to run a calculation through multiprocessing’ 257 . Note: The first time you run this you will get all the VASP output.ppn’] = 6 JASPRC[’multiprocessing.Figure 105: Equation of state for Cu using the multiprocessing module. I have not figured out how to integrate this method with the queue system.e.eos import EquationOfState import numpy as np 7 8 JASPRC[’queue. At the moment.walltime=10:00:00 cu-mp. 0]. -0.(0.0]. 1.6).get_volume() return v. 1.06] 82 83 84 85 86 87 88 calculators = [] # reset list for f in factors: newatoms = atoms. debug=logging. -0.format(COUNTER) COUNTER += 1 89 90 91 92 93 94 95 96 97 calc = jasp(label.format(COUNTER) COUNTER += 1 49 50 51 52 53 54 55 56 calc = jasp(label.close() pool.04. 1.format(**locals()) 75 76 77 78 79 80 81 ### ################################################################ ## STEP 2. E) v1. 0. kpts=(6.get_volume() 39 40 41 42 43 44 45 46 47 48 # Step 1 COUNTER = 0 calculators = [] # list of calculators to be run factors = [-0.0.6.Pool(processes=3) # ask for 6 cores but run MPI on 2 cores 62 63 64 65 66 # get the output from running each calculation out = pool.05.get_atoms() e = atoms.0. e 28 29 30 # this only runs in the main script.02.23 24 25 26 27 with calculator as calc: atoms = calc. calculators) pool.0]])) v0 = atoms.1] for f in factors: newatoms = atoms. 0. 0. kpts=(6. debug=logging.6). atoms=newatoms) calculators. 0.5 * a*np. encut=350. [0. cell=0. 0. 1.05.06.append(calc) 59 60 61 # now we set up the Pool of processes pool = multiprocessing.get_potential_energy() v = atoms.set_volume(v0*(1 + f)) label = ’bulk/cu-mp2/step1-{0}’.append(calc) 98 99 pool = multiprocessing.set_volume(v1*(1 + f)) label = ’bulk/cu-mp2/step2-{0}’. 0.0. eos around the minimum ## ################################################################# factors = [-0.02.copy() newatoms.fit() print ’step1: v1 = {v1}’. 0.Pool(processes=3) 100 258 . not in processes on other cores if __name__ == ’__main__’: 31 32 33 34 35 36 37 38 # setup an atoms object a = 3. 0.0. atoms=newatoms) 57 58 calculators.DEBUG. 0. 0. 0. xc=’PBE’. [1.0. B = eos.04.join() # this makes the script wait here until all jobs are done 67 68 69 70 # now proceed with analysis V = [x[0] for x in out] E = [x[1] for x in out] 71 72 73 74 eos = EquationOfState(V.6 atoms = Atoms([Atom(’Cu’. 0))]. xc=’PBE’. isym=2.6.0.array([[1.copy() newatoms.map(do_calculation. isym=2. e1.0.0.1. encut=350.DEBUG. 90) & (f <= 1.py).0216189798 Figure 106: Second view of a Cu equation of state computed with multiprocessing.png’. step1: v1 = 12.array(V)/v1 113 114 115 # only take points within +. xml. python. sqlite jasp has some capability for representing a calculation result in an archival format.show=True) Open the python script (dft-scripts/script-249. xml.0218897111 step2: v2 = 12.plot(’images/cu-mp2-eos. B = eos. 9.4.1) 116 117 118 119 120 eos = EquationOfState(V[ind].array(E) 111 112 f = np. These are under development.join() # wait here for calculations to finish 104 105 106 107 # proceed with analysis V += [x[0] for x in out] E += [x[1] for x in out] 108 109 110 V = np. calculators) pool.array(V) E = np. The main point of these methods is to make it easy to create archive files that are machine readable for supplementary information in publications.fit() print ’step2: v2 = {v2}’.map(do_calculation.10% of the minimum ind = (f >=0. The formats currently under development are json. 259 .format(**locals()) eos.101 102 103 out = pool. e2. E[ind]) v2. python and sqlite.5 Exporting data json.close() pool. from numpy import array from ase import Atom. kpts = array([13. 0.818. 260 . reciprocal = False. Atoms from jasp import * atoms = Atoms([Atom(’Cu’. nbands = 9.g. "aexx": null. txt = ’-’.818]]) with jasp(’bulk/alloy/cu’. e. "aggax": null.0.818. "amix_mag": null. isif = 4. { "INCAR": { "addgrid": null. 1.818. "amix": null. 1. 0.0. nsw = 10. "algo": null.python Open the python script (dft-scripts/script-250. encut = 350. 13]).818]. 1. cell = [[1. 0. it does not currently get magnetic moments on the atoms. [0. gamma = False.py). There are some limitations. "aggac": null.[0.0.py). 0. "bmix": null. atoms=atoms) as calc: # your code here json 1 from jasp import * 2 3 4 with jasp(’bulk/alloy/cu’) as calc: print calc.0].818.0.0]). prec = ’Normal’.pretty_json Open the python script (dft-scripts/script-251.0. 1 from jasp import * 2 3 4 with jasp(’bulk/alloy/cu’) as calc: print calc. 1. 13. "aldac": null. "amin": null. xc = ’PBE’.python This is code that should reconstruct the python code needed to run a particular calculation. ibrion = 2. [1. "gga": null. "ftimemax": null. "falphadec": null. "enaug": null. "istart": null. "lbfgsmem": null. "encutgw": null. "idipol": null. "ftimeinc": null. "kspacing": null. "deper": null. "ebreak": null. "iband": null. "emin": null. "jacobian": null. "dipol": null. "ferwe": null. "dfnmax": null. "icharg": null. "fdstep": null. "ferdo": null. "hfscreen": null. "ismear": null. "ibrion": 2. "encut": 350. "ddr": null. "laechg": null. "ispin": null. "falpha": null. "isym": null. "kpuse": null. "ftimedec": null. "images": null. "fnmin": null. 261 . "kgamma": null. "iniwav": null. "iwavpr": null. "encutfock": null. "drotmax": null."bmix_mag": null. "lasph": null. "eint": null. "invcurve": null. "iopt": null. "ediff": null. "ediffg": null. "lasync": null. "emax": null. "ialgo": null. "isif": 4. "dfnmin": null.0. "ichain": null. "ngyf": null. "ldipol": null. "lwave": null. "lthomas": null. "ngx": null. "lhfcalc": null. "nelmin": null. "lmaxmix": null. "nblk": null. "nelect": null. "ldau": null. "nbmod": null. "lvhar": null. "ldneb": null. 262 . "ngz": null. "lvdw": null. "maxmix": null. "nbands": 9. "lepsilon": null. "lorbit": null. "nelmdl": null. "nfree": null. "luse_vdw": null. "lcorr": null. "ldaul": null. "lvtot": null. "nelm": null. "lnebcell": null. "ldautype": null. "lsepk": null. "lpard": null. "ngy": null. "ldau_luj": null. "lclimb": null. "llineopt": null. "magmom": null. "maxmove": null. "ldiag": null. "lplane": null. "lelf": null. "loptics": null. "ldauu": null. "lglobal": null. "ltangentold": null. "lscalapack": null. "ldauj": null. "ngxf": null. "ldauprint": null. "ngzf": null."lcharg": null. "lscalu": null. "lsepb": null. 1. "symprec": null. "system": null. "voskown": null. "nomegar": null. "npar": null. "vdwgr": null.818. "nkredx": null. [ 263 . 0. "sigma": null. "smass": null. "sdr": null. "snl": null."nkred": null. "nsim": null. "stol": null. "potim": null. "zab_vdw": null. "vdwrn": null. "param1": null. "nkredy": null.818.818. "prec": "Normal". "rwigs": null. "nkredz": null. "sdalpha": null. "precfock": null. 1. "ropt": null. "atoms": { "cell": [ [ 1. "weimin": null.0 ]. "time": null. "timestep": null. "param2": null. "pomass": null. "zval": null }. "teend": null. "spring": null.0. "tebeg": null. [ 1.818 ]. "nomega": null. "nwrite": null. "nupdown": null. "nsw": 10. 0. 0</pyxs:prop> 264 .0. 1. true ].0. "positions": [ [ 0. "symbols": [ "Cu" ].0. true. "input": { "gamma": false. "tags": [ 0 ] }. 13.818 ] ]. 13 ]. "reciprocal": false. 1 from jasp import * 2 3 4 with jasp(’bulk/alloy/cu’) as calc: print calc. 0.xml Open the python script (dft-scripts/script-252. 1.0. 0.0 ] ].cl/pyxser/model/" version="1.818.0" type="vasp" module="jasp. "setups": null.coder.py). <?xml version="1. "xc": "PBE" } } xml This relies on the pyxser module. "kpts": [ 13. "kpts_nintersections": null. "txt": "-". <pyxs:col type="dict" name="d"> <pyxs:col type="dict" name="INCAR"> <pyxs:prop type="str" name="prec">Normal</pyxs:prop> <pyxs:prop type="float" name="encut">350. "pbc": [ true.0" encoding="utf-8"?> <pyxs:obj xmlns:pyxs="http://projects. 818</pyxs:prop> </pyxs:col> </pyxs:col> <pyxs:col type="list" name="symbols"> <pyxs:prop type="str" name="symbols">Cu</pyxs:prop> </pyxs:col> <pyxs:col type="list" name="pbc"> <pyxs:prop type="bool" name="pbc">True</pyxs:prop> <pyxs:prop type="bool" name="pbc">True</pyxs:prop> <pyxs:prop type="bool" name="pbc">True</pyxs:prop> </pyxs:col> <pyxs:col type="list" name="positions"> <pyxs:col type="list" name="positions"> <pyxs:prop type="float" name="positions">0.0</pyxs:prop> <pyxs:prop type="float" name="positions">0.0</pyxs:prop> <pyxs:prop type="float" name="positions">0.<pyxs:prop type="int" name="nbands">9</pyxs:prop> <pyxs:prop type="int" name="isif">4</pyxs:prop> <pyxs:prop type="int" name="nsw">10</pyxs:prop> <pyxs:prop type="int" name="ibrion">2</pyxs:prop> </pyxs:col> <pyxs:col type="dict" name="input"> <pyxs:col type="list" name="kpts"> <pyxs:prop type="int" name="kpts">13</pyxs:prop> <pyxs:prop type="int" name="kpts">13</pyxs:prop> <pyxs:prop type="int" name="kpts">13</pyxs:prop> </pyxs:col> <pyxs:prop type="bool" name="reciprocal">False</pyxs:prop> <pyxs:prop type="str" name="xc">PBE</pyxs:prop> <pyxs:prop type="str" name="txt">-</pyxs:prop> <pyxs:prop type="bool" name="gamma">False</pyxs:prop> </pyxs:col> <pyxs:col type="dict" name="atoms"> <pyxs:col type="list" name="cell"> <pyxs:col type="list" name="cell"> <pyxs:prop type="float" name="cell">1.818</pyxs:prop> <pyxs:prop type="float" name="cell">1.0</pyxs:prop> <pyxs:prop type="float" name="cell">1.818</pyxs:prop> <pyxs:prop type="float" name="cell">0.0</pyxs:prop> <pyxs:prop type="float" name="cell">1.0</pyxs:prop> </pyxs:col> <pyxs:col type="list" name="cell"> <pyxs:prop type="float" name="cell">0.818</pyxs:prop> <pyxs:prop type="float" name="cell">1.818</pyxs:prop> </pyxs:col> <pyxs:col type="list" name="cell"> <pyxs:prop type="float" name="cell">1.0</pyxs:prop> </pyxs:col> </pyxs:col> </pyxs:col> </pyxs:col> </pyxs:obj> 265 .818</pyxs:prop> <pyxs:prop type="float" name="cell">0. 9.relpath(potcar.3*ENMAX ZVAL = get_ZVAL(potcar) 25 26 print ’|{POTCAR:30s}|{ENMIN}|{ENMAX}|{HIGH:1.POTCAR import * from ase.sort() for symbol in chemical_symbols: 13 14 15 potcars = glob.4.glob(’{0}/POTPAW_PBE/{1}*/POTCAR’. symbol)) 16 17 for potcar in potcars: 18 19 20 21 22 23 24 POTCAR = os.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. elect.format(os.environ[’VASP_PP_PATH’].data import chemical_symbols import glob.path.format(**locals()) Open the python script (dft-scripts/script-253.’ ’#+ATTR_LaTeX: longtable’ ’| POTCAR | ENMIN | ENMAX | prec=high (eV) | # val. 266 . os 4 5 6 7 8 9 print print print print print ’#+tblname: POTCAR’ ’#+caption: Parameters for POTPAW_PBE POTCAR files. 1 2 3 from jasp.3f}|{ZVAL}|’. |’ ’|-’ 10 11 12 chemical_symbols.environ[’VASP_PP_PATH’]+’/POTPAW_PBE’)[:-7] ENMIN = get_ENMIN(potcar) ENMAX = get_ENMAX(potcar) HIGH = 1. os.py). 225 Al 180.037 136.082 295.859 Au_new 172.0 12.992 538.992 538.658 247.0 5.0 5.658 247.399 297.187 401.976 267.948 298.645 Ce_3 135.0 11.494 413.178 172.0 3.0 3.0 7.0 2.446 384.0 400.426 273.019 Ba_sv 140.797 Ag 187.943 Br 162.024 As_d 216.969 348.651 375.190 Cd 205.0 11.51 208.702 271.000 Cr 170.939 266.071 Cs_sv 165.0 11.846 324.0 4.375 Bi_d 182.408 187.311 As_d_GW 259.0 4.0 6.854 280.0 4.0 12.446 384.413 Cu_f 221.0 2.0 520.187 401.494 413.562 C_d 310.0 15.3 312.471 514.781 273.0 4.0 700.080 elect.585 295.375 B_h 500.901 356.771 390.0 4.457 229.0 21.471 C 300.420 Ca_sv 199.777 105.795 266.0 11.042 354.0 15.461 229.0 .0 5.0 11.21 243.0 910.757 274.585 295.807 Be_sv 231.0 14.0 15.954 318.603 395.237 223.603 395.706 Bi 78. POTCAR ENMIN ENMAX prec=high (eV) # val.706 Bi 78.943 B 238.225 240.0 21.875 332.0 10.286 235.358 Co 200.932 Ba_sv 140.172 450.264 281.000 Co_new 200.844 324.143 B_s 201.0 7.629 346.0 4.390 Am 191.68 271.934 269.526 208.89 309.672 Ce_h 224.0 9.0 5.544 321.264 281.373 Be 185. 11.0 3.943 298.977 267.0 12.408 187.851 315.189 C_h 500.261 265.865 387.0 364.037 136.112 C_s 205.851 315.0 8.360 Co_sv 292.548 Bi_pv 231.251 346.000 Cl_h 306.688 266.665 119.554 155.Table 8: Parameters for POTPAW_PBE POTCAR files.681 345.0 3.284 At_d 199.246 As_GW 156.0 17.968 348.906 255.586 346.925 299.43 209.188 Br 162.0 12.112 Cr_sv 296.262 265.926 Au 172.870 Ce 204.800 Ag_pv 223.544 321.362 507.342 356.606 414.263 741.0 4.0 7.0 9.245 350. Ac 129.0 12.908 Ag_new 187.0 7.138 242.877 Cl 196.0 17.755 133.311 227.0 2.0 9.138 242.637 Ar 199.471 514.0 15.073 161.0 4.964 181.373 Be 185.198 216.393 346.198 216.190 C_h_nr 556.0 700.383 249.0 17.238 220.0 11.548 Bi_pv 231.136 531.807 Be_sv 231.0 14.955 C_GW 310.313 As 156.318 286.75 401.385 249.563 308.067 102.0 7.21 243.385 Cr_pv 199.000 Bi_d 182.777 105.488 288.9 389.0 10.75 401.126 At 121.0 17.0 910.388 267 Cr_sv_new 296.0 10.683 345.080 Cu_new 221.563 308.852 409.582 Ca_pv 89.207 Cr_pv_new 199.89 309.0 8.143 Ca 77.0 11.684 964. you get an integer! This is usually not a problem if there is no emainder in the division. if you divide two integers.6/site-packages/ pymatgen 10. If you are not careful. e. For me this installs here: ~/. 1 pip install --user some-package Open the python script (dft-scripts/script-254. 1 2 3 4 nPd = 4 nCu = 5 x_Cu = nCu/(nPd + nCu) print ’x_cu = {0} (integer division)’. 1 2 nPd = 4 nCu = 5 3 4 5 6 # now cast as floats x_Cu = float(nCu)/(nPd + nCu) print ’x_cu = {0}’.py).format(x_Cu) 5 6 7 8 # now cast as floats x_Cu = float(nCu)/float(nPd + nCu) print ’x_cu = {0} (float division)’.10 Python 10. if there is a remainder.6. but you can also tell easy_install where to install a package. and that remainder is important. In python 2.555555555556 268 .3 Integer division math gotchas It pays to be careful when dividing by integers because you can get unexpected results if you do not know the integer division rules.7/site-packages That may or may not be on your Python path.555555555556 (float division) Note that if one of the numbers is a float. python will automatically cast the integer as a float.py). This usually works if the directory is on your PYTHONPATH easy_install -d ~/lib/python2. 10. you get the wrong answer! You can convert (also called casting) a number to a float using the float command. 6/3=2.format(x_Cu) Open the python script (dft-scripts/script-256. Usually you need root access to install a python package. x_cu = 0 (integer division) x_cu = 0.1 easy_install as a user easy_install is a python command-line utility that automatically installs python packages. x_cu = 0. and return a float. you will lose it.g. But.py).format(x_Cu) Open the python script (dft-scripts/script-255.2 pip as a user pip is even better than easy_install these days. Here is an example of calculating the mole fraction of a species from integer numbers of atoms in the unit cell.local/lib/python2. 8th edition. Density Functional Theory: A Practical Introduction. Steckel. [8] B.1016/S0360-0564(02)45013-4.1103/RevModPhys. Density functional theory as a major tool in computational materials science. [4] Charles Kittel.1045. G.aps. Angewandte Chemie International Edition in English. URL http://dx. Arias. Theoretical surface science and catalysiscalculations and concepts. D.1103/RevModPhys.198708461. 1989. David Mermin. [7] Roald Hoffmann. Density-Functional Theory of Atoms and Molecules. org/doi/10. 1995.1146/ annurev. Electronic structure and catalysis on metal surfaces.aps.ms. Parr and W. 2005.1146/ annurev.org/doi/10. Rev.1045. Nørskov. 2009. C.60.org/doi/abs/10. ISSN 1521-3773. URL http://www.100301. URL http://www. In Helmut Knozinger Bruce C. A Chemist’s Guide to Density Functional Theory. [2] R. P. URL http://link.131630. you can tell python a number is a float by adding a decimal to it. 2002. Iterative minimization techniques for ab initio total-energy calculations: molecular dynamics and conjugate gradients.64. Oct 1992. pages 71 – 129. Saunders College Publishing.1103/RevModPhys.53. W. doi: 10.25. Holthausen. C. T. Payne. Teter. doi: 10. 26(9):846–878. C.Finally.. [9] Jeff Greeley. 2001. x_cu = 0. You do not need to put a 0 after the decimal. Wiley-VCH.physchem. 2 edition. [6] Roald Hoffmann. Mod.60. Wiley.com/science/article/pii/S0360056402450134.annualreviews. Oxford Science Publications. Rev. and Manos Mavrikakis. Phys.py). A. URL http://link.org/10. [3] W. 2000. Sholl and Janice A.080195. Annual Review of Physical Chemistry.. Academic Press. Hammer and J.format(x_Cu) Open the python script (dft-scripts/script-257. 1987. Wiley. Jens K. 1103/RevModPhys.1002/anie. Yang. 64:1045–1097. 60:601–628. doi: 10. Nørskov.601. editor. Joannopoulos. Introduction to Solid State Physics. D. Jul 1988. How chemistry and physics meet in the solid state. Impact of Surface Science on Catalysis. [5] N.198708461. but you can. Mod. Solid State Physics. Ashcroft and N. doi: 10. nCu = 5 # this is a float 3 4 5 x_Cu = nCu/(nPd + nCu) print ’x_cu = {0}’. 25(1):7–36. Annual Review of Materials Science.doi. [11] M. volume 45 of Advances in Catalysis. 1976.64. [10] A J Freeman and E Wimmer.physchem.sciencedirect.1002/anie. doi: 10. M.53.601. Koch and M.1146/annurev. Phys. 000255. 1 2 nPd = 4.K.131630. A chemical and theoretical way to look at bonding on surfaces.555555555556 11 References References [1] David S. doi: 10.100301. Gates. 269 . and J. Allan. 53(1):319–348. Dover Publications. Containing Papers of a Mathematical and Physical Character. Phys. Hammer. Sham. Proceedings of the Royal Society of London.pdf and http://www. [16] R. Seitsonen. Wilson. doi: 10.1691. Parr.1103/PhysRevB.dk/~{}bligaard/masterthesis/masterdirectory/ project/project.de/diss/2000/seitsonen_ari.1253.pdf.A1133. ISSN 09501207. 714–733.136.1103/RevModPhys.a study toward improving the precision of electron density functional calculations of atomistic systems. URL http://link. Hansen.org/doi/10. org/doi/10.71. ISSN 0927-0256. Inc. Nobel lecture: Quantum chemical models. [22] John A.org/doi/10. URL http://www. 136:B864–B871. URL http://link..71. 1929. School of Mathematics and Natural Sciences.tu-berlin.1103/PhysRevB. Improved adsorption energetics within densityfunctional theory using revised perdew-burke-ernzerhof functionals. Mod. http://edocs.59. Computational Materials Science.1103/PhysRev. E.49. Efficiency of ab-initio total energy calculations for metals and semiconductors using a plane-wave basis set.fysik. URL http://www. URL http:// link. [17] L.1103/PhysRevLett. Technical University of Denmark.. [19] P. University of Vienna. Nobel lecture: Electronic structure of matter-wave functions and density functionals.org/doi/10. 6(1):15 – 50. 2002.140. http://www. URL http://link. P. Robert G. [14] T. Rev. Series A.fysik. Balduz.1267. Furthmüller. Scheffler. Nørskov. Jr. J. Kohn. doi: 10.1103/PhysRev.1103/PhysRev. Technical University of Denmark. 123(792):pp. Kresse and J. Oct 1999.aps. [24] John P. Dec 1982. A. Self-consistent equations including exchange and correlation effects.7413. Phys.2134.1691. 1996.. and M. Pehlke. Introduction to Quantum Mechanics with Applications to Chemistry.7413. L. Quantum mechanics of many-electron systems. 57:2134–2145.1103/ RevModPhys.1103/ PhysRevB.B864. Technical University of Berlin. Pople. Rev.1267. Inhomogeneous electron gas. doi: 10. Rev. URL http://link. Rev. [20] P. Mod. Rev.pdf. doi: 10. Phys.B864.aps. Phys. 2000.at/download/diss_part1. 71:1253–1266. Exchange and Correlation Functionals . 140:A1133–A1138.59.org/doi/10. Hirschl. Kohn and L. Dirac. M. doi: 10. doi: 10.sciencedirect. and Jose L. Master’s thesis. Jan 1998.1103/PhysRev. [25] B. B.dk/ ~{}bligaard/phdthesis/phdproject.49. [18] W.hirschl. Hohenberg and W. aps. Nov 1964. 59:7413– 7421. B.dtu.1103/RevModPhys. Density-functional theory for fractional particle number: Derivative discontinuities of the energy. PhD thesis.136. Rev. Binary Transition Metal Alloys and Their Surfaces.at/download/diss_part2.. doi: 10. Pseudopotential study of binding properties of solids within generalized gradient approximations: The role of core-valence exchange correlation. Oct 1999. doi: 10. and J. Phys. Mar 1999. http://www. B. Understanding Materials Properties on the Basis of Density Functional Theory Calculations.. [21] W.aps. 2000. http://www. 270 .1103/PhysRevB. Bockstedte. URL http://link. Nov 1965. Lett. M. B.1253. 49:1691– 1694.pdf.. Bligaard. Fuchs.1016/0927-0256(96)00008-0.hirschl.com/ science/article/pii/0927025696000080.1103/ PhysRevLett.aps. Pauling and E.aps. PhD thesis. Bligaard. [13] T. PhD thesis.57.org/doi/10.1103/RevModPhys. Perdew.dtu.jstor. K.[12] G.71.org/doi/10. Phys.org/stable/95222. URL http://link. Institut für Materialphysik.A1133. Theoretical Investigations into adsorption and co-adsorption on transition-metal surfaces as models to heterogeneous catalysis.2134. Phys. Rev. [15] A. Kohn. [23] M.pdf. 71:1267–1274.71. Mel Levy. 1963.140.57. 2003.aps. URL http://link.5747. Efficient pseudopotentials for plane-wave calculations. Phys. 56:15629–15646. 41:7892–7895. B.49.iop. From ultrasoft pseudopotentials to the projector augmented-wave method.aps.aps. May 1994.org/link/?JCP/122/234102/1.47. 137:A1441– A1443.aps.1103/PhysRevB.1103/PhysRevB. [29] N.51. Rev. Phys. URL http://link. doi: 10.org/doi/10. Mortensen. Feb 1995.org/0953-8984/1/i=4/a=005. B. Makov and M. 271 .1103/PhysRev.5188.59. Furthmüller.aps.15629. 59:1758–1775. J. 8:5747–5753.7892.54. 1103/PhysRevB. Jun 1976. Monkhorst and James D.1103/PhysRevB.14251.54. doi: 10. Rev. URL http://link.035109.1926272. 1(4):689. Rev. Kresse and J.1103/PhysRevB. Dec 1973.1103/PhysRevB. doi: 10.org/doi/10. Chadi and Marvin L. 2005. Rev.aps.5747. Rev. Rev. Ab initio molecular-dynamics simulation of the liquid-metal/amorphoussemiconductor transition in germanium. B. [31] E.13. Mar 1965. Thermal properties of the inhomogeneous electron gas. URL http://link. Kresse and J. Jacobsen.4014.137. B.aps.558. [35] N. [27] D. URL http://link.1103/PhysRevB.org/doi/10. doi: 10. J. Calculation of the vacancy formation energy in aluminium.1103/PhysRevB. Phys. 8. doi: 10. Phys.1103/PhysRevB.558. [38] G. G. Efficient iterative schemes for ab initio total-energy calculations using a plane-wave basis set. 47:558–561. co.1758. Phys.50. [40] Joachim Paier.1103/PhysRevB. Phys.org/doi/10. 1989.1063/1. C.7892. doi: 10.1758.A1441.aps. doi: 10. and J. doi: 10.13. Ab initio molecular dynamics for liquid metals. J. Rev.org/ doi/10. B.1103/PhysRevB. Dec 1997.aps.1103/PhysRevB. Phys.1993. [34] M J Gillan. URL http://link. Periodic boundary conditions in ab initio calculations.aps.1103/PhysRevB. G.org/ doi/10. B.14251. The Journal of Chemical Physics.43. [33] G. The Perdew–Burke–Ernzerhof exchange-correlation functional applied to the G2-1 test set using a plane-wave basis set. 43:1993–2006. B.org/doi/10.1103/PhysRevB.50.11169. B.56. Ultrasoft pseudopotentials applied to magnetic fe. Apr 1990. Phys. Projector augmented-wave method. [32] P.1103/PhysRevB.1103/PhysRevB.4014.11169.1103/PhysRevB. URL http://link. Cohen. Oct 1996. Phys. URL http://link. URL http://link.aps. Rev. 54:11169–11186.1103/PhysRevB.41. B.56. Moroni.1103/PhysRevB. 71:035109. Dec 1994. Jan 2005.1103/PhysRevB.aps. B. 47.[26] G.org/doi/10. Payne. 49:14251–14269. and K.1103/ PhysRev. Rev.org/doi/10. Special points for brillouin-zone integrations. Hafner. Phys.aps.1103/PhysRevB. [28] Hendrik J. and ni: From atoms to solids. [30] David Vanderbilt. URL http://link. E. doi: 10. Kresse and D. Troullier and José Luriaas Martins. [36] J. 51:4014–4022.41. Martijn Marsman. Kresse and J. doi: 10. URL http://link. Robin Hirschl.org/ doi/10. and Georg Kresse. Furthmüller. W. Soft self-consistent pseudopotentials in a generalized eigenvalue formalism. B.. Rev. doi: 10. URL http://link.org/doi/10. URL http://stacks. B. Hafner.59. [37] G. Jan 1991.5188. Journal of Physics: Condensed Matter.71. 13:5188–5192.15629. doi: 10.49.035109.17953. Phys.51.137. Special points in the brillouin zone. Rev. David Mermin.17953.71. URL http: //link. doi: 10. [39] G. L. Jan 1993.1103/ PhysRevB.A1441. Kresse. Real-space grid implementation of the projector augmented wave method. Hansen.8. Rev.org/doi/10. Rev.1993. doi: 10. Jan 1999.aps. Hafner. B. 50:17953–17979.org/doi/10. URL http://link.1103/PhysRevB. Joubert.43. 122(23):234102.1103/PhysRevB. Pack. aip. Phys. Phys. Blöchl. 1955.com/ science/article/pii/S0927025605001849. Pople.aip. 2002. 118:813–826. [49] R. van de Walle. Benjamin Ellingson.006. doi: 10. Vibrational and dielectric properties of c6 0 from densityfunctional perturbation theory. and Hannes Jónsson. 128(8): 084714. M. The Journal of Chemical Physics. John M. URL http://link.2005.org/link/?JCP/128/134106/1. Kroes. ISSN 0364-5916. [44] Jr.acs. Feb 2002. Calphad. Rye Terrell. DongEung Kim. A. Manz and David S. doi: 10. 1997. Mattsson. Phys. Henkelman.1007/s00214-007-0328-0. Journal of Chemical Theory and Computation.2835596. URL http://link. and Graeme Henkelman. 100(11):8537–8539. Paul C. ISSN 0927-0256. ISSN 0927-0256.org/link/?JCP/106/1063/1. The Journal of Chemical Physics. 2010. 2010. Wills.1809574. 1994. and G. [45] Paolo Giannozzi and Stefano Baroni. J.[41] Larry A. Jorge Marques. Krishnan Raghavachari. Mattsson.1016/S0364-5916(02)80006-2. Symmetry numbers and chemical reaction rates. Theoretical Chemistry Accounts: Theory.1063/1. sciencedirect. Symmetry-general least-squares extraction of elastic data for strained materials from ab initio calculations of stress.1063/1. 47(4): 1040 – 1048.1103/ PhysRevB. Tomáš Bučko.1007/s00214-007-0328-0.org/doi/ abs/10. Dover Publications.473182. The alloy theoretic automated toolkit: A user guide.C.org/link/?JCP/128/084714/1. Asta.65. and Thomas R. Yi Wang. URL http://stacks. URL http://link. The Journal of Chemical Physics. [43] Thomas A. doi: 10. [52] Shun-Li Shang. URL http://www. [53] A. Jonsson. [46] David Karhánek.com/science/article/pii/S0927025609004558. 2010.1063/1. [47] Antonio Fernández-Ramos. and Donald Truhlar. B. Cross. 128(13):134106. doi: 10. J. and Jürgen Hafner. Computational Materials Science. doi: 10.1016/j. Decius.org/0953-8984/ 22/i=26/a=265006. The Journal of Chemical Physics. doi: 10.1063/1. A density-functional study of the adsorption of methane-thiol on the (111) surfaces of the Ni-group metals: II.aps.65.commatsci. Computational Materials Science. G.04. Journal of Physics: Condensed Matter.commatsci. Comparison of methods for finding saddle points without knowledge of the final states. and Zi-Kui Liu. 36(3):354 – 360. URL http://pubs.104104. The Journal of Chemical Physics. 10. doi: 10. Chemically meaningful atomic charges that reproduce the electrostatic potential in periodic and nonperiodic materials. doi: 10. URL http://link. [42] Graeme Henkelman. and H. 121(20):9776–9792. Bright Wilson.466753. 6(8):2455–2468. Olsen. and John A.12. The am05 density functional applied to solids.sciencedirect. URL http://dx.aip. 2007.1103/PhysRevB.aip. 22(26):265006.sciencedirect. Andri Arnaldsson. E. Rev. Arnaldsson.org/doi/10. G. URL http://link. [51] Yvon Le Page and Paul Saxe. 2006. Curtiss. vibrational spectroscopy. Joachim Paier. 106(3):1063–1079. A.1021/ct100125x.104104.2841941. doi: 10.doi. Ceder.org/link/?JCP/121/ 9776/1. doi: 10. aip. 65:104104. Optimization methods for finding minimum energy paths. First-principles thermodynamics from phonon and debye model: Application to ni and ni3al. A fast and robust algorithm for bader decomposition of charge density. 26(4):539 – 553.iop. Redfern. Georg Kresse. 2004. Assessment of gaussian-2 and density functional theories for the computation of enthalpies of formation.1016/j. Rickard Armiento. [50] Ann E. 272 .010.2009. 2008. Molecular Vibrations: The Theory of Infrared and Raman Vibrational Spectra. Sholl.aip.org/link/?JCP/100/8537/1. 2008. [48] Daniel Sheppard. and Modeling (Theoretica Chimica Acta). Rubén Meana-Pañeda. URL http://www. URL http://www. and Paul C. URL http://link.1021/ct100125x. Computation.org/10.com/science/article/pii/S0364591602800062. ISSN 1432881X.1063/1. [68] F. Order and Phase Stability in Alloys. Phys.L Skriver. [67] A.73. Ducastelle.5048. Perdew and Alex Zunger. B. [62] J.16317. doi: 10.56. Cottrell. Population analysis of plane-wave electronic structure calculations of bulk materials. and Jose M Soler.1103/PhysRevB. and Gerbrand Ceder. 73:195107.1103/RevModPhys. Jones and O.com/science/article/pii/ 003810989500341X. 1991. [65] M.12042. URL http://www.com/science/article/ pii/S0364591608001314.16317. B.org/doi/10.56. 2002.calphad.sciencedirect. Dec 1997. 61:689–746. Multicomponent multisublattice alloys. 1999. ISSN 1381-1169. 195107. and M. URL http://pubs. [61] R. P. doi: 10. What do the Kohn-Sham Orbitals and Eigenvalues Mean? Journal of the American Chemical Society. Rev. B. doi: 10.1103/PhysRevB. [58] Leonard Kleinman. Significance of the highest occupied Kohn-Sham eigenvalue. Solid State Communications. Pickard.1103/PhysRevB.K Nørskov. C.acs.aps. B Hammer.1063/1.aps.org/doi/10. B. 54:16317–16320.195107. Phys. [60] O. ISSN 0038-1098. ISSN 0364-5916.1016/S1381-1169(96)00348-2. doi: 10.org/doi/10.1103/PhysRevB. 1995.56.1021/ja9826892.sciencedirect. The density functional formalism. 23:5048–5079. Self-interaction correction to density-functional approximations for many-electron systems.1016/j. J. URL http://link. Comment on "Significance of the highest occupied Kohn-Sham eigenvalue". nonconfigurational entropy and other additions to the alloy theoretic automated toolkit. Nov 1997. 1103/PhysRevB. aps. Emilio Artacho.61. Mod. URL http://link. doi: 10. URL http://link. Gritsenko and E. Shah. doi: 10.1103/PhysRevB. [64] M. <ce:title>Tools for Computational Thermodynamics</ce:title>.5048..12.1016/0038-1098(95)00341-X.16021. [59] Ralf Stowasser and Roald Hoffmann.[54] Axel van de Walle. C.1103/RevModPhys. 95(10):685 – 690. R. Rev. Phys. Payne.61. Segall.12042. Journal of Molecular Catalysis A: Chemical. Phys. Jul 1989. Pickard.56. URL http://link. Mol. doi: 10. Payne.1103/PhysRevB. URL http://link.aip. The Journal of Chemical Physics.56. D. Surface electronic structure and reactivity of transition and noble metals. J.com/science/article/pii/S1381116996003482. [63] Daniel Sanchez-Portal. Phys. Population analysis in plane wave electronic structure calculations. Rev. Calphad. 33(2):266 – 278.aps. 56:16029–16030. and J.1103/PhysRevB. Segall.1103/PhysRevB.2008.aps. [55] Lei Wang. Reply to "Comment on ’Significance of the highest occupied Kohn-Sham eigenvalue’ ".16029. URL http://link. and M.org/doi/10. C.16021. sciencedirect. Rev.org/doi/10. Thomas Maxisch. R. Dec 1997. [66] A Ruban. 273 . P Stoltze. Oxidation energies of transition metal oxides within the GGA + U framework. Rev. V. C.aps. doi: 10.56.aps. 1997.54.689. 2009.689.1103/PhysRevB. [56] Leonard Kleinman. Rev. O.005. Gunnarsson.org/doi/10.54. Introduction to the Modern Theory of Metals. 1996. B. Rev. Phys. doi: 10. J.73. URL http://www.1021/ja9826892. Elsevier Science Publishers. 121(14):3414–3420.23. Baerends. doi: 10. [57] John P. 1988.. its applications and prospects. D. URL http://link.1103/PhysRevB.org/doi/10. URL http://www.1516800. The analog of Koopmans’ theorem in spin-density functional theory.16029. Projection of plane-wave calculations into atomic orbitals. 89(2):571–577.23. H.1103/ PhysRevB. Dec 1996. Perdew and Mel Levy. doi: 10. URL http://link. Phys. Phys. May 2006. May 1981. B. The Institute of Metals.org/link/?JCP/117/9154/1. 115 (3):421 – 429. 117(20):9154–9159. Shah. 56: 12042–12045. 56:16021–16028. doi: 10.org/doi/abs/10. M. [74] Paula Havu. [75] Wei Chen. 274 . W. R.1103/PhysRevB.org/doi/10. Extraction of aluminium surface energies from slab calculations: perturbative and non-perturbative approaches. doi: 10. Peter Blaha. and Matthias Scheffler. URL http://link.75.1103/RevModPhys.2307.59.1103/ PhysRevLett. Wolverton. Notker Rösch.1103/PhysRevLett. G. Oct 1997. 1992.1103/PhysRevB. doi: 10.82. 56:10518–10525. editors. The Journal of Chemical Physics. 2003. Boettger. doi: 10. doi: 10.[69] D. [80] Fabien Tran. 83. The Institute of Materials. S.83. URL http://link. [70] Stefano Baroni. Ville Havu. Johnson.515.abstract. [72] Daniel Sheppard. Trickey.0408127102. Extracting convergent surface formation energies from slab calculations.org/0953-8984/10/ i=4/a=017. URL http://stacks. Jun 1994.1103/PhysRevB. Phys.2003.1103/RevModPhys. Phys. sciencedirect. surfaces. Frenken. and C. Boettger.1016/j. Rev. [77] J. C.org/doi/10. Cottrell. Caspersen and Emily A.017. B. 1103/PhysRevB. Phys. 73:515–562.10518.org/ doi/10. H. Pettifor and A.org/doi/10.161418. org/doi/10.aps.161418. and Karlheinz Schwarz. Lett.56.115131. Phonons and related crystal properties from density-functional perturbation theory. doi: 10. [71] Kyle J. 2005.75. van der Veen. Rev. Horn. and C. and K. Henriques. Andrea Dal Corso.10518. J. Missing-row surface reconstruction of ag(110) induced by potassium adsorption. C.49. URL http://link. Holub-Krappe. Penghao Xiao. Uwe Birkenheuer.org/doi/10. doi: 10. Almeida. E. 74 (1–8):209 – 217. B. [73] G.2307. A generalized solid-state nudged elastic band method. 83:075415. John R. URL http://www.progsurf. ISSN 0079-6816. doi: 10. Krans.aip. Electon Theory in Alloy Design. Sabin. First-principles cluster expansion study of missing-row reconstructions of fcc (110) surfaces. Duane D. 10(4):893. 73. Rev.49. Varga. Rev.56. B.iop. Rev.org/content/ 102/19/6738.org/link/?JCP/136/074103/ 1. [76] J. Patrick Rinke. Feb 2011. Stefano de Gironcoli. and Paolo Giannozzi. Phys.075415.1103/PhysRevB.1063/1. and S. Smith. Schneider. 59:2307– 2310. Volker Blum.aps.1103/PhysRevB. Mar 2007. 75:115131. URL http://link. Proceedings of the National Academy of Sciences of the United States of America. 82:161418. [78] J. doi: 10. and M.com/science/article/pii/S0079681603000777. Phys.08. URL http://link.515.82. Nonconvergence of surface energies obtained from thin-film calculations. Journal of Physics: Condensed Matter.org/doi/10.115131. B.1073/pnas. Performance on molecules. and Graeme Henkelman. URL http://link.16798. Schmid. 49:16798–16800. A.M. L.1103/PhysRevB. Robert Laskowski.. William Chemelewski. Progress in Surface Science. P. Pt(100) quasihexagonal reconstruction: A comparison between scanning tunneling microscopy data and effective medium theory simulation calculations. Rev. 102(19):6738–6743.aps.1103/PhysRevB. David Schmidt. B.73. and solids of the Wu-Cohen GGA exchange-correlation energy functional. Oct 2010.075415. 2012. doi: 10. Phys. F.16798. Ritz. Nov 1987.aps. doi: 10. 1998.pnas. M. Phys. John R.59. Jul 2001.1103/PhysRevB. Mod. Large-scale surface reconstruction energetics of pt(100) and au(100) by all-electron density functional theory. Borg. William F.aps. [79] Carlos Fiolhais..3684549.aps. Peter Apell. Rønning. L. 136 (7):074103.aps. URL http://www. Finding transition states for crystalline solid/solid phase transformations. B. Rev.1103/PhysRevB. URL http://link. Carter. URL http://link. 63:033405.1103/PhysRevB. [91] John R. 2006.org/link/?JCP/134/104709/1.200602223. Dipole correction for surface supercell calculations.63. 113(22):9901–9904.075437. Uberuaga. Rev. 46. Phys.susc. [84] Jörg Neugebauer and Matthias Scheffler.200602223. ISSN 0039-6028. Phys. B. The Journal of Chemical Physics. A.1063/1. 2009.acs. Density functional theory study of H and CO adsorption on alkali-promoted Mo2 C surfaces. Rev.aps. Feb 2008.205412.1021/jp200950a.045414. Surface Science. 1998. URL http://link. B. The surface energy of metals.1329672. doi: 10. The Journal of Physical Chemistry C. Jul 2010. 411(12):186 – 202.1103/ PhysRevB. B.1103/PhysRevB.jcat. 2009. [85] Lennart Bengtsson.1103/PhysRevB.org/doi/10. [88] Spencer D. and Matthias Scheffler. H. and Manos Mavrikakis.1103/PhysRevB.12301.79. doi: 10. Jan 2001.com/science/article/pii/S0039602809001186.11.aps. URL http: //www. Correlations in coverage-dependent atomic adsorption energies on pd(111).16067.12301.sciencedirect. [90] John R.org/doi/10. doi: 10.59.46.2009. sciencedirect.sciencedirect. Kitchin. Rev.1103/PhysRevB.16067.1016/S0039-6028(98)00363-X. doi: 10.doi. The Journal of Chemical Physics. URL http://www. URL http://link. Kitchin. Alloy surface segregation in reactive environments: First-principles atomistic thermodynamics study of Ag3 Pd(111) in oxygen atmospheres. Phys.1021/jp200950a. Adsorbate-substrate and adsorbate-adsorbate interactions of Na and K adlayers on Al(111). A simple rule of thumb for diffusion on transition-metal surfaces. Rev.033405.org/link/?JCP/113/ 9901/1. Kitchin.033405. doi: 10. and J.021. 115(14):6870– 6876.1103/PhysRevB. Phys.aip.2008.1103/PhysRevB.L. Jeff Greeley. aip.1016/j. B. Skriver.org/doi/abs/10.aps. Sholl.com/science/article/pii/S0021951708004314. Ruban. doi: 10. Surface Science.org/doi/10. doi: 10. Blas P. Phys. Vitos. URL http://link. URL http://link. 134(10):104709. URL http://link. Journal of Catalysis. 261(2):188 – 194. [87] Nilay İnoğlu and John R.aps.020. Rev. B. doi: 10.01.205412.1103/PhysRevB. [86] Yoshitada Morikawa. [82] Nilay İnoğlu and John R. doi: 10.1103/PhysRevB.1103/PhysRevB. URL http://www. ISSN 1521-3773. Karsten Reuter. Kitchin. Simple model explaining and predicting coverage-dependent atomic adsorption energies on transition metal surfaces. ISSN 0021-9517. doi: 10. Dec 1992. 45(42):7046– 7049. May 2009. Nilay Inoglu. Miller and John R. [92] Anand Udaykumar Nilekar.1103/PhysRevB.org/doi/10. Adsorption geometries and vibrational modes of C2 H2 on the si(001) surface. 2000.org/10. Kitchin. Kitchin. 275 . 46:16067–16080. May 1999. doi: 10.org/ doi/10. Configurational correlations in the coverage dependent adsorption energies of oxygen atoms on late transition metal fcc(111) surfaces.045414.82.1063/1. URL http://link. doi: 10. 59:12301– 12304. A climbing image nudged elastic band method for finding saddle points and minimum energy paths. 603(5):794 – 801. and David S. 79:205412. Phys. and Hannes Jonsson. org/doi/10.1016/j.82. Miller. 2011. ISSN 0039-6028. Angewandte Chemie International Edition.V. B.075437.1002/anie. URL http://link. Relating the coverage dependence of oxygen adsorption on Au and Pt fcc(111) surfaces through adsorbate-induced surface electronic structure effects.79.77. [93] Graeme Henkelman. URL http://pubs. 2011. Kollár.com/science/article/pii/S003960289800363X.59. doi: 10. Rev. Liwei Li.63.[81] Jeong Woo Han. [89] Spencer D.3561287. [83] L. and John R.aps. Atomistic thermodynamics study of the adsorption and the effects of water–gas shift reactants on cu catalysts under reaction conditions. URL http://link.1002/ anie. 82:045414.77.aps. URL http://dx. 77:075437. 1103/PhysRevB.82. C. 84:045115.28. M.1016/S0966-9795(02)00127-9. Bott. Ab initio study of high-pressure behavior of a low compressibility metal and a hard material: osmium and diamond.1038/371683a0. 2006.1021/jp810518x.70. doi: 10. 1995. E. Klein.5480. A. and A.org/doi/10. URL http://link. Moore. Classification of chemical bonds based on topological analysis of electron localization functions. [103] Michael J. URL http://www. 82. B. Deshlahra. Meredig. <http://fsf.224107.org/> 276 .70. Formation enthalpies by mixing GGA and GGA + U calculations. Lingzhu Kong. Harris. Murray.84. and P. Phys.045115.045115. B. Higher-accuracy van der waals density functional. [99] B.aps. Rev.acs. 2008 Free Software Foundation. Phys. John Wiley and Sons.doi.aps. doi: 10.5480.84.sciencedirect.pdf. Silvi and A Savin. doi: 10. Thompson. URL http://link. [102] C. 1994.3. and Dimitri A.org/doi/10.C. chapter First principles calculations of elastic properties of metals. Langreth. H. Zemzemi. L.com/science/article/pii/S0966979502001279.28. Proceedings of the National Academy of Sciences of the United States of America.jstor. URL http://dx. Rev. Wolf.1103/PhysRevB. Phys. Inc. ISSN 1096-987X. doi: 10. 82:195128. URL http://link. doi: 10. Charles J. Kristin A. Volume I: Principles. B. 30(9):pp.1002/jcc. volume I. URL http://link. doi: 10. Anton. 2009. First-principles calculation of the equilibrium ground-state properties of transition metals: Applications to Nb and Mo. Methfessel. Éamonn D. Barry M. 2001. 3 November 2008 Copyright (C) 2000. Shyue Ping Ong. Fischer.20495. Aug 2010. 12 GNU Free Documentation License GNU Free Documentation License Version 1. ISSN 00278424. Mayer.1103/PhysRevB. [96] Anubhav Jain. URL http://pubs. Mehl. 2002. [100] M. URL http://www. Intermetallics. Semiempirical gga-type density functional constructed with a long-range dispersion correction. 371:683–686. 1944. Rev.[94] P. Hebbache and M. URL http://cst-www.mil/users/mehl/papers/cij453. [104] B. Dec 2004.navy. 11(1):23 – 32. 27(15):1787–1799. Jul 2011. J. Hansen. 113(16):4125–4133. Schneider.aps. doi: 10. Schmidt.195128. Geoffroy Hautier.aps. Bengt I. Phys.1103/PhysRevB. [97] Kyuho Lee. URL http://link. B. 2003. M. 70:224107. H. pages 195–210. Rev. and Gerbrand Ceder. 28:5480–5486. Wolverton. Nov 2010. [98] Stefan Grimme. F.224107. Murnaghan. van de Walle. E. Rev.org/doi/10. A. Intermetallic Compounds: Principles and Principles. The Journal of Physical Chemistry A.org/10. Lundqvist.1021/jp810518x. [101] F. J.1103/PhysRevB. A periodic density functional theory analysis of co chemisorption on pt(111) in the presence of uniform electric fields†. nrl.1103/PhysRevB. doi: 10. ISSN 0966-9795. Fu and K. Ab-initio calculation of the elastic constants and thermal expansion coefficients of laves phases. Christopher C.081101. Nov 1983. and David C.org/ doi/abs/10.081101.org/stable/87468. B. 82:081101.aps. Nature.org/10. URL http://dx. Papaconstantopoulos. 244–247.1002/jcc.1103/PhysRevB.org/doi/10. Method for locating low-energy solutions within DFT + u.1103/PhysRevB. Phys.doi. Journal of Computational Chemistry. D.82. E. [95] B. 2007.20495.1103/PhysRevB. The compressibility of media under extreme pressures. Sticht.82.1103/PhysRevB.195128.org/doi/10. Ho. Persson. and W. below. 1. but changing it is not allowed. This License is a kind of "copyleft". APPLICABILITY AND DEFINITIONS This License applies to any manual or other work. A "Modified Version" of the Document means any work containing the Document or a portion of it. We have designed this License in order to use it for manuals for free software. You accept the license if you copy. if the Document is in part a textbook of mathematics. or of legal. regardless of subject matter or whether it is published as a printed book. But this License is not limited to software manuals. Such a notice grants a world-wide. or with modifications and/or translated into another language. ethical or political position regarding 277 . We recommend this License principally for works whose purpose is instruction or reference. unlimited in duration. and is addressed as "you". in any medium. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. it can be used for any textual work. commercial.Everyone is permitted to copy and distribute verbatim copies of this license document. while not being considered responsible for modifications made by others. to use that work under the conditions stated herein. modify or distribute the work in a way requiring permission under copyright law. royalty-free license. or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it. PREAMBLE The purpose of this License is to make a manual. this License preserves for the author and publisher a way to get credit for their work. textbook. Any member of the public is a licensee. a Secondary Section may not explain any mathematics. either commercially or noncommercially. with or without modifying it. which means that derivative works of the document must themselves be free in the same sense.) The relationship could be a matter of historical connection with the subject or with related matters. 0. philosophical. refers to any such manual or work. because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. Secondarily. (Thus. either copied verbatim. It complements the GNU General Public License. which is a copyleft license designed for free software. that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The "Document". and the machine-generated HTML. the material this License requires to appear in the title page. "Title Page" means the text near the most prominent appearance of the work’s title. SGML or XML using a publicly available DTD. The Document may contain zero Invariant Sections. in the notice that says that the Document is released under this License. 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. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. SGML or XML for which the DTD and/or processing tools are not generally available. in the notice that says that the Document is released under this License. A "Transparent" copy of the Document means a machine-readable copy. as Front-Cover Texts or Back-Cover Texts. The "publisher" means any person or entity that distributes copies of the Document to the public. Examples of transparent image formats include PNG. The "Title Page" means. PostScript or PDF designed for human modification. PostScript or PDF produced by some word processors for output purposes only. XCF and JPG. (Here XYZ stands for a 278 . legibly.them. 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. has been arranged to thwart or discourage subsequent modification by readers is not Transparent. the title page itself. An image format is not Transparent if used for any substantial amount of text. The "Invariant Sections" are certain Secondary Sections whose titles are designated. as being those of Invariant Sections. A copy made in an otherwise Transparent file format whose markup. The "Cover Texts" are certain short passages of text that are listed. For works in formats which do not have any title page as such. and a Back-Cover Text may be at most 25 words. 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 that is not "Transparent" is called "Opaque". Opaque formats include proprietary formats that can be read and edited only by proprietary word processors. plus such following pages as are needed to hold. or absence of markup. Examples of suitable formats for Transparent copies include plain ASCII without markup. Texinfo input format. If the Document does not identify any Invariant Sections then there are none. for a printed book. represented in a format whose specification is available to the general public. A Front-Cover Text may be at most 5 words. LaTeX input format. and standard-conforming simple HTML. preceding the beginning of the body of the text. and the Document’s license notice requires Cover Texts. all these Cover Texts: Front-Cover Texts on the front cover. If you distribute a large enough number of copies you must also follow the conditions in section 3. If you publish or distribute Opaque copies of the Document numbering more than 100. Both covers must also clearly and legibly identify you as the publisher of these copies. numbering more than 100. you must enclose the copies in covers that carry. you may accept compensation in exchange for copies. and you may publicly display copies. These Warranty Disclaimers are considered to be included by reference in this License. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. and Back-Cover Texts on the back cover. clearly and legibly. The front cover must present the full title with all words of the title equally prominent and visible. "Dedications". 3. and continue the rest onto adjacent pages. "Endorsements".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. and that you add no other conditions whatsoever to those of this License. but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. as long as they preserve the title of the Document and satisfy these conditions.specific section name mentioned below. and the license notice saying this License applies to the Document are reproduced in all copies. provided that this License. either commercially or noncommercially. can be treated as verbatim copying in other respects. You may add other material on the covers in addition. If the required texts for either cover are too voluminous to fit legibly. you must either include a machine-readable Transparent copy along with each Opaque copy. or "History". You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. 2. you should put the first ones listed (as many as fit reasonably) on the actual cover. Copying with changes limited to the covers. However. under the same conditions stated above. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document. VERBATIM COPYING You may copy and distribute the Document in any medium. You may also lend copies. such as "Acknowledgements". the copyright notices. or state in or with each Opaque copy a computer-network location from which the general network-using 279 . as the publisher. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document’s license notice. you must do these things in the Modified Version: A. if any) a title distinct from that of the Document. Include an unaltered copy of this License. to give them a chance to provide you with an updated version of the Document. F. provided that you release the Modified Version under precisely this License. You may use the same title as a previous version if the original publisher of that version gives permission. and publisher of the Document as given on its Title Page. year. unless they release you from this requirement. year. Preserve all the copyright notices of the Document. List on the Title Page. It is requested. G. if it has fewer than five). when you begin distribution of Opaque copies in quantity. Use in the Title Page (and on the covers. If you use the latter option. then add an item describing the Modified Version as stated in the previous sentence. to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. I. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above. and publisher of the Modified Version as given on the Title Page. and from those of previous versions (which should. E. In addition. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. Preserve the section Entitled "History".public has access to download using public-standard network protocols a complete Transparent copy of the Document. State on the Title page the name of the publisher of the Modified Version. new authors. together with at least five of the principal authors of the Document (all of its principal authors. with the Modified Version filling the role of the Document. free of added material. H. D. and add to it an item stating at least the title. If there is no section Entitled "History" in the Document. B. create one stating the title. if there were any. be listed in the History section of the Document). in the form shown in the Addendum below. immediately after the copyright notices. Include. 4. 280 . thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. Preserve its Title. a license notice giving the public permission to use the Modified Version under the terms of this License. as authors. you must take reasonably prudent steps. one or more persons or entities responsible for authorship of the modifications in the Modified Version. C. authors. but not required. that you contact the authors of the Document well before redistributing any large number of copies. and likewise the network locations given in the Document for previous versions it was based on. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. given in the Document for public access to a Transparent copy of the Document. to the end of the list of Cover Texts in the Modified Version. you may not add another. statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. O. N. you may at your option designate some or all of these sections as invariant. For any section Entitled "Acknowledgements" or "Dedications". previously added by you or by arrangement made by the same entity you are acting on behalf of. L. add their titles to the list of Invariant Sections in the Modified Version’s license notice. unaltered in their text and in their titles. Preserve all the Invariant Sections of the Document. 5. Preserve the Title of the section. M. Such a section may not be included in the Modified Version. or if the original publisher of the version it refers to gives permission. and a passage of up to 25 words as a Back-Cover Text. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. These may be placed in the "History" section. If the Document already includes a cover text for the same cover. COMBINING DOCUMENTS You may combine the Document with other documents released under this License. Section numbers or the equivalent are not considered part of the section titles. These titles must be distinct from any other section titles. You may add a passage of up to five words as a Front-Cover Text. on explicit permission from the previous publisher that added the old one. Delete any section Entitled "Endorsements". and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. Preserve any Warranty Disclaimers. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. You may add a section Entitled "Endorsements". K. You may omit a network location for a work that was published at least four years before the Document itself. To do this. provided it contains nothing but endorsements of your Modified Version by various parties--for example.J. Preserve the network location. but you may replace the old one. under the terms defined in section 4 above for modified 281 . if any. likewise combine any sections Entitled "Acknowledgements". unmodified. and that you preserve all their Warranty Disclaimers. If the Cover Text requirement of section 3 is applicable to these copies of the Document. make the title of each such section unique by adding at the end of it. In the combination. If there are multiple Invariant Sections with the same name but different contents. and distribute it individually under this License. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License. this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. provided you insert a copy of this License into the extracted document. forming one section Entitled "History". 7. and list them all as Invariant Sections of your combined work in its license notice. and multiple identical Invariant Sections may be replaced with a single copy. provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. 6. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works. and follow this License in all other respects regarding verbatim copying of that document. and any sections Entitled "Dedications". You may extract a single document from such a collection. you must combine any sections Entitled "History" in the various original documents. provided that you include in the combination all of the Invariant Sections of all of the original documents. or else a unique number. the name of the original author or publisher of that section if known. in or on a volume of a storage or distribution medium. You must delete all sections Entitled "Endorsements". then if the Document is less than one half of the entire aggregate. When the Document is included in an aggregate. the Document’s Cover Texts may be placed on covers that bracket the Document within the aggregate. or the 282 . is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation’s users beyond what the individual works permit. in parentheses. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. The combined work need only contain one copy of this License.versions. and replace the individual copies of this License in the various documents with a single copy that is included in the collection. sublicense.electronic equivalent of covers if the Document is in electronic form. or "History". 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. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer. modify. or distribute it is void. "Dedications". if you cease all violation of this License. provided that you also include the original English version of this License and the original versions of those notices and disclaimers. TERMINATION You may not copy. 283 . and (b) permanently. If your rights have been terminated and not permanently reinstated. If a section in the Document is Entitled "Acknowledgements". TRANSLATION Translation is considered a kind of modification. then your license from a particular copyright holder is reinstated (a) provisionally. and will automatically terminate your rights under this License. and you cure the violation prior to 30 days after your receipt of the notice. so you may distribute translations of the Document under the terms of section 4. receipt of a copy of some or all of the same material does not give you any rights to use it. Moreover. You may include a translation of this License. and any Warranty Disclaimers. and all the license notices in the Document. modify. the original version will prevail. Any attempt otherwise to copy. sublicense. or distribute the Document except as expressly provided under this License. 8. this is the first time you have received notice of violation of this License (for any work) from that copyright holder. if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Otherwise they must appear on printed covers that bracket the whole aggregate. unless and until the copyright holder explicitly and finally terminates your license. the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. Replacing Invariant Sections with translations requires special permission from their copyright holders. 9. your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means. but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. However. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new. See http://www.0 license published by Creative Commons Corporation. If the Document specifies that a proxy can decide which future versions of this License can be used. RELICENSING "Massive Multiauthor Collaboration Site" (or "MMC Site") means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. a not-for-profit corporation with a principal place of business in San Francisco. California. 2009.10.gnu. Such new versions will be similar in spirit to the present version. 2008. and subsequently incorporated in whole or in part into the MMC. (1) had no cover texts or invariant sections.org/copyleft/. but may differ in detail to address new problems or concerns. in whole or in part. you may choose any version ever published (not as a draft) by the Free Software Foundation. as well as future copyleft versions of that license published by that same organization. and (2) were thus incorporated prior to November 1. "Incorporate" means to publish or republish a Document. as part of another Document. An MMC is "eligible for relicensing" if it is licensed under this License. 284 . If the Document does not specify a version number of this License. The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1. A public wiki that anybody can edit is an example of such a server. provided the MMC is eligible for relicensing. revised versions of the GNU Free Documentation License from time to time. you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document specifies that a particular numbered version of this License "or any later version" applies to it. and if all works that were first published under this License somewhere other than this MMC. 11. A "Massive Multiauthor Collaboration" (or "MMC") contained in the site means any set of copyrightable works thus published on the MMC site. "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3. that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document. Each version of the License is given a distinguishing version number. 13 Index 285 . 77 reconstruction. 2 molecular weight. 20 moment of inertia. 168 atomistic thermodynamics. 32 HSE06. 158 SIGMA. 208 infrared intensity. 195 bader. 163 286 . 57 KPOINTS. 45 work function. 87 jasp. 52 vibrations. 48 ISMEAR. 127 center of mass. 21 cohesive energy. 21 nudged elastic band. 204 dipole correction. 103 convergence ENCUT.Index adsorption energy. 166 dipole moment. 38 band structure. 103 DFT+U. 87 thermochemistry.
Copyright © 2024 DOKUMEN.SITE Inc.