ASE Manual - Campos

ASE Manual
Release 3.9.0.3865
CAMd
October 14, 2014
CONTENTS
1
Atomic Simulation Environment
1.1 News . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
4
2
Overview
7
3
Installation requirements
9
4
Download
4.1 Latest stable release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2 Latest development release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
11
11
5
Installation
5.1 Installation on OS X . . . . . . . . . . . . .
5.2 Installation with package manager on Linux .
5.3 Windows . . . . . . . . . . . . . . . . . . .
5.4 Manual installation . . . . . . . . . . . . . .
5.5 Run the tests . . . . . . . . . . . . . . . . .
5.6 Video tutorial . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
13
14
15
15
16
Tutorials
6.1 Python . . . .
6.2 ASE . . . . . .
6.3 NumPy . . . .
6.4 Further reading
6.5 Videos . . . .
6
7
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
17
17
20
61
62
67
Documentation for modules in ASE
7.1 The Atoms object . . . . . . .
7.2 The Atom object . . . . . . . .
7.3 Units . . . . . . . . . . . . . .
7.4 The ase.data module . . . .
7.5 File input and output . . . . . .
7.6 Examples . . . . . . . . . . . .
7.7 ASE-GUI . . . . . . . . . . . .
7.8 Command line tool . . . . . . .
7.9 Creating atomic structures . . .
7.10 Structure optimization . . . . .
7.11 Parallel calculations . . . . . .
7.12 Visualization . . . . . . . . . .
7.13 ASE-VTK . . . . . . . . . . .
7.14 Calculators . . . . . . . . . . .
7.15 Constraints . . . . . . . . . . .
7.16 Nudged elastic band . . . . . .
7.17 Vibration analysis . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
69
69
81
83
83
83
86
88
96
100
115
120
120
126
128
165
171
173
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
i
7.18
7.19
7.20
7.21
7.22
7.23
7.24
7.25
7.26
7.27
7.28
7.29
7.30
7.31
7.32
Phonon calculations . . . . . . . . . . . .
Example . . . . . . . . . . . . . . . . . .
Thermochemistry . . . . . . . . . . . . . .
Infrared intensities . . . . . . . . . . . . .
Molecular dynamics . . . . . . . . . . . .
Density Functional Theory . . . . . . . . .
Electron transport . . . . . . . . . . . . .
The data module . . . . . . . . . . . . . .
Trajectory files . . . . . . . . . . . . . . .
Utillity functions and classes . . . . . . . .
Building neighbor-lists . . . . . . . . . . .
Setting up an OPLS force field calculation
A database for atoms . . . . . . . . . . . .
Genetic Algorithm . . . . . . . . . . . . .
Dimer method . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
175
175
178
184
186
191
200
201
203
207
208
209
210
216
230
8
Frequently Asked Questions
8.1 ASE-GUI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2 General . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.3 Download . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
233
233
233
234
9
Glossary
235
10 Mailing Lists
237
10.1 Internet Relay Chat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
11 License
11.1 Human-readable version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11.2 Legal version of the license . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11.3 What happens when ASE Calculators are under another license? . . . . . . . . . . . . . . . . . .
239
239
239
239
12 ASE development
241
12.1 Development topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
12.2 Creating an encrypted password for SVN access . . . . . . . . . . . . . . . . . . . . . . . . . . 268
13 Bugs!
269
13.1 Bug report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
13.2 Known bugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
14 Porting old ASE-2 code to version 3
271
14.1 The ASE2ase tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
Bibliography
273
Python Module Index
275
Index
277
ii
ASE Manual, Release 3.9.0.3865
• Introduction to ASE - what is it?
• Download and installation instructions
• Tutorials
• Documentation for modules in ASE
• Frequently Asked Questions
• Mailing Lists
• Glossary
• License
• ASE development
• Bugs!
• Porting old ASE-2 code to version 3
The complete table of contents:
CONTENTS
1
ASE Manual, Release 3.9.0.3865
2
CONTENTS
CHAPTER
ONE
ATOMIC SIMULATION ENVIRONMENT
The Atomic Simulation Environment (ASE) is the common part of the simulation tools developed at CAMd. ASE
provides Python modules for manipulating and visualizing atoms, running and analyzing simulations, The code is
freely available under the GNU LGPL license.
Actively maintained ase.calculators:
Gaussian
Supported ase.calculators (we are looking for maintainers!):
3
ASE Manual, Release 3.9.0.3865
Mopac
1.1 News
• ASE version 3.8.0 released (22 October 2013).
• ASE version 3.7.0 released (13 May 2013).
• ASE version 3.6.0 released (24 February 2012).
• Bugfix release: ASE version 3.5.1 (24 May 2011).
• ASE version 3.5.0 released (13 April 2011).
• ASE version 3.4.1 released (11 August 2010).
• ASE version 3.4 released (23 April 2010).
• ASE version 3.3 released (11 January 2010).
• ASE version 3.2 released (4 September 2009).
• ASE has reached revision 1000 (16 July 2009).
• ASE version 3.1.0 released (27 March 2009).
• Improved ase.vibrations module:
intensities (13 March 2009).
More accurate and possibility to calculate infrared
• ASE version 3.0.0 released (13 November 2008).
4
Chapter 1. Atomic Simulation Environment
ASE Manual, Release 3.9.0.3865
• Asap version 3.0.2 released (15 October 2008).
• An experimental abinit interface released (9 June 2008).
• Thursday April 24 will be ASE documentation-day. Ten people from CAMd/Cinf will do a “doc-sprint”
from 9 to 16. (17 Apr 2008)
• The new ASE-3.0 Sphinx page is now up and running! (2 Apr 2008)
• A beta version of the new ASE-3.0 will be used for the electronic structure course at CAMd. (10 Jan 2008)
1.1. News
5
ASE Manual, Release 3.9.0.3865
6
Chapter 1. Atomic Simulation Environment
CHAPTER
TWO
OVERVIEW
ASE is an Atomistic Simulation Environment written in the Python programming language with the aim of setting
up, steering, and analyzing atomistic simulations. The ASE has been constructed with a number of “design goals”
that make it:
• Easy to use:
Setting up an atomistic total energy calculation or molecular dynamics simulation with ASE is simple and
straightforward. ASE can be used via a graphical user interface, a Command line tool and the
Python language. Python scripts are easy to follow (see What is Python? for a short introduction). It is
simple for new users to get access to all of the functionality of ASE.
• Flexible:
Since ASE is based on the Python scripting language it is possible to perform very complicated simulation
tasks without any code modifications. For example, a sequence of calculations may be performed with the
use of simple “for-loop” constructions. There exist ASE modules for performing many standard simulation
tasks.
• Customizable:
The Python code in ASE is structured in modules intended for different purposes. There are
ase.calculators for calculating energies, forces and stresses, ase.md and ase.optimize
modules for controlling the motion of atoms, constraints objects and filters for performing
nudged-elastic-band calculations etc. The modularity of the object-oriented code make it simple
to contribute new functionality to ASE.
• Pythonic:
It fits nicely into the rest of the Python world with use of the popular NumPy package for numerical work
(see Numeric arrays in Python for a short introduction). The use of the Python language allows ASE to be
used both interactively as well as in scripts.
• Open to participation:
The CAMPOS Atomic Simulation Environment is released under the GNU Lesser General Public License
version 2.1 or any later version. See the files COPYING and COPYING.LESSER which accompany the
downloaded files, or see the license at GNU’s web server at http://www.gnu.org/licenses/. Everybody is
invited to participate in using and developing the code.
7
ASE Manual, Release 3.9.0.3865
8
Chapter 2. Overview
CHAPTER
THREE
INSTALLATION REQUIREMENTS
The following packages are required for basic ASE functionality:
1. Python 2.6 - 2.7.
2. NumPy.
It is highly recommended (but not required) to install also these:
3. matplotlib.
4. libpng.
5. pygtk.
6. SciPy.
Matplotlib and libpng are needed for writing png files, and together with pygtk are needed for ASE’s
simple GUI (called ase-gui, see ase.gui). Some of these packages may already be installed on your system.
Specific information for different operating systems is provided at Installation.
9
ASE Manual, Release 3.9.0.3865
10
Chapter 3. Installation requirements
CHAPTER
FOUR
DOWNLOAD
4.1 Latest stable release
The latest stable release can be obtained from SVN or as a tar-file.
Note: The recommended installation path is $HOME.
When using svn please set the following variable:
• bash:
export ASE_TAGS=https://svn.fysik.dtu.dk/projects/ase/tags/
• csh/tcsh:
setenv ASE_TAGS https://svn.fysik.dtu.dk/projects/ase/tags/
Release
3.8.1
3.8.0
3.7.1
3.7.0
3.6.0
3.5.1
3.4.1
3.4.0
3.3.1
3.2.0
3.1.0
3.0.0
Date
Nov 22 2013
Oct 22 2013
May 16 2013
May 13 2013
Feb 24 2012
May 24 2011
Aug 11 2010
Apr 23 2010
Jan 20 2010
Sep 4 2009
Mar 27 2009
Nov 13 2008
Retrieve as svn checkout
svn co -r 3440 $ASE_TAGS/3.8.1 ase-3.8.1
svn co -r 3420 $ASE_TAGS/3.8.0 ase-3.8.0
svn co -r 3184 $ASE_TAGS/3.7.1 ase-3.7.1
svn co -r 3168 $ASE_TAGS/3.7.0 ase-3.7.0
svn co -r 2515 $ASE_TAGS/3.6.0 ase-3.6.0
svn co -r 2175 $ASE_TAGS/3.5.1 ase-3.5.1
svn co -r 1765 $ASE_TAGS/3.4.1 ase-3.4.1
svn co -r 1574 $ASE_TAGS/3.4.0 ase-3.4.0
svn co -r 1390 $ASE_TAGS/3.3.1 ase-3.3.1
svn co -r 1121 $ASE_TAGS/3.2.0 ase-3.2.0
svn co -r 846 $ASE_TAGS/3.1.0 ase-3.1.0
svn co -r 657 $ASE_TAGS/3.0.0 ase-3.0.0
Retrieve as tar-file
python-ase-3.8.1.3440.tar.gz
python-ase-3.8.0.3420.tar.gz
python-ase-3.7.1.3184.tar.gz
python-ase-3.7.0.3168.tar.gz
python-ase-3.6.0.2515.tar.gz
python-ase-3.5.1.2175.tar.gz
python-ase-3.4.1.1765.tar.gz
python-ase-3.4.0.1574.tar.gz
python-ase-3.3.1.1390.tar.gz
python-ase-3.2.0.1121.tar.gz
python-ase-3.1.0.846.tar.gz
python-ase-3.0.0.657.tar.gz
4.2 Latest development release
The latest revision can be obtained like this:
$ svn checkout https://svn.fysik.dtu.dk/projects/ase/trunk ase
or from the daily snapshot: python-ase-snapshot.tar.gz.
Note: The recommended checkout path is $HOME.
11
ASE Manual, Release 3.9.0.3865
12
Chapter 4. Download
CHAPTER
FIVE
INSTALLATION
After performing the installation do not forget to Run the tests!
5.1 Installation on OS X
For installation with http://mxcl.github.com/homebrew/ please follow instructions at Homebrew.
5.2 Installation with package manager on Linux
Install the binaries with the software package manager of your Linux distribution.
This is the preferred way to install on a Linux system.
If you prefer to install from sources follow Manual installation.
The currently supported systems include (issue the commands below as root):
• Fedora:
yum install python-ase
• RHEL/CentOS - available after enabling https://fedoraproject.org/wiki/EPEL:
yum install python-ase
• openSUSE 13.1:
zypper ar -f http://download.opensuse.org/repositories/home:/dtufys/openSUSE_13.1/home:dtufys
yast -i python-ase
yast -i python-matplotlib # optionally
• Debian 7.0:
sudo
wget
sudo
sudo
sudo
bash -c ’echo "deb http://download.opensuse.org/repositories/home:/dtufys/Debian_7.0 /"
http://download.opensuse.org/repositories/home:/dtufys/Debian_6.0/Release.key && sudo ap
apt-get update
apt-get install python-ase
apt-get install python-matplotlib # optionally
• Ubuntu 14.04:
sudo
wget
sudo
sudo
sudo
bash -c ’echo "deb http://download.opensuse.org/repositories/home:/dtufys/xUbuntu_14.04
http://download.opensuse.org/repositories/home:/dtufys/xUbuntu_14.04/Release.key && sudo
apt-get update
apt-get install python-ase
apt-get install python-matplotlib # optionally
13
ASE Manual, Release 3.9.0.3865
Note: Alternative packages for Ubuntu are provided at Ubuntu package.
For the full list of supported distributions check https://build.opensuse.org/package/show?package=pythonase&project=home%3Adtufys
Note: Explore the repositories - more software packages are available!
Note: If you prefer to install manually, proceed to Manual installation, or alternatively, manually unpack the
RPMS, e.g.:
#
$
#
$
#
$
#
$
#
$
#
$
#
$
download the packages + dependencies (you can do that also manually!)
yumdownloader --resolve python-ase
unpack into the current directory
find . -name "*.rpm" | xargs -t -I file sh -c "rpm2cpio file | cpio -idm"
modify profile.d environment scripts
find . -name "*.*sh" | xargs -t -I file sh -c ’sed -i "s#PA=/usr#PA=$PWD/usr#" file’
modify environment modules scripts
find . -name "*.modules" | xargs -t -I file sh -c ’sed -i "s# /usr# $PWD/usr#" file’
make scripts executable
find . -name "*.*sh" | xargs -t -I file sh -c "chmod u+x file"
source the scripts (example for bash)
for f in �find . -name "*.sh"�; do source $f; done
verify the desired installation location is used
python -c "import ase; print ase.__file__"
This method works for all the RPM packages from the repository (like gpaw), however not for the external,
distribution provided packages, which may require manually creating the environment scripts.
5.3 Windows
Note: ASE is not yet fully functional on Windows! https://trac.fysik.dtu.dk/projects/ase/ticket/62
On Windows the following packages need to installed. On the command prompt:
Note:
installation assumes the python TARGETDIR C:\Python27, leave also the default C:\Program
Files\pythonxy.
• pythonxy. Download the exe installer and install with:
Python(x,y)-2.7.2.2.exe /Log="%TMP%\pythonxy_install.log" /S
Note: Open Task Manager and control when the process in finished.
• pygtk_win32. Download the msi pygtk-all-in-one installer. Specify the correct TARGETDIR and install:
pygtk-all-in-one-2.24.2.win32-py2.7.msi TARGETDIR="%HOMEDRIVE%\Python27" ALLUSERS=1 /l*vx "%T
Note: If performing clicking-installation make sure that the default python Windows TARGETDIR is selected.
• Download the python-ase-win32.msi installer and install with:
14
Chapter 5. Installation
ASE Manual, Release 3.9.0.3865
python-ase-X.X.X.win32.msi /l*vx "%TMP%\python-ase_install.log" /passive
Note: You can build the msi ASE package on Windows with:
python setup.py bdist_msi
The msi package will be created under the dist directory.
5.4 Manual installation
After the Download of ASE source create the link to the requested version, e.g.:
• if retrieved from svn:
$ cd $HOME
$ ln -s ase-3.8.0 ase
• if retrieved as tar-file:
$ cd $HOME
$ tar zxf python-ase-3.8.0.3420.tar.gz
$ ln -s python-ase-3.8.0.3420 ase
It is sufficient to put the directory $HOME/ase in your PYTHONPATH environment variable, and the directory
$HOME/ase/tools in your PATH environment variable. Do this permanently in your ~/.bashrc file:
export PYTHONPATH=$HOME/ase:$PYTHONPATH
export PATH=$HOME/ase/tools:$PATH
or your ~/.cshrc file:
setenv PYTHONPATH ${HOME}/ase:${PYTHONPATH}
setenv PATH ${HOME}/ase/tools:${PATH}
Instead of HOME, you may use any other directory.
Alternatively, you can install ASE to the user-specific site-packages directory with:
$ cd ase
$ python setup.py install --user
This way, the ASE modules are found on the python path without any explicit configuration, though you still need
to ensure that $HOME/.local/bin (or on Windows, %APPDATA%/Python/Scripts) is on your PATH.
Optional, NOT recommended way of installing ASE system-wide is:
$ cd ase
$ sudo python setup.py install
This is one of the best ways to ruin a Linux system.
5.5 Run the tests
Make sure that everything works by running the test suite. This will create many files, so run the tests in a
new directory (preferably using bash):
$ bash
$ mkdir /tmp/testase.$$; cd /tmp/testase.*
$ python -c "from ase.test import test; test(verbosity=2, display=True)" 2>&1 | tee testase.log
5.4. Manual installation
15
ASE Manual, Release 3.9.0.3865
Note: The last test ase/test/COCu111.py requires closing the graphics windows to terminate the whole test-suite.
Note: If matplotlib or pygtk is not installed, this test will fail - avoid this with display=False.
If any of the tests fail, then please send us testase.log (see Bugs!).
5.6 Video tutorial
In the video: Overview of the features of ASE, followed by a Manual installation of ASE on a Linux system.
Note: Use “Right Click -> Play” to play.
16
Chapter 5. Installation
CHAPTER
SIX
TUTORIALS
6.1 Python
If you are not familiar with Python please read What is Python?.
6.1.1 What is Python?
This section will give a very brief introduction to the Python language.
See Also:
• The Python home page.
• Python Recipes.
• Try a Python quick reference card or a different reference card.
Executing Python code
You can execute Python code interactively by starting the interpreter like this:
$ python
Python 2.5.1 (r251:54863, Mar 7 2008, 04:10:12)
[GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print ’hello’
hello
You can also put the print ’hello’ line in a file (hello.py) and execute it as a Python script:
$ python hello.py
hello
Or like this:
$ python -i hello.py
hello
>>> print ’hi!’
hi!
Finally, you can put #!/usr/bin/env python in the first line of the hello.py file, make it executable
(chmod +x hello.py) and execute it like any other executable.
Tip: For interactive Python sessions, it is very convenient to have a personal .pythonrc file:
17
ASE Manual, Release 3.9.0.3865
import rlcompleter
import readline
readline.parse_and_bind("tab: complete")
from ase import *
and point the PYTHONSTARTUP environment variable at it (see rlcompleter for details).
Tip: For an even better interactive experience, use ipython.
Types
Python has the following predefined types:
type
bool
int
float
complex
str
tuple
list
dict
file
description
boolean
integer
floating point number
complex number
string
tuple
list
dictionary
file
example
False
117
1.78
0.5 + 2.0j
’abc’
(1, ’hmm’, 2.0)
[1, ’hmm’, 2.0]
{’a’: 7.0, 23: True}
open(’stuff.dat’, ’w’)
A dict object is mapping from keys to values:
>>> d = {’s’: 0, ’p’: 1}
>>> d[’d’] = 2
>>> d
{’p’: 1, ’s’: 0, ’d’: 2}
>>> d[’p’]
1
In this example all keys are strings and all values are integers. Types can be freely mixed in the same dictionary;
any type can be used as a value and most types can be used as keys (mutable objects cannot be keys).
A list object is an ordered collection of arbitrary objects:
>>> l = [1, (’gg’, 7), ’hmm’]
>>> l[1]
(’gg’, 7)
>>>
>>> l
[1, (’gg’, 7), ’hmm’, 1.2]
>>> l[-2]
’hmm’
Indexing a list with negative numbers counts from the end of the list, so element -2 is the second last.
A tuple behaves like a list - except that it can’t be modified in place. Objects of types list and dict are
mutable - all the other types listed in the table are immutable, which means that once an object has been created,
it can not change. Tuples can therefore be used as dictionary keys, lists cannot.
Note: List and dictionary objects can change. Variables in Python are references to objects - think of the =
operator as a “naming operator”, not as an assignment operator. This is demonstrated here:
>>>
>>>
>>>
>>>
18
a = [’q’, ’w’]
b = a
a.append(’e’)
a
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
[’q’, ’w’, ’e’]
>>> b
[’q’, ’w’, ’e’]
The line b = a gives a new name to the array, and both names now refer to the same list.
However, often a new object is created and named at the same time, in this example the number 42 is not modified,
a new number 47 is created and given the name d. And later, e is a name for the number 47, but then a new number
48 is created, and e now refers to that number:
>>> c = 42
>>> d = c + 5
>>> c
42
>>> d
47
>>> e = d
>>> e += 1
>>> (d, e)
(47, 48)
Note: Another very important type is the ndarray type described here: Numeric arrays in Python. It is an array
type for efficient numerics, and is heavily used in ASE.
Loops
A loop in Python can be done like this:
>>> things = [’a’, 7]
>>> for x in things:
...
print x
...
a
7
The things object could be any sequence. Strings, tuples, lists, dictionaries, ndarrays and files are sequences.
Try looping over some of these types.
Often you need to loop over a range of numbers:
>>> for i in range(5):
...
print i, i*i
...
0 0
1 1
2 4
3 9
4 16
Functions and classes
A function is defined like this:
>>> def f(x, m=2, n=1):
...
y = x + n
...
return y**m
...
>>> f(5)
36
6.1. Python
19
ASE Manual, Release 3.9.0.3865
>>> f(5, n=8)
169
Here f is a function, x is an argument, m and n are keywords with default values 2 and 1 and y is a variable.
A class is defined like this:
>>> class A:
...
def __init__(self, b):
...
self.c = b
...
def m(self, x):
...
return self.c * x
...
def get_c(self)
...
return self.c
You can think of a class as a template for creating user defined objects. The __init__() function is called a
constructor, it is being called when objects of this type are being created.
In the class A __init__ is a constructor, c is an attribute and m and get_c are methods.
>>>
>>>
7
>>>
7
>>>
21
a = A(7)
a.c
a.get_c()
a.m(3)
Here we make an instance/object a of type A.
Importing modules
If you put the definitions of the function f and the class C in a file stuff.py, then you can use that code from
another piece of code:
from stuff import f, C
print f(1, 2)
print C(1).m(2)
or:
import stuff
print stuff.f(1, 2)
print stuff.C(1).m(2)
or:
import stuff as st
print st.f(1, 2)
print st.C(1).m(2)
Python will look for stuff.py in these directories:
1. current working directory
2. directories listed in your PYTHONPATH
3. Python’s own system directory (typically /usr/lib/python2.5)
and import the first one found.
6.2 ASE
Most of the tutorials will use the EMT potential, but any other Calculator could be plugged in instead.
20
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
6.2.1 Introduction: Nitrogen on copper
This section gives a quick (and incomplete) overview of what ASE can do.
We will calculate the adsorption energy of a nitrogen molecule on a copper surface. This is done by calculating
the total energy for the isolated slab and for the isolated molecule. The adsorbate is then added to the slab and
relaxed, and the total energy for this composite system is calculated. The adsorption energy is obtained as the sum
of the isolated energies minus the energy of the composite system.
Here is a picture of the system after the relaxation:
Please have a look at the following script N2Cu.py:
from
from
from
from
from
from
ase import Atoms
ase.visualize import view
ase.calculators.emt import EMT
ase.constraints import FixAtoms
ase.optimize import QuasiNewton
ase.lattice.surface import fcc111,add_adsorbate
h = 1.85
d = 1.10
slab = fcc111(’Cu’, size=(4,4,2), vacuum=10.0)
slab.set_calculator(EMT())
e_slab = slab.get_potential_energy()
molecule = Atoms(’2N’, positions=[(0., 0., 0.), (0., 0., d)])
molecule.set_calculator(EMT())
e_N2 = molecule.get_potential_energy()
add_adsorbate(slab, molecule, h, ’ontop’)
constraint = FixAtoms(mask=[a.symbol != ’N’ for a in slab])
slab.set_constraint(constraint)
dyn = QuasiNewton(slab, trajectory=’N2Cu.traj’)
dyn.run(fmax=0.05)
print ’Adsorption energy:’, e_slab + e_N2 - slab.get_potential_energy()
#view(slab)
Assuming you have ASE setup correctly (Installation requirements) run the script:
python N2Cu.py
Please read below what the script does.
6.2. ASE
21
ASE Manual, Release 3.9.0.3865
Atoms
The Atoms object is a collection of atoms. Here is how to define a N2 molecule by directly specifying the position
of two nitrogen atoms:
from ase import Atoms
d = 1.10
molecule = Atoms(’2N’, positions=[(0., 0., 0.), (0., 0., d)])
You can also build crystals using, for example, the lattice module which returns Atoms objects corresponding to
common crystal structures. Let us make a Cu (111) surface:
from ase.lattice.surface import fcc111
slab = fcc111(’Cu’, size=(4,4,2), vacuum=10.0)
Calculators
Many ase.calculators can be used with ASE, including emt, Asap, Dacapo, GPAW, Abinit, Vasp. See the
ASE home page for the full list.
In this overview we use the effective medium theory (EMT) calculator, as it is very fast and hence useful for
getting started.
We can attach a calculator to the previously created Atoms objects:
from ase.calculators.emt import EMT
slab.set_calculator(EMT())
molecule.set_calculator(EMT())
and use it to calculate the total energies for the systems by using the get_potential_energy() method
from the Atoms class:
e_slab = slab.get_potential_energy()
e_N2 = molecule.get_potential_energy()
Structure relaxation
Let’s use the QuasiNewton minimizer to optimize the structure of the N2 molecule adsorbed on the Cu surface.
First add the adsorbate to the Cu slab, for example in the on-top position:
h = 1.85
add_adsorbate(slab, molecule, h, ’ontop’)
In order to speed up the relaxation, let us keep the Cu atoms fixed in the slab by using FixAtoms from the
constraints module. Only the N2 molecule is then allowed to relax to the equilibrium structure:
from ase.constraints import FixAtoms
constraint = FixAtoms(mask=[a.symbol != ’N’ for a in slab])
slab.set_constraint(constraint)
Now attach the QuasiNewton minimizer to the system and save the trajectory file. Run the minimizer with the
convergence criteria that the force on all atoms should be less than some fmax:
from ase.optimize import QuasiNewton
dyn = QuasiNewton(slab, trajectory=’N2Cu.traj’)
dyn.run(fmax=0.05)
Note: The general documentation on structure optimizations contains information about different algorithms,
saving the state of an optimizer and other functionality which should be considered when performing expensive
relaxations.
22
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
Input-output
Writing the atomic positions to a file is done with the write() function:
from ase.io import write
write(’slab.xyz’, slab)
This will write a file in the xyz-format. Possible formats are:
format
xyz
cube
pdb
traj
py
description
Simple xyz-format
Gaussian cube file
Protein data bank file
ASE’s own trajectory format
Python script
Reading from a file is done like this:
from ase.io import read
slab_from_file = read(’slab.xyz’)
If the file contains several configurations, the default behavior of the write() function is to return the last
configuration. However, we can load a specific configuration by doing:
read(’slab.traj’)
read(’slab.traj’, -1)
read(’slab.traj’, 0)
# last configuration
# same as above
# first configuration
Visualization
The simplest way to visualize the atoms is the view() function:
from ase.visualize import view
view(slab)
This will pop up a ase.gui window. Alternative viewers can be used by specifying the optional keyword
viewer=... - use one of �ase.gui’, �gopenmol’, �vmd’, or �rasmol’. (Note that these alternative viewers are not
a part of ASE and will need to be installed by the user separately.) The VMD viewer can take an optional data
argument to show 3D data:
view(slab, viewer=’VMD’, data=array)
Molecular dynamics
Let us look at the nitrogen molecule as an example of molecular dynamics with the VelocityVerlet algorithm. We first create the VelocityVerlet object giving it the molecule and the time step for the integration
of Newton’s law. We then perform the dynamics by calling its run() method and giving it the number of steps
to take:
from ase.md.verlet import VelocityVerlet
from ase import units
dyn = VelocityVerlet(molecule, dt=1.0 * units.fs)
for i in range(10):
pot = molecule.get_potential_energy()
kin = molecule.get_kinetic_energy()
print ’%2d: %.5f eV, %.5f eV, %.5f eV’ % (i, pot + kin, pot, kin)
dyn.run(steps=20)
6.2. ASE
23
ASE Manual, Release 3.9.0.3865
6.2.2 Manipulating atoms
XXX rewrite this: use fcc111() function and do some relaxation ...
We will set up a one layer slab of Ni atoms with one Ag adatom.
Define the slab atoms:
>>> from ase import Atoms
>>> atoms = Atoms(’Ni4’, [(0, 0, 0),
...
(0.45, 0, 0),
...
(0, 0.5, 0),
...
(0.5, 0.5, 0)])
Have a look at the individual atoms:
>>> atoms[0]
Atom(’Ni’, [0.0, 0.0, 0.0], atoms=..., index=0)
>>> atoms[1]
Atom(’Ni’, [0.45, 0.0, 0.0], atoms=..., index=1)
>>> atoms[2]
Atom(’Ni’, [0.0, 0.5, 0.0], atoms=..., index=2)
>>> atoms[3]
Atom(’Ni’, [0.5, 0.5, 0.0], atoms=..., index=3)
Let us assume we forgot how many atoms we set up:
>>> atoms[4]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IndexError: list index out of range
Wrong because we only have four atoms
>>> len(atoms)
4
Change the position of the 2nd atom in the list
>>> atoms[1].x = 0.5
>>> atoms.get_positions()
array([[ 0. , 0. , 0. ],
[ 0.5, 0. , 0. ],
[ 0. , 0.5, 0. ],
[ 0.5, 0.5, 0. ]])
What is the unit cell so far?
>>> atoms.get_cell()
array([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
Now, setup a p(2x2) cell in a hexagonal surface. Here, a is the fcc lattice constant, the cell is 10 layers high:
>>> from numpy import sqrt
>>> a = 3.55
>>> cell = [(2/sqrt(2.)*a, 0, 0),
...
(1/sqrt(2.)*a, sqrt(3./2.)*a, 0),
...
(0, 0, 10*sqrt(3.)/3.*a)]
>>> cell
[(5.0204581464244864, 0, 0),
(2.5102290732122432, 4.3478442934401409, 0),
(0, 0, 20.495934556231713)]
>>> atoms.set_cell(cell, scale_atoms=True)
24
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
The argument scale_atoms=True indicates that the atomic positions should be scaled with the unit cell. The
default is scale_atoms=False indicating that the cartesian coordinates remain the same when the cell is changed.
>>> atoms.get_positions()
array([[ 0.
, 0.
,
[ 2.51022907, 0.
,
[ 1.25511454, 2.17392215,
[ 3.76534361, 2.17392215,
0.
0.
0.
0.
],
],
],
]])
Plot the whole system by bringing up the ase.gui:
>>> from ase.visualize import view
>>> view(atoms)
Within the viewer (called ase-gui) it is possible to repeat the unit cell in all three directions (using the Repeat
в†’ View window).
We now add an adatom. Since the supercell is now declared as the unit cell for our atoms we can either add the
atom using its cartesian coordinates in Angstrom or rescale the unit cell and use scaled coordinates. We try the
latter:
>>>
>>>
>>>
>>>
>>>
>>>
from numpy import identity
from ase import Atom
xyzcell = identity(3) # The 3x3 unit matrix
atoms.set_cell(xyzcell, scale_atoms=True) # Set the unit cell and rescale
atoms.append(Atom(’Ni’, (1/6., 1/6., .1)))
atoms.set_cell(cell, scale_atoms=True) # Set the unit cell and scale back
The structure now looks like this:
6.2. ASE
25
ASE Manual, Release 3.9.0.3865
>>> view(atoms)
6.2.3 Atomization energy
The following script will calculate the atomization energy of a nitrogen molecule:
from ase import Atoms
from ase.calculators.emt import EMT
atom = Atoms(’N’, calculator=EMT())
e_atom = atom.get_potential_energy()
d = 1.1
molecule = Atoms(’2N’, [(0., 0., 0.), (0., 0., d)])
molecule.set_calculator(EMT())
e_molecule = molecule.get_potential_energy()
e_atomization = e_molecule - 2 * e_atom
print ’Nitrogen atom energy: %5.2f eV’ %e_atom
print ’Nitrogen molecule energy: %5.2f eV’ %e_molecule
print ’Atomization energy: %5.2f eV’ %-e_atomization
First, an Atoms object containing one nitrogen is created and a fast EMT calculator is attached to it simply as an
argument. The total energy for the isolated atom is then calculated and stored in the e_atom variable.
The molecule object is defined, holding the nitrogen molecule at the experimental bond length. The EMT
calculator is then attached to the molecule and the total energy is extracted into the e_molecule variable.
Running the script will produce the output:
Nitrogen atom energy: 4.97 eV
Nitrogen molecule energy: 0.04 eV
Atomization energy: 9.90 eV
6.2.4 Finding lattice constants
See Also:
Equation of state.
HCP
Let’s try to find the a and c lattice constants for HCP nickel using the EMT potential.
First, we make a good initial guess for a and c using the FCC nearest neighbor distance and the ideal c/a ratio:
import numpy as np
a0 = 3.52 / np.sqrt(2)
c0 = np.sqrt(8 / 3.0) * a0
26
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
and create a trajectory for the results:
from ase.io import PickleTrajectory
traj = PickleTrajectory(’Ni.traj’, ’w’)
Finally, we do the 9 calculations (three values for a and three for c):
from ase.lattice import bulk
from ase.calculators.emt import EMT
eps = 0.01
for a in a0 * np.linspace(1 - eps, 1 + eps, 3):
for c in c0 * np.linspace(1 - eps, 1 + eps, 3):
ni = bulk(’Ni’, ’hcp’, a=a, c=c)
ni.set_calculator(EMT())
ni.get_potential_energy()
traj.write(ni)
Analysis
Now, we need to extract the data from the trajectory. Try this:
>>> from ase.lattice import bulk
>>> ni = bulk(’Ni’, ’hcp’, a=2.5, c=4.0)
>>> ni.cell
array([[ 2.5
, 0.
, 0.
[-1.25
, 2.16506351, 0.
[ 0.
, 0.
, 4.
],
],
]])
So, we can get a and c from ni.cell[0, 0] and ni.cell[2, 2]:
from ase.io import read
configs = read(’Ni.traj@:’)
energies = [config.get_potential_energy() for config in configs]
a = np.array([config.cell[0, 0] for config in configs])
c = np.array([config.cell[2, 2] for config in configs])
We fit the energy to this expression:
p0 + p1 a + p2 c + p3 a2 + p4 ac + p5 c2
The best fit is found like this:
functions = np.array([a**0, a, c, a**2, a * c, c**2])
p = np.linalg.lstsq(functions.T, energies)[0]
and we can find the minimum like this:
p0 = p[0]
p1 = p[1:3]
p2 = np.array([(2 * p[3], p[4]),
(p[4], 2 * p[5])])
a0, c0 = np.linalg.solve(p2.T, -p1)
Results:
a
2.466
c
4.023
Using the stress tensor
One can also use the stress tensor to optimize the unit cell:
6.2. ASE
27
ASE Manual, Release 3.9.0.3865
from ase.optimize import BFGS
from ase.constraints import StrainFilter
sf = StrainFilter(ni)
opt = BFGS(sf)
opt.run(0.005)
If you want the optimization path in a trajectory, add these lines before calling the run() method:
traj = PickleTrajectory(’path.traj’, ’w’, ni)
opt.attach(traj)
6.2.5 Equation of state
First, do a bulk calculation for different lattice constants:
import numpy as np
from ase import Atoms
from ase.io.trajectory import PickleTrajectory
from ase.calculators.emt import EMT
a = 4.0 # approximate lattice constant
b = a / 2
ag = Atoms(’Ag’,
cell=[(0,b,b), (b,0,b), (b,b,0)],
pbc=1,
calculator=EMT()) # use EMT potential
cell = ag.get_cell()
traj = PickleTrajectory(’Ag.traj’, ’w’)
for x in np.linspace(0.95, 1.05, 5):
ag.set_cell(cell * x, scale_atoms=True)
traj.write(ag)
This will write a trajectory file containing five configurations of FCC silver for five different lattice constans. Now,
analyse the result with the EquationOfState class and this script:
from ase.io import read
from ase.units import kJ
from ase.utils.eos import EquationOfState
configs = read(’Ag.traj@0:5’) # read 5 configurations
# Extract volumes and energies:
volumes = [ag.get_volume() for ag in configs]
energies = [ag.get_potential_energy() for ag in configs]
eos = EquationOfState(volumes, energies)
v0, e0, B = eos.fit()
print B / kJ * 1.0e24, ’GPa’
eos.plot(’Ag-eos.png’)
28
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
A quicker way to do this analysis, is to use the ase.gui tool:
$ ase-gui Ag.traj
And then choose Tools в†’ Bulk modulus.
6.2.6 Using the spacegroup subpackage
The most evident usage of the spacegroup subpackage is to set up an initial unit of a bulk structure. For this you
only need to supply the unique atoms and their scaled positions, space group and lattice parameters.
Examples of setting up bulk structures
We start by showing some examples of how to set up some common or interesting bulk structures using
ase.lattice.spacegroup.crystal(). This function takes a lot of arguments, of which the most important are:
symbols [string | sequence of strings] Either a string formula or sequence of element symbols. E.g.
�NaCl’ and (�Na’, �Cl’) are equivalent.
basis [list of scaled coordinates] Coordinates of the non-equivalent sites in units of the lattice vectors.
spacegroup [int | string | Spacegroup instance] Space group given either as its number in International Tables or as its Hermann-Mauguin (or international) symbol.
setting [1 | 2] Space group setting.
cellpar [[a, b, c, alpha, beta, gamma]] Cell parameters with angles in degree. Is not used when cell
is given.
6.2. ASE
29
ASE Manual, Release 3.9.0.3865
Aluminium (fcc)
from ase.lattice.spacegroup import crystal
a = 4.05
al = crystal(’Al’, [(0,0,0)], spacegroup=225, cellpar=[a, a, a, 90, 90, 90])
The spacegroup argument can also be entered with its Hermann-Mauguin symbol, e.g. spacegroup=225 is equivalent to spacegroup=’F m -3 m’.
Iron (bcc)
from ase.lattice.spacegroup import crystal
a = 2.87
fe = crystal(’Fe’, [(0,0,0)], spacegroup=229, cellpar=[a, a, a, 90, 90, 90])
Magnesium (hcp)
from ase.lattice.spacegroup import crystal
a = 3.21
c = 5.21
mg = crystal(’Mg’, [(1./3., 2./3., 3./4.)], spacegroup=194,
cellpar=[a, a, c, 90, 90, 120])
Diamond
30
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
from ase.lattice.spacegroup import crystal
a = 3.57
diamond = crystal(’C’, [(0,0,0)], spacegroup=227, cellpar=[a, a, a, 90, 90, 90])
Sodium chloride
from ase.lattice.spacegroup import crystal
a = 5.64
nacl = crystal([’Na’, ’Cl’], [(0, 0, 0), (0.5, 0.5, 0.5)], spacegroup=225,
cellpar=[a, a, a, 90, 90, 90])
Rutile
from ase.lattice.spacegroup import crystal
a = 4.6
c = 2.95
rutile =crystal([’Ti’, ’O’], basis=[(0, 0, 0), (0.3, 0.3, 0.0)],
spacegroup=136, cellpar=[a, a, c, 90, 90, 90])
6.2. ASE
31
ASE Manual, Release 3.9.0.3865
CoSb3 skutterudite
Skutterudites are quite interesting structures with 32 atoms in the unit cell.
from ase.lattice.spacegroup import crystal
a = 9.04
skutterudite = crystal((’Co’, ’Sb’),
basis=[(0.25,0.25,0.25), (0.0, 0.335, 0.158)],
spacegroup=204,
cellpar=[a, a, a, 90, 90, 90])
#ase.view(skutterudite)
Often this structure is visualised with the Cobalt atoms on the corners. This can easily be accomplished with
ASE using ase.utils.geometry.cut(). Below is the origo argument used to put the Cobalt atom on the
corners and extend to include all corner and edge atoms, even those belonging to neighbouring unit cells.
32
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
import numpy as np
import ase.utils.geometry as geometry
import ase.io as io
# Create a new atoms instance with Co at origo including all atoms on the
# surface of the unit cell
cosb3 = geometry.cut(skutterudite, origo=(0.25, 0.25, 0.25), extend=1.01)
# Define the atomic bonds to show
bondatoms = []
symbols = cosb3.get_chemical_symbols()
for i in xrange(len(cosb3)):
for j in xrange(i):
if (symbols[i] == symbols[j] == ’Co’ and
cosb3.get_distance(i, j) < 4.53):
bondatoms.append((i, j))
elif (symbols[i] == symbols[j] == ’Sb’ and
cosb3.get_distance(i, j) < 2.99):
bondatoms.append((i, j))
# Create nice-looking image using povray
io.write(’spacegroup-cosb3.pov’, cosb3,
transparent=False,
display=False,
run_povray=True,
camera_type=’perspective’,
canvas_width=320,
radii=0.4,
rotation=’90y’,
bondlinewidth=0.07,
bondatoms=bondatoms,
)
6.2. ASE
33
ASE Manual, Release 3.9.0.3865
The Spacegroup class
The
ase.lattice.spacegroup.Spacegroup
class
is
used
internally
by
the
ase.lattice.spacegroup.crystal() function, but might sometimes also be useful if
you want to know e.g.
the symmetry operations of a given space group.
Instances of the
ase.lattice.spacegroup.Spacegroup class are immutable objects holding space group information, such as symmetry operations.
Let us e.g. consider the fcc structure. To print information about the space group, do
from ase.lattice.spacegroup import Spacegroup
sg = Spacegroup(225)
’Space group:’, sg.no, sg.symbol
’Primitive cell:\n’, sg.scaled_primitive_cell
’Reciprocal cell:\n’, sg.scaled_reciprocal_cell
’Lattice type:’, sg.lattice
’Lattice sub-translations’, sg.subtrans
’Centerosymmetric’, sg.centerosymmetric
’Rotation matrices (not including inversions)\n’, sg.rotations
’Translation vectors (not including inversions)\n’, sg.translations
print
print
print
print
print
print
print
print
or simply
print sg
Or, if you want to figure out what sites in the unit cell are equivalent to (0, 0, 0.5), simply do
sites,kinds = sg.equivalent_sites([(0, 0, 0.5)])
where sites will be an array containing the scaled positions of the four symmetry-equivalent sites.
6.2.7 Dissociation tutorial
from
from
from
from
from
ase import Atoms
ase.calculators.emt import EMT
ase.constraints import FixAtoms
ase.optimize import QuasiNewton
ase.io import write
# Find the initial and final states for the reaction.
# Set up a (3 x 3) two layer slab of Ru:
a = 2.70
c = 1.59 * a
sqrt3 = 3. ** .5
bulk = Atoms(’2Cu’, [(0., 0., 0.), (1./3, 1./3, -0.5*c)],
tags=(1, 1),
pbc=(1, 1, 0))
bulk.set_cell([(a,
0,
0),
(a / 2, sqrt3 * a / 2, 0),
(0,
0,
1)])
slab = bulk.repeat((4, 4, 1))
#
#
x
y
z
d
Initial state.
Add the molecule:
= a / 2.
= a * 3. ** .5 / 6.
= 1.8
= 1.10 # N2 bond length
34
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
# Molecular state parallel to the surface:
slab += Atoms(’2N’, [(x, y, z), (x + sqrt3 * d / 2, y + d / 2, z)])
# Use the EMT calculator for the forces and energies:
slab.set_calculator(EMT())
# We don’t want to worry about the Cu degrees of freedom:
mask = [atom.symbol == ’Cu’ for atom in slab]
slab.set_constraint(FixAtoms(mask=mask))
relax = QuasiNewton(slab)
relax.run(fmax=0.05)
print ’initial state:’, slab.get_potential_energy()
write(’N2.traj’, slab)
# Now the final state.
# Move the second N atom to a neighboring hollow site:
slab[-1].position = (x + a, y, z)
relax.run()
print ’final state: ’, slab.get_potential_energy()
write(’2N.traj’, slab)
import numpy as np
from
from
from
from
from
ase.io import read
ase.constraints import FixAtoms
ase.calculators.emt import EMT
ase.neb import NEB
ase.optimize.fire import FIRE as QuasiNewton
initial = read(’N2.traj’)
final = read(’2N.traj’)
configs = [initial.copy() for i in range(8)] + [final]
constraint = FixAtoms(mask=[atom.symbol != ’N’ for atom in initial])
for config in configs:
config.set_calculator(EMT())
config.set_constraint(constraint)
band = NEB(configs)
band.interpolate()
# Create a quickmin object:
relax = QuasiNewton(band)
relax.run(steps=20)
e0 = initial.get_potential_energy()
for config in configs:
d = config[-2].position - config[-1].position
print np.linalg.norm(d), config.get_potential_energy() - e0
6.2.8 Diffusion of gold atom on Al(100) surface (NEB)
First, set up the initial and final states:
6.2. ASE
35
ASE Manual, Release 3.9.0.3865
from
from
from
from
ase.lattice.surface import fcc100, add_adsorbate
ase.constraints import FixAtoms
ase.calculators.emt import EMT
ase.optimize import QuasiNewton
# 2x2-Al(001) surface with 3 layers and an
# Au atom adsorbed in a hollow site:
slab = fcc100(’Al’, size=(2, 2, 3))
add_adsorbate(slab, ’Au’, 1.7, ’hollow’)
slab.center(axis=2, vacuum=4.0)
# Make sure the structure is correct:
#view(slab)
# Fix second and third layers:
mask = [atom.tag > 1 for atom in slab]
#print mask
slab.set_constraint(FixAtoms(mask=mask))
# Use EMT potential:
slab.set_calculator(EMT())
# Initial state:
qn = QuasiNewton(slab, trajectory=’initial.traj’)
qn.run(fmax=0.05)
# Final state:
slab[-1].x += slab.get_cell()[0, 0] / 2
qn = QuasiNewton(slab, trajectory=’final.traj’)
qn.run(fmax=0.05)
Note: Notice how the tags are used to select the constrained atoms
Now, do the NEB calculation:
from
from
from
from
from
ase.io import read
ase.constraints import FixAtoms
ase.calculators.emt import EMT
ase.neb import NEB
ase.optimize import BFGS
initial = read(’initial.traj’)
final = read(’final.traj’)
36
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
constraint = FixAtoms(mask=[atom.tag > 1 for atom in initial])
images = [initial]
for i in range(3):
image = initial.copy()
image.set_calculator(EMT())
image.set_constraint(constraint)
images.append(image)
images.append(final)
neb = NEB(images)
neb.interpolate()
qn = BFGS(neb, trajectory=’neb.traj’)
qn.run(fmax=0.05)
Visualize the results with:
ase-gui neb.traj
and select Tools->NEB.
Note: For this reaction, the reaction coordinate is very simple: The x-coordinate of the Au atom. In such cases,
the NEB method is overkill, and a simple constraint method should be used like in this tutorial: Diffusion of gold
atom on Al(100) surface (constraint).
See Also:
• ase.neb
• ase.constraints
• Diffusion of gold atom on Al(100) surface (constraint)
• fcc100()
Parallelizing over images with MPI
Instead of having one process do the calculations for all three internal images in turn, it will be faster to have
three processes do one image each. In order to be able to run python with MPI you need a special parallel python
interpreter, for example gpaw-python.
6.2. ASE
37
ASE Manual, Release 3.9.0.3865
The example below can then be run with mpiexec в€’ np3gpaw в€’ pythondif f usion3.py:
from
from
from
from
from
from
from
ase.io import read
ase.constraints import FixAtoms
ase.calculators.emt import EMT
ase.neb import NEB
ase.optimize import BFGS
ase.io.trajectory import PickleTrajectory
ase.parallel import rank, size
initial = read(’initial.traj’)
final = read(’final.traj’)
constraint = FixAtoms(mask=[atom.tag > 1 for atom in initial])
images = [initial]
j = rank * 3 // size # my image number
for i in range(3):
image = initial.copy()
if i == j:
image.set_calculator(EMT())
image.set_constraint(constraint)
images.append(image)
images.append(final)
neb = NEB(images, parallel=True)
neb.interpolate()
qn = BFGS(neb)
if rank % (size // 3) == 0:
traj = PickleTrajectory(’neb%d.traj’ % j, ’w’, images[1 + j], master=True)
qn.attach(traj)
qn.run(fmax=0.05)
6.2.9 Diffusion of gold atom on Al(100) surface (constraint)
In this tutorial, we will calculate the energy barrier that was found using the NEB method in the Diffusion of gold
atom on Al(100) surface (NEB) tutorial. Here, we use a simple FixedPlane constraint that forces the Au atom
to relax in the yz-plane only:
from
from
from
from
ase.lattice.surface import fcc100, add_adsorbate
ase.constraints import FixAtoms, FixedPlane
ase.calculators.emt import EMT
ase.optimize import QuasiNewton
# 2x2-Al(001) surface with 3 layers and an
# Au atom adsorbed in a hollow site:
slab = fcc100(’Al’, size=(2, 2, 3))
add_adsorbate(slab, ’Au’, 1.7, ’hollow’)
slab.center(axis=2, vacuum=4.0)
# Make sure the structure is correct:
#from ase.visualize import view
#view(slab)
# Fix second and third layers:
mask = [atom.tag > 1 for atom in slab]
#print mask
fixlayers = FixAtoms(mask=mask)
# Constrain the last atom (Au atom) to move only in the yz-plane:
plane = FixedPlane(-1, (1, 0, 0))
38
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
slab.set_constraint([fixlayers, plane])
# Use EMT potential:
slab.set_calculator(EMT())
for i in range(5):
qn = QuasiNewton(slab, trajectory=’mep%d.traj’ % i)
qn.run(fmax=0.05)
# Move gold atom along x-axis:
slab[-1].x += slab.get_cell()[0, 0] / 8
The result can be analysed with the command ase-gui mep?.traj -n -1 (choose Tools в†’ NEB). The barrier is
found to be 0.35 eV - exactly as in the NEB tutorial.
Here is a side-view of the path (unit cell repeated twice):
See Also:
• ase.neb
• ase.constraints
• Diffusion of gold atom on Al(100) surface (NEB)
• fcc100()
6.2.10 Molecular dynamics
Note: These examples can be used without Asap installed, then the ase.EMT calculator (implemented in Python)
is used, but nearly superhuman patience is required.
Here we demonstrate now simple molecular dynamics is performed. A crystal is set up, the atoms are given
momenta corresponding to a temperature of 300K, then Newtons second law is integrated numerically with a time
step of 5 fs (a good choice for copper).
"Demonstrates molecular dynamics with constant energy."
from
from
from
from
from
ase.calculators.emt import EMT
ase.lattice.cubic import FaceCenteredCubic
ase.md.velocitydistribution import MaxwellBoltzmannDistribution
ase.md.verlet import VelocityVerlet
ase import units
6.2. ASE
39
ASE Manual, Release 3.9.0.3865
# Use Asap for a huge performance increase if it is installed
useAsap = False
if useAsap:
from asap3 import EMT
size = 10
else:
size = 3
# Set up a crystal
atoms = FaceCenteredCubic(directions=[[1,0,0],[0,1,0],[0,0,1]], symbol="Cu",
size=(size,size,size), pbc=True)
# Describe the interatomic interactions with the Effective Medium Theory
atoms.set_calculator(EMT())
# Set the momenta corresponding to T=300K
MaxwellBoltzmannDistribution(atoms, 300*units.kB)
# We want to run MD with constant energy using the VelocityVerlet algorithm.
dyn = VelocityVerlet(atoms, 5*units.fs) # 5 fs time step.
#Function to print the potential, kinetic and total energy
def printenergy(a):
epot = a.get_potential_energy() / len(a)
ekin = a.get_kinetic_energy() / len(a)
print ("Energy per atom: Epot = %.3feV Ekin = %.3feV (T=%3.0fK)
(epot, ekin, ekin/(1.5*units.kB), epot+ekin))
Etot = %.3feV" %
# Now run the dynamics
printenergy(atoms)
for i in range(20):
dyn.run(10)
printenergy(atoms)
Note how the total energy is conserved, but the kinetic energy quickly drops to half the expected value. Why?
Instead of printing within a loop, it is possible to use an “observer” to observe the atoms and do the printing (or
more sophisticated analysis).
"Demonstrates molecular dynamics with constant energy."
from
from
from
from
from
ase.calculators.emt import EMT
ase.lattice.cubic import FaceCenteredCubic
ase.md.velocitydistribution import MaxwellBoltzmannDistribution
ase.md.verlet import VelocityVerlet
ase import units
# Use Asap for a huge performance increase if it is installed
useAsap = True
if useAsap:
from asap3 import EMT
size = 10
else:
size = 3
# Set up a crystal
atoms = FaceCenteredCubic(directions=[[1,0,0],[0,1,0],[0,0,1]], symbol="Cu",
size=(size,size,size), pbc=True)
# Describe the interatomic interactions with the Effective Medium Theory
atoms.set_calculator(EMT())
40
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
# Set the momenta corresponding to T=300K
MaxwellBoltzmannDistribution(atoms, 300*units.kB)
# We want to run MD with constant energy using the VelocityVerlet algorithm.
dyn = VelocityVerlet(atoms, 5*units.fs) # 5 fs time step.
#Function to print the potential, kinetic and total energy.
def printenergy(a=atoms):
#store a reference to atoms in the definition.
epot = a.get_potential_energy() / len(a)
ekin = a.get_kinetic_energy() / len(a)
print ("Energy per atom: Epot = %.3feV Ekin = %.3feV (T=%3.0fK) Etot = %.3feV" %
(epot, ekin, ekin/(1.5*units.kB), epot+ekin))
# Now run the dynamics
dyn.attach(printenergy, interval=10)
printenergy()
dyn.run(200)
Constant temperature MD
Often, you want to control the temperature of an MD simulation. This can be done with the Langevin dynamics
module. In the previous examples, replace the line dyn = VelocityVerlet(...) with:
dyn = Langevin(atoms, 5*units.fs, T*units.kB, 0.002)
where T is the desired temperature in Kelvin. You also need to import Langevin, see the class below.
The Langevin dynamics will then slowly adjust the total energy of the system so the temperature approaches the
desired one.
As a slightly less boring example, let us use this to melt a chunk of copper by starting the simulation without any
momentum of the atoms (no kinetic energy), and with a desired temperature above the melting point. We will also
save information about the atoms in a trajectory file called moldyn3.traj.
"Demonstrates molecular dynamics with constant energy."
from
from
from
from
from
ase.calculators.emt import EMT
ase.lattice.cubic import FaceCenteredCubic
ase.md.langevin import Langevin
ase.io.trajectory import PickleTrajectory
ase import units
from asap3 import EMT
size = 10
# Way too slow with ase.EMT !
T = 1500 # Kelvin
# Set up a crystal
atoms = FaceCenteredCubic(directions=[[1,0,0],[0,1,0],[0,0,1]], symbol="Cu",
size=(size,size,size), pbc=False)
# Describe the interatomic interactions with the Effective Medium Theory
atoms.set_calculator(EMT())
# We want to run MD with constant energy using the Langevin algorithm
# with a time step of 5 fs, the temperature T and the friction
# coefficient to 0.02 atomic units.
dyn = Langevin(atoms, 5*units.fs, T*units.kB, 0.002)
#Function to print the potential, kinetic and total energy.
def printenergy(a=atoms):
#store a reference to atoms in the definition.
epot = a.get_potential_energy() / len(a)
6.2. ASE
41
ASE Manual, Release 3.9.0.3865
ekin = a.get_kinetic_energy() / len(a)
print ("Energy per atom: Epot = %.3feV Ekin = %.3feV (T=%3.0fK)
(epot, ekin, ekin/(1.5*units.kB), epot+ekin))
dyn.attach(printenergy, interval=50)
Etot = %.3feV" %
#We also want to save the positions of all atoms after every 100th time step.
traj = PickleTrajectory("moldyn3.traj", ’w’, atoms)
dyn.attach(traj.write, interval=50)
# Now run the dynamics
printenergy()
dyn.run(5000)
After running the simulation, you can study the result with the command
ase-gui moldyn3.traj
Try plotting the kinetic energy. You will not see a well-defined melting point due to finite size effects (including
surface melting), but you will probably see an almost flat region where the inside of the system melts. The
outermost layers melt at a lower temperature.
Note: The Langevin dynamics will by default keep the position and momentum of the center of mass unperturbed.
This is another improvement over just setting momenta corresponding to a temperature, as we did before.
Isolated particle MD
When simulating isolated particles with MD, it is sometimes preferable to set random momenta corresponding to
a specific temperature and let the system evolve freely. With a relatively high temperature, the is however a risk
that the collection of atoms will drift out of the simulation box because the randomized momenta gave the center
of mass a small but non-zero velocity too.
Let us see what happens when we propagate a nanoparticle for a long time:
"Demonstrates molecular dynamics for isolated particles."
ase.calculators.emt import EMT
ase.cluster.cubic import FaceCenteredCubic
ase.optimize import QuasiNewton
ase.md.velocitydistribution import MaxwellBoltzmannDistribution, \
Stationary, ZeroRotation
from ase.md.verlet import VelocityVerlet
from ase import units
from
from
from
from
# Use Asap for a huge performance increase if it is installed
useAsap = True
if useAsap:
from asap3 import EMT
size = 4
else:
size = 2
# Set up a nanoparticle
atoms = FaceCenteredCubic(’Cu’, surfaces=[[1,0,0],[1,1,0],[1,1,1]],
layers=(size,size,size), vacuum=4)
# Describe the interatomic interactions with the Effective Medium Theory
atoms.set_calculator(EMT())
# Do a quick relaxation of the cluster
qn = QuasiNewton(atoms)
42
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
qn.run(0.001, 10)
# Set the momenta corresponding to T=1200K
MaxwellBoltzmannDistribution(atoms, 1200*units.kB)
Stationary(atoms) # zero linear momentum
ZeroRotation(atoms) # zero angular momentum
# We want to run MD using the VelocityVerlet algorithm.
dyn = VelocityVerlet(atoms, 5*units.fs, trajectory=’moldyn4.traj’) # save trajectory.
#Function to print the potential, kinetic and total energy.
def printenergy(a=atoms):
#store a reference to atoms in the definition.
epot = a.get_potential_energy() / len(a)
ekin = a.get_kinetic_energy() / len(a)
print ("Energy per atom: Epot = %.3feV Ekin = %.3feV (T=%3.0fK) Etot = %.3feV" %
(epot, ekin, ekin/(1.5*units.kB), epot+ekin))
dyn.attach(printenergy, interval=10)
# Now run the dynamics
printenergy()
dyn.run(2000)
After running the simulation, use ase-gui to compare the results with how it looks if you comment out either the
line that says Stationary(atoms), ZeroRotation(atoms) or both.
ase-gui moldyn4.traj
Try playing the movie with a high frame rate and set frame skipping to a low number. Can you spot the subtle
difference?
6.2.11 Partly occupied Wannier Functions
from ase.structure import molecule
from gpaw import GPAW
atoms = molecule(’C6H6’)
atoms.center(vacuum=3.5)
calc = GPAW(h=.21, xc=’PBE’, txt=’benzene.txt’, nbands=18)
atoms.set_calculator(calc)
atoms.get_potential_energy()
calc.set(fixdensity=True, txt=’benzene-harris.txt’,
nbands=40, eigensolver=’cg’, convergence={’bands’: 35})
atoms.get_potential_energy()
calc.write(’benzene.gpw’, mode=’all’)
from gpaw import restart
from ase.dft import Wannier
atoms, calc = restart(’benzene.gpw’, txt=None)
# Make wannier functions of occupied space only
wan = Wannier(nwannier=15, calc=calc)
wan.localize()
for i in range(wan.nwannier):
wan.write_cube(i, ’benzene15_%i.cube’ % i)
# Make wannier functions using (three) extra degrees of freedom.
wan = Wannier(nwannier=18, calc=calc, fixedstates=15)
6.2. ASE
43
ASE Manual, Release 3.9.0.3865
wan.localize()
wan.save(’wan18.pickle’)
for i in range(wan.nwannier):
wan.write_cube(i, ’benzene18_%i.cube’ % i)
from ase.dft import Wannier
from gpaw import restart
atoms, calc = restart(’benzene.gpw’, txt=None)
wan = Wannier(nwannier=18, calc=calc, fixedstates=15, file=’wan18.pickle’)
import pylab as pl
weight_n = pl.sum(abs(wan.V_knw[0])**2, 1)
N = len(weight_n)
F = wan.fixedstates_k[0]
pl.figure(1, figsize=(12, 4))
pl.bar(range(1, N+1), weight_n, width=0.65, bottom=0,
color=’k’, edgecolor=’k’, linewidth=None,
align=’center’, orientation=’vertical’)
pl.plot([F+.5, F+.5], [0, 1], ’k--’)
pl.axis(xmin=.32, xmax=N+1.33, ymin=0, ymax=1)
pl.xlabel(’Eigenstate’)
pl.ylabel(’Projection of wannier functions’)
pl.savefig(’spectral_weight.png’)
pl.show()
import numpy as np
from ase import Atoms
from ase.dft.kpoints import monkhorst_pack
from gpaw import GPAW
kpts = monkhorst_pack((13, 1, 1)) + [1e-5, 0, 0]
calc = GPAW(h=.21, xc=’PBE’, kpts=kpts, nbands=12, txt=’poly.txt’,
eigensolver=’cg’, convergence={’bands’: 9})
CC = 1.38
CH = 1.094
a = 2.45
x = a / 2.
y = np.sqrt(CC**2 - x**2)
atoms = Atoms(’C2H2’, pbc=(True, False, False), cell=(a, 8., 6.),
calculator=calc, positions=[[0,
0, 0],
[x,
y, 0],
[x, y+CH, 0],
[0, -CH, 0]])
atoms.center()
atoms.get_potential_energy()
calc.write(’poly.gpw’, mode=’all’)
import numpy as np
from ase.dft import Wannier
from gpaw import restart
atoms, calc = restart(’poly.gpw’, txt=None)
# Make wannier functions using (one) extra degree of freedom
wan = Wannier(nwannier=6, calc=calc, fixedenergy=1.5)
wan.localize()
wan.save(’poly.pickle’)
wan.translate_all_to_cell((2, 0, 0))
for i in range(wan.nwannier):
44
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
wan.write_cube(i, ’polyacetylene_%i.cube’ % i)
# Print Kohn-Sham bandstructure
ef = calc.get_fermi_level()
f = open(’KSbands.txt’, ’w’)
for k, kpt_c in enumerate(calc.get_ibz_k_points()):
for eps in calc.get_eigenvalues(kpt=k):
print >> f, kpt_c[0], eps - ef
# Print Wannier bandstructure
f = open(’WANbands.txt’, ’w’)
for k in np.linspace(-.5, .5, 100):
for eps in np.linalg.eigvalsh(wan.get_hamiltonian_kpoint([k, 0, 0])).real:
print >> f, k, eps - ef
import pylab as pl
fig = pl.figure(1, dpi=80, figsize=(4.2, 6))
fig.subplots_adjust(left=.16, right=.97, top=.97, bottom=.05)
# Plot KS bands
k, eps = pl.load(’KSbands.txt’, unpack=True)
pl.plot(k, eps, ’ro’, label=’DFT’, ms=9)
# Plot Wannier bands
k, eps = pl.load(’WANbands.txt’, unpack=True)
pl.plot(k, eps, ’k.’, label=’Wannier’)
pl.plot([-.5, .5], [1, 1], ’k:’, label=’_nolegend_’)
pl.text(-.5, 1, ’fixedenergy’, ha=’left’, va=’bottom’)
pl.axis(’tight’)
pl.xticks([-.5, -.25, 0, .25, .5],
[ r’$X$’, r’$\Delta$’, r’$\Gamma$’, r’$\Delta$’, r’$X$’], size=16)
pl.ylabel(r’$E - E_F\ \rm{(eV)}$’, size=16)
pl.legend()
pl.savefig(’bands.png’, dpi=80)
pl.show()
6.2.12 Constrained minima hopping (global optimization)
This is an example of a search for a global optimum geometric configuration using the minima hopping algorithm,
along with the Hookean class of constraints. This type of approach is useful in searching for the global optimum
position of adsorbates on a surface while enforcing that the adsorbates’ identity is preserved.
The below example looks at finding the optimum configuration of a Cu2 adsorbate on a fixed Pt (110) surface.
Although this is not a physically relevant simulation — these elements (Cu, Pt) were chosen only because they
work with the EMT calculator – one can imagine replacing the Cu2 adsorbate with CO, for example, to find
its optimum binding configuration under the constraint that the CO does not dissociate into separate C and O
adsorbates.
This also uses the Hookean constraint in two different ways. In the first, it constrains the Cu atoms to feel a
restorative force if their interatomic distance exceeds 2.6 Angstroms; this preserves the dimer character of the
Cu2 , and if they are near each other they feel no constraint. The second constrains one of the Cu atoms to feel
a downward force if its position exceeds a z coordinate of 15 Angstroms. Since the Cu atoms are tied together,
we don’t necessarily need to put such a force on both of the Cu atoms. This second constraint prevents the Cu2
adsorbate from flying off the surface, which would lead to it exploring a lot of irrelevant configurational space,
such as up in the vacuum or on the bottom of the next periodic slab.
from ase import Atoms, Atom
from ase.lattice.surface import fcc110
from ase.optimize.minimahopping import MinimaHopping
6.2. ASE
45
ASE Manual, Release 3.9.0.3865
from ase.calculators.emt import EMT
from ase.constraints import FixAtoms, Hookean
# Make the Pt 110 slab.
atoms = fcc110(’Pt’, (2, 2, 2), vacuum=7.)
# Add the Cu2 adsorbate.
adsorbate = Atoms([Atom(’Cu’, atoms[7].position + (0., 0., 2.5)),
Atom(’Cu’, atoms[7].position + (0., 0., 5.0))])
atoms.extend(adsorbate)
# Constrain the surface to be fixed and a Hookean constraint between
# the adsorbate atoms.
constraints = [FixAtoms(indices=[atom.index for atom in atoms if
atom.symbol==’Pt’]),
Hookean(a1=8, a2=9, rt=2.6, k=15.),
Hookean(a1=8, a2=(0., 0., 1., -15.), k=15.),]
atoms.set_constraint(constraints)
# Set the calculator.
calc = EMT()
atoms.set_calculator(calc)
# Instantiate and run the minima hopping algorithm.
hop = MinimaHopping(atoms,
Ediff0=2.5,
T0=4000.)
hop(totalsteps=10)
This script will produce 10 molecular dynamics and 11 optimization files. It will also produce a file called
�minima.traj’ which contains all of the accepted minima. You can look at the progress of the algorithm in the
file hop.log in combination with the trajectory files.
Alternatively, there is a utility to allow you to visualize the progress of the algorithm. You can run this from within
the same directory as your algorithm as:
from ase.optimize.minimahopping import MHPlot
mhplot = MHPlot()
mhplot.save_figure(’summary.png’)
This will make a summary figure, which should look something like the one below. As the search is inherently
random, yours will look different than this (and this will look different each time the documentation is rebuilt). In
this figure, you will see on the Epot axes the energy levels of the conformers found. The flat bars represent the
energy at the end of each local optimization step. The checkmark indicates the local minimum was accepted; red
arrows indicate it was rejected for the three possible reasons. The black path between steps is the potential energy
during the molecular dynamics (MD) portion of the step; the dashed line is the local optimization on termination
of the MD step. Note the y axis is broken to allow different energy scales between the local minima and the space
explored in the MD simulations. The T and Ediff plots show the values of the self-adjusting parameters as the
algorithm progresses.
46
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
You can see examples of the implementation of this for real adsorbates as well as find suitable parameters for the
Hookean constraints:
Andrew Peterson
Global optimization of adsorbate–surface structures while preserving molecular identity
Top. Catal., Vol. 57, 40 (2014)
6.2. ASE
47
ASE Manual, Release 3.9.0.3865
6.2.13 Optimization with a Genetic Algorithm
A genetic algorithm (GA) has been implemented for global structure optimization within ase. The optimizer
consists of its own module ase.ga which includes all classes needed for the optimizer.
Details about the implemented method is described in the supplemental material of
L. B. Vilhelmsen and B. Hammer
Systematic Study of Au6 to Au12 Gold Clusters on MgO(100) F Centers Using Density-Functional
Theory
Physical Review Letters, Vol. 108 (Mar 2012), 126101
and in the main text of
L. B. Vilhelmsen, K. S. Walton and D. S. Sholl
Structure and Mobility of Metal Clusters in MOFs: Au, Pd, and AuPd Clusters in MOF-74
Journal of the American Chemical Society, Vol. 134, No. 30, pp. 12807-12816
Any questions about how to use the GA can be asked at the mailing list.
A Brief Overview of the Implementation
The GA relies on the ase.db module for tracking which structures have been found. Before the GA optimization
starts the user therefore needs to prepare this database and appropriate folders. This is done trough an initialization
script as the one described in the next section. In this initialization the starting population is generated and added
to the database.
After initialization the main script is run. This script defines objects responsible for the different parts of the GA
and then creates and locally relaxes new candidates. It is up to the user to define when the main script should
terminate. An example of a main script is given in the next section. Notice that because of the persistent data
storage the main script can be executed multiple times to generate new candidates.
The GA implementation generally follows a responsibility driven approach. This means that each part of the GA
is isolated into individual classes making it possible to put together an optimizer satisfying the needs of a specific
optimization problem.
This tutorial will use the following parts of the GA:
• A population responsible for proposing new candidates to pair together.
• A paring operator which combines two candidates.
• A set of mutations.
• A comparator which determines if two structures are different.
• A starting population generator.
Each of the above components are described in the supplemental material of the first reference given above and
will not be discussed here. The example will instead focus on the technical aspect of executing the GA.
A Basic Example
The user needs to specify the following three properties about the structure that needs to be optimized.
• A list of atomic numbers for the structure to be optimized
• A super cell in which to do the optimization. If the structure to optimize resides on a surface or in a support
this supercell contains the atoms which should not be considered explicitly by the GA.
• A box defining the volume of the super cell in which to randomly distribute the starting population.
As an example we will find the structure of a Ag2 Au2 cluster on a Au(111) surface using the EMT optimizer.
The script doing all the initialisations should be run in the folder in which the GA optimisation is to take place.
The script looks as follows:
48
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
from ase.ga.data import PrepareDB
from ase.ga.startgenerator import StartGenerator
from ase.ga.utilities import closest_distances_generator
from ase.ga.utilities import get_all_atom_types
from ase.constraints import FixAtoms
import numpy as np
from ase.lattice.surface import fcc111
db_file = ’gadb.db’
# create the surface
slab = fcc111(’Au’, size=(4, 4, 1), vacuum=10.0, orthogonal=True)
slab.set_constraint(FixAtoms(mask=len(slab) * [True]))
# define the volume in which the adsorbed cluster is optimized
# the volume is defined by a corner position (p0)
# and three spanning vectors (v1, v2, v3)
pos = slab.get_positions()
cell = slab.get_cell()
p0 = np.array([0., 0., max(pos[:, 2]) + 2.])
v1 = cell[0, :] * 0.8
v2 = cell[1, :] * 0.8
v3 = cell[2, :]
v3[2] = 3.
# Define the composition of the atoms to optimize
atom_numbers = 2 * [47] + 2 * [79]
# define the closest distance two atoms of a given species can be to each other
unique_atom_types = get_all_atom_types(slab, atom_numbers)
cd = closest_distances_generator(atom_numbers=unique_atom_types,
ratio_of_covalent_radii=0.7)
# create the starting population
sg = StartGenerator(slab=slab,
atom_numbers=atom_numbers,
closest_allowed_distances=cd,
box_to_place_in=[p0, [v1, v2, v3]])
# generate the starting population
population_size = 20
starting_population = [sg.get_new_candidate() for i in xrange(population_size)]
# from ase.visualize import view
# view(starting_population)
# uncomment these lines
# to see the starting population
# create the database to store information in
d = PrepareDB(db_file_name=db_file,
simulation_cell=slab,
stoichiometry=atom_numbers,)
# population_size=population_size)
for a in starting_population:
d.add_unrelaxed_candidate(a)
Having initialized the GA optimization we now need to actually run the GA. The main script running the GA
consists of first an initialization part, and then a loop proposing new structures and locally optimizing them. The
main script can look as follows:
from
from
from
from
random import random
ase.io import write
ase.optimize import BFGS
ase.calculators.emt import EMT
6.2. ASE
49
ASE Manual, Release 3.9.0.3865
from
from
from
from
from
from
from
from
from
from
ase.ga.data import DataConnection
ase.ga.population import Population
ase.ga.standard_comparators import InteratomicDistanceComparator
ase.ga.cutandsplicepairing import CutAndSplicePairing
ase.ga.utilities import closest_distances_generator
ase.ga.utilities import get_all_atom_types
ase.ga.offspring_creator import OperationSelector
ase.ga.standardmutations import MirrorMutation
ase.ga.standardmutations import RattleMutation
ase.ga.standardmutations import PermutationMutation
# Change the following three parameters to suit your needs
population_size = 20
mutation_probability = 0.3
n_to_test = 20
# Initialize the different components of the GA
da = DataConnection(’gadb.db’)
atom_numbers_to_optimize = da.get_atom_numbers_to_optimize()
n_to_optimize = len(atom_numbers_to_optimize)
slab = da.get_slab()
all_atom_types = get_all_atom_types(slab, atom_numbers_to_optimize)
blmin = closest_distances_generator(all_atom_types,
ratio_of_covalent_radii=0.7)
comp = InteratomicDistanceComparator(n_top=n_to_optimize,
pair_cor_cum_diff=0.015,
pair_cor_max=0.7,
dE=0.02,
mic=False)
pairing = CutAndSplicePairing(slab, n_to_optimize, blmin)
mutations = OperationSelector([1., 1., 1.],
[MirrorMutation(blmin, n_to_optimize),
RattleMutation(blmin, n_to_optimize),
PermutationMutation(n_to_optimize)])
# Relax all unrelaxed structures (e.g. the starting population)
while da.get_number_of_unrelaxed_candidates() > 0:
a = da.get_an_unrelaxed_candidate()
a.set_calculator(EMT())
print(’Relaxing starting candidate {0}’.format(a.info[’confid’]))
dyn = BFGS(a, trajectory=None, logfile=None)
dyn.run(fmax=0.05, steps=100)
a.set_raw_score(-a.get_potential_energy())
da.add_relaxed_step(a)
# create the population
population = Population(data_connection=da,
population_size=population_size,
comparator=comp)
# test n_to_test new candidates
for i in xrange(n_to_test):
print(’Now starting configuration number {0}’.format(i))
a1, a2 = population.get_two_candidates()
a3, desc = pairing.get_new_individual([a1, a2])
if a3 == None:
continue
da.add_unrelaxed_candidate(a3, description=desc)
# Check if we want to do a mutation
50
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
if random() < mutation_probability:
a3_mut, desc = mutations.get_new_individual([a3])
if a3_mut != None:
da.add_unrelaxed_step(a3_mut, desc)
a3 = a3_mut
# Relax the new candidate
a3.set_calculator(EMT())
dyn = BFGS(a3, trajectory=None, logfile=None)
dyn.run(fmax=0.05, steps=100)
a3.set_raw_score(-a3.get_potential_energy())
da.add_relaxed_step(a3)
population.update()
write(’all_candidates.traj’, da.get_all_relaxed_candidates())
The above script proposes and locally relaxes 20 new candidates. To speed up the execution of this sample the
local relaxations are limited to 100 steps. This restriction should not be set in a real application. Note it is
important to set the the raw_score, as it is what is being optimized (maximized). It is really an input in the
atoms.info[’key_value_pairs’] dictionary.
The GA progress can be monitored by running the tool ase/ga/tools/get_all_candidates in the same
folder as the GA. This will create a trajectory file all_candidates.traj which includes all locally relaxed
candidates the GA has tried. This script can be run at the same time as the main script is running. This is possible
because the ase.db database is being updated as the GA progresses.
Running the GA in Parallel
One of the great advantages of a GA is that many structures can be relaxed in parallel. This GA implementation
includes two classes which facilitates running the GA in parallel. One class can be used for running several single
threaded optimizations simultaneously on the same compute node, and the other class integrates the GA into the
PBS queuing system used at many high performance computer clusters.
Relaxations in Parallel on the Same Computer
In order to relax several structures simultaneously on the same computer a seperate script relaxing one structure
needs to be created. Continuing the example from above we therefore create a script taking as input the filename of
the structure to relax and which as output saves a trajectory file with the locally optimized structure. It is important
that the relaxed structure is named as in this script, since the parallel integration assumes this file naming scheme.
For the example described above this script could look like
from ase.optimize import BFGS
from ase.io import read, write
from ase.calculators.emt import EMT
from ase.ga.relax_attaches import VariansBreak
from ase.ga.atoms_attach import enable_raw_score_methods
import sys
fname = sys.argv[1]
print(’Now relaxing {}’.format(fname))
a = read(fname)
a.set_calculator(EMT())
dyn = BFGS(a, trajectory=None, logfile=None)
vb = VariansBreak(a, dyn)
dyn.attach(vb.write)
dyn.run(fmax=0.05)
6.2. ASE
51
ASE Manual, Release 3.9.0.3865
enable_raw_score_methods(a)
a.set_raw_score(-a.get_potential_energy())
write(fname[:-5] + ’_done.traj’, a)
print(’Done relaxing {}’.format(fname))
The main script needs to initialize the parallel controller and then the script needs to be changed the two places
where structures are relaxed. The changed main script now looks like
from random import random
from ase.io import write
import time
from ase.ga.data import DataConnection
from ase.ga.population import Population
from ase.ga.standard_comparators import InteratomicDistanceComparator
from ase.ga.cutandsplicepairing import CutAndSplicePairing
from ase.ga.offspring_creator import OperationSelector
from ase.ga.standardmutations import MirrorMutation
from ase.ga.standardmutations import RattleMutation
from ase.ga.standardmutations import PermutationMutation
from ase.ga.utilities import closest_distances_generator
from ase.ga.utilities import get_all_atom_types
from ase.ga.parallellocalrun import ParallelLocalRun
population_size = 20
mutation_probability = 0.3
n_to_test = 100
# Initialize the different components of the GA
da = DataConnection(’gadb.db’)
tmp_folder = ’tmp_folder/’
# An extra object is needed to handle the parallel execution
parallel_local_run = ParallelLocalRun(data_connection=da,
tmp_folder=tmp_folder,
n_simul=4,
calc_script=’calc.py’)
atom_numbers_to_optimize = da.get_atom_numbers_to_optimize()
n_to_optimize = len(atom_numbers_to_optimize)
slab = da.get_slab()
all_atom_types = get_all_atom_types(slab, atom_numbers_to_optimize)
blmin = closest_distances_generator(all_atom_types,
ratio_of_covalent_radii=0.7)
comp = InteratomicDistanceComparator(n_top=n_to_optimize,
pair_cor_cum_diff=0.015,
pair_cor_max=0.7,
dE=0.02,
mic=False)
pairing = CutAndSplicePairing(slab, n_to_optimize, blmin)
mutations = OperationSelector([1., 1., 1.],
[MirrorMutation(blmin, n_to_optimize),
RattleMutation(blmin, n_to_optimize),
PermutationMutation(n_to_optimize)])
# Relax all unrelaxed structures (e.g. the starting population)
while da.get_number_of_unrelaxed_candidates() > 0:
a = da.get_an_unrelaxed_candidate()
parallel_local_run.relax(a)
52
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
# Wait until the starting population is relaxed
while parallel_local_run.get_number_of_jobs_running() > 0:
time.sleep(5.)
# create the population
population = Population(data_connection=da,
population_size=population_size,
comparator=comp)
# test n_to_test new candidates
for i in xrange(n_to_test):
print(’Now starting configuration number {0}’.format(i))
a1, a2 = population.get_two_candidates()
a3, desc = pairing.get_new_individual([a1, a2])
if a3 is None:
continue
da.add_unrelaxed_candidate(a3, description=desc)
# Check if we want to do a mutation
if random() < mutation_probability:
a3_mut, desc = mutations.get_new_individual([a3])
if a3_mut is not None:
da.add_unrelaxed_step(a3_mut, desc)
a3 = a3_mut
# Relax the new candidate
parallel_local_run.relax(a3)
population.update()
# Wait until the last candidates are relaxed
while parallel_local_run.get_number_of_jobs_running() > 0:
time.sleep(5.)
write(’all_candidates.traj’, da.get_all_relaxed_candidates())
Notice how the main script is not cluttered by the local optimization logic and is therefore now also easier to read.
n_simul controls the number of simultaneous relaxations, and can of course also be set to 1 effectively giving
the same result as in the non parallel situation.
The relax method on the ParallelLocalRun class only returns control to the main script when there is an
execution thread available. In the above example the relax method immediately returns control to the main script
the first 4 times it is called, but the fifth time control is first returned when one of the first four relaxations have
been completed.
Running the GA together with a queing system
The GA has been implemented with first principles structure optimization in mind. When using for instance DFT
calculations for the local relaxations relaxing one structure can take many hours. For this reason the GA has been
made so that it can work together with queing systems where each candidate is relaxed in a separate job. With this
in mind the main script of the GA can thus also be considered a controller script which every time it is invoked
gathers the current population, checks with a queing system for the number of jobs submitted, and submits new
jobs. For a typical application the main script can thus be invoked by a crontab once every hour.
To run the GA together with a queing system the user needs to specify a function which takes as input a job name
and the path to the trajectory file that needs to be submitted (the jtg function in the sample script below). From
this the function generates a PBS job file which is submitted to the queing system. The calculator script specified
in the jobfile needs to obey the same naming scheme as the sample calculator script in the previous section. The
sample relaxation script given in the previous can be used as starting point for a relaxation script.
Handling of the parallel logic is in this case in the main script. The parameter n_simul given to the PBSQueueRun
object determines how many relaxations should be in the queuing system simultaneously. The main script now
6.2. ASE
53
ASE Manual, Release 3.9.0.3865
looks the following:
from
from
from
from
from
from
from
from
from
from
from
from
from
random import random
ase.io import write
ase.ga.data import DataConnection
ase.ga.population import Population
ase.ga.standard_comparators import InteratomicDistanceComparator
ase.ga.cutandsplicepairing import CutAndSplicePairing
ase.ga.offspring_creator import OperationSelector
ase.ga.standardmutations import MirrorMutation
ase.ga.standardmutations import RattleMutation
ase.ga.standardmutations import PermutationMutation
ase.ga.utilities import closest_distances_generator
ase.ga.utilities import get_all_atom_types
ase.ga.pbs_queue_run import PBSQueueRun
def jtg(job_name, traj_file):
s = ’#!/bin/sh\n’
s += ’#PBS -l nodes=1:ppn=12\n’
s += ’#PBS -l walltime=48:00:00\n’
s += ’#PBS -N {0}\n’.format(job_name)
s += ’#PBS -q q12\n’
s += ’cd $PBS_O_WORKDIR\n’
s += ’python calc.py {0}\n’.format(traj_file)
return s
population_size = 20
mutation_probability = 0.3
# Initialize the different components of the GA
da = DataConnection(’gadb.db’)
tmp_folder = ’tmp_folder/’
# The PBS queing interface is created
pbs_run = PBSQueueRun(da,
tmp_folder=tmp_folder,
job_prefix=’Ag2Au2_opt’,
n_simul=5,
job_template_generator=jtg)
atom_numbers_to_optimize = da.get_atom_numbers_to_optimize()
n_to_optimize = len(atom_numbers_to_optimize)
slab = da.get_slab()
all_atom_types = get_all_atom_types(slab, atom_numbers_to_optimize)
blmin = closest_distances_generator(all_atom_types,
ratio_of_covalent_radii=0.7)
comp = InteratomicDistanceComparator(n_top=n_to_optimize,
pair_cor_cum_diff=0.015,
pair_cor_max=0.7,
dE=0.02,
mic=False)
pairing = CutAndSplicePairing(slab, n_to_optimize, blmin)
mutations = OperationSelector([1., 1., 1.],
[MirrorMutation(blmin, n_to_optimize),
RattleMutation(blmin, n_to_optimize),
PermutationMutation(n_to_optimize)])
# Relax all unrelaxed structures (e.g. the starting population)
while (da.get_number_of_unrelaxed_candidates() > 0
and not pbs_run.enough_jobs_running()):
a = da.get_an_unrelaxed_candidate()
pbs_run.relax(a)
54
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
# create the population
population = Population(data_connection=da,
population_size=population_size,
comparator=comp)
# Submit new candidates until enough are running
while (not pbs_run.enough_jobs_running()
and len(population.get_current_population()) > 2):
a1, a2 = population.get_two_candidates()
a3, desc = pairing.get_new_individual([a1, a2])
if a3 is None:
continue
da.add_unrelaxed_candidate(a3, description=desc)
if random() < mutation_probability:
a3_mut, desc = mutations.get_new_individual([a3])
if a3_mut is not None:
da.add_unrelaxed_step(a3_mut, desc)
a3 = a3_mut
pbs_run.relax(a3)
write(’all_candidates.traj’, da.get_all_relaxed_candidates())
6.2.14 GA Search for stable FCC alloys
In this tutorial we will emulate an older paper [JГіhannesson] and determine the most stable FCC alloy using the
genetic algorithm. Since the purpose is only the tutorial we will limit the phase space to the elements supported
by the EMT potential. The search is also equivalent to the recent search for mixed metal ammines with superior
properties for ammonia storage described here:
P. B. Jensen, S. Lysgaard, U. J. Quaade and T. Vegge
Designing Mixed Metal Halide Ammines for Ammonia Storage Using Density Functional Theory
and Genetic Algorithms
Physical Chemistry Chemical Physics, Vol 16, No. 36, pp. 19732-19740, (2014)
Contents
• GA Search for stable FCC alloys
– Basic outline of the search
– Setting up reference database
– Initial population
– Run the algorithm
– Extending the algorithm
* Extra mutation operators
* Prevent identical calculations from being performed
* Reuse of calculations between algorithm runs
Basic outline of the search
1. Choose the phase space of your problem. Is the number of possible individuals large enough to prevent a
full screening and is the fitness function too discontinuous for a traditional optimization by derivation? If
so continue.
2. Choose model structures and calculate references in those structures. Put the results somewhere accesible
for a script initiated by the genetic algorithm.
6.2. ASE
55
ASE Manual, Release 3.9.0.3865
3. Choose suitable parameters like population size (general rule of thumb for the population size: log2 (N) <
pop size < 2log2 (N), where N is the size of the phase space), convergence criteria etc.
4. Create the initial population.
5. Choose procreation operators, i.e. how should offspring be produced. New operators can easily be created
by modifying the existing operators.
6. Run the algorithm.
Here we would like to predict the most stable fcc alloys. In this tutorial we only have the EMT potential available
thus we are limited to the supported metal elements: Al, Ni, Cu, Pd, Ag, Pt and Au. We limit ourselves to at most
4 different metals in one structure, thereby having only 74 = 2401 candidates in the phase space, symmetry would
make this number even lower but the number is fitting for this tutorial.
For a real application of the algorithm it is necessary to use a more sophisticated calculator, in that case each
individual calculation is performed on a cluster by submitting to a queuing system. How this is achieved in the
algorithm is covered in Optimization with a Genetic Algorithm.
Setting up reference database
Now we need to set up a database in which reference calculations can be stored. This can either be in a central
database server where keywords distinguish between different references or dedicated separate databases for each
different type of reference calculations.
In the following script, ga_fcc_references.py, we put the references in the database file refs.db. Our
model structure is fcc which is loaded with ase.lattice.cubic.FaceCenteredCubic(). We perform
a volume relaxation to find the optimal lattice constant and lowest energy, which we save in the database as
key-value pairs for quick retrieval.
import numpy as np
from
from
from
from
ase.lattice.cubic import FaceCenteredCubic
ase.calculators.emt import EMT
ase.utils.eos import EquationOfState
ase.db import connect
db = connect(’refs.db’)
metals = [’Al’, ’Au’, ’Cu’, ’Ag’, ’Pd’, ’Pt’, ’Ni’]
for m in metals:
atoms = FaceCenteredCubic(m)
atoms.set_calculator(EMT())
e0 = atoms.get_potential_energy()
a = atoms.cell[0][0]
eps = 0.05
volumes = (a * np.linspace(1 - eps, 1 + eps, 9))**3
energies = []
for v in volumes:
atoms.set_cell([v**(1. / 3)] * 3, scale_atoms=True)
energies.append(atoms.get_potential_energy())
eos = EquationOfState(volumes, energies)
v1, e1, B = eos.fit()
atoms.set_cell([v1**(1. / 3)] * 3, scale_atoms=True)
ef = atoms.get_potential_energy()
db.write(atoms, metal=m,
latticeconstant=v1**(1. / 3),
energy_per_atom=ef / len(atoms))
56
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
Initial population
We choose a population size of 10 individuals and create the initial population by randomly selecting four elements
for each starting individual.
import random
from ase import Atoms
from ase.ga.data import PrepareDB
metals = [’Al’, ’Au’, ’Cu’, ’Ag’, ’Pd’, ’Pt’, ’Ni’]
population_size = 10
# Create database
db = PrepareDB(’fcc_alloys.db’,
population_size=population_size,
metals=metals)
# Create starting population
for i in xrange(population_size):
atoms_string = [random.choice(metals) for _ in xrange(4)]
db.add_unrelaxed_candidate(Atoms(atoms_string),
atoms_string=’’.join(atoms_string))
Note how we add the population size and metals as extra key-value pairs when we create the database
fcc_alloys.db. We can then retrieve these parameters later when running the main script to avoid having to input the same parameters twice.
We can study our initial population by doing (on the command-line):
$ ase-db fcc_alloys.db -c +atoms_string
the term atoms_string determines the order in which the elements are put into the model structure. So it is
possible to fully describe an individual by just providing the atoms_string.
Run the algorithm
from
from
from
from
from
from
ase.ga.data import DataConnection
ase.ga.element_mutations import RandomElementMutation
ase.ga.element_crossovers import OnePointElementCrossover
ase.ga.offspring_creator import OperationSelector
ase.ga.population import Population
ase.ga.convergence import GenerationRepetitionConvergence
from ga_fcc_alloys_relax import relax
# Specify the number of generations this script will run
num_gens = 40
db = DataConnection(’fcc_alloys.db’)
ref_db = ’refs.db’
# Retrieve saved parameters
population_size = db.get_param(’population_size’)
metals = db.get_param(’metals’)
# Specify the procreation operators for the algorithm
# Try and play with the mutation operators that move to nearby
# places in the periodic table
oclist = ([1, 1], [RandomElementMutation(metals),
OnePointElementCrossover(metals)])
6.2. ASE
57
ASE Manual, Release 3.9.0.3865
operation_selector = OperationSelector(*oclist)
# Pass parameters to the population instance
pop = Population(data_connection=db,
population_size=population_size)
# We form generations in this algorithm run and can therefore set
# a convergence criteria based on generations
cc = GenerationRepetitionConvergence(pop, 3)
# Relax the starting population
while db.get_number_of_unrelaxed_candidates() > 0:
a = db.get_an_unrelaxed_candidate()
relax(a, ref_db)
db.add_relaxed_step(a)
pop.update()
# Run the algorithm
for _ in xrange(num_gens):
if cc.converged():
print(’converged’)
break
for i in xrange(population_size):
a1, a2 = pop.get_two_candidates(with_history=False)
op = operation_selector.get_operator()
a3, desc = op.get_new_individual([a1, a2])
db.add_unrelaxed_candidate(a3, description=desc)
relax(a3, ref_db)
db.add_relaxed_step(a3)
pop.update()
# Print the current population to monitor the evolution
print([’-’.join(p.get_chemical_symbols()) for p in pop.pop])
In this script we run a generational GA as opposed to the pool GA outlined in Optimization with a Genetic
Algorithm. This is achieved by having two for-loops; the innermost loop runs the number of times specified by
the population size it corresponds to one generation. The outermost loop runs as many generations as specified in
num_gens. The function pop.update() is called after the innermost loop has finished thereby only adding
individuals to the population after a whole generation is calculated.
After each generation is finished the population is printed to the screen so we can follow the evolution. The
calculated individuals are continuously added to fcc_alloys.db, we can evaluate them directly by doing from
the command line (in another shell instance if the GA is still running):
$ ase-db fcc_alloys.db -c +atoms_string,raw_score,generation,hof -s raw_score
To prevent clutter we import the relax function from the following script:
import numpy as np
from
from
from
from
ase.lattice.cubic import FaceCenteredCubic
ase.calculators.emt import EMT
ase.utils.eos import EquationOfState
ase.db import connect
def relax(input_atoms, ref_db):
atoms_string = input_atoms.get_chemical_symbols()
# Open connection to the database with reference data
58
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
db = connect(ref_db)
# Load our model structure which is just FCC
atoms = FaceCenteredCubic(’X’, latticeconstant=1.)
atoms.set_chemical_symbols(atoms_string)
# Compute the average lattice constant of the metals in this individual
# and the sum of energies of the constituent metals in the fcc lattice
# we will need this for calculating the heat of formation
a = 0
ei = 0
for m in set(atoms_string):
dct = db.get(metal=m)
count = atoms_string.count(m)
a += count * dct.latticeconstant
ei += count * dct.energy_per_atom
a /= len(atoms_string)
atoms.set_cell([a, a, a], scale_atoms=True)
# Since calculations are extremely fast with EMT we can also do a volume
# relaxation
atoms.set_calculator(EMT())
eps = 0.05
volumes = (a * np.linspace(1 - eps, 1 + eps, 9))**3
energies = []
for v in volumes:
atoms.set_cell([v**(1. / 3)] * 3, scale_atoms=True)
energies.append(atoms.get_potential_energy())
eos = EquationOfState(volumes, energies)
v1, ef, B = eos.fit()
latticeconstant = v1**(1. / 3)
# Calculate the heat of formation by subtracting ef with ei
hof = (ef - ei) / len(atoms)
# Place the calculated parameters in the info dictionary of the
# input_atoms object
input_atoms.info[’key_value_pairs’][’hof’] = hof
# Raw score must always be set
input_atoms.info[’key_value_pairs’][’raw_score’] = -hof
input_atoms.info[’key_value_pairs’][’latticeconstant’] = latticeconstant
# Setting the atoms_string directly for easier analysis
atoms_string = ’’.join(input_atoms.get_chemical_symbols())
input_atoms.info[’key_value_pairs’][’atoms_string’] = atoms_string
The relaxation script is naturally similar to the script we used to calculate the references.
Note that the global optimum is PtNi3 with a -0.11 eV heat of formation, whereas the second worst alloy is AlNi3
heat of formation 0.26 eV. This result is in complete contrast to the conclusion obtained in [JГіhannesson], where
AlNi3 is the most stable alloy within the phase space chosen here. Obviously there is a limit to the predictive
power of EMT!
Extending the algorithm
There are different ways one can extend the algorithm and make it more complex and sophisticated, all employed
in [Jensen]:
6.2. ASE
59
ASE Manual, Release 3.9.0.3865
Extra mutation operators
Instead of only using random operations we can include some that mutates elements to other elements nearby in
the periodic table:
from
from
from
from
from
from
ase.ga.element_mutations import RandomElementMutation
ase.ga.element_mutations import MoveDownMutation
ase.ga.element_mutations import MoveUpMutation
ase.ga.element_mutations import MoveLeftMutation
ase.ga.element_mutations import MoveRightMutation
ase.ga.element_crossovers import OnePointElementCrossover
...
oclist = ([4,1,1,1,1,8], [RandomElementMutation([metals]),
MoveDownMutation([metals]),
MoveUpMutation([metals]),
MoveLeftMutation([metals]),
MoveRightMutation([metals]),
OnePointElementCrossover([metals])
mut_selector = MutationSelector(*oclist)
These operators takes advantage of the fact that chemically like elements (close in the periodic table) exhibit
similar properties and the substitution of one to a chemically similar elements could refine the properties of an
alloy in the population. A natural extension of these operators would be to use a different ordering of the elements
than the periodic table; e.g. Pettifor chemical scale, electronegativity, etc.
Note how we have set the probabilities for selecting operators differently.
The probability for
RandomElementMutation is equal to the sum of the move mutations. Similarly the probability of
OnePointElementCrossover is equal to the sum of all the mutation operators. This is to prevent the search
from being purely local.
Prevent identical calculations from being performed
In the current main script there is no check to determine whether an identical calculation has been performed, this
is easy to check in this regime where model structures are used and we can just use the atoms_string. We
insert the following in the inner loop:
for i in xrange(population_size):
dup = True
while dup:
a1, a2 = pop.get_two_candidates(with_history=False)
op = operation_selector.get_operator()
a3, desc = op.get_new_individual([a1, a2])
dup = db.is_duplicate(atoms_string=’’.join(a3.get_chemical_symbols()))
Since the fcc model structure is completely symmetric we could compare sorted versions of the atoms_string,
thereby ruling out individuals containing the same elements in different order.
Reuse of calculations between algorithm runs
Since genetic algorithms are inherently random in nature one can never be sure to obtain the global minimum with
only one algorithm run, it is customary to perform more runs and check that the results agree. In this case it is
vital to be able to reuse identical calculations between runs.
We do the following from the command line to create a new database file containing only the relaxed structures:
$ ase-db fcc_alloys.db relaxed=1 -i all_relaxed.db
60
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
We subsequently add this to the relaxation script:
def relax(input_atoms, ref_db):
atoms_string = input_atoms.get_chemical_symbols()
relaxed_db = connect(’all_relaxed.db’)
save_relax = True
try:
dct = relaxed_db.get(atoms_string=’’.join(atoms_string))
except KeyError:
# Open connection to the database with reference data
db = connect(ref_db)
# Omitting lines up to the point where hof has been calculated
...
else:
hof = dct.hof
latticeconstant = dct.latticeconstant
save_relax = False
# Place the calculated parameters in the info dictionary of the
# input_atoms object
...
# Put this at the very end
if save_relax:
relaxed_db.write(input_atoms,relaxed=1,
key_value_pairs=input_atoms.info[’key_value_pairs’])
Before the actual calculation is performed all_relaxed.db is checked to see if it has been calculated before; if
so we just collect the heat of formation, but if not we do the calculation and save it directly to all_relaxed.db.
Note: this addition assumes that Prevent identical calculations from being performed.
6.3 NumPy
If your ASE scripts make extensive use of matrices you may want to familiarize yourself with Numeric arrays in
Python.
6.3.1 Numeric arrays in Python
Links to NumPy’s webpage:
• Numpy and Scipy Documentation
• Numpy user guide
ASE makes heavy use of an extension to Python called NumPy. The NumPy module defines an ndarray type that
can hold large arrays of uniform multidimensional numeric data. An array is similar to a list or a tuple, but
it is a lot more powerful and efficient.
XXX More examples from everyday ASE-life here ...
>>> import numpy as np
>>> a = np.zeros((3, 2))
>>> a[:, 1] = 1.0
>>> a[1] = 2.0
>>> a
array([[ 0., 1.],
[ 2., 2.],
[ 0., 1.]])
>>> a.shape
6.3. NumPy
61
ASE Manual, Release 3.9.0.3865
(3, 2)
>>> a.ndim
2
The conventions of numpy’s linear algebra package:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
import numpy as np
# Make a random hermitian matrix, H
H = np.random.rand(6, 6) + 1.j * np.random.rand(6, 6)
H = H + H.T.conj()
# Determine eigenvalues and rotation matrix
eps, U = np.linalg.eigh(H)
# Sort eigenvalues
sorted_indices = eps.real.argsort()
eps = eps[sorted_indices]
U = U[:, sorted_indices]
# Make print of numpy arrays less messy:
np.set_printoptions(precision=3, suppress=True)
# Check that U diagonalizes H:
print np.dot(np.dot(U.T.conj(), H), U) - np.diag(eps)
print np.allclose(np.dot(np.dot(U.T.conj(), H), U), np.diag(eps))
# The eigenvectors of H are the *coloumns* of U:
np.allclose(np.dot(H, U[:, 3]), eps[3] * U[:, 3])
np.allclose(np.dot(H, U), eps * U)
The rules for multiplying 1D arrays with 2D arrays:
• 1D arrays and treated like shape (1, N) arrays (row vectors).
• left and right multiplications are treated identically.
• A length m row vector can be multiplied with an n × m matrix, producing the same result as if replaced by
a matrix with n copies of the vector as rows.
• A length n column vector can be multiplied with an n × m matrix, producing the same result as if replaced
by a matrix with m copies of the vector as columns.
Thus, for the arrays below:
>>>
>>>
>>>
>>>
>>>
M = np.arange(5 * 6).reshape(5, 6) # A matrix af shape (5, 6)
v5 = np.arange(5) + 10
# A vector of length 5
v51 = v5[:, None]
# A length 5 column vector
v6 = np.arange(6) - 12
# A vector of length 6
v16 = v6[None, :]
# A length 6 row vector
The following identities hold:
v6 * M == v16 * M == M * v6 == M * v16 == M * v16.repeat(5, 0)
v51 * M == M * v51 == M * v51.repeat(6, 1)
The exact same rules apply for adding and subtracting 1D arrays to / from 2D arrays.
6.4 Further reading
For more details:
• Look at the documentation for the individual modules.
62
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
• See the automatically generated documentation Epydoc: ase.
• Browse the source code online.
• Have a look at siesta exercises:
6.4.1 Exercises
Exercise 2 contains a script which takes somewhat long time. For this reason you may want to submit the script
to Niflheim in advance, before analyzing the results in Exercise 1.
Siesta 1: Basis Sets
This exercise is intended to illustrate the definition of basis sets with different numbers of orbitals and localization
radii in SIESTA. It is based on the H2 O molecule. You will first use standard basis sets generated by SIESTA,
and then a basis set specifically optimized for the H2 O molecule. The tips at the end of this page will help you in
analyzing the results of the calculations.
We are going to use the ASE interface to the siesta calculator, for the official SIESTA documentation see here.
Part 1: Standard basis sets
In the following script you will relax the structure of the H2 O molecule to find its equilibrium structure.
import time
import numpy as np
from ase import Atoms, units
from ase.optimize import QuasiNewton
from ase.calculators.siesta import Siesta
# Set up a H2O molecule by specifying atomic positions
h2o = Atoms(symbols=’H2O’,
positions=[( 0.776070, 0.590459, 0.00000),
(-0.776070, 0.590459, 0.00000),
(0.000000, -0.007702, -0.000001)],
pbc=(1,1,1))
# Center the molecule in the cell with some vacuum around
h2o.center(vacuum=6.0)
# Select some energy-shifts for the basis orbitals
e_shifts = [0.01,0.1,0.2,0.3,0.4,0.5]
# Run the relaxation for each energy shift, and print out the
# corresponding total energy, bond length and angle
for e_s in e_shifts:
starttime = time.time()
calc = Siesta(’h2o’,meshcutoff=200.0 * units.Ry, mix=0.5, pulay=4)
calc.set_fdf(’PAO.EnergyShift’, e_s * units.eV)
calc.set_fdf(’PAO.SplitNorm’, 0.15)
calc.set_fdf(’PAO.BasisSize’, ’SZ’)
h2o.set_calculator(calc)
# Make a -traj file named h2o_current_shift.traj:
dyn = QuasiNewton(h2o, trajectory=’h2o_%s.traj’ % e_s)
dyn.run(fmax=0.02)
# Perform the relaxation
E = h2o.get_potential_energy()
print
# Make the output more readable
6.4. Further reading
63
ASE Manual, Release 3.9.0.3865
print "E_shift: %.2f" %e_s
print "----------------"
print "Total Energy: %.4f" % E
# Print total energy
d = h2o.get_distance(0,2)
print "Bond length: %.4f" % d
# Print bond length
p = h2o.positions
d1 = p[0] - p[2]
d2 = p[1] - p[2]
r = np.dot(d1, d2) / (np.linalg.norm(d1) * np.linalg.norm(d2))
angle = np.arccos(r) / pi * 180
print "Bond angle: %.4f" % angle
# Print bond angle
endtime = time.time()
walltime = endtime - starttime
print ’Wall time: %.5f’ % walltime
print
# Make the output more readable
Run the script using three different basis sets: single-Z (SZ), double-Z (DZ) and double-Z plus polarization (DZP).
Run it in different directories for each basis set, since the run will produce a large amount of output files. The
bases are defined in the script through these three lines:
calc.set_fdf(’PAO.BasisSize’,’SZ’)
calc.set_fdf(’PAO.EnergyShift’,e_s * eV)
calc.set_fdf(’PAO.SplitNorm’,0.15)
For each of the basis sets the script will run the relaxation for different EnergyShift parameters. Look at the
results as a function of basis size and localization radius (or energy shift).
In particular, you should look at:
• Total energy
• Bond lenghts at the relaxed structure
• Bond angles at the relaxed structure
• Execution time
• Radius of each of the orbitals
• Shape of the orbitals
The script will print bond lengths and angles, total energy plus the wall time for each energy shift. The radii of the
orbitals from the last run can be found in the file h2o.txt along with miscellaneous other informations. Orbital
shapes from the last run are stored in the ORB.* files, which contain the value of the orbitals versus radius. (Note
that the standard way to plot the orbitals is to multiply the orbital by rl ).
You can visualize both the static atoms and the relaxation trajectory using the the ASE gui. For example you can
visualize the relaxation trajectory from the command line by doing:
$ ase-gui h2o_0.1.traj
Note that you will get a trajectory file .traj for each energy shift in the loop.
Try to get plots like the following, obtained for a SZ basis:
64
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
Try to answer these questions:
1. What is the best basis set that you have found? Why?
2. How do the results compare with experiment?
3. What do you consider a reasonable basis for the molecule, if you need an accuracy in the geometry of about
1%?
4. In order to assess convergence with respect to basis set size, should you compare the results with the experimental ones, or with those of a converged basis set calculation?
Part 2: Optimized basis sets
You will now do the same calculations as in Part 1, but now using a basis set specifically optimized for the H2 O
molecule. Use the following optimized block instead of the basis-definition lines in Part1:
calc.set_fdf(’PAO.Basis’,
["""H
2
0.22
n=1
0
2
E
4.971
1.771
1.000
1.000
n=2
1
1
E
4.988
1.000
O
3
-0.20
n=2
0
2
E
5.000
2.581
1.000
1.000
n=2
1
2
E
6.4. Further reading
2.07
0.00
0.89
0.01
0.00
1.31
0.00
5.28
65
ASE Manual, Release 3.9.0.3865
6.500
2.487
1.000
1.000
n=3
2
1
3.923
1.000"""])
E
104.31
0.00
Compare the parameters with those of the calculations in Part 1.
Do the runs with this basis set, and compare the results with the previous ones.
Tips
Tip 1: You can see the radii of the orbitals in the output file, just after the line reading:
printput: Basis input ----------------------------------------------
Tip 2: You can look at the shape of the orbitals by plotting the contents of the ORB* files generated by SIESTA.
Tip 3: You will find a lot of information on the run in the .txt output file
Tip 4: In ag you can select View в†’ VMD to start the VMD viewer. There you can change the atom representation
to what you feel is more convenient. Do that by selecting Graphics в†’ Representations in the top bar.
Tip 5: SIESTA will store basis functions in ORB.* files. These files can be plotted using the xmgrace command
on the GBAR like this:
$ xmgrace ORB.S1.1.O ORB.S2.1.O
Siesta 2: Molecular Dynamics
This exercise is intended to illustrate a Molecular Dynamics run with the SIESTA calculator. The system is a
Si(001) surface, in the 2x1 reconstruction with asymmetric dimers. The simulation cell contains two dimers. An
H2 molecule approaches the surface, above one of the dimers, and dissociates, ending up with a H atom bonded
to each of the Si atoms in the dimer (and thus leading to a symmetric dimer). You can get the xyz file with the
initial geometry doc/exercises/siesta2/geom.xyz.
from
from
from
from
from
ase.io import read
ase.constraints import FixAtoms
ase.calculators.siesta import Siesta
ase.md import VelocityVerlet
ase import units
# Read in the geometry from a xyz file, set the cell, boundary conditions and center
atoms = read(’geom.xyz’)
atoms.set_cell([7.66348,7.66348,7.66348*2])
atoms.set_pbc((1,1,1))
atoms.center()
# Set initial velocities for hydrogen atoms along the z-direction
p = atoms.get_momenta()
p[0,2]= -1.5
p[1,2]= -1.5
atoms.set_momenta(p)
# Keep some atoms fixed during the simulation
atoms.set_constraint(FixAtoms(indices=range(18,38)))
# Set the calculator and attach it to the system
calc = Siesta(’si001+h2’,basis=’SZ’,xc=’PBE’,meshcutoff=50*units.Ry)
calc.set_fdf(’PAO.EnergyShift’, 0.25 * units.eV)
calc.set_fdf(’PAO.SplitNorm’, 0.15)
atoms.set_calculator(calc)
66
Chapter 6. Tutorials
ASE Manual, Release 3.9.0.3865
# Set the VelocityVerlet algorithm and run it
dyn = VelocityVerlet(atoms,dt=1.0 * units.fs,trajectory=’si001+h2.traj’)
dyn.run(steps=100)
Note that both H atoms are given an initial velocity towards the surface through the lines:
p = atoms.get_momenta()
p[0,2]= -1.5
p[1,2]= -1.5
atoms.set_momenta(p)
Run the program, and check the results. You can visualize the dynamics using the trajectory file with the help of
the ASE gui. For example you can visualize the behaviour of the potential and total energies during the dynamics
by doing:
$ ase-gui -b si001+h2.traj -g i,e,e+ekin
The -b option turns on plotting of bonds between the atoms. Check that the total energy is a conserved quantity
in this microcanonical simulation.
You can also use VMD to visualize the trajectory. To do this, you need a .xyz file that you can write using
ase-gui:
$ ase-gui si001+h2.traj -o si.xyz -r 2,2,1
Then simply open the file using VMD:
$ vmd si.xyz
and set Graphics/Representations from the main menu in order to get a nice picture.
You can also try to repeat the simulation with a different dynamics. For instance you can model a canonical
ensemble with the Langevin dynamics, which couples the system to a heat bath:
dyn = Langevin(atoms, 1 * fs, kB * 300, 0.002, trajectory=traj)
6.5 Videos
The following video tutorials are available:
• Overview and installation of ASE, by Anthony Goodrow (duration: ~5min 30sec; size: 26 MB) - en:
6.5. Videos
67
ASE Manual, Release 3.9.0.3865
68
Chapter 6. Tutorials
CHAPTER
SEVEN
DOCUMENTATION FOR MODULES IN
ASE
Quick links:
atom
db
gui
md
phonons
transport
vibrations
atoms
dft
infrared
neb
spacegroup
thermochemistry
visualize
calculators
data
io
optimize
structure
units
vtk
constraints
ga
lattice
parallel
surface
utils
See Also:
• Tutorials
• Automatically generated documentation (API)
• Source code
• Presentation about ASE: ase-talk.pdf
List of all modules:
7.1 The Atoms object
The Atoms object is a collection of atoms. Here is how to define a CO molecule:
from ase import Atoms
d = 1.1
co = Atoms(’CO’, positions=[(0, 0, 0), (0, 0, d)])
Here, the first argument specifies the type of the atoms and we used the positions keywords to specify their
positions. Other possible keywords are: numbers, tags, momenta, masses, magmoms and charges.
Here is how you could make an infinite gold wire with a bond length of 2.9 Г…:
from ase import Atoms
d = 2.9
L = 10.0
wire = Atoms(’Au’,
positions=[(0, L / 2, L / 2)],
cell=(d, L, L),
pbc=(1, 0, 0))
69
ASE Manual, Release 3.9.0.3865
Here, two more optional keyword arguments were used:
cell: Unit cell size This can be a sequence of three numbers for an orthorhombic unit cell or three by three
numbers for a general unit cell (a sequence of three sequences of three numbers). The default value is [1.0,
1.0, 1.0].
pbc: Periodic boundary conditions The default value is False - a value of True would give periodic boundary
conditions along all three axes. It is possible to give a sequence of three booleans to specify periodicity
along specific axes.
You can also use the following methods to work with the unit cell and the boundary conditions: set_pbc(),
set_cell(), get_cell(), and get_pbc().
7.1.1 Working with the array methods of Atoms objects
Like with a single Atom the properties of a collection of atoms can be accessed and changed with get- and setmethods. For example the positions of the atoms can be addressed as
>>> a = Atoms(’N3’, [(0, 0, 0), (1, 0, 0), (0, 0, 1)])
>>> a.get_positions()
array([[ 0., 0., 0.],
[ 1., 0., 0.],
[ 0., 0., 1.]])
>>> a.set_positions([(2, 0, 0), (0, 2, 2), (2, 2, 0)])
>>> a.get_positions()
array([[ 2., 0., 0.],
[ 0., 2., 2.],
[ 2., 2., 0.]])
Here is the full list of the get/set methods operating on all the atoms at once. The get methods return an array
of quantities, one for each atom; the set methods take similar arrays. E.g. get_positions() return N * 3
numbers, get_atomic_numbers() return N integers.
These methods return copies of the internal arrays, it is thus safe to modify the returned arrays.
70
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
get_atomic_numbers()
get_charges()
get_chemical_symbols()
get_initial_magnetic_moments()
get_magnetic_moments()
get_masses()
get_momenta()
get_forces()
get_positions()
get_potential_energies()
get_scaled_positions()
get_stresses()
get_tags()
get_velocities()
set_atomic_numbers()
set_charges()
set_chemical_symbols()
set_initial_magnetic_moments()
set_masses()
set_momenta()
set_positions()
set_scaled_positions()
set_tags()
set_velocities()
There are also a number of get/set methods that operate on quantities common to all the atoms or defined for the
collection of atoms:
get_calculator()
get_cell()
get_center_of_mass()
get_kinetic_energy()
get_magnetic_moment()
get_number_of_atoms()
get_pbc()
get_potential_energy()
get_stress()
get_total_energy()
get_volume()
set_calculator()
set_cell()
set_pbc()
7.1.2 Unit cell and boundary conditions
The Atoms object holds a unit cell which by default is the 3x3 unit matrix as can be seen from
>>> a.get_cell()
array([[ 1., 0.,
[ 0., 1.,
[ 0., 0.,
0.],
0.],
1.]])
The cell can be defined or changed using the set_cell() method. Changing the unit cell does per default not
move the atoms:
>>> a.set_cell(2 * identity(3))
>>> a.get_cell()
array([[ 2., 0., 0.],
[ 0., 2., 0.],
[ 0., 0., 2.]])
>>> a.get_positions()
array([[ 2., 0., 0.],
[ 1., 1., 0.],
[ 2., 2., 0.]])
However if we set scale_atoms=True the atomic positions are scaled with the unit cell:
>>> a.set_cell(identity(3), scale_atoms=True)
>>> a.get_positions()
array([[ 1. , 0. , 0. ],
[ 0.5, 0.5, 0. ],
[ 1. , 1. , 0. ]])
7.1. The Atoms object
71
ASE Manual, Release 3.9.0.3865
The set_pbc() method specifies whether periodic boundary conditions are to be used in the directions of the
three vectors of the unit cell. A slab calculation with periodic boundary conditions in x and y directions and free
boundary conditions in the z direction is obtained through
>>> a.set_pbc((True, True, False))
7.1.3 Special attributes
It is also possible to work directly with the attributes positions, numbers, pbc and cell. Here we change
the position of the 2nd atom (which has count number 1 because Python starts counting at zero) and the type of
the first atom:
>>> a.positions[1] = (1, 1, 0)
>>> a.get_positions()
array([[2., 0., 0.],
[1., 1., 0.],
[2., 2., 0.]])
>>> a.positions
array([[2., 0., 0.],
[1., 1., 0.],
[2., 2., 0.]])
>>> a.numbers
array([7, 7, 7])
>>> a.numbers[0] = 13
>>> a.get_chemical_symbols()
[’Al’, ’N’, ’N’]
Check for periodic boundary conditions:
>>> a.pbc # equivalent to a.get_pbc()
array([False, False, False], dtype=bool)
>>> a.pbc.any()
False
>>> a.pbc[2] = 1
>>> a.pbc
array([False, False, True], dtype=bool)
7.1.4 Adding a calculator
A calculator can be attached to the atoms with the purpose of calculating energies and forces on the atoms. ASE
works with many different ase.calculators.
A calculator object calc is attached to the atoms like this:
>>> a.set_calculator(calc)
After the calculator has been appropriately setup the energy of the atoms can be obtained through
>>> a.get_potential_energy()
The term “potential energy” here means for example the total energy of a DFT calculation, which includes both
kinetic, electrostatic, and exchange-correlation energy for the electrons. The reason it is called potential energy is
that the atoms might also have a kinetic energy (from the moving nuclei) and that is obtained with
>>> a.get_kinetic_energy()
In case of a DFT calculator, it is up to the user to check exactly what the get_potential_energy() method
returns. For example it may be the result of a calculation with a finite temperature smearing of the occupation
numbers extrapolated to zero temperature. More about this can be found for the different ase.calculators.
The following methods can only be called if a calculator is present:
72
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
• get_potential_energy()
• get_potential_energies()
• get_forces()
• get_stress()
• get_stresses()
• get_total_energy()
• get_magnetic_moments()
• get_magnetic_moment()
Not all of these methods are supported by all calculators.
7.1.5 List-methods
method
+
+=, extend()
append()
*
*=, repeat()
len
del
pop()
example
wire2 = wire + co
wire += co
wire.extend(co)
wire.append(Atom(’H’))
wire3 = wire * (3, 1, 1)
wire *= (3, 1, 1)
wire.repeat((3, 1, 1))
len(co)
del wire3[0]
del wire3[[1,3]]
oxygen = wire2.pop()
Note that the del method can be used with the more powerful numpy-style indexing, as in the second example
above. This can be combined with python list comprehension in order to selectively delete atoms within an ASE
Atoms object. For example, the below code creates an ethanol molecule and subsequently strips all the hydrogen
atoms from it:
from ase.structure import molecule
atoms = molecule(’CH3CH2OH’)
del atoms[[atom.index for atom in atoms if atom.symbol==’H’]]
7.1.6 Other methods
• center()
• translate()
• rotate()
• rotate_euler()
• get_dihedral()
• set_dihedral()
• rotate_dihedral()
• rattle()
• set_constraint()
• set_distance()
• copy()
7.1. The Atoms object
73
ASE Manual, Release 3.9.0.3865
• get_center_of_mass()
• get_distance()
• get_distances()
• get_all_distances()
• get_volume()
• has()
• edit()
7.1.7 List of all Methods
class ase.atoms.Atoms(symbols=None, positions=None, numbers=None, tags=None, momenta=None,
masses=None,
magmoms=None,
charges=None,
scaled_positions=None, cell=None, pbc=None, celldisp=None, constraint=None, calculator=None, info=None)
Atoms object.
The Atoms object can represent an isolated molecule, or a periodically repeated structure. It has a unit cell
and there may be periodic boundary conditions along any of the three unit cell axes.
Information about the atoms (atomic numbers and position) is stored in ndarrays. Optionally, there can be
information about tags, momenta, masses, magnetic moments and charges.
In order to calculate energies, forces and stresses, a calculator object has to attached to the atoms object.
Parameters:
symbols: str (formula) or list of str Can be a string formula, a list of symbols or a list of Atom objects.
Examples: �H2O’, �COPt12’, [’H’, �H’, �O’], [Atom(�Ne’, (x, y, z)), ...].
positions: list of xyz-positions Atomic positions. Anything that can be converted to an ndarray of shape
(n, 3) will do: [(x1,y1,z1), (x2,y2,z2), ...].
scaled_positions: list of scaled-positions Like positions, but given in units of the unit cell. Can not be set
at the same time as positions.
numbers: list of int Atomic numbers (use only one of symbols/numbers).
tags: list of int Special purpose tags.
momenta: list of xyz-momenta Momenta for all atoms.
masses: list of float Atomic masses in atomic units.
magmoms: list of float or list of xyz-values Magnetic moments. Can be either a single value for each
atom for collinear calculations or three numbers for each atom for non-collinear calculations.
charges: list of float Atomic charges.
cell: 3x3 matrix Unit cell vectors. Can also be given as just three numbers for orthorhombic cells. Default
value: [1, 1, 1].
celldisp: Vector Unit cell displacement vector. To visualize a displaced cell around the center of mass of a
Systems of atoms. Default value = (0,0,0)
pbc: one or three bool Periodic boundary conditions flags. Examples: True, False, 0, 1, (1, 1, 0), (True,
False, False). Default value: False.
constraint: constraint object(s) Used for applying one or more constraints during structure optimization.
calculator: calculator object Used to attach a calculator for calculating energies and atomic forces.
info: dict of key-value pairs Dictionary of key-value pairs with additional information about the system.
The following keys may be used by ase:
74
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
• spacegroup: Spacegroup instance
• unit_cell: �conventional’ | �primitive’ | int | 3 ints
• adsorbate_info:
Items in the info attribute survives copy and slicing and can be store to and retrieved from trajectory
files given that the key is a string, the value is picklable and, if the value is a user-defined object, its
base class is importable. One should not make any assumptions about the existence of keys.
Examples:
These three are equivalent:
>>>
>>>
>>>
>>>
d
a
a
a
=
=
=
=
1.104 # N2 bondlength
Atoms(’N2’, [(0, 0, 0), (0, 0, d)])
Atoms(numbers=[7, 7], positions=[(0, 0, 0), (0, 0, d)])
Atoms([Atom(’N’, (0, 0, 0)), Atom(’N’, (0, 0, d)])
FCC gold:
>>> a = 4.05 # Gold lattice constant
>>> b = a / 2
>>> fcc = Atoms(’Au’,
...
cell=[(0, b, b), (b, 0, b), (b, b, 0)],
...
pbc=True)
Hydrogen wire:
>>> d = 0.9 # H-H distance
>>> L = 7.0
>>> h = Atoms(’H’, positions=[(0, L / 2, L / 2)],
...
cell=(d, L, L),
...
pbc=(1, 0, 0))
append(atom)
Append atom to end.
calc
Calculator object.
cell
Attribute for direct manipulation of the unit cell.
center(vacuum=None, axis=(0, 1, 2))
Center atoms in unit cell.
Centers the atoms in the unit cell, so there is the same amount of vacuum on all sides.
vacuum: float (default: None) If specified adjust the amount of vacuum when centering. If vacuum=10.0 there will thus be 10 Angstrom of vacuum on each side.
axis: int or sequence of ints Axis or axes to act on. Default: Act on all axes.
constraints
Constraints of the atoms.
copy()
Return a copy.
edit()
Modify atoms interactively through ase-gui viewer.
Conflicts leading to undesirable behaviour might arise when matplotlib has been pre-imported with
certain incompatible backends and while trying to use the plot feature inside the interactive ag. To
circumvent, please set matplotlib.use(�gtk’) before calling this method.
extend(other)
Extend atoms object by appending atoms from other.
7.1. The Atoms object
75
ASE Manual, Release 3.9.0.3865
get_all_distances(mic=False)
Return distances of all of the atoms with all of the atoms.
Use mic=True to use the Minimum Image Convention.
get_angle(list)
Get angle formed by three atoms.
calculate angle between the vectors list[1]->list[0] and list[1]->list[2], where list contains the atomic
indexes in question.
get_angular_momentum()
Get total angular momentum with respect to the center of mass.
get_array(name, copy=True)
Get an array.
Returns a copy unless the optional argument copy is false.
get_atomic_numbers()
Get integer array of atomic numbers.
get_calculation_done()
Let the calculator calculate its thing, using the current input.
get_calculator()
Get currently attached calculator object.
get_cell()
Get the three unit cell vectors as a 3x3 ndarray.
get_celldisp()
Get the unit cell displacement vectors .
get_center_of_mass(scaled=False)
Get the center of mass.
If scaled=True the center of mass in scaled coordinates is returned.
get_charges()
Get calculated charges.
get_chemical_formula(mode=’hill’)
Get the chemial formula as a string based on the chemical symbols.
Parameters:
mode: There are three different modes available:
�all’: The list of chemical symbols are contracted to at string, e.g. [’C’, �H’, �H’, �H’, �O’, �H’]
becomes �CHHHOH’.
�reduce’: The same as �all’ where repeated elements are contracted to a single symbol and a
number, e.g. �CHHHOCHHH’ is reduced to �CH3OCH3’.
�hill’: The list of chemical symbols are contracted to a string following the Hill notation (alphabetical order with C and H first), e.g. �CHHHOCHHH’ is reduced to �C2H6O’ and �SOOHOHO’
to �H2O4S’. This is default.
get_chemical_symbols()
Get list of chemical symbol strings.
get_dihedral(list)
Calculate dihedral angle.
Calculate dihedral angle between the vectors list[0]->list[1] and list[2]->list[3], where list contains the
atomic indexes in question.
76
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
get_dipole_moment()
Calculate the electric dipole moment for the atoms object.
Only available for calculators which has a get_dipole_moment() method.
get_distance(a0, a1, mic=False)
Return distance between two atoms.
Use mic=True to use the Minimum Image Convention.
get_distances(a, indices, mic=False)
Return distances of atom No.i with a list of atoms
Use mic=True to use the Minimum Image Convention.
get_forces(apply_constraint=True)
Calculate atomic forces.
Ask the attached calculator to calculate the forces and apply constraints. Use apply_constraint=False
to get the raw forces.
get_initial_charges()
Get array of initial charges.
get_initial_magnetic_moments()
Get array of initial magnetic moments.
get_kinetic_energy()
Get the kinetic energy.
get_magnetic_moment()
Get calculated total magnetic moment.
get_magnetic_moments()
Get calculated local magnetic moments.
get_masses()
Get array of masses.
get_momenta()
Get array of momenta.
get_moments_of_inertia(vectors=False)
Get the moments of inertia along the principal axes.
The three principal moments of inertia are computed from the eigenvalues of the symmetric inertial tensor. Periodic boundary conditions are ignored. Units of the moments of inertia are
amu*angstrom**2.
get_number_of_atoms()
Returns the number of atoms.
Equivalent to len(atoms) in the standard ASE Atoms class.
get_pbc()
Get periodic boundary condition flags.
get_positions(wrap=False)
Get array of positions. If wrap==True, wraps atoms back into unit cell.
get_potential_energies()
Calculate the potential energies of all the atoms.
Only available with calculators supporting per-atom energies (e.g. classical potentials).
get_potential_energy(force_consistent=False, apply_constraint=True)
Calculate potential energy.
Ask the attached calculator to calculate the potential energy and apply constraints.
ply_constraint=False to get the raw forces.
7.1. The Atoms object
Use ap-
77
ASE Manual, Release 3.9.0.3865
When supported by the calculator, either the energy extrapolated to zero Kelvin or the energy consistent with the forces (the free energy) can be returned.
get_reciprocal_cell()
Get the three reciprocal lattice vectors as a 3x3 ndarray.
Note that the commonly used factor of 2 pi for Fourier transforms is not included here.
get_scaled_positions()
Get positions relative to unit cell.
Atoms outside the unit cell will be wrapped into the cell in those directions with periodic boundary
conditions so that the scaled coordinates are between zero and one.
get_stress(voigt=True)
Calculate stress tensor.
Returns an array of the six independent components of the symmetric stress tensor, in the traditional
Voigt order (xx, yy, zz, yz, xz, xy) or as a 3x3 matrix. Default is Voigt order.
get_stresses()
Calculate the stress-tensor of all the atoms.
Only available with calculators supporting per-atom energies and stresses (e.g. classical potentials).
Even for such calculators there is a certain arbitrariness in defining per-atom stresses.
get_tags()
Get integer array of tags.
get_temperature()
Get the temperature. in Kelvin
get_total_energy()
Get the total energy - potential plus kinetic energy.
get_velocities()
Get array of velocities.
get_volume()
Get volume of unit cell.
has(name)
Check for existence of array.
name must be one of: �tags’, �momenta’, �masses’, �magmoms’, �charges’.
new_array(name, a, dtype=None, shape=None)
Add new array.
If shape is not None, the shape of a will be checked.
numbers
Attribute for direct manipulation of the atomic numbers.
pbc
Attribute for direct manipulation of the periodic boundary condition flags.
pop(i=-1)
Remove and return atom at index i (default last).
positions
Attribute for direct manipulation of the positions.
rattle(stdev=0.001, seed=42)
Randomly displace atoms.
This method adds random displacements to the atomic positions, taking a possible constraint into
account. The random numbers are drawn from a normal distribution of standard deviation stdev.
For a parallel calculation, it is important to use the same seed on all processors!
78
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
repeat(rep)
Create new repeated atoms object.
The rep argument should be a sequence of three positive integers like (2,3,1) or a single integer (r)
equivalent to (r,r,r).
rotate(v, a=None, center=(0, 0, 0), rotate_cell=False)
Rotate atoms based on a vector and an angle, or two vectors.
Parameters:
v: Vector to rotate the atoms around. Vectors can be given as strings: �x’, �-x’, �y’, ... .
a = None: Angle that the atoms is rotated around the vecor �v’. If an angle is not specified, the length
of �v’ is used as the angle (default). The angle can also be a vector and then �v’ is rotated into �a’.
center = (0, 0, 0): The center is kept fixed under the rotation. Use �COM’ to fix the center of mass,
�COP’ to fix the center of positions or �COU’ to fix the center of cell.
rotate_cell = False: If true the cell is also rotated.
Examples:
Rotate 90 degrees around the z-axis, so that the x-axis is rotated into the y-axis:
>>>
>>>
>>>
>>>
>>>
>>>
a = pi / 2
atoms.rotate(’z’, a)
atoms.rotate((0, 0, 1), a)
atoms.rotate(’-z’, -a)
atoms.rotate((0, 0, a))
atoms.rotate(’x’, ’y’)
rotate_dihedral(list, angle, mask=None)
Rotate dihedral angle.
Complementing the two routines above: rotate a group by a predefined dihedral angle, starting from
its current configuration
rotate_euler(center=(0, 0, 0), phi=0.0, theta=0.0, psi=0.0)
Rotate atoms via Euler angles.
See e.g http://mathworld.wolfram.com/EulerAngles.html for explanation.
Parameters:
center : The point to rotate about. A sequence of length 3 with the coordinates, or �COM’ to select
the center of mass, �COP’ to select center of positions or �COU’ to select center of cell.
phi : The 1st rotation angle around the z axis.
theta : Rotation around the x axis.
psi : 2nd rotation around the z axis.
set_angle(list, angle, mask=None)
Set angle formed by three atoms.
Sets the angle between vectors list[1]->list[0] and list[1]->list[2].
Same usage as in set_dihedral.
set_array(name, a, dtype=None, shape=None)
Update array.
If shape is not None, the shape of a will be checked. If a is None, then the array is deleted.
set_atomic_numbers(numbers)
Set atomic numbers.
set_calculator(calc=None)
Attach calculator object.
7.1. The Atoms object
79
ASE Manual, Release 3.9.0.3865
set_cell(cell, scale_atoms=False, fix=None)
Set unit cell vectors.
Parameters:
cell : Unit cell. A 3x3 matrix (the three unit cell vectors) or just three numbers for an orthorhombic
cell.
scale_atoms [bool] Fix atomic positions or move atoms with the unit cell? Default behavior is to not
move the atoms (scale_atoms=False).
Examples:
Two equivalent ways to define an orthorhombic cell:
>>> a.set_cell([a, b, c])
>>> a.set_cell([(a, 0, 0), (0, b, 0), (0, 0, c)])
FCC unit cell:
>>> a.set_cell([(0, b, b), (b, 0, b), (b, b, 0)])
set_chemical_symbols(symbols)
Set chemical symbols.
set_constraint(constraint=None)
Apply one or more constrains.
The constraint argument must be one constraint object or a list of constraint objects.
set_dihedral(list, angle, mask=None)
set the dihedral angle between vectors list[0]->list[1] and list[2]->list[3] by changing the atom indexed
by list[3] if mask is not None, all the atoms described in mask (read: the entire subgroup) are moved
example: the following defines a very crude ethane-like molecule and twists one half of it by 30
degrees.
>>> atoms = Atoms(’HHCCHH’, [[-1, 1, 0], [-1, -1, 0], [0, 0, 0],
[1, 0, 0], [2, 1, 0], [2, -1, 0]])
>>> atoms.set_dihedral([1,2,3,4],7*pi/6,mask=[0,0,0,1,1,1])
set_distance(a0, a1, distance, fix=0.5, mic=False)
Set the distance between two atoms.
Set the distance between atoms a0 and a1 to distance. By default, the center of the two atoms will be
fixed. Use fix=0 to fix the first atom, fix=1 to fix the second atom and fix=0.5 (default) to fix the center
of the bond.
set_initial_charges(charges=None)
Set the initial charges.
set_initial_magnetic_moments(magmoms=None)
Set the initial magnetic moments.
Use either one or three numbers for every atom (collinear or non-collinear spins).
set_masses(masses=’defaults’)
Set atomic masses.
The array masses should contain a list of masses. In case the masses argument is not given or for those
elements of the masses list that are None, standard values are set.
set_momenta(momenta)
Set momenta.
set_pbc(pbc)
Set periodic boundary condition flags.
80
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
set_positions(newpositions)
Set positions, honoring any constraints.
set_scaled_positions(scaled)
Set positions relative to unit cell.
set_tags(tags)
Set tags for all atoms. If only one tag is supplied, it is applied to all atoms.
set_velocities(velocities)
Set the momenta by specifying the velocities.
translate(displacement)
Translate atomic positions.
The displacement argument can be a float an xyz vector or an nx3 array (where n is the number of
atoms).
write(filename, format=None, **kwargs)
Write yourself to a file.
7.2 The Atom object
ASE defines a python class called Atom to setup and handle atoms in electronic structure and molecular simulations. From a python script, atoms can be created like this:
>>>
>>>
>>>
>>>
from
a1 =
a2 =
a3 =
ase import Atom
Atom(’Si’, (0, 0, 0))
Atom(’H’, (1.3, 0, 0), mass=2)
Atom(position=(0, 0, 0), Z=14)
# same is a1
class ase.atom.Atom(symbol=’X’, position=(0, 0, 0), tag=None, momentum=None, mass=None, magmom=None, charge=None, atoms=None, index=None)
Class for representing a single atom.
Parameters:
symbol: str or int Can be a chemical symbol (str) or an atomic number (int).
position: sequence of 3 floats Atomi position.
tag: int Special purpose tag.
momentum: sequence of 3 floats Momentum for atom.
mass: float Atomic mass in atomic units.
magmom: float or 3 floats Magnetic moment.
charge: float Atomic charge.
The first argument to the constructor of an Atom object is the chemical symbol, and the second argument is the
position in Г… units (see ase.units). The position can be any numerical sequence of length three. The properties
of an atom can also be set using keywords like it is done in the a2 and a3 examples above.
More examples:
>>> a = Atom(’O’, charge=-2)
>>> b = Atom(8, charge=-2)
>>> c = Atom(’H’, (1, 2, 3), magmom=1)
>>> print a.charge, a.position
-2 [ 0. 0. 0.]
>>> c.x = 0.0
>>> c.position
array([ 0., 2., 3.])
>>> b.symbol
7.2. The Atom object
81
ASE Manual, Release 3.9.0.3865
’O’
>>>
>>>
1
>>>
>>>
3
c.tag = 42
c.number
c.symbol = ’Li’
c.number
If the atom object belongs to an Atoms object, then assigning values to the atom attributes will change the corresponding arrays of the atoms object:
>>> OH = Atoms(’OH’)
>>> OH[0].charge = -1
>>> OH.get_charges()
array([-1., 0.])
Another example:
>>> for atom in bulk:
...
if atom.symbol == ’Ni’:
...
atom.magmom = 0.7 # set initial magnetic moment
The different properties of an atom can be obtained and changed via attributes (position, number, tag,
momentum, mass, magmom, charge, x, y, z):
>>> a1.position = [1, 0, 0]
>>> a1.position
array([ 1., 0., 0.])
>>> a1.z = 2.5
>>> a1.position
array([ 1. , 0. , 2.5])
>>> a2.magmom = 1.0
That last line will set the initial magnetic moment that some calculators use (similar to the
set_initial_magnetic_moments() method).
Note: The position and momentum attributes refer to mutable objects, so in some cases, you may want to
use a1.position.copy() in order to avoid changing the position of a1 by accident.
7.2.1 Getting an Atom from an Atoms object
Indexing an Atoms object returns an Atom object still remembering that it belongs to the collective Atoms:
Modifying it will also change the atoms object:
>>> from ase.structures import molecule
>>> atoms = molecule(’CH4’)
>>> atoms.get_positions()
array([[ 0.
, 0.
, 0.
],
[ 0.629118, 0.629118, 0.629118],
[-0.629118, -0.629118, 0.629118],
[ 0.629118, -0.629118, -0.629118],
[-0.629118, 0.629118, -0.629118]])
>>> a = atoms[2]
>>> a
Atom(’H’, [-0.62911799999999996, -0.62911799999999996, 0.62911799999999996], index=2)
>>> a.x = 0
>>> atoms.get_positions()
array([[ 0.
, 0.
, 0.
],
[ 0.629118, 0.629118, 0.629118],
[ 0.
, -0.629118, 0.629118],
82
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
[ 0.629118, -0.629118, -0.629118],
[-0.629118, 0.629118, -0.629118]])
See Also:
Atom: All the details!
ase.atoms: More information about how to use collections of atoms.
ase.calculators: Information about how to calculate forces and energies of atoms.
7.3 Units
Physical units are defined in the ase/units.py module. Electron volts (eV) and angstroms (Ang) are defined as 1.0.
Other units are nm, Bohr, Hartree or Ha, kJ, kcal, mol, Rydberg or Ry, second, fs and kB.
Note: All constants are taken from the 1986 CODATA.
Examples:
>>> from ase.units import *
>>> 2 * Bohr
1.0583545150138329
>>> 25 * Rydberg
340.14244569396635
>>> 100 * kJ/mol
1.0364272141304978
>>> 300 * kB
0.025852157076770025
>>> 0.1 * fs
0.009822693531550318
>>> print ’1 Hartree = ’+str(Hartree*mol/kcal)+’ kcal/mol’
7.4 The ase.data module
This module defines the following variables: atomic_masses, atomic_names, chemical_symbols,
covalent_radii, cpk_colors and reference_states. All of these are lists that should be indexed
with an atomic number:
>>> from ase.data import atomic_names, atomic_masses
>>> atomic_names[92]
’Uranium’
>>> atomic_masses[2]
4.0026000000000002
If you don’t know the atomic number of some element, then you can look it up in the atomic_numbers
dictionary:
>>> from ase.data import atomic_numbers, covalent_radii
>>> atomic_numbers[’Cu’]
29
>>> covalent_radii[29]
1.1699999999999999
7.5 File input and output
The ase.io module has two basic functions: read() and write(). The two methods are described here:
7.3. Units
83
ASE Manual, Release 3.9.0.3865
ase.io.read(filename, index=None, format=None)
Read Atoms object(s) from file.
filename: str Name of the file to read from.
index: int or slice If the file contains several configurations, the last configuration will be returned by
default. Use index=n to get configuration number n (counting from zero).
format: str Used to specify the file-format. If not given, the file-format will be guessed by the filetype
function.
Known formats:
format
short name
GPAW restart-file
gpw
Dacapo netCDF output file
dacapo
Old ASE netCDF trajectory
nc
Virtual Nano Lab file
vnl
ASE pickle trajectory
traj
ASE bundle trajectory
bundle
GPAW text output
gpaw-text
CUBE file
cube
XCrySDen Structure File
xsf
Dacapo text output
dacapo-text
XYZ-file
xyz
VASP POSCAR/CONTCAR file vasp
VASP OUTCAR file
vasp_out
SIESTA STRUCT file
struct_out
ABINIT input file
abinit
V_Sim ascii file
v_sim
Protein Data Bank
pdb
CIF-file
cif
FHI-aims geometry file
aims
FHI-aims output file
aims_out
VTK XML Image Data
vti
VTK XML Structured Grid
vts
VTK XML Unstructured Grid
vtu
TURBOMOLE coord file
tmol
TURBOMOLE gradient file
tmol-gradient
exciting input
exi
AtomEye configuration
cfg
WIEN2k structure file
struct
DftbPlus input file
dftb
CASTEP geom file
cell
CASTEP output file
castep
CASTEP trajectory file
geom
ETSF format
etsf.nc
DFTBPlus GEN format
gen
CMR db/cmr-file
db
CMR db/cmr-file
cmr
LAMMPS dump file
lammps
EON reactant.con file
eon
Gromacs coordinates
gro
Gaussian com (input) file
gaussian
Gaussian output file
gaussian_out
Quantum espresso in file
esp_in
Quantum espresso out file
esp_out
Extended XYZ file
extxyz
Continued on next page
84
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Table 7.1 – continued from previous page
format
short name
NWChem input file
nw
ase.io.write(filename, images, format=None, **kwargs)
Write Atoms object(s) to file.
filename: str Name of the file to write to.
images: Atoms object or list of Atoms objects A single Atoms object or a list of Atoms objects.
format: str Used to specify the file-format. If not given, the file-format will be taken from suffix of the
filename.
The accepted output formats:
format
ASE pickle trajectory
ASE bundle trajectory
CUBE file
XYZ-file
VASP POSCAR/CONTCAR file
ABINIT input file
Protein Data Bank
CIF-file
XCrySDen Structure File
FHI-aims geometry file
gOpenMol .plt file
Python script
Encapsulated Postscript
Portable Network Graphics
Persistance of Vision
VTK XML Image Data
VTK XML Structured Grid
VTK XML Unstructured Grid
TURBOMOLE coord file
exciting
AtomEye configuration
WIEN2k structure file
CASTEP cell file
DftbPlus input file
ETSF
DFTBPlus GEN format
CMR db/cmr-file
CMR db/cmr-file
EON reactant.con file
Gromacs coordinates
GROMOS96 (only positions)
X3D
X3DOM HTML
Extended XYZ file
short name
traj
bundle
cube
xyz
vasp
abinit
pdb
cif
xsf
aims
plt
py
eps
png
pov
vti
vts
vtu
tmol
exi
cfg
struct
cell
dftb
etsf.nc
gen
db
cmr
eon
gro
g96
x3d
html
extxyz
The use of additional keywords is format specific.
The cube and plt formats accept (plt requires it) a data keyword, which can be used to write a 3D array
to the file along with the nuclei coordinates.
The vti, vts and vtu formats are all specifically directed for use with MayaVi, and the latter is designated
for visualization of the atoms whereas the two others are intended for volume data. Further, it should be
7.5. File input and output
85
ASE Manual, Release 3.9.0.3865
noted that the vti format is intended for orthogonal unit cells as only the grid-spacing is stored, whereas
the vts format additionally stores the coordinates of each grid point, thus making it useful for volume date
in more general unit cells.
The eps, png, and pov formats are all graphics formats, and accept the additional keywords:
rotation: str (default �’) The rotation angles, e.g. �45x,70y,90z’.
show_unit_cell: int (default 0) Can be 0, 1, 2 to either not show, show, or show all of the unit cell.
radii: array or float (default 1.0) An array of same length as the list of atoms indicating the sphere radii.
A single float specifies a uniform scaling of the default covalent radii.
bbox: 4 floats (default None) Set the bounding box to (xll, yll, xur, yur) (lower left, upper right).
colors: array (default None) An array of same length as the list of atoms, indicating the rgb color code
for each atom. Default is the jmol_colors of ase/data/colors.
scale: int (default 20) Number of pixels per Angstrom.
For the pov graphics format, scale should not be specified. The elements of the color array can additionally be strings, or 4 and 5 vectors for named colors, rgb + filter, and rgb + filter + transmit specification.
This format accepts the additional keywords:
run_povray, display, pause, transparent, canvas_width, canvas_height,
camera_dist, image_plane, camera_type, point_lights, area_light, background,
textures, celllinewidth, bondlinewidth, bondatoms
The xyz format accepts a comment string using the comment keyword:
comment: str (default �’) Optional comment written on the second line of the file.
The read() function is only designed to retrieve the atomic configuration from a file, but for the CUBE format
you can import the function:
ase.io.read_cube_data()
which will return a (data, atoms) tuple:
from ase.io.cube import read_cube_data
data, atoms = read_cube_data(’abc.cube’)
7.6 Examples
from ase.lattice.surface import *
adsorbate = Atoms(’CO’)
adsorbate[1].z = 1.1
a = 3.61
slab = fcc111(’Cu’, (2, 2, 3), a=a, vacuum=7.0)
add_adsorbate(slab, adsorbate, 1.8, ’ontop’)
Write PNG image:
write(’slab.png’, slab * (3, 3, 1), rotation=’10z,-80x’)
86
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Write POVRAY file:
write(’slab.pov’, slab * (3, 3, 1), rotation=’10z,-80x’)
This will write both a slab.pov and a slab.ini file. Convert to PNG with the command povray
slab.ini or use the run_povray=True option:
Here is an example using bbox:
d = a / 2**0.5
write(’slab.pov’, slab * (2, 2, 1),
bbox=(d, 0, 3 * d, d * 3**0.5))
Note that the XYZ-format does not contain information about the unic cell:
>>> write(’slab.xyz’, slab)
>>> a = read(’slab.xyz’)
>>> a.get_cell()
array([[ 1., 0., 0.],
[ 0., 1., 0.],
7.6. Examples
87
ASE Manual, Release 3.9.0.3865
[ 0., 0., 1.]])
>>> a.get_pbc()
array([False, False, False], dtype=bool)
Use ASE’s native format for writing all information:
>>> write(’slab.traj’, slab)
>>> b = read(’slab.traj’)
>>> b.get_cell()
array([[ 5.10531096e+00, -4.11836034e-16,
[ 2.55265548e+00,
4.42132899e+00,
[ 8.11559027e+00,
4.68553823e+00,
>>> b.get_pbc()
array([ True, True, True], dtype=bool)
1.99569088e-16],
7.11236625e-17],
1.32527034e+01]])
A script showing all of the povray parameters, and generating the image below, can be found here:
save_pov.py
An other example showing how to change colors and textures in pov can be found here:
../tutorials/saving_graphics.py.
7.7 ASE-GUI
The graphical user-interface allows users to visualize, manipulate, and render molecular systems and atoms objects. It also allows to setup and run a number of calculations and can be used to transfer between different file
formats.
88
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
7.7.1 ase-gui basics and command line options
General use
Visualizing a system with ase-gui is straight-forward using a regular mouse. The scroll function allows to change
the magnification, the left mouse button selects atoms, the right mouse button allows to rotate, and the middle
button allows to translate the system on the screen.
Depending on the number of selected atoms, ase-gui automatically measures different quantities:
Selection
single atom
two atoms
three atoms
four atoms, selected sequentially
more than four atoms
measurement
xyz position and atomic symbol
interatomic distance and symbols
all three internal angles and symbols
Measures the dihedral angle, e.g. the angle between bonds 12 and 34
chemical composition of selection.
ase-gui can save the following file formats:
File format
xyz
traj
pdb
cube
py
vnl
png
pov
eps
in
POSCAR
bundle
cif
Comment
XYZ file
ASE trajectory
PDB file
Gaussian cube file
Python script
VNL file
Portable Network Graphics
Persistance of Vision
Encapsulated PostScript
FHI-aims geometry input
VASP geometry input
ASE bundle trajectory
Crystallographic Information File
Files
The ase-gui program can read all the file formats the ASE’s read() function can understand.
$ ase-gui N2Fe110-path.traj
7.7. ASE-GUI
89
ASE Manual, Release 3.9.0.3865
Selecting part of a trajectory
A Python-like syntax for selecting a subset of configurations can be used.
list[start:stop:step], you use filaname@start:stop:step:
$
$
$
$
$
$
$
ase-gui
ase-gui
ase-gui
ase-gui
ase-gui
ase-gui
ase-gui
x.traj@0:10:1
x.traj@0:10
x.traj@:10
x.traj@-10:
x.traj@0
x.traj@-1
x.traj@::2
#
#
#
#
#
#
#
Instead of the Python syntax
first 10 images
first 10 images
first 10 images
last 10 images
first image
last image
every second image
If you want to select the same range from many files, the you can use the -n or --image-number option:
$ ase-gui -n -1 *.traj
$ ase-gui -n 0 *.traj
# last image from all files
# first image from all files
Tip: Type ase-gui -h for a description of all command line options.
Writing files
$ ase-gui -n -1 a*.traj -o new.traj
Possible formats are: traj, xyz, cube, pdb, eps, png, and pov. For details, see the io module documentation.
Interactive use
The ase-gui program can also be launched directly from a Python script or interactive session:
>>> from ase import *
>>> atoms = ...
>>> view(atoms)
or
>>> view(atoms, repeat=(3, 3, 2))
or, to keep changes to your atoms:
>>> atoms.edit()
NEB calculations
Use Tools в†’ NEB to plot energy barrier.
$ ase-gui --interpolate 3 initial.xyz final.xyz -o interpolated_path.traj
Plotting data from the command line
Plot the energy relative to the energy of the first image as a function of the distance between atom 0 and 5:
$ ase-gui -g "d(0,5),e-E[0]" x.traj
$ ase-gui -t -g "d(0,5),e-E[0]" x.traj > x.dat
# No GUI, write data to stdout
The symbols are the same as used in the plotting data function.
90
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Defaults for ase-gui
Using a file ~/.ase/gui.py, certain defaults can be set. If it exists, this file is executed after initializing the
variables and colours normally used in ase-gui. One can change the default graphs that are plotted, and the default
radii for displaying specific atoms. This example will display the energy evolution and the maximal force in a
graph and also display Cu atoms (Z=29) with a radius of 1.6 Angstrom.
gui_default_settings[’gui_graphs_string’] = "i, e - min(E), fmax"
gui_default_settings[’covalent_radii’] = [[29,1.6]]
High contrast settings for ase-gui
In revision 2600 or later, it is possible to change the foreground and background colors used to draw the atoms,
for instance to draw white graphics on a black background. This can be done in ~/.ase/gui.py.
gui_default_settings[’gui_foreground_color’] = ’#ffffff’ #white
gui_default_settings[’gui_background_color’] = ’#000000’ #black
To change the color scheme of graphs it is necessary to change the default behaviour of Matplotlib in a similar
way by using a file ~/.matplotlib/matplotlibrc.
patch.edgecolor
text.color
axes.facecolor
axes.edgecolor
axes.labelcolor
axes.color_cycle
xtick.color
ytick.color
grid.color
figure.facecolor
figure.edgecolor
:
:
:
:
:
:
:
:
:
:
:
white
white
black
white
white
b, g, r, c, m, y, w
white
white
white
0.1
black
Finally, the color scheme of the windows themselves (i.e. menus, buttons and text etc.) can be changed by
choosing a different desktop theme. In Ubuntu it is possible to get white on a dark background by selecting the
theme HighContrastInverse under Appearances in the system settings dialog.
7.7.2 Edit
Add atoms
Allows to add single atoms or a group of atoms to an existing atoms object. If the description is an atom or a
known molecule from the g1, g2, or g3 set (e.g. CH4), then the structure from the data molecule is used. In
addition, a molecule can also be imported from file via the load molecule button.
The specified position can either be absolute, or determined automatically via
auto+<dist>
where auto is the centre of mass of the currently selected atoms, and <dist> is the distance toward the viewing
plane.
The molecule-to-be is rotated into the current viewing plane before addition into the system. Two options exist for
choosing the origin within the new atoms, it can be either the centre of mass or the origin of the loaded geometry.
Modify
Menu to allow modification of the atomic symbol, an attached tag, or its magnetic moment.
7.7. ASE-GUI
91
ASE Manual, Release 3.9.0.3865
Copy/Paste
Allows to copy parts of an existing system to a clipboard, and pastes via the same infrastructure as the Add
atoms functionality. Note that the on-screen orientation of the pasted atoms will be the same as at the time of
copying. Note also that, by default, the origin of the pasted system is taken to be the atom furthest away from the
viewing point.
7.7.3 View
Repeat
Menu to allow repetition of periodic unit cells. Use the �Set unit cell’ button to set the overall unit cell to the
current one.
Rotate
Menu to manually fine tune the viewing angle. Use �Update’ button to set the menu to the current angle.
Colors
The colors menu allows numerous ways to change the color scheme and to encode additional information into
the display colors. This includes automatic coloring by atomic numbers (default), user-specified atomic number
scheme, coloring by tags, forces, or completely manually specified colors. In addition, several standard color
scales are available.
Settings
Basic viewing settings. Also allows to constrain/unconstrain atoms and to mark selected atoms as invisible.
7.7.4 Tools
Graphs
Allows to graph different quantities for a given trajectory. A �save’ button also gives the opportunity to save the
data to file.
This example plots the maximal force for each image i and could help in investigating the convergence properties
for relaxations:
i, e-min(E), fmax
These are the symbols that can be used:
92
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Symbol
e
epot
ekin
fmax
fave
d(n1,n2)
R[n,0-2]
i
E[i]
F[n,0-2]
M[n]
A[0-2,0-2]
s
a(n1,n2,n3)
dih(n1,n2,n3,n4)
T
Interpretation
total energy
potential energy
kinetic energy
maximum force
average force
distance between two atoms
position of atom number n
current image number
energy of image number i
force on atom number n
magnetic moment of atom number n
unit-cell basis vectors
path length
tangle between atoms n1, n2 and n3, centered on n2
dihedral angle between n1, n2, n3, and n4
temperature (requires velocity)
Movie
Allows to play the current trajectory as a movie using a number of different settings. Default duration is 5 s.
Expert mode
Python interface to all ase-gui functions, with numerous extra commands defined that help to modify and visualize
a system. The commands come in two flavors, the first is interpreted on an atom-by-atom basis (e.g. operates on
position, color, etc) and the second is based on the entire frame. The flavor of a given line is determined from the
first command. Note that the frame-based commands can be used in atom-based operations, but not vice versa.
See below for some examples.
Regular python syntax applies to the commands and numpy has been imported as np.
Two buttons allow to reduce the operation to a given frame:
Only selected
atoms (sa)
Only current
frame (cf)
Restricts operation only to the selected atoms. The text command sa activates or
deactivates this button.
Restricts operation only to the current frame, useful for long trajectories. The text
command cf activates or deactivates this button.
List of atom-based commands with a few examples:
Command
x,y,z
r,g,b
rad
s
f
Z
m
d
Interpretation
Cartesian coordinates. Example: x += A[0][0]
Color components, invoking the expert mode changes the color mode to manual and allows to
address all colors individually. Example: r =
(z-min(R[:,2]))/(max(R[:,2])-min(R[:,2]))
atomic display radius
Boolean to control the selection of an atom. Example: s = Z == 6 and x > 5 or s = d
== False
force on an atom
atomic number
magnetic moment
dynamic, e.g. d = False fixes an atom
List of frame-based and global commands and global objects with examples:
7.7. ASE-GUI
93
ASE Manual, Release 3.9.0.3865
Command
e
fmax
A
E
F
M
R
S
D
del S
sa,cf
frame
center
cov
self
gui
img
Interpretation
total energy
maximal force
unit cell
total energy array of all frames. Example: e-min(E)
all forces in one frame
all magnetic moments
all atomic positions
boolean array of the entire selection
boolean array of dynamic atoms (False = atom is fixed)
deletes current selection
toggles the selected-atoms-only or the current-frame-only buttons
provides and edits the frame number in a trajectory
centers system in its unit cell
array of original covalent radii
expert mode window
ase-gui GUI object, this controls the entire ase-gui session
ase-gui images object, all physical data is stored here
To save data between commands, one has to assign variables to parent objects in the gui, e.g. via
self.temp_var = R-img.P[0,:]. DISCLAIMER: Doing so might risk the functionality of the entire
ase-gui session if you accidentally overwrite basic functionality of the gui or the image objects stored within.
Finally, recurring selections of commands collected as scripts can be executed as
exec <filename>
If the file in question is saved in the directory ~/.ase/ then just the filename will also do.
Constraints
Allows to set (or remove) constraints based on the currently selected atoms.
Render scene
Graphical interface to the ASE povray interface, ideally it requires that povray is installed on your computer to
function, but it also can be used just to export the complete set of povray files.
The texture of each atom is adjustable: The default texture is applied to all atoms, but then additional textures
can be defined based on selections (Create new texture from current selection). These can be
obtained either from selecting atoms by hand or by defining a selection with a boolean expression, for example
Z==6 and x>5 and y<0 will select all carbons with coordinates x>5 and y<0. The available commands are
listed in the Help on textures window.
A movie-making mode (render all N frames) is also available. After rendering, the frames can be stitched
together using the convert unix program e.g.
localhost:doc hanke$ convert -delay 4.17 temp.*.png temp.gif
For this particular application it might be a good idea to use a white background instead of the default transparent
option.
Move atoms
Allows selected atoms to be moved using the arrow keys. The direction is always parallel to the plane of the
screen. Two possible movements are available: Just pressing the arrow keys will move by 0.1 Angstrom, shift
+ arrow keys will move by 0.01 Angstrom.
94
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Rotate atoms
Allows sets of atoms to be rotated using the arrow keys. Different rotation modes are available depending on the
number of selected atoms. Again, two modes are available. Just the arrow keys will rotate by 2.5 degrees, and
shift + arrow keys will rotate by 0.5 deg.
number of
atoms labeled
0 atoms, 1, 3, 5
or more atoms
2 atoms
4 atoms,
selected
sequentially
rotation mode
uses the centre of mass of the atoms to be rotated as the rotation centre.
Defines the vector connecting the two atoms as rotation axis.
Defines the vector connecting the two atoms as rotation axis. This mode has the advantage
that the dihedral angle is measured at the same time, thus allowing one to monitor the
degree of rotation.
Orient atoms
stub
NEB
stub
Bulk Modulus
stub
7.7.5 Setup
The setup menus allow for the intuitive creation of numerous standard surfaces, nanoparticles, graphene and
graphene nanoribbons, as well as nanotubes.
Along with creating the geometry within ase-gui, a button provides the necessary python code allowing one to
recreate the exact same geometry in ASE scripts.
7.7.6 Calculate
Set calculator
Allows gui to choose a calculator for internal computations (see below). Different density functional codes and
force fields, as well as the EMT calculator are available. For the FHI-aims and VASP calculators, it is also possible
to export an entire set of input files.
Energy and forces
Invokes the currently set calculator and provides energies and optional forces for all atoms.
Energy minimization
Runs an ASE relaxation using the currently selected calculator with a choice of relaxation algorithm and convergence criteria. Great for quickly (pre-)relaxing a molecule before placing it into a bigger system.
7.7. ASE-GUI
95
ASE Manual, Release 3.9.0.3865
Scale system
Stub
7.8 Command line tool
Warning: This was an experiment that went bad! Don’t use it!
The ase program can be used to do calculations with ASE supported calculators on the command line without
having to write a Python script. The syntax is:
$ ase [calculator] [task] [options] system(s)
The name of the calculator must be lower case and will default to EMT. The task must be molecule or bulk.
There are several ways to specify the system or systems to perform the calculations on:
• Chemical names: H2O or Fe. Default molecule definitions are used.
• Range of chemical symbols: Sc-Zn (3d-metals)
• Special names: G2, G2_1 or S22
• File names: benzene.xyz or slab.traj
The exact meaning of these names will depend on the task.
Simple examples:
$ ase emt H2 --relax=0.01
$ ase abinit bulk Si -a 5.5 -p ecut=150 -k 4,4,4
7.8.1 Command line options
General options:
-h, --help
Show help message and exit.
-t TAG, --tag=TAG
String tag added to filenames.
-M <M1,M2,...>, --magnetic-moment=<M1,M2,...> Magnetic moment(s). Use “-M 1” or “-M
2.3,-2.3”.
-G, --gui
Pop up ASE’s GUI.
-s, --write-summary Write summary.
--slice=<start:stop:step> Select subset of calculations using Python slice syntax. Use ”::2” to do
every second calculation and ”:-5” to do the last five.
-w FILENAME, --write-to-file=FILENAME Write configuration to file.
-i, --interactive-python-session Run calculation inside interactive Python session. A possible
$PYTHONSTARTUP script will be imported and the “atoms” variable refers
to the Atoms object.
-l, --use-lock-files
Skip calculations where the json lock-file or result file already exists.
-R FMAX, --relax=FMAX Relax internal coordinates using L-BFGS algorithm.
-F <N,x>, --fit=<N,x> Find optimal bondlength and vibration frequency for dimer molecules or
optimal volume and bulk modulus for bulk systems using N points and a
variation from -x % to +x % for the bondlength or lattice constants.
--constrain-tags=<T1,T2,...> Constrain atoms with tags T1, T2, ...
96
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
-k <K1,K2,K3>, --monkhorst-pack=<K1,K2,K3> Monkhorst-Pack sampling of BZ. Example:
“4,4,4”: 4x4x4 k-points, “4,4,4g”: same set of k-points shifted to include the
Gamma point.
--k-point-density=K_POINT_DENSITY Density of k-points in Г….
-p <key=value,...>, --parameters=<key=value,...> Comma-separated key=value pairs of calculator specific parameters.
Options specific to the molecule task:
-v VACUUM, --vacuum=VACUUM Amount of vacuum to add around isolated systems (in
Angstrom).
--unit-cell=CELL
Unit cell. Examples: “10.0” or “9,10,11” (in Angstrom).
--bond-length=BOND_LENGTH Bond length of dimer in Angstrom.
--atomize
Calculate Atomization energies.
Options specific to the bulk task:
-x CRYSTAL_STRUCTURE, --crystal-structure=CRYSTAL_STRUCTURE Crystal
ture.
struc-
-a LATTICE_CONSTANT, --lattice-constant=LATTICE_CONSTANT Lattice constant in Г….
--c-over-a=C_OVER_A c/a ratio.
-O, --orthorhombic Use orthorhombic unit cell.
-C, --cubic
Use cubic unit cell.
-r REPEAT, --repeat=REPEAT Repeat unit cell. Use “-r 2” or “-r 2,3,1”.
7.8.2 Molecules
Example:
$ ase abinit H2 -p ecut=200,xc=LDA -F 5,1 --atomize
This will calculate the energy of a H2 molecule using Abinit with a planewave cutoff of 200 eV and the LDA
XC-functional. A fit using 5 points and a variation of the bond length from -1 % to +1 % is made and in addition
the energy of a single hydrogen atom is also calculated.
Results are written to json files and can be analysed with:
$ ase abinit H H2 -s
name
E
eV
H2
-29.703
H
-12.426
E-E0
eV
0.022
d0
Ang
0.770
hnu
meV
556.096
Ea
eV
4.852
Ea0
eV
4.873
Note: The json files are simple text files that can be more or less’ed or pretty printed with python -m
json.tool H2-molecule-abinit.jon.
7.8.3 Bulk systems
Example:
$ ase bulk Ni Cu Pd Ag Pt Au -F 5,1
Here we used the default EMT potential and the result is:
7.8. Command line tool
97
ASE Manual, Release 3.9.0.3865
$ ase bulk Ni Cu Pd Ag Pt Au -s
name
E
E-E0
eV
eV
Ni
-0.009
0.005
Ag
0.002
0.002
Pt
-0.000
0.000
Au
0.003
0.003
Pd
0.000
0.001
Cu
-0.006
0.001
V0
Ang^3
10.600
16.775
15.080
16.684
14.588
11.565
B
GPa
175.978
100.151
278.087
173.868
179.105
134.439
More examples
Anti-ferromagnetic bcc iron:
$ ase vasp bulk -x bcc Fe -C -M 2.3,-2.3 -p xc=PBE -k 8,8,8
Bulk silicon (128 atoms, О“ point only):
$ ase abinit bulk Si -r 4,4,4 -k 1,1,1 -a 5.46
Bulk aluminum in orthorhombic cell with LDA and fixed rmt:
$ ase elk bulk --orthorhombic Al -k 4,4,4 -a 4.05 -p "swidth=0.1,rmt={’Al’: 1.9}"
7.8.4 Batch jobs
Suppose you want to run a large number of similar calculations like relaxing the structure of all the molecules in
the G2-1 database. You could do that by submitting this job to your compute cluster:
$ ase gpaw G2_1 -v 6.0 -p xc=vdW-DF,h=0.18 -R 0.02
The molecule task will expand G2_1 to a lot of molecules, so it makes sense to use -l option
(--use-lock-files) and submit the same job many times. A lock file will be created for each started calculation and calculations with existing lock file skipped. Moreover the calculations can be run in parallel (if parallel
version of GPAW is installed):
$ mpiexec gpaw-python �which ase� gpaw G2_1 -v 6.0 -p xc=vdW-DF,h=0.18 -R 0.02 -l
7.8.5 Making your own tasks
FCC clusters with 13 atoms
Put this in m13.py:
from
from
from
from
math import sqrt
ase.cluster.cubic import FaceCenteredCubic
ase.tasks.molecule import MoleculeTask
ase.data import covalent_radii, atomic_numbers
class M13Task(MoleculeTask):
taskname = ’m13’
def build_system(self, name):
if self.bond_length is None:
b = 2 * covalent_radii[atomic_numbers[name]]
else:
b = self.bond_length
return FaceCenteredCubic(name, [(1, 0, 0)], [1],
latticeconstant=b * sqrt(2))
98
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
task = M13Task()
Then do this:
$ ase m13.py Pt -R 0.01
The relaxed EMT bondlength of 2.62 Г… can be extracted from the created trajectory like this:
$ ase-gui -tg
10.9824302706
10.0805658256
9.61654400875
9.57510700742
9.57424531861
"e,fmax,d(0,9)" Pt-m13-emt.traj
2.27575724833 2.72
1.45353946744 2.68
0.447140179352 2.64
0.0656434401881 2.6222281202
0.00239771758341 2.62450316817
or like this:
>>> from ase.io import read
>>> pt = read(’Pt-m13-emt.traj’)
>>> pt.get_distance(0, 9)
2.6245031681662452
Convergence test
See convergence.py.
7.8.6 To be done
• Optimize c/a ratio.
• Implement different way of cell sampling for eos: [a0 + s for s in [x * np.array(range(- N/2 + 1, N/2 +
1))]] where x is sampling step length, N number of steps. Current way of sampling gives different length of
sampling interval depending on the lattice constant guess a0. DONE
• Write results to file (pickel, csv, cmr (db), traj, ...) per system, together with json file!
• Split off EnergyTask from Task.
• Set correct magnetic moments for atoms. DONE
• Allow setting charges in ase.tasks.task
• Check occupation numbers and requested total magnetic moments for molecules/atoms. DONE
• Add –exclude option.
• Relax cell. DONE
• Optimize first then fit. DONE
• Behavior of -w option?
• Reaction task?
• Rethink analysis and summary stuff:
– it would be nice to calculate for example cohesive energies on the command line, i.e. using
species belonging to different tasks
– analysis should be more modular: one may want for example to calculate zpe energies for adsorption systems including molecules and surfaces and print the zpe correction for a given reaction.
• ase.tasks.main - print complete architecture string in case of error (like in ase/test/__init__.py)
7.8. Command line tool
99
ASE Manual, Release 3.9.0.3865
7.9 Creating atomic structures
See Also:
• The ase.lattice module
• The spacegroup module
• The surface module
7.9.1 Molecules
The G2-database of common molecules is available:
ase.structure.molecule(name, data=None, **kwargs)
Create formula base on data. If data is None assume G2 set. kwargs currently not used.
Example:
>>> from ase.structure import molecule
>>> atoms = molecule(’H2O’)
7.9.2 Common bulk crystals
ase.lattice.bulk(name, crystalstructure=None, a=None, c=None, covera=None, orthorhombic=False, cubic=False)
Creating bulk systems.
Crystal structure and lattice constant(s) will be guessed if not provided.
name: str Chemical symbol or symbols as in �MgO’ or �NaCl’.
crystalstructure: str Must be one of sc, fcc, bcc, hcp, diamond, zincblende, rocksalt, cesiumchloride,
fluorite or wurtzite.
a: float Lattice constant.
c: float Lattice constant.
covera: float c/a raitio used for hcp. Default is ideal ratio: sqrt(8/3).
orthorhombic: bool Construct orthorhombic unit cell instead of primitive cell which is the default.
cubic: bool Construct cubic unit cell if possible.
examples:
>>> from ase.lattice import bulk
>>> a1 = bulk(’Cu’, ’fcc’, a=3.6)
>>> a2 = bulk(’Cu’, ’fcc’, a=3.6, orthorhombic=True)
>>> a3 = bulk(’Cu’, ’fcc’, a=3.6, cubic=True)
>>> a1.cell
array([[ 0. , 1.8, 1.8],
[ 1.8, 0. , 1.8],
[ 1.8, 1.8, 0. ]])
>>> a2.cell
array([[ 2.54558441, 0.
, 0.
],
[ 0.
, 2.54558441, 0.
],
[ 0.
, 0.
, 3.6
]])
>>> a3.cell
array([[ 3.6, 0. , 0. ],
[ 0. , 3.6, 0. ],
[ 0. , 0. , 3.6]])
100
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
7.9.3 Nanotubes
ase.structure.nanotube(n, m, length=1, bond=1.42, symbol=’C’, verbose=False)
examples:
>>> from ase.structure import nanotube
>>> cnt1 = nanotube(6, 0, length=4)
>>> cnt2 = nanotube(3, 3, length=6, bond=1.4, symbol=’Si’)
7.9.4 Graphene nanoribbons
ase.structure.graphene_nanoribbon(n, m, type=’zigzag’, saturated=False, C_H=1.09,
C_C=1.42,
vacuum=2.5,
magnetic=None,
initial_mag=1.12,
sheet=False,
main_element=’C’,
saturate_element=’H’, vacc=None)
Create a graphene nanoribbon.
Creates a graphene nanoribbon in the x-z plane, with the nanoribbon running along the z axis.
Parameters:
n: int The width of the nanoribbon.
m: int The length of the nanoribbon.
type: str The orientation of the ribbon. Must be either �zigzag’ or �armchair’.
saturated: bool If true, hydrogen atoms are placed along the edge.
C_H: float Carbon-hydrogen bond length. Default: 1.09 Angstrom.
C_C: float Carbon-carbon bond length. Default: 1.42 Angstrom.
vacuum: float Amount of vacuum added to both sides. Default 2.5 Angstrom.
magnetic: bool Make the edges magnetic.
initial_mag: float Magnitude of magnetic moment if magnetic=True.
sheet: bool If true, make an infinite sheet instead of a ribbon.
examples:
7.9. Creating atomic structures
101
ASE Manual, Release 3.9.0.3865
>>> from ase.structure import graphene_nanoribbon
>>> gnr1 = graphene_nanoribbon(3, 4, type=’armchair’, saturated=True)
>>> gnr2 = graphene_nanoribbon(2, 6, type=’zigzag’, saturated=True,
>>>
C_H=1.1, C_C=1.4, vacuum=6.0,
>>>
magnetic=True, initial_mag=1.12)
7.9.5 Surfaces
Common surfaces
A number of utility functions are provided to set up the most common surfaces, to add vacuum layers, and to add
adsorbates to a surface. In general, all surfaces can be set up with the modules described in the section General
crystal structures and surfaces, but these utility functions make common tasks easier.
Example
To setup an Al(111) surface with a hydrogen atom adsorbed in an on-top position:
from ase.lattice.surface import fcc111
slab = fcc111(’Al’, size=(2,2,3), vacuum=10.0)
This will produce a slab 2x2x3 times the minimal possible size, with a (111) surface in the z direction. A 10 Г…
vacuum layer is added on each side.
To set up the same surface with with a hydrogen atom adsorbed in an on-top position 1.5 Г… above the top layer:
from ase.lattice.surface import fcc111, add_adsorbate
slab = fcc111(’Al’, size=(2,2,3))
add_adsorbate(slab, ’H’, 1.5, ’ontop’)
slab.center(vacuum=10.0, axis=2)
Note that in this case is is probably not meaningful to use the vacuum keyword to fcc111, as we want to leave 10
Г… of vacuum after the adsorbate has been added. Instead, the center() method of the Atoms is used to add
the vacuum and center the system.
The atoms in the slab will have tags set to the layer number: First layer atoms will have tag=1, second layer atoms
will have tag=2, and so on. Adsorbates get tag=0:
>>> print atoms.get_tags()
[3 3 3 3 2 2 2 2 1 1 1 1 0]
This can be useful for setting up ase.constraints (see Diffusion of gold atom on Al(100) surface (NEB)).
102
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Utility functions for setting up surfaces
All the functions setting up surfaces take the same arguments.
symbol: The chemical symbol of the element to use.
size: A tuple giving the system size in units of the minimal unit cell.
a: (optional) The lattice constant. If specified, it overrides the expermental lattice constant of the element. Must
be specified if setting up a crystal structure different from the one found in nature.
c: (optional) Extra HCP lattice constant. If specified, it overrides the expermental lattice constant of the element.
Can be specified if setting up a crystal structure different from the one found in nature and an ideal c/a ratio
is not wanted (c/a = (8/3)1/2 ).
vacuum: The thickness of the vacuum layer. The specified amount of vacuum appears on both sides of the slab.
Default value is None, meaning not to add any vacuum. In that case a “vacuum” layer equal to the interlayer
spacing will be present on the upper surface of the slab. Specify vacuum=0.0 to remove it.
orthogonal: (optional, not supported by all functions). If specified and true, forces the creation of a unit cell with
orthogonal basis vectors. If the default is such a unit cell, this argument is not supported.
Each function defines a number of standard adsorption sites that can later be used when adding an adsorbate with
ase.lattice.surface.add_adsorbate().
The following functions are provided
ase.lattice.surface.fcc100(symbol, size, a=None, vacuum=0.0)
ase.lattice.surface.fcc110(symbol, size, a=None, vacuum=0.0)
ase.lattice.surface.bcc100(symbol, size, a=None, vacuum=0.0)
ase.lattice.surface.hcp10m10(symbol, size, a=None, c=None, vacuum=0.0)
ase.lattice.surface.diamond100(symbol, size, a=None, vacuum=0.0)
These allways give orthorhombic cells:
7.9. Creating atomic structures
103
ASE Manual, Release 3.9.0.3865
fcc100
fcc110
bcc100
hcp10m10
diamond100
ase.lattice.surface.fcc111(symbol, size, a=None, vacuum=0.0, orthogonal=False)
ase.lattice.surface.fcc211(symbol, size, a=None, vacuum=0.0, orthogonal=True)
ase.lattice.surface.bcc110(symbol, size, a=None, vacuum=0.0, orthogonal=False)
ase.lattice.surface.bcc111(symbol, size, a=None, vacuum=0.0, orthogonal=False)
104
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
ase.lattice.surface.hcp0001(symbol, size, a=None, c=None, vacuum=0.0, orthogonal=False)
ase.lattice.surface.diamond111(symbol, size, a=None, vacuum=0.0, orthogonal=False)
These can give both non-orthorhombic and orthorhombic cells:
7.9. Creating atomic structures
105
ASE Manual, Release 3.9.0.3865
fcc111
fcc211
not implemented
bcc110
bcc111
hcp0001
106
diamond111
Chapter 7. Documentation for modules in ASE
not implemented
ASE Manual, Release 3.9.0.3865
The adsorption sites are marked with:
ontop
hollow
fcc
hcp
bridge
shortbridge
longbridge
Adding new utility functions If you need other surfaces than the ones above, the easiest is to look in the source
file surface.py, and adapt one of the existing functions. Please contribute any such function that you make either
by checking it into SVN or by mailing it to the developers.
Adding adsorbates
After a slab has been created, a vacuum layer can be added. It is also possible to add one or more adsorbates.
ase.lattice.surface.add_adsorbate(slab, adsorbate, height, position=(0, 0), offset=None,
mol_index=0)
Add an adsorbate to a surface.
This function adds an adsorbate to a slab. If the slab is produced by one of the utility functions in
ase.lattice.surface, it is possible to specify the position of the adsorbate by a keyword (the supported keywords depend on which function was used to create the slab).
If the adsorbate is a molecule, the atom indexed by the mol_index optional argument is positioned on top
of the adsorption position on the surface, and it is the responsibility of the user to orient the adsorbate in a
sensible way.
This function can be called multiple times to add more than one adsorbate.
Parameters:
slab: The surface onto which the adsorbate should be added.
adsorbate: The adsorbate. Must be one of the following three types: A string containing the chemical
symbol for a single atom. An atom object. An atoms object (for a molecular adsorbate).
height: Height above the surface.
position: The x-y position of the adsorbate, either as a tuple of two numbers or as a keyword (if the surface is produced by one of the functions in ase.lattice.surfaces).
offset (default: None): Offsets the adsorbate by a number of unit cells.
more than one adsorbate.
Mostly useful when adding
mol_index (default: 0): If the adsorbate is a molecule, index of the atom to be positioned above the location specified by the position argument.
Note position is given in absolute xy coordinates (or as a keyword), whereas offset is specified in unit cells.
This can be used to give the positions in units of the unit cell by using offset instead.
ase.lattice.surface.add_vacuum(atoms, vacuum)
Add vacuum layer to the atoms.
Parameters:
atoms: An Atoms object most likely created by one of the ase.lattice modules.
vacuum: The thickness of the vacuum layer (in Angstrom).
Create specific non-common surfaces
New in version 3.5.2. In addition to the most normal surfaces, a function has been constructed to create more
uncommon surfaces that one could be interested in. It is constructed upon the Miller Indices defining the surface
and can be used for both fcc, bcc and hcp structures. The theory behind the implementation can be found here:
general_surface.pdf.
7.9. Creating atomic structures
107
ASE Manual, Release 3.9.0.3865
ase.lattice.surface.surface(lattice, indices, layers, vacuum=0.0, tol=1e-10)
Create surface from a given lattice and Miller indices.
lattice: Atoms object or str Bulk lattice structure of alloy or pure metal. One can also give the chemical
symbol as a string, in which case the correct bulk lattice will be generated automatically.
indices: sequence of three int Surface normal in Miller indices (h,k,l).
layers: int Number of equivalent layers of the slab.
vacuum: float Amount of vacuum added on both sides of the slab.
Example
To setup a Au(211) surface with 9 layers and 10 Г… of vacuum:
from ase.lattice.surface import surface
s1 = surface(’Au’, (2, 1, 1), 9)
s1.center(vacuum=10, axis=2)
This is the easy way, where you use the experimental lattice constant for gold bulk structure. You can write:
from ase.visualize import view
view(s1)
or simply s1.edit() if you want to see and rotate the structure.
108
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Next example is a molybdenum bcc(321) surface where we decide what lattice constant to use:
from ase.lattice import bulk
Mobulk = bulk(’Mo’, ’bcc’, a=3.16, cubic=True)
s2 = surface(Mobulk, (3, 2, 1), 9)
s2.center(vacuum=10, axis=2)
7.9. Creating atomic structures
109
ASE Manual, Release 3.9.0.3865
As the last example, creation of alloy surfaces is also very easily carried out with this module. In this example,
two Pt3 Rh fcc(211) surfaces will be created:
a = 4.0
from ase import Atoms
Pt3Rh = Atoms(’Pt3Rh’,
scaled_positions=[(0, 0, 0),
(0.5, 0.5, 0),
(0.5, 0, 0.5),
(0, 0.5, 0.5)],
cell=[a, a, a],
pbc=True)
s3 = surface(Pt3Rh, (2, 1, 1), 9)
s3.center(vacuum=10, axis=2)
Pt3Rh.set_chemical_symbols(’PtRhPt2’)
s4 = surface(Pt3Rh , (2, 1, 1), 9)
s4.center(vacuum=10, axis=2)
110
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
7.9.6 General crystal structures and surfaces
Modules for creating crystal structures are found in the module ase.lattice. Most Bravais lattices are implemented, as are a few important lattices with a basis. The modules can create lattices with any orientation (see
below). These modules can be used to create surfaces with any crystal structure and any orientation by later adding
a vacuum layer with ase.lattice.surface.add_vacuum().
Example
To set up a slab of FCC copper with the [1,-1,0] direction along the x-axis, [1,1,-2] along the y-axis and [1,1,1]
along the z-axis, use:
7.9. Creating atomic structures
111
ASE Manual, Release 3.9.0.3865
from ase.lattice.cubic import FaceCenteredCubic
atoms = FaceCenteredCubic(directions=[[1,-1,0], [1,1,-2], [1,1,1]],
size=(2,2,3), symbol=’Cu’, pbc=(1,1,0))
The minimal unit cell is repeated 2*2*3 times. The lattice constant is taken from the database of lattice constants in
ase.data module. There are periodic boundary conditions along the x and y axis, but free boundary conditions
along the z axis. Since the three directions are perpendicular, a (111) surface is created.
To set up a slab of BCC copper with [100] along the first axis, [010] along the second axis, and [111] along the
third axis use:
from ase.lattice.cubic import BodyCenteredCubic
atoms = BodyCenteredCubic(directions=[[1,0,0], [0,1,0], [1,1,1]],
size=(2,2,3), symbol=’Cu’, pbc=(1,1,0),
latticeconstant=4.0)
Since BCC is not the natural crystal structure for Cu, a lattice constant has to be specified. Note that since the
repeat directions of the unit cell are not orthogonal, the Miller indices of the surfaces will not be the same as the
Miller indices of the axes. The indices of the surfaces in this example will be (1,0,-1), (0,1,-1) and (0,0,1).
Available crystal lattices
The following modules are currently available (the * mark lattices with a basis):
• lattice.cubic
– SimpleCubic
– FaceCenteredCubic
– BodyCenteredCubic
– Diamond (*)
• lattice.tetragonal
– SimpleTetragonal
– CenteredTetragonal
• lattice.orthorhombic
– SimpleOrthorhombic
– BaseCenteredOrthorhombic
– FaceCenteredOrthorhombic
– BodyCenteredOrthorhombic
• lattice.monoclinic
– SimpleMonoclinic
– BaseCenteredMonoclinic
• lattice.triclinic
– Triclinic
• lattice.hexagonal
– Hexagonal
– HexagonalClosedPacked (*)
– Graphite (*)
112
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
• The rhombohedral (or trigonal) lattices are not implemented. They will be implemented when the need
arises (and if somebody can tell us the precise definition of the 4-number Miller indices - we only know that
they are “almost the same as in hexagonal lattices”).
• lattice.compounds
Lattices with more than one element. These are mainly intended as examples allowing you to define new
such lattices. Currenly, the following are defined
– B1 = NaCl = Rocksalt
– B2 = CsCl
– B3 = ZnS = Zincblende
– L1_2 = AuCu3
– L1_0 = AuCu
Usage
The lattice objects are called with a number of arguments specifying e.g. the size and orientation of the lattice.
All arguments should be given as named arguments. At a minimum the symbol argument must be specified.
symbol The element, specified by the atomic number (an integer) or by the atomic symbol (i.e. �Au’). For
compounds, a tuple or list of elements should be given. This argument is mandatory.
directions and/or miller: Specifies the orientation of the lattice as the Miller indices of the three basis vectors of the supercell (directions=...) and/or as the Miller indices of the three surfaces
(miller=...). Normally, one will specify either three directions or three surfaces, but any combination that is both complete and consistent is allowed, e.g. two directions and two surface miller indices (this
example is slightly redundant, and consistency will be checked). If only some directions/miller indices are
specified, the remaining should be given as None. If you intend to generate a specific surface, and prefer to
specify the miller indices of the unit cell basis (directions=...), it is a good idea to give the desired
Miller index of the surface as well to allow the module to test for consistency. Example:
>>> atoms = BodyCenteredCubic(directions=[[1,-1,0],[1,1,-1],[0,0,1]],
...
miller=[None, None, [1,1,2]], ...)
If neither directions nor miller are specified, the default is directions=[[1,0,0],
[0,1,0], [0,0,1]].
size: A tuple of three numbers, defining how many times the fundamental repeat unit is repeated. Default:
(1,1,1). Be aware that if high-index directions are specified, the fundamental repeat unit may be large.
latticeconstant: The lattice constant. If no lattice constant is specified, one is extracted from
ASE.ChemicalElements provided that the element actually has the crystal structure you are creating. Depending on the crystal structure, there will be more than one lattice constant, and they are specified by giving
a dictionary or a tuple (a scalar for cubic lattices). Distances are given in Angstrom, angles in degrees.
Structure
Cubic
Tetragonal
Orthorhombic
Triclinic
Monoclinic
Hexagonal
Lattice constants
a
(a, c)
(a, b, c)
(a, b, c, О±, ОІ, Оі)
(a, b, c, alpha)
(a, c)
Dictionary-keys
�a’
�a’, �c’ or �c/a’
�a’, �b’ or �b/a’, �c’ or �c/a’
�a’, �b’ or �b/a’, �c’ or �c/a’, �alpha’, �beta’, �gamma’
�a’, �b’ or �b/a’, �c’ or �c/a’, �alpha’
�a’, �c’ or �c/a’
Example:
>>> atoms = Monoclinic( ... , latticeconstant={’a’: 3.06,
...
’b/a’: 0.95, ’c/a’: 1.07, ’alpha’: 74})
debug: Controls the amount of information printed. 0: no info is printed. 1 (the default): The indices of surfaces
and unit cell vectors are printed. 2: Debugging info is printed.
7.9. Creating atomic structures
113
ASE Manual, Release 3.9.0.3865
Defining new lattices
Often, there is a need for new lattices - either because an element crystallizes in a lattice that is not a simple
Bravais lattice, or because you need to work with a compound or an ordered alloy.
All the lattice generating objects are instances of a class, you generate new lattices by deriving a new class and
instantiating it. This is best explained by an example. The diamond lattice is two interlacing FCC lattices, so it
can be seen as a face-centered cubic lattice with a two-atom basis. The Diamond object could be defined like this:
from ase.lattice.cubic import FaceCenteredCubicFactory
class DiamondFactory(FaceCenteredCubicFactory):
"""A factory for creating diamond lattices."""
xtal_name = ’diamond’
bravais_basis = [[0, 0, 0], [0.25, 0.25, 0.25]]
Diamond = DiamondFactory()
Lattices with more than one element
Lattices with more than one element is made in the same way. A new attribute, element_basis, is added,
giving which atoms in the basis are which element. If there are four atoms in the basis, and element_basis is
(0,0,1,0), then the first, second and fourth atoms are one element, and the third is the other element. As an
example, the AuCu3 structure (also known as L12 ) is defined as:
# The L1_2 structure is "based on FCC", but is really simple cubic
# with a basis.
class AuCu3Factory(SimpleCubicFactory):
"A factory for creating AuCu3 (L1_2) lattices."
bravais_basis = [[0, 0, 0], [0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]
element_basis = (0, 1, 1, 1)
AuCu3 = L1_2 = AuCu3Factory()
Sometimes, more than one crystal structure can be used to define the crystal structure, for example the Rocksalt
structure is two interpenetrating FCC lattices, one with one kind of atoms and one with another. It would be
tempting to define it as
class NaClFactory(FaceCenteredCubicFactory):
"A factory for creating NaCl (B1, Rocksalt) lattices."
bravais_basis = [[0, 0, 0], [0.5, 0.5, 0.5]]
element_basis = (0, 1)
B1 = NaCl = Rocksalt = NaClFactory()
but if this is used to define a finite system, one surface would be covered with one type of atoms, and the opposite
surface with the other. To maintain the stochiometry of the surfaces, it is better to use the simple cubic lattice with
a larger basis:
# To prevent a layer of element one on one side, and a layer of
# element two on the other side, NaCl is based on SimpleCubic instead
# of on FaceCenteredCubic
class NaClFactory(SimpleCubicFactory):
"A factory for creating NaCl (B1, Rocksalt) lattices."
bravais_basis = [[0, 0, 0], [0, 0, 0.5], [0, 0.5, 0], [0, 0.5, 0.5],
[0.5, 0, 0], [0.5, 0, 0.5], [0.5, 0.5, 0],
[0.5, 0.5, 0.5]]
element_basis = (0, 1, 1, 0, 1, 0, 0, 1)
114
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
B1 = NaCl = Rocksalt = NaClFactory()
More examples can be found in the file ase/lattice/compounds.py.
ASE contains a number of modules for setting up atomic structures, mainly molecules, bulk crystals and surfaces.
Some of these modules have overlapping functionality, but strike a different balance between flexibility and easeof-use.
Common bulk crystals
The ase.lattice.bulk() function can be used to create the most common bulk crystal structures. The
function creates a single unit cell oriented such that the number of atoms in the cell is minimal.
Read more: Common bulk crystals.
Common surfaces
The ase.lattice.surface module contains a number of functions for creating the most common surfaces
in a minimal unit cell, and for adding adsorbates to these surfaces.
Read more: Surfaces.
Nanotubes and nanoribbons
The functions ase.structure.nanotube() and ase.structure.graphene_nanoribbon() can
be used to create Carbon nanotubes and graphene sheets or nanoribbons. Per default, they create Carbon nanotubes
and sheets, but other elements can be used.
Read more: Nanotubes and Graphene nanoribbons.
Generally oriented bulk crystals and surfaces
The ase.lattice module contains functions for creating most common crystal structures with arbitrary orientation. The user can specify the desired Miller index along the three axes of the simulation, and the smallest
periodic structure fulfilling this specification is created. Thirteen of the 14 Bravais lattices are supported by the
module, as are a few lattices with a basis, and lattices for some of the most common compounds/alloys. The
modules makes it possible to define further lattices based on the supported Bravais lattices.
Both bulk crystals and surfaces can be created.
Read more: General crystal structures and surfaces.
Molecules
Some common molecules can be constructed using the ase.structure.molecule() function.
Read more: Molecular data.
7.10 Structure optimization
The optimization algorithms can be roughly divided into local optimization algorithms which find a nearby local
minimum and global optimization algorithms that try to find the global minimum (a much harder task).
7.10.1 Local optimization
The local optimization algorithms available in ASE are:
LBFGSLineSearch, MDMin, and FIRE.
BFGS, LBFGS, BFGSLineSearch,
See Also:
Performance test for all ASE local optimizers.
MDMin and FIRE both use Newtonian dynamics with added friction, to converge to an energy minimum, whereas
the others are of the quasi-Newton type, where the forces of consecutive steps are used to dynamically update a
7.10. Structure optimization
115
ASE Manual, Release 3.9.0.3865
Hessian describing the curvature of the potential energy landscape. You can use the QuasiNewton synonym for
BFGSLineSearch because this algorithm is in many cases the optimal of the quasi-Newton algorithms.
All of the local optimizer classes have the following structure:
class Optimizer:
def __init__(self, atoms, restart=None, logfile=None):
def run(self, fmax=0.05, steps=100000000):
def get_number_of_steps():
The convergence criterion is that the force on all individual atoms should be less than fmax:
max |Fa | < fmax
a
BFGS
The BFGS object is one of the minimizers in the ASE package. The below script uses BFGS to optimize the
structure of a water molecule, starting with the experimental geometry:
from ase import Atoms
from ase.optimize import BFGS
from ase.calculators.emt import EMT
import numpy as np
d = 0.9575
t = np.pi / 180 * 104.51
water = Atoms(’H2O’,
positions=[(d, 0, 0),
(d * np.cos(t), d * np.sin(t), 0),
(0, 0, 0)],
calculator=EMT())
dyn = BFGS(water)
dyn.run(fmax=0.05)
which produces the following output. The columns are the solver name, step number, clock time, potential energy
(eV), and maximum force.:
BFGS:
BFGS:
BFGS:
BFGS:
BFGS:
0
1
2
3
4
19:45:25
19:45:25
19:45:25
19:45:25
19:45:25
2.769633
2.154560
1.906812
1.880255
1.879488
8.6091
4.4644
1.3097
0.2056
0.0205
When doing structure optimization, it is useful to write the trajectory to a file, so that the progress of the optimization run can be followed during or after the run:
dyn = BFGS(water, trajectory=’H2O.traj’)
dyn.run(fmax=0.05)
Use the command ase-gui H2O.traj to see what is going on (more here: ase.gui). The trajectory file can
also be accessed using the module ase.io.trajectory.
The attach method takes an optional argument interval=n that can be used to tell the structure optimizer
object to write the configuration to the trajectory file only every n steps.
During a structure optimization, the BFGS and LBFGS optimizers use two quantities to decide where to move the
atoms on each step:
• the forces on each atom, as returned by the associated Calculator object
• the Hessian matrix, i.e. the matrix of second derivatives
coordinates.
116
∂2E
∂xi ∂xj
of the total energy with respect to nuclear
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
If the atoms are close to the minimum, such that the potential energy surface is locally quadratic, the Hessian
and forces accurately determine the required step to reach the optimal structure. The Hessian is very expensive to
calculate a priori, so instead the algorithm estimates it by means of an initial guess which is adjusted along the
way depending on the information obtained on each step of the structure optimization.
It is frequently practical to restart or continue a structure optimization with a geometry obtained from a previous
relaxation. Aside from the geometry, the Hessian of the previous run can and should be retained for the second
run. Use the restart keyword to specify a file in which to save the Hessian:
dyn = BFGS(atoms=system, trajectory=’qn.traj’, restart=’qn.pckl’)
This will create an optimizer which saves the Hessian to qn.pckl (using the Python pickle module) on each
step. If the file already exists, the Hessian will also be initialized from that file.
The trajectory file can also be used to restart a structure optimization, since it contains the history of all forces and
positions, and thus whichever information about the Hessian was assembled so far:
dyn = BFGS(atoms=system, trajectory=’qn.traj’)
dyn.replay_trajectory(’history.traj’)
This will read through each iteration stored in history.traj, performing adjustments to the Hessian as appropriate. Note that these steps will not be written to qn.traj. If restarting with more than one previous trajectory
file, use ase-gui to concatenate them into a single trajectory file first:
$ ase-gui part1.traj part2.traj -o history.traj
The file history.traj will then contain all necessary information.
When switching between different types of optimizers, e.g. between BFGS and LBFGS, the pickle-files specified
by the restart keyword are not compatible, but the Hessian can still be retained by replaying the trajectory as
above.
LBFGS
LBFGS is the limited memory version of the BFGS algorithm, where the inverse of Hessian matrix is updated instead of the Hessian itself. Two ways exist for determining the atomic step: Standard LBFGS and
LBFGSLineSearch. For the first one, both the directions and lengths of the atomic steps are determined by the
approximated Hessian matrix. While for the latter one, the approximated Hessian matrix is only used to find out
the directions of the line searches and atomic steps, the step lengths are determined by the forces.
To start a structure optimization with LBFGS algorithm is similar to BFGS. A typical optimization should look
like:
dyn = LBFGS(atoms=system, trajectory=’lbfgs.traj’, restart=’lbfgs.pckl’)
where the trajectory and the restart save the trajectory of the optimization and the vectors needed to generate the
Hessian Matrix.
FIRE
Read about this algorithm here:
Erik Bitzek, Pekka Koskinen, Franz Gähler, Michael Moseler, and Peter Gumbsch
Structural Relaxation Made Simple
Physical Review Letters, Vol. 97, 170201 (2006)
MDMin
The MDmin algorithm is a modification of the usual velocity-Verlet molecular dynamics algorithm. Newtons
second law is solved numerically, but after each time step the dot product between the forces and the momenta is
checked. If it is zero, the system has just passed through a (local) minimum in the potential energy, the kinetic
7.10. Structure optimization
117
ASE Manual, Release 3.9.0.3865
energy is large and about to decrease again. At this point, the momentum is set to zero. Unlike a “real” molecular
dynamics, the masses of the atoms are not used, instead all masses are set to one.
The MDmin algorithm exists in two flavors, one where each atom is tested and stopped individually, and one
where all coordinates are treated as one long vector, and all momenta are set to zero if the dot product between the
momentum vector and force vector (both of length 3N) is zero. This module implements the latter version.
Although the algorithm is primitive, it performs very well because it takes advantage of the physics of the problem.
Once the system is so near the minimum that the potential energy surface is approximately quadratic it becomes
advantageous to switch to a minimization method with quadratic convergence, such as Conjugate Gradient or
Quasi Newton.
SciPy optimizers
SciPy provides a number of optimizers. An interface module for a couple of these have been written for ASE.
Most notable are the optimizers SciPyFminBFGS and SciPyFminCG. These are called with the regular syntax and
can be imported as:
from ase.optimize.sciopt import SciPyFminBFGS, SciPyFminCG
class ase.optimize.sciopt.SciPyFminBFGS(atoms, logfile=’-�, trajectory=None,
back_always=False, alpha=70.0)
Quasi-Newton method (Broydon-Fletcher-Goldfarb-Shanno)
call-
Initialize object
Parameters:
callback_always: book Should the callback be run after each force call (also in the linesearch)
alpha: float Initial guess for the Hessian (curvature of energy surface). A conservative value of 70.0 is the
default, but number of needed steps to converge might be less if a lower value is used. However, a
lower value also means risk of instability.
class ase.optimize.sciopt.SciPyFminCG(atoms,
logfile=’-�,
trajectory=None,
back_always=False, alpha=70.0)
Non-linear (Polak-Ribiere) conjugate gradient algorithm
call-
Initialize object
Parameters:
callback_always: book Should the callback be run after each force call (also in the linesearch)
alpha: float Initial guess for the Hessian (curvature of energy surface). A conservative value of 70.0 is the
default, but number of needed steps to converge might be less if a lower value is used. However, a
lower value also means risk of instability.
See Also:
SciPyFminBFGS, SciPyFminCG
BFGSLineSearch
BFGSLineSearch is the BFGS algorithm with a line search mechanism that enforces the step taken fulfills the
Wolfe conditions, so that the energy and absolute value of the force decrease monotonically. Like the LBFGS
algorithm the inverse of the Hessian Matrix is updated.
The usage of BFGSLineSearch algorithm is similar to other BFGS type algorithms. A typical optimization should
look like:
from ase.optimize.bfgslinesearch import BFGSLineSearch
dyn = BFGSLineSearch(atoms=system, trajectory=’bfgs_ls.traj’, restart=’bfgs_ls.pckl’)
118
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
where the trajectory and the restart save the trajectory of the optimization and the information needed to generate
the Hessian Matrix.
Note: In many of the examples, tests, exercises and tutorials, QuasiNewton is used – it is a synonym for
BFGSLineSearch.
The BFGSLineSearch algorithm is not compatible with nudged elastic band calculations.
7.10.2 Global optimization
There are currently two global optimisation algorithms available.
Basin hopping
The global optimization algorithm can be used quite similar as a local optimization algorithm:
from ase import *
from ase.optimize.basin import BasinHopping
bh = BasinHopping(atoms=system,
# the system to optimize
temperature=100 * kB, # ’temperature’ to overcome barriers
dr=0.5,
# maximal stepwidth
optimizer=LBFGS,
# optimizer to find local minima
fmax=0.1,
# maximal force for the optimizer
)
Read more about this algorithm here:
David J. Wales and Jonathan P. K. Doye
Global Optimization by Basin-Hopping and the Lowest Energy Structures of Lennard-Jones Clusters
Containing up to 110 Atoms
J. Phys. Chem. A, Vol. 101, 5111-5116 (1997)
and here:
David J. Wales and Harold A. Scheraga
Global Optimization of Clusters, Crystals, and Biomolecules
Science, Vol. 285, 1368 (1999)
Minima hopping
The minima hopping algorithm was developed and described by Goedecker:
Stefan Goedecker
Minima hopping: An efficient search method for the global minimum of the potential energy surface
of complex molecular systems
J. Chem. Phys., Vol. 120, 9911 (2004)
This algorithm utilizes a series of alternating steps of NVE molecular dynamics and local optimizations, and has
two parameters that the code dynamically adjusts in response to the progress of the search. The first parameter
is the initial temperature of the NVE simulation. Whenever a step finds a new minimum this temperature is
decreased; if the step finds a previously found minimum the temperature is increased. The second dynamically
adjusted parameter is Ediff , which is an energy threshold for accepting a newly found minimum. If the new
minimum is no more than Ediff eV higher than the previous minimum, it is acccepted and Ediff is decreased; if it
is more than Ediff eV higher it is rejected and Ediff is increased. The method is used as:
from ase.optimize.minimahopping import MinimaHopping
opt = MinimaHopping(atoms=system)
opt(totalsteps=10)
7.10. Structure optimization
119
ASE Manual, Release 3.9.0.3865
This will run the algorithm until 10 steps are taken; alternatively, if totalsteps is not specified the algorithm will
run indefinitely (or until stopped by a batch system). A number of optional arguments can be fed when initializing
the algorithm as keyword pairs. The keywords and default values are:
T0: 1000., # K, initial MD �temperature’
beta1: 1.1, # temperature adjustment parameter
beta2: 1.1, # temperature adjustment parameter
beta3: 1. / 1.1, # temperature adjustment parameter
Ediff0: 0.5, # eV, initial energy acceptance threshold
alpha1 : 0.98, # energy threshold adjustment parameter
alpha2 : 1. / 0.98, # energy threshold adjustment parameter
mdmin : 2, # criteria to stop MD simulation (no. of minima)
logfile: �hop.log’, # text log
minima_threshold : 0.5, # A, threshold for identical configs
timestep : 1.0, # fs, timestep for MD simulations
optimizer : QuasiNewton, # local optimizer to use
minima_traj : �minima.traj’, # storage file for minima list
Specific definitions of the alpha, beta, and mdmin parameters can be found in the publication by Goedecker.
minima_threshold is used to determine if two atomic configurations are identical; if any atom has moved by
more than this amount it is considered a new configuration. Note that the code tries to do this in an intelligent
manner: atoms are considered to be indistinguishable, and translations are allowed in the directions of the periodic
boundary conditions. Therefore, if a CO is adsorbed in an ontop site on a (211) surface it will be considered
identical no matter which ontop site it occupies.
The trajectory file minima_traj will be populated with the accepted minima as they are found. A log of the
progress is kept in logfile.
The code is written such that a stopped simulation (e.g., killed by the batching system when the maximum wall
time was exceeded) can usually be restarted without too much effort by the user. In most cases, the script can be
resubmitted without any modification – if the logfile and minima_traj are found, the script will attempt
to use these to resume. (Note that you may need to clean up files left in the directory by the calculator, however,
such as the .nc file produced by Jacapo.)
Note that these searches can be quite slow, so it can pay to have multiple searches running at a time. Multiple
searches can run in parallel and share one list of minima. (Run each script from a separate directory but specify
the location to the same absolute location for minima_traj). Each search will use the global information of the
list of minima, but will keep its own local information of the initial temperature and Ediff .
For an example of use, see the Constrained minima hopping (global optimization) tutorial.
7.11 Parallel calculations
ase.parallel.paropen(name, mode=’r’, buffering=0)
MPI-safe version of open function.
In read mode, the file is opened on all nodes. In write and append mode, the file is opened on the master
only, and /dev/null is opened on all other nodes.
ase.parallel.parprint(*args, **kwargs)
MPI-safe print - prints only from master.
7.12 Visualization
ase.visualize.view(atoms, data=None, viewer=None, repeat=None)
120
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
This provides an interface to various visualization tools, such as ase.gui, ase.visualize.vtk, RasMol,
VMD, VTK, gOpenMol, or Avogadro. The default viewer is the ase.gui, described in the ase.gui module. The
simplest invocation is:
>>> from ase.visualize import view
>>> view(atoms)
where atoms is any Atoms object. Alternative viewers can be used by specifying the optional keyword
viewer=... - use one of �ase.gui’, �gopenmol’, �vmd’, or �rasmol’. The VMD and Avogadro viewers can
take an optional data argument to show 3D data, such as charge density:
>>> view(atoms, viewer=’VMD’, data=array)
If you do not wish to open an interactive gui, but rather visualize your structure by dumping directly to a graphics
file; you can use the write command of the ase.io module, which can write �eps’, �png’, and �pov’ files
directly, like this:
>>> write(’image.png’, atoms)
7.12.1 Mayavi
The ase.visualize.mlab.plot() function can be used from the command-line:
python -m ase.visualize.mlab abc.cube
to plot data from a cube-file or alternatively a wave function or an electron density from a calculator restart file:
python -m ase.visualize.mlab -C gpaw abc.gpw
Options:
-h, --help
show this help message and exit
-n INDEX, --band-index=INDEX Band index counting from zero.
-s SPIN, --spin-index=SPIN Spin index: zero or one.
-c CONTOURS, --contours=CONTOURS Use “-c 3” for 3 contours or “-c -0.5,0.5”
for specific values. Default is four contours.
-r REPEAT, --repeat=REPEAT Example: “-r 2,2,2”.
-C NAME, --calculator-name=NAME Name of calculator.
ase.visualize.mlab.plot(atoms, data, contours)
Plot atoms, unit-cell and iso-surfaces using Mayavi.
Parameters:
atoms: Atoms object Positions, atomiz numbers and unit-cell.
data: 3-d ndarray of float Data for iso-surfaces.
countours: list of float Contour values.
7.12.2 VTK
The Visualization Toolkit (VTK) is a powerful platform-independent graphics engine, which comes as an open
source graphics toolkit licensed under the BSD license. It is available for a wide range of programming languages,
including easily scriptable interfaces in Python and Tcl.
In the scientific community, VTK is used by thousands of researchers and developers for 3D computer graphics,
image processing, and visualization. VTK includes a suite of 3D interaction widgets within the development
framework for information visualization, integrating GUI toolkits such as Qt and Tk into a highly flexible design
platform.
7.12. Visualization
121
ASE Manual, Release 3.9.0.3865
For visualization purposes within ASE, two different VTK-approaches are supported, namely:
Scripted on-the-fly rendering ASE includes VTK-scripting for easy data visualization using the
ase.visualize.vtk module. Development is in progress, so you might want to check out
the latest development release from SVN (see Latest development release).
Interactive rendering MayaVi is an easy-to-use GUI for VTK. With Enthought’s traits-based VTKwrapper (TVTK), constructing VTK pipelines has been simplified greatly by introducing three
basic concepts: data sources, filters and visualization modules. MayaVi also supports the VTK
file formats, including the flexible VTK XML, which in ASE can be used to export atomic
positions, forces and volume data using the write command in the ase.io module.
A key feature of VTK is the inherent ability to use MPI for parallel rending, which is provided with built-in
parallel composite rendering objects to handle domain decomposition and subsequent recombination of the raster
information. This is particularly useful for non-interactive ray tracing, batch isosurface generation and in-situ
visualization of simulation data in cluster computing.
See Also:
ParaView is a VTK-based open-source, multi-platform data analysis and visualization application for extremely
large data-sets using distributed memory computing resources and parallel rendering through MPI.
7.12.3 PrimiPlotter
The PrimiPlotter is intended to do on-the-fly plotting of the positions of the atoms during long molecular dynamics
simulations. The module ase.visualize.primiplotter contains the PrimiPlotter and the various output
modules, see below.
class ase.visualize.primiplotter.PrimiPlotter(atoms, verbose=0, timing=0, interval=1,
initframe=0)
Primitive PostScript-based plots during a simulation.
The PrimiPlotter plots atoms during simulations, extracting the relevant information from the list of atoms.
It is created using the list of atoms as an argument to the constructor. Then one or more output devices must
be attached using set_output(device). The list of supported output devices is at the end.
The atoms are plotted as circles. The system is first rotated using the angles specified by set_rotation([vx,
vy, vz]). The rotation is vx degrees around the x axis (positive from the y toward the z axis), then vy degrees
around the y axis (from x toward z), then vz degrees around the z axis (from x toward y). The rotation
matrix is the same as the one used by RasMol.
Per default, the system is scaled so it fits within the canvas (autoscale mode). Autoscale mode is enabled and
disables using autoscale(“on”) or autoscale(“off”). A manual scale factor can be set with set_scale(scale),
this implies autoscale(“off”). The scale factor (from the last autoscale event or from set_scale) can be
obtained with get_scale(). Finally, an explicit autoscaling can be triggered with autoscale(“now”), this is
mainly useful before calling get_scale or before disabling further autoscaling. Finally, a relative scaling
factor can be set with SetRelativeScaling(), it is multiplied to the usual scale factor (from autoscale or from
set_scale). This is probably only useful in connection with autoscaling.
The radii of the atoms are obtained from the first of the following methods which work:
1.If the radii are specified using PrimiPlotter.set_radii(r), they are used. Must be an array, or a single
number.
2.If the atoms has a get_atomic_radii() method, it is used. This is unlikely.
3.If the atoms has a get_atomic_numbers() method, the corresponding covalent radii are extracted from
the ASE.ChemicalElements module.
4.If all else fails, the radius is set to 1.0 Angstrom.
The atoms are colored using the first of the following methods which work.
1.If colors are explicitly set using PrimiPlotter.set_colors(), they are used.
122
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
2.If these colors are specified as a dictionary, the tags (from atoms.get_tags()) are used as an index into
the dictionary to get the actual colors of the atoms.
3.If a color function has been set using PrimiPlotter.set_color_function(), it is called with the atoms as
an argument, and is expected to return an array of colors.
4.If the atoms have a get_colors() method, it is used to get the colors.
5.If these colors are specified as a dictionary, the tags (from atoms.get_tags()) are used as an index into
the dictionary to get the actual colors of the atoms.
6.If all else fails, the atoms will be white.
The colors are specified as an array of colors, one color per atom. Each color is either a real number from
0.0 to 1.0, specifying a grayscale (0.0 = black, 1.0 = white), or an array of three numbers from 0.0 to 1.0,
specifying RGB values. The colors of all atoms are thus a Numerical Python N-vector or a 3xN matrix.
In cases 1a and 3a above, the keys of the dictionary are integers, and the values are either numbers
(grayscales) or 3-vectors (RGB values), or strings with X11 color names, which are then translated to RGB
values. Only in case 1a and 3a are strings recognized as colors.
Some atoms may be invisible, and thus left out of the plot. Invisible atoms are determined from the following
algorithm. Unlike the radius or the coloring, all points below are tried and if an atom is invisible by any
criterion, it is left out of the plot.
1.All atoms are visible.
2.If PrimiPlotter.set_invisible() has be used to specify invisible atoms, any atoms for which the value is
non-zero becomes invisible.
3.If an invisiblility function has been set with PrimiPlotter.set_invisibility_function(), it is called with
the atoms as argument. It is expected to return an integer per atom, any non-zero value makes that
atom invisible.
4.If a cut has been specified using set_cut, any atom outside the cut is made invisible.
Note that invisible atoms are still included in the algorithm for positioning and scaling the plot.
The following output devices are implemented.
PostScriptFile(prefix): Create PS files names prefix0000.ps etc.
PnmFile(prefix): Similar, but makes PNM files.
GifFile(prefix): Similar, but makes GIF files.
JpegFile(prefix): Similar, but makes JPEG files.
X11Window(): Show the plot in an X11 window using ghostscript.
Output devices writing to files take an extra optional argument to the constructor, compress, specifying if
the output file should be gzipped. This is not allowed for some (already compressed) file formats.
Instead of a filename prefix, a filename containing a % can be used. In that case the filename is expected to
expand to a real filename when used with the Python string formatting operator (%) with the frame number
as argument. Avoid generating spaces in the file names: use e.g. %03d instead of %3d.
Parameters to the constructor:
atoms: The atoms to be plottet.
verbose = 0: Write progress information to stderr.
timing = 0: Collect timing information.
interval = 1: If specified, a plot is only made every interval’th time update() is called. Deprecated, normally
you should use the interval argument when attaching the plotter to e.g. the dynamics.
initframe = 0: Initial frame number, i.e. the number of the first plot.
log(message)
logs a message to the file set by set_log.
7.12. Visualization
123
ASE Manual, Release 3.9.0.3865
plot()
Create a plot now. Does not respect the interval timer.
This method makes a plot unconditionally. It does not look at the interval variable, nor is this plot
taken into account in the counting done by the update() method if an interval variable was specified.
set_color_function(colors)
Set a color function, to be used to color the atoms.
set_colors(colors)
Explicitly set the colors of the atoms.
The colors can either be a dictionary mapping tags to colors or an array of colors, one per atom.
Each color is specified as a greyscale value from 0.0 to 1.0 or as three RGB values from 0.0 to 1.0.
set_dimensions(dims)
Set the size of the canvas (a 2-tuple).
set_invisibility_function(invfunc)
Set an invisibility function.
set_invisible(inv)
Choose invisible atoms.
set_log(log)
Sets a file for logging.
log may be an open file or a filename.
set_output(device)
Attach an output device to the plotter.
set_radii(radii)
Set the atomic radii. Give an array or a single number.
set_rotation(rotation)
Set the rotation angles (in degrees).
update(newatoms=None)
Cause a plot (respecting the interval setting).
update causes a plot to be made. If the interval variable was specified when the plotter was create, it
will only produce a plot with that interval. update takes an optional argument, newatoms, which can
be used to replace the list of atoms with a new one.
7.12.4 FieldPlotter
The FieldPlotter is intended to plot fields defined on the atoms in large-scale simulations. The fields could be e.g.
pressure, stress or temperature (kinetic energy), i.e. any quantity that in a given simulation is best defined on a
per-atom basis, but is best interpreted as a continuum field.
The current version of FieldPlotter only works if the number of atoms is at least 5-10 times larger than the number
of pixels in the plot.
class ase.visualize.fieldplotter.FieldPlotter(atoms, datasource=None, verbose=0,
timing=0, interval=1, initframe=0)
log(message)
logs a message to the file set by set_log.
plot(data=None)
Create a plot now. Does not respect the interval timer.
This method makes a plot unconditionally. It does not look at the interval variable, nor is this plot
taken into account in the counting done by the update() method if an interval variable was specified.
124
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
If data is specified, it must be an array of numbers with the same length as the atoms. That data will
then be plotted. If no data is given, the data source specified when creating the plotter is used.
set_background(value)
Set the data value of the background. See also set_background_color
Set the value of the background (parts of the plot without atoms) to a specific value, or to �min’ or
�max’ representing the minimal or maximal data values on the atoms.
Calling set_background cancels previous calls to set_background_color.
set_background_color(color)
Set the background color. See also set_background.
Set the background color. Use a single value in the range [0, 1[ for gray values, or a tuple of three such
values as an RGB color.
Calling set_background_color cancels previous calls to set_background.
set_black_white_colors(reverse=False)
Set the color to Black-White (greyscale)
set_color_function(colors)
Set a color function, to be used to color the atoms.
set_data_range(range1, range2=None)
Set the range of the data used when coloring.
This function sets the range of data values mapped unto colors in the final plot.
Three possibilities:
�data’: Autoscale using the data on visible atoms. The range goes from the lowest to the highest
value present on the atoms. If only a few atoms have extreme values, the entire color range may
not be used on the plot, as many values may be averaged on each point in the plot.
�plot’: Autoscale using the data on the plot. Unlike �data’ this guarantees that the entire color
range is used.
min, max: Use the range [min, max]
set_dimensions(dims)
Set the size of the canvas (a 2-tuple).
set_invisibility_function(invfunc)
Set an invisibility function.
set_invisible(inv)
Choose invisible atoms.
set_log(log)
Sets a file for logging.
log may be an open file or a filename.
set_output(device)
Attach an output device to the plotter.
set_plot_plane(plane)
Set the plotting plane to xy, xz or yz (default: xy)
set_radii(radii)
Set the atomic radii. Give an array or a single number.
set_red_yellow_colors(reverse=False)
Set colors to Black-Red-Yellow-White (a.k.a. STM colors)
set_rotation(rotation)
Set the rotation angles (in degrees).
7.12. Visualization
125
ASE Manual, Release 3.9.0.3865
update(newatoms=None)
Cause a plot (respecting the interval setting).
update causes a plot to be made. If the interval variable was specified when the plotter was create, it
will only produce a plot with that interval. update takes an optional argument, newatoms, which can
be used to replace the list of atoms with a new one.
7.13 ASE-VTK
For ASE, the vtk interface consists of Python modules for automatic visualization of positions, bonds, forces and
volume data (e.g. wave functions) from an Atoms object, provided such data is made available by the calculator.
Note: The Python modules in ASE are intended to wrap lower-level functionality of the VTK object models
in small and easy-to-comprehend classes. To be able to distinguish between build-in VTK objects and their
wrappers, and because VTK uses the CamelCase naming convention whereas ASE uses lower-case cf. our coding
conventions, all variables referring to VTK built-in types are prefixed by vtk_. However, both VTK and wrapper
classes are named according to the standard vtkFooBar.
7.13.1 Representing atoms
class ase.visualize.vtk.atoms.vtkAtoms(atoms, scale=1)
Bases: ase.visualize.vtk.module.vtkModuleAnchor, ase.visualize.vtk.grid.vtkAtomicPositi
Provides fundamental representation for Atoms-specific data in VTK.
The vtkAtoms class plots atoms during simulations, extracting the relevant information from the list of
atoms. It is created using the list of atoms as an argument to the constructor. Then one or more visualization
modules can be attached using add_module(name, module).
Example:
>>>
>>>
>>>
>>>
va = vtkAtoms(atoms)
va.add_forces()
va.add_axes()
XXX va.add_to_renderer(vtk_ren)
Construct a fundamental VTK-representation of atoms.
atoms: Atoms object or list of Atoms objects The atoms to be plotted.
scale = 1: float or int Relative scaling of all Atoms-specific visualization.
add_axes()
Add an orientation indicator for the cartesian axes. An appropriate vtkAxesModule is added to the
module anchor under axes.
add_cell()
Add a box outline of the cell using atoms.get_cell(). The existing vtkUnitCellModule is added
to the module anchor under cell.
add_forces()
Add force vectors for the atoms using atoms.get_forces(). A vtkGlyphModule is added to the
module anchor under force.
add_velocities()
Add velocity vectors for the atoms using atoms.get_velocities(). A vtkGlyphModule is added to
the module anchor under velocity.
126
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Atom-centered data
The superclass vtkAtomicPositions implements the basic concepts for representing atomic-centered data
in VTK.
class ase.visualize.vtk.grid.vtkAtomicPositions(pos, cell)
Provides an interface for adding Atoms-centered data to VTK modules. Atomic positions, e.g. obtained
using atoms.get_positions(), constitute an unstructured grid in VTK, to which scalar and vector can be added
as point data sets.
Just like Atoms, instances of vtkAtomicPositions can be divided into subsets, which makes it easy
to select atoms and add properties.
Example:
>>>
>>>
>>>
>>>
cell = vtkUnitCellModule(atoms)
apos = vtkAtomicPositions(atoms.get_positions(), cell)
apos.add_scalar_property(atoms.get_charges(), ’charges’)
apos.add_vector_property(atoms.get_forces(), ’forces’)
Construct basic VTK-representation of a set of atomic positions.
pos: NumPy array of dtype float and shape (n,3) Cartesian positions of the atoms.
cell: Instance of vtkUnitCellModule of subclass thereof Holds information equivalent to that of
atoms.get_cell().
add_scalar_property(data, name=None, active=True)
Add VTK-representation of scalar data at the atomic positions.
data: NumPy array of dtype float and shape (n,) Scalar values corresponding to the atomic positions.
name=None: str Unique identifier for the scalar data.
active=True: bool Flag indicating whether to use as active scalar data.
add_vector_property(data, name=None, active=True)
Add VTK-representation of vector data at the atomic positions.
data: NumPy array of dtype float and shape (n,3) Vector components corresponding to the
atomic positions.
name=None: str Unique identifier for the vector data.
active=True: bool Flag indicating whether to use as active vector data.
get_points(subset=None)
Return (subset of) vtkPoints containing atomic positions.
subset=None: list of int A list of indices into the atomic positions; ignored if None.
get_unstructured_grid(subset=None)
Return (subset of) an unstructured grid of the atomic positions.
subset=None: list of int A list of indices into the atomic positions; ignored if None.
Predefined shapes
The class vtkGlyphModule implements the lower-level objects for representing predefined shapes (glyphs) in
VTK.
class ase.visualize.vtk.module.vtkGlyphModule(vtk_pointset,
glyph_source,
scalemode=None, colormode=None)
Modules represent a unified collection of VTK objects needed for introducing basic visualization concepts
such as surfaces or shapes.
7.13. ASE-VTK
127
ASE Manual, Release 3.9.0.3865
A common trait of all modules is the need for an actor representation and corresponding generic properties
such as lighting, color and transparency.
Poly data modules are based on polygonal data sets, which can be mapped into graphics primitives suitable
for rendering within the VTK framework.
Glyph modules construct these polygonal data sets by replicating a glyph source across a specific set of
points, using available scalar or vector point data to scale and orientate the glyph source if desired.
Example:
>>>
>>>
>>>
>>>
>>>
>>>
atoms = molecule(’C60’)
cell = vtkUnitCellModule(atoms)
apos = vtkAtomicPositions(atoms.get_positions(), cell)
vtk_ugd = apos.get_unstructured_grid()
glyph_source = vtkAtomSource(’C’)
glyph_module = vtkGlyphModule(vtk_ugd, glyph_source)
Construct VTK-representation of a module containing glyphs. These glyphs share a common source, defining their geometrical shape, which is cloned and oriented according to the input data.
vtk_pointset: Instance of vtkPointSet or subclass thereof A vtkPointSet defines a set of positions,
which may then be assigned specific scalar of vector data across the entire set.
glyph_source: Instance of ~vtk.vtkCustomGlyphSource or subclass thereof Provides the basic shape
to distribute over the point set.
get_actor()
Return the actor representing this module in a rendering scene.
set_actor(vtk_act)
Set the actor representing this module in a rendering scene.
set_property(vtk_property)
Set the property of the actor representing this module.
7.14 Calculators
For ASE, a calculator is a black box that can take atomic numbers and atomic positions from an Atoms object
and calculate the energy and forces and sometimes also stresses.
In order to calculate forces and energies, you need to attach a calculator object to your atoms object:
>>> a = read(’molecule.xyz’)
>>> e = a.get_potential_energy()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/jjmo/ase/ase/atoms.py", line 399, in get_potential_energy
raise RuntimeError(’Atoms object has no calculator.’)
RuntimeError: Atoms object has no calculator.
>>> from ase.calculators.abinit import Abinit
>>> calc = Abinit(...)
>>> a.set_calculator(calc)
>>> e = a.get_potential_energy()
>>> print e
-42.0
Here, we used the set_calculator() method to attach an instance of the ase.calculators.abinit
class and then we asked for the energy.
Alternatively, a calculator can be attached like this:
atoms = Atoms(..., calculator=Abinit(...))
or this:
128
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
atoms.calc = Abinit(...)
7.14.1 Supported calculators
The calculators can be divided in three groups:
1. Asap, GPAW and Hotbit have their own native ASE interfaces.
2. ABINIT, CASTEP, DFTB+, ELK, EXCITING, FHI-aims, FLEUR, GAUSSIAN, Gromacs, Jacapo,
LAMMPS, MOPAC, NWChem, SIESTA, TURBOMOLE and VASP, have Python wrappers in the ASE
package, but the actual FORTRAN/C/C++ codes are not part of ASE.
3. Pure python implementations included in the ASE package: EMT, EAM, Lennard-Jones and Morse.
name
Asap
GPAW
Hotbit
abinit
castep
dftb
eam
elk
exciting
aims
fleur
gaussian
gromacs
jacapo
lammps
mopac ...
nwchem
siesta
turbomole
vasp
emt
lj
morse
description
Highly efficient EMT code
Real-space/plane-wave/LCAO PAW code
DFT based tight binding
Plane-wave pseudopotential code
Plane-wave pseudopotential code
DFT based tight binding
Embedded Atom Method
Full Potential LAPW code
Full Potential LAPW code
Numeric atomic orbital, full potential code
Full Potential LAPW code
Gaussian based electronic structure code
Classical molecular dynamics code
Plane-wave ultra-soft pseudopotential code
Classical molecular dynamics code
Gaussian based electronic structure code
LCAO pseudopotential code
Fast atom orbital code
Plane-wave PAW code
Effective Medium Theory calculator
Lennard-Jones potential
Morse potential
The calculators included in ASE are used like this:
>>> from ase.calculators.abc import ABC
>>> calc = ABC(...)
where abc is the module name and ABC is the class name.
7.14.2 Calculator keywords
Example for a hypothetical ABC calculator:
ABC(restart=None, ignore_bad_restart_file=False, label=None,
atoms=None, parameters=None, command=’abc > PREFIX.abc’,
xc=None, kpts=[1, 1, 1], smearing=None,
charge=0.0, nbands=None, **kwargs)
Create ABC calculator
restart: str Prefix for restart file. May contain a directory. Default is None: don’t restart.
ignore_bad_restart_file: bool Ignore broken or missing restart file. By default, it is an error if the restart
file is missing or broken.
7.14. Calculators
129
ASE Manual, Release 3.9.0.3865
label: str Name used for all files. May contain a directory.
atoms: Atoms object Optional Atoms object to which the calculator will be attached. When restarting,
atoms will get its positions and unit-cell updated from file.
command: str Command used to start calculation.
ASE_ABC_COMMAND environment variable.
This will override any value in an
parameters: str Read parameters from file.
xc: str XC-functional (’LDA’, ’PBE’, ...).
kpts: Brillouin zone sampling:
• (1,1,1): Gamma-point
• (n1,n2,n3): Monkhorst-Pack grid
• (n1,n2,n3,’gamma’): Shifted Monkhorst-Pack grid that includes Γ
• [(k11,k12,k13),(k21,k22,k23),...]: Explicit list in units of the reciprocal lattice
vectors
• kpts=3.5: k-point density as in 3.5 k-points per Å−1 .
smearing: tuple The smearing of occupation numbers. Must be a tuple:
• (’Fermi-Dirac’, width)
• (’Gaussian’, width)
• (’Methfessel-Paxton’, width, n), where n is the order (n = 0 is the same as
’Gaussian’)
Lower-case names are also allowed. The width parameter is given in eV units.
charge: float Charge of the system in units of |e| (charge=1 means one electron has been removed).
Default is charge=0.
nbands: int Number of bands. Each band can be occupied by two electrons.
Not all of the above arguments make sense for all of ASE’s calculators. As an example, Gromacs will not accept
DFT related keywords such as xc and smearing. In addition to the keywords mentioned above, each calculator
may have native keywords that are specific to only that calculator.
Keyword arguments can also be set or changed at a later stage using the set() method:
ase.calculators.set(key1=value1, key2=value2, ...)
EAM
Introduction
The Embedded Atom Method (EAM) 1 is a classical potential which is good for modelling metals, particularly
fcc materials. Because it is an equiaxial potential the EAM does not model directional bonds well. However, the
Angular Dependent Potential (ADP) 2 which is an extended version of EAM is able to model directional bonds
and is also included in the EAM calculator.
Generally all that is required to use this calculator is to supply a potential file or as a set of functions that describe
the potential. The files containing the potentials for this calculator are not included but many suitable potentials
can be downloaded from The Interatomic Potentials Repository Project at http://www.ctcms.nist.gov/potentials/
1
2
M.S. Daw and M.I. Baskes, Phys. Rev. Letters 50 (1983) 1285.
Y. Mishin, M.J. Mehl, and D.A. Papaconstantopoulos, Acta Materialia 53 2005 4029–4041.
130
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Theory
A single element EAM potential is defined by three functions: the embedded energy, electron density and the pair
potential. A two element alloy contains the individual three functions for each element plus cross pair interactions.
The ADP potential has two additional sets of data to define the dipole and quadrupole directional terms for each
alloy and their cross interactions.
The total energy Etot of an arbitrary arrangement of atoms is given by the EAM potential as
Etot =
F (ВЇ
ПЃi ) +
i
1
2
П†(rij )
i=j
and
ПЃВЇi =
ПЃ(rij )
j
where F is an embedding function, namely the energy to embed an atom i in the combined electron density
ПЃВЇi which is contributed from each of its neighbouring atoms j by an amount ПЃ(rij ), П†(rij ) is the pair potential
function representing the energy in bond ij which is due to the short-range electro-static interaction between
atoms, and rij is the distance between an atom and its neighbour for that bond.
The ADP potential is defined as
Etot =
F (ВЇ
ПЃi ) +
i
1
2
П†(rij ) +
i=j
1
2
2
(ВµО±
i ) +
i,О±
1
2
2
(О»О±ОІ
i ) в€’
i,О±,ОІ
1
6
ОЅi2
i
О±ОІ
О±ОІ
where ВµО±
i is the dipole vector, О»i is the quadrupole tensor and ОЅi is the trace of О»i .
Running the Calculator
EAM calculates the cohesive atom energy and forces. Internally the potential functions are defined by splines
which may be directly supplied or created by reading the spline points from a data file from which a spline
function is created. The LAMMPS compatible .alloy and .adp formats are supported. The LAMMPS .eam
format is slightly different from the .alloy format and is currently not supported.
For example:
from ase.calculators.eam import EAM
mishin = EAM(potential=’Al99.eam.alloy’)
mishin.write_potential(’new.eam.alloy’)
mishin.plot()
slab.set_calculator(mishin)
slab.get_potential_energy()
slab.get_forces()
The breakdown of energy contribution from the indvidual components are stored in the calculator instance
.results[’energy_components’]
7.14. Calculators
131
ASE Manual, Release 3.9.0.3865
Arguments
Keyword
Description
potential
file of potential in .alloy or .adp format (This is generally all you need to supply)
elements[N] array of N element abbreviations
embedded_energy[N]
arrays of embedded energy functions
electron_density[N]
arrays of electron density functions
phi[N,N]
arrays of pair potential functions
d_embedded_energy[N]
arrays of derivative embedded energy functions
d_electron_density[N]
arrays of derivative electron density functions
d_phi[N,N]
arrays of derivative pair potentials functions
d[N,N],
ADP dipole and quadrupole function
q[N,N]
d_d[N,N],
ADP dipole and quadrupole derivative functions
d_q[N,N]
skin
skin distance passed to NeighborList(). If no atom has moved more than the skin-distance
since the last call to the update() method then the neighbor list can be reused. Defaults
to 1.0.
form
the form of the potential alloy or adp. This will be determined from the file suffix or
must be set if using equations
Additional parameters for writing potential files
The following parameters are only required for writing a potential in .alloy or .adp format file.
Keyword
header
Z[N]
mass[N]
a[N]
lattice[N]
nrho
drho
nr
dr
Description
Three line text header. Default is standard message.
Array of atomic number of each element
Atomic mass of each element
Array of lattice parameters for each element
Lattice type
No. of rho samples along embedded energy curve
Increment for sampling density
No. of radial points along density and pair potential curves
Increment for sampling radius
Special features
.plot() Plots the individual functions. This may be called from multiple EAM potentials to compare the shape
of the individual curves. This function requires the installation of the Matplotlib libraries.
Notes/Issues
• Although currently not fast, this calculator can be good for trying small calculations or for creating new
potentials by matching baseline data such as from DFT results. The format for these potentials is compatible
with LAMMPS and so can be used either directly by LAMMPS or with the ASE LAMMPS calculator
interface.
• Supported formats are the LAMMPS .alloy and .adp. The .eam format is currently not supported.
The form of the potential will be determined from the file suffix.
• Any supplied values will override values read from the file.
• The derivative functions, if supplied, are only used to calculate forces.
• There is a bug in early versions of scipy that will cause eam.py to crash when trying to evaluate splines of a
potential with one neighbor such as caused by evaluating a dimer.
132
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Example:
import numpy as np
from ase.calculators.eam import EAM
from ase.lattice import bulk
# test to generate an EAM potential file using a simplified
# approximation to the Mishin potential Al99.eam.alloy data
from scipy.interpolate import InterpolatedUnivariateSpline as spline
cutoff = 6.28721
n = 21
rs = np.arange(0, n) * (cutoff / n)
rhos = np.arange(0, 2, 2. / n)
#
#
#
#
#
generated from
mishin = EAM(potential=’../potentials/Al99.eam.alloy’)
m_density = mishin.electron_density[0](rs)
m_embedded = mishin.embedded_energy[0](rhos)
m_phi = mishin.phi[0,0](rs)
m_density = np.array([2.78589606e-01,
1.06069912e-01,
7.76263116e-02,
8.13915861e-02,
2.27910928e-02,
3.65836583e-03,
1.48749693e-03,
2.02694937e-01,
8.42517168e-02,
8.23214224e-02,
6.59095390e-02,
1.13713167e-02,
2.60587564e-03,
7.40019174e-04,
1.45334053e-01,
7.65140344e-02,
8.53322309e-02,
4.28915711e-02,
6.05020311e-03,
2.06750708e-03,
6.21225205e-05])
m_embedded = np.array([1.04222211e-10, -1.04142633e+00, -1.60359806e+00,
-1.89287637e+00, -2.09490167e+00, -2.26456628e+00,
-2.40590322e+00, -2.52245359e+00, -2.61385603e+00,
-2.67744693e+00, -2.71053295e+00, -2.71110418e+00,
-2.69287013e+00, -2.68464527e+00, -2.69204083e+00,
-2.68976209e+00, -2.66001244e+00, -2.60122024e+00,
-2.51338548e+00, -2.39650817e+00, -2.25058831e+00])
m_phi = np.array([6.27032242e+01, 3.49638589e+01, 1.79007014e+01,
8.69001383e+00, 4.51545250e+00, 2.83260884e+00,
1.93216616e+00, 1.06795515e+00, 3.37740836e-01,
1.61087890e-02, -6.20816372e-02, -6.51314297e-02,
-5.35210341e-02, -5.20950200e-02, -5.51709524e-02,
-4.89093894e-02, -3.28051688e-02, -1.13738785e-02,
2.33833655e-03, 4.19132033e-03, 1.68600692e-04])
m_densityf = spline(rs, m_density)
m_embeddedf = spline(rhos, m_embedded)
m_phif = spline(rs, m_phi)
a = 4.05 # Angstrom lattice spacing
al = bulk(’Al’, ’fcc’, a=a)
mishin_approx = EAM(elements=[’Al’], embedded_energy=np.array([m_embeddedf]),
electron_density=np.array([m_densityf]),
phi=np.array([[m_phif]]), cutoff=cutoff, form=’alloy’,
# the following terms are only required to write out a file
Z=[13], nr=n, nrho=n, dr=cutoff / n, drho=2. / n,
lattice=[’fcc’], mass=[26.982], a=[a])
7.14. Calculators
133
ASE Manual, Release 3.9.0.3865
al.set_calculator(mishin_approx)
mishin_approx_energy = al.get_potential_energy()
mishin_approx.write_potential(’Al99-test.eam.alloy’)
mishin_check = EAM(potential=’Al99-test.eam.alloy’)
al.set_calculator(mishin_check)
mishin_check_energy = al.get_potential_energy()
print ’Cohesive Energy for Al = ’, mishin_approx_energy, ’ eV’
error = (mishin_approx_energy - mishin_check_energy) / mishin_approx_energy
print ’read/write check error = ’, error
assert abs(error) < 1e-4
Pure Python EMT calculator
The EMT potential is included in the ASE package in order to have a simple calculator that can be used for quick
demonstrations and tests.
Warning: If you want to do a real application using EMT, you should used the much more efficient implementation in the ASAP calculator.
class ase.calculators.emt.EMT
Right now, the only supported elements are: H, C, N, O, Al, Ni, Cu, Pd, Ag, Pt and Au. The EMT parameters for
the metals are quite realistic for many purposes, whereas the H, C, N and O parameters are just for fun!
ABINIT
Introduction
ABINIT is a density-functional theory code based on pseudopotentials and a planewave basis.
Environment variables
ASE_ABINIT_COMMAND
Must be set to something like this:
abinis < PREFIX.files > PREFIX.log
where abinis is the executable.
ABINIT_PP_PATH
A directory containing the pseudopotential files (at least of .fhi type).
Abinit does not provide tarballs of pseudopotentials so the easiest way is to download and unpack
http://wiki.fysik.dtu.dk/abinit-files/abinit-pseudopotentials-2.tar.gz
Set the environment variables in your in your shell configuration file:
export ASE_ABINIT_COMMAND="abinis < PREFIX.files > PREFIX.log"
PP=${HOME}/abinit-pseudopotentials-2
export ABINIT_PP_PATH=$PP/LDA_FHI
export ABINIT_PP_PATH=$PP/GGA_FHI:$ABINIT_PP_PATH
export ABINIT_PP_PATH=$PP/LDA_HGH:$ABINIT_PP_PATH
export ABINIT_PP_PATH=$PP/LDA_PAW:$ABINIT_PP_PATH
export ABINIT_PP_PATH=$PP/LDA_TM:$ABINIT_PP_PATH
134
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
export ABINIT_PP_PATH=$PP/GGA_FHI:$ABINIT_PP_PATH
export ABINIT_PP_PATH=$PP/GGA_HGHK:$ABINIT_PP_PATH
export ABINIT_PP_PATH=$PP/GGA_PAW:$ABINIT_PP_PATH
ABINIT Calculator
Abinit does not specify a default value for the plane-wave cutoff energy. You need to set them as in the example
at the bottom of the page, otherwise calculations will fail. Calculations wihout k-points are not parallelized by
default and will fail! To enable band paralellization specify Number of BanDs in a BLOCK (nbdblock).
Pseudopotentials
Pseudopotentials in the ABINIT format are available on the pseudopotentials website. A database of user contributed pseudopotentials is also available there.
Example 1
Here is an example of how to calculate the total energy for bulk Silicon ase/test/abinit/abinit_Si.py.
CASTEP
Introduction
CASTEP 3 W is a software package which uses density functional theory to provide a good atomic-level description of all manner of materials and molecules. CASTEP can give information about total energies, forces and
stresses on an atomic system, as well as calculating optimum geometries, band structures, optical spectra, phonon
spectra and much more. It can also perform molecular dynamics simulations.
The CASTEP calculator interface class offers intuitive access to all CASTEP settings and most results. All
CASTEP specific settings are accessible via attribute access (i.e. calc.param.keyword = ... or
calc.cell.keyword = ...)
Getting Started:
Set the environment variables appropriately for your system.
>>> export CASTEP_COMMAND=’ ... ’
>>> export CASTEP_PP_PATH=’ ... ’
Note: alternatively to CASTEP_PP_PATH one can set PSPOT_DIR as CASTEP consults this by default, i.e.
>>> export PSPOT_DIR=’ ... ’
Running the Calculator
The default initialization command for the CASTEP calculator is
class ase.calculators.castep.Castep(directory=’CASTEP’, label=’castep’)
3 S. J. Clark, M. D. Segall, C. J. Pickard, P. J. Hasnip, M. J. Probert, K. Refson, M. C. Payne Zeitschrift fГјr Kristallographie 220(5-6)
pp.567- 570 (2005) PDF.
7.14. Calculators
135
ASE Manual, Release 3.9.0.3865
To do a minimal run one only needs to set atoms, this will use all default settings of CASTEP, meaning LDA,
singlepoint, etc..
With a generated castep_keywords.py in place all options are accessible by inspection, i.e. tab-completion.
This works best when using ipython.
All options can be accessed via calc.param.<TAB>
or calc.cell.<TAB> and documentation is printed with calc.param.<keyword> ?
or
calc.cell.<keyword> ?. All options can also be set directly using calc.keyword = ... or
calc.KEYWORD = ... or even calc.KeYwOrD or directly as named arguments in the call to the
constructor (e.g. Castep(task=’GeometryOptimization’)).
All options that go into the .param file are held in an CastepParam instance, while all options that go into
the .cell file and don’t belong to the atoms object are held in an CastepCell instance. Each instance can
be created individually and can be added to calculators by attribute assignment, i.e. calc.param = param or
calc.cell = cell.
All internal variables of the calculator start with an underscore (_). All cell attributes that clearly belong into
the atoms object are blocked. Setting calc.atoms_attribute (e.g. = positions) is sent directly to the
atoms object.
Arguments:
KeyDescription
word
directory
The relative path where all input and output files will be placed. If this does not exist, it will be
created. Existing directories will be moved to directory-TIMESTAMP unless
self._rename_existing_dir is set to false.
label The prefix of .param, .cell, .castep, etc. files.
136
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Additional Settings
Internal
Description
Setting
_castep_command
(=castep): the actual shell command used to call CASTEP.
_check_checkfile
(=True): this makes write_param() only write a continue or reuse statement if the
addressed .check or .castep_bin file exists in the directory.
_copy_pspots (=False): if set to True the calculator will actually copy the needed pseudo-potential
(*.usp) file, usually it will only create symlinks.
_export_settings
(=True): if this is set to True, all calculator internal settings shown here will be included
in the .param in a comment line (#) and can be read again by merge_param. merge_param
can be forced to ignore this directive using the optional argument
ignore_internal_keys=True.
_force_write (=True): this controls wether the *cell and *param will be overwritten.
_prepare_input_only
(=False): If set to True, the calculator will create *cell und *param file but not start the
calculation itself. If this is used to prepare jobs locally and run on a remote cluster it is
recommended to set _copy_pspots = True.
_castep_pp_path
(=’.’) : the place where the calculator will look for pseudo-potential files.
_rename_existing_dir
(=True) : when using a new instance of the calculator, this will move directories out of
the way that would be overwritten otherwise, appending a date string.
_set_atoms
(=False) : setting this to True will overwrite any atoms object previously attached to the
calculator when reading a .castep file. By de- fault, the read() function will only create a
new atoms object if none has been attached and other- wise try to assign forces etc. based
on the atom’s positions. _set_atoms=True could be necessary if one uses CASTEP’s
internal geometry optimization (calc.param.task=’GeometryOptimization’)
because then the positions get out of sync. Warning: this option is generally not
recommended unless one knows one really needs it. There should never be any need, if
CASTEP is used as a single-point calculator.
_track_output(=False) : if set to true, the interface will append a number to the label on all input and
output files, where n is the number of calls to this instance. Warning: this setting may consume a lot more disk space because of the additio- nal *check files.
_try_reuse
(=_track_output) : when setting this, the in- terface will try to fetch the reuse file
from the previous run even if _track_output is True. By de- fault it is equal to
_track_output, but may be overridden.
Since this behavior may not always be desirable for single-point calculations. Regular
reuse for e.g. a geometry-optimization can be achieved by setting calc.param.reuse
= True.
Special features:
.dryrun_ok() Runs castep_command seed -dryrun in a temporary directory return True if all variables initialized ok. This is a fast way to catch errors in the input. Afterwards _kpoints_used is set.
.merge_param() Takes a filename or filehandler of a .param file or CastepParam instance and merges it into
the current calculator instance, overwriting current settings
.keyword.clear() Can be used on any option like calc.param.keyword.clear() or
calc.cell.keyword.clear() to return to the CASTEP default.
.initialize() Creates all needed input in the _directory. This can then copied to and run in a place
without ASE or even python.
.set_pspot(’<library>’) This automatically sets the pseudo-potential for all present species to
<Species>_<library>.usp. Make sure that _castep_pp_path is set correctly.
print(calc) Prints a short summary of the calculator settings and atoms.
ase.io.castep.read_seed(’path-to/seed’) Given
you
have
a
combination
of
seed.{param,cell,castep} this will return an atoms object with the last ionic positions in the .castep
7.14. Calculators
137
ASE Manual, Release 3.9.0.3865
file and all other settings parsed from the .cell and .param file. If no .castep file is found the positions are
taken from the .cell file. The output directory will be set to the same directory, only the label is preceded
by �copy_of_’ to avoid overwriting.
Notes/Issues:
• Currently only the FixAtoms constraint is fully supported for reading and writing.
• There is no support for the CASTEP unit system. Units of eV and Angstrom are used throughout. In particular when converting total energies from different calculators, one should check that the same CODATA
version is used for constants and conversion factors, respectively.
Example:
"""This simple demo calculates the total energy of CO molecules
using once LDA and once PBE as xc-functional. Obviously
some parts in this scripts are longer than necessary, but are shown
to demonstrate some more features."""
import ase
import ase.calculators.castep, ase.io.castep
calc = ase.calculators.castep.Castep()
directory = ’CASTEP_ASE_DEMO’
# include interface settings in .param file
calc._export_settings = True
# reuse the same directory
calc._directory = directory
calc._rename_existing_dir = False
calc._label = ’CO_LDA’
# necessary for tasks with changing positions
# such as GeometryOptimization or MolecularDynamics
calc._set_atoms = True
# Param settings
calc.param.xc_functional = ’LDA’
calc.param.cut_off_energy = 400
# Prevent CASTEP from writing *wvfn* files
calc.param.num_dump_cycles = 0
# Cell settings
calc.cell.kpoint_mp_grid = ’1 1 1’
calc.cell.fix_com = False
calc.cell.fix_all_cell = True
# Set and clear and reset settings (just for shows)
calc.param.task = ’SinglePoint’
# Reset to CASTEP default
calc.param.task.clear()
# all of the following are identical
calc.param.task = ’GeometryOptimization’
calc.task = ’GeometryOptimization’
calc.TASK = ’GeometryOptimization’
calc.Task = ’GeometryOptimization’
138
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
# Prepare atoms
mol = ase.atoms.Atoms(’CO’, [[0, 0, 0], [0, 0, 1.2]], cell=[10, 10, 10])
mol.set_calculator(calc)
# Check for correct input
if calc.dryrun_ok():
print(’%s : %s ’ % (mol.calc._label, mol.get_potential_energy()))
else:
print("Found error in input")
print(calc._error)
# Read all settings from previous calculation
mol = ase.io.castep.read_seed(’%s/CO_LDA’ % directory)
# Use the OTF pseudo-potential we have just generated
mol.calc.set_pspot(’OTF’)
# Change some settings
mol.calc.param.xc_functional = ’PBE’
# don’t forget to set an appropriate label
mol.calc._label = ’CO_PBE’
# Recalculate the potential energy
print(’%s : %s ’ % (mol.calc._label, mol.get_potential_energy()))
DftbPlus
Introduction
DftbPlus is a density-functional based tight-binding code using atom centered orbitals. This interface makes it
possible to use DftbPlus as a calculator in ASE. You need to register at DftbPlus site to download the code.
Additionally you need Slater-Koster files for the combination of atom types of your system. These can be obtained
at dftb.org.
Environment variables
Set environment variables in your configuration file (what is the directory for the Slater-Koster files and what is
the name of the executable):
• bash:
$ DFTB_PREFIX=/my_disk/my_name/lib/Dftb+sk/mio-0-1/
$ DFTB_COMMAND=~/bin/DFTB+/dftb+_s081217.i686-linux
(an example)
(an example)
• csh/tcsh:
$ setenv DFTB_PREFIX /my_disk/my_name/lib/Dftb+sk/mio-0-1/
$ setenv DFTB_COMMAND ~/bin/DFTB+/dftb+_s081217.i686-linux
(an example)
(an example)
DftbPlus Calculator (a FileIOCalculator)
The file �geom.out.gen’ contains the input and output geometry and it will be updated during the dftb calculations.
If restart == None it is assumed that a new input file �dftb_hsd.in’ will be written by ase using default keywords
and the ones given by the user.
If restart != None it is assumed that keywords are in file restart
All Keywords to the dftb calculator can be set by ase.
7.14. Calculators
139
ASE Manual, Release 3.9.0.3865
Parameters
restart: str (default None) If restart == None it is assumed that a new input file �dftb_hsd.in’ will
be written by ase using default keywords and the ones given by the user.
If restart != None it is assumed that keywords are in file �restart’
ignore_bad_restart_file: bool (default False) Ignore broken or missing restart file. By defauls, it is
an error if the restart file is missing or broken.
label: str (default �dftb’) Name used for all files. May contain a directory.
atoms: Atoms object (default None) Optional Atoms object to which the calculator will be attached. When restarting, atoms will get its positions and unit-cell updated from file.
kpts: (default None) Brillouin zone sampling:
• (1,1,1): Gamma-point
• (n1,n2,n3): Monkhorst-Pack grid
• (n1,n2,n3,’gamma’): Shifted Monkhorst-Pack grid that includes Γ
• [(k11,k12,k13),(k21,k22,k23),...]: Explicit list in units of the reciprocal
lattice vectors
• kpts=3.5: k-point density as in 3.5 k-points per Å−1 .
run_manyDftb_steps: bool (default False) If True the Dftb calculator is running many steps by its
own. If False all the relaxations/ molecular dynamis is done by ASE
Example: Geometry Optimization by ASE
from ase.calculators.dftb import Dftb
from ase.optimize import QuasiNewton
from ase.io import write
from ase.structure import molecule
test = molecule(’H2O’)
test.set_calculator(Dftb(label=’h2o’,
atoms=test,
Hamiltonian_MaxAngularMomentum_=’’,
Hamiltonian_MaxAngularMomentum_O=’"p"’,
Hamiltonian_MaxAngularMomentum_H=’"s"’,
))
dyn = QuasiNewton(test, trajectory=’test.traj’)
dyn.run(fmax=0.01)
write(’test.final.xyz’, test)
Example: Geometry Optimization by DFTB
#!/usr/bin/env python
#
import os
from
from
from
from
ase import Atoms
ase.calculators.dftb import Dftb
ase.optimize import QuasiNewton
ase.io import write, read
from ase.structure import molecule
140
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
test = molecule(’H2O’)
test.set_calculator(Dftb(label=’h2o’,atoms=test,
run_manyDftb_steps = True,
Driver_=’ConjugateGradient’,
Driver_MaxForceComponent=’1E-4’,
Driver_MaxSteps=1000,
Hamiltonian_MaxAngularMomentum_ = ’’,
Hamiltonian_MaxAngularMomentum_O = ’"p"’,
Hamiltonian_MaxAngularMomentum_H = ’"s"’,
))
dyn = QuasiNewton(test, trajectory=’test.traj’)
dyn.run(fmax=100, steps=0)
test = read(’geo_end.gen’)
write(’test.final.xyz’, test)
Example: NVE md followed by NVT md (both by DFTB)
This is unphysical because of at least two reasons - oxygen does not have spin here - the berendsen coupling is too
strong (0.01 here should be 0.0001) .. literalinclude:: dftb_ex3_make_2h2o.py
exciting
Introduction
exciting is a full-potential all-electron density-functional-theory (DFT) package based on the linearized augmented planewave (LAPW) method. It can be applied to all kinds of materials, irrespective of the atomic species
involved, and also allows for the investigation of the core region. The website is http://exciting-code.org/
The module depends on lxml http://lxml.de
There are two ways to construct the exciting calculator.
1. Using keyword arguments to specify groundstate attributes
2. Use paramdict to specify an input file structure with a data structure of dictionaries.
Constructor with Groundstate Keywords One is by giving parameters of the ground state in the constructor.
The possible attributes can be found at http://exciting-code.org/ref:groundstate
class ase.calculators.exciting.Exciting(bin=’excitingser’,
xctype=’LDA_PW’)
kpts=(4,
4,
4),
Parameter Dictionary When the paramdict keyword is used, the calculator translates the dictionary given
into the exciting XML file format. Note $EXCITINGROOT environmental variable should be set: details at
http://exciting-code.org/tutorials-boron
import os
from ase import Atoms
from ase.calculators.exciting import Exciting
# test structure, not real
a = Atoms(’N3O’, [(0, 0, 0), (1, 0, 0), (0, 0, 1), (0.5, 0.5, 0.5)], pbc=True)
calculator = Exciting(
7.14. Calculators
141
ASE Manual, Release 3.9.0.3865
dir=’excitingtestfiles’,
speciespath=os.environ[’EXCITINGROOT’]+’/species’,
paramdict={’title’:{’text()’:’N3O’},
’groundstate’:{’ngridk’:’1 2 3’,’tforce’:’true’},
’relax’:{},
’properties’:{’dos’:{},
’bandstructure’:
{’plot1d’:{’path’:{’steps’:’100’,
’point’:
[{’coord’:’0.75000
0.50000
0.25000’, ’label’:’W’},
{’coord’:’0.50000
0.50000
0.50000’, ’label’:’L’},
{’coord’:’0.00000
0.00000
0.00000’, ’label’:’G’},
{’coord’:’0.50000
0.50000
0.00000’, ’label’:’X’},
{’coord’:’0.75000
0.50000
0.25000’, ’label’:’W’},
{’coord’:’0.75000
0.37500
0.37500’, ’label’:’K’}]
}}}}})
calculator.write(a)
The calculator constructure above is used to create this exciting input file:
<?xml version=’1.0’ encoding=’UTF-8’?>
<input xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http:/
<title>N3O</title>
<structure speciespath="$EXCITINGROOT/species/" autormt="false">
<crystal>
<basevect>1.88972595820018 0.00000000000000 0.00000000000000</basevect>
<basevect>0.00000000000000 1.88972595820018 0.00000000000000</basevect>
<basevect>0.00000000000000 0.00000000000000 1.88972595820018</basevect>
</crystal>
<species chemicalSymbol="N" speciesfile="N.xml">
<atom coord="0.00000000000000 0.00000000000000 0.00000000000000"/>
<atom coord="0.00000000000000 0.00000000000000 0.00000000000000"/>
<atom coord="0.00000000000000 0.00000000000000 0.00000000000000"/>
</species>
<species chemicalSymbol="O" speciesfile="O.xml">
<atom coord="0.50000000000000 0.50000000000000 0.50000000000000"/>
</species>
</structure>
<relax/>
<groundstate tforce="true" ngridk="1 2 3"/>
<properties>
<dos/>
<bandstructure>
<plot1d>
<path steps="100">
<point coord="0.75000
0.50000
0.25000" label="W"/>
<point coord="0.50000
0.50000
0.50000" label="L"/>
<point coord="0.00000
0.00000
0.00000" label="G"/>
<point coord="0.50000
0.50000
0.00000" label="X"/>
<point coord="0.75000
0.50000
0.25000" label="W"/>
<point coord="0.75000
0.37500
0.37500" label="K"/>
</path>
</plot1d>
</bandstructure>
</properties>
</input>
The translation follows the following rules: String values are translated to attributes. Nested dictionaries are
translated to sub elements. A list of dictionaries is translated to a list of sub elements named after the key of which
the list is the value. The special key “text()” results in text content of the enclosing tag.
142
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Muffin Tin Radius
Sometimes it is necessary to specify a fixed muffin tin radius different from the default. The muffin tin radii can
be set by adding a custom array to the atoms object with the name “rmt”:
atoms.new_array(’rmt’, np.array([-1.0, -1.0, 2.3, 2.0] * Bohr))
Each entry corresponds to one atom. If the rmt value is negative, the default value is used. This array is correctly
updated if the atoms are added or removed.
Exciting Calculator Class
class ase.calculators.exciting.Exciting(dir=’calc’, paramdict=None, speciespath=None,
bin=’excitingser’, kpts=(1, 1, 1), **kwargs)
Exciting calculator object constructor
dir: string directory in which to execute exciting
paramdict: dict Dictionary containing XML parameters. String values are translated to attributes, nested
dictionaries are translated to sub elements. A list of dictionaries is translated to a list of sub elements
named after the key of which the list is the value.
default: None
speciespath: string Directory or URL to look up species files
bin: string Path or executable name of exciting
default: excitingser
kpts: integer list length 3 Number of k-points
kwargs: dictionary like list of key value pairs to be converted into groundstate attributes
FHI-aims
Introduction
FHI-aims is a all-electron full-potential density functional theory code using a numeric local orbital basis set. This
interface provides all that should be required to run FHI-aims from within ASE.
Running the Calculator
The default initialization command for the FHI-aims calculator is
class ase.calculators.aims.Aims(output_template = �aims’, track_output = False)
In order to run a calculation, you have to ensure that at least the following str variables are specified, either in
the initialization or as shell variables:
keydescription
word
run_command
The full command required to run FHI-aims from a shell, including anything to do with an MPI
wrapper script and the number of tasks. An alternative way to set this command is via the shell
variable AIMS_COMMAND, which is checked upon initialization and when starting a run.
species_dir
Directory where the species defaults are located that should be used. Can also be specified with
the system variable AIMS_SPECIES_DIR.
xc
The minimal physical specification: what kind of calculation should be done.
In addition, you might want to specify at least one of self-consistency accuracy commands (see below) in order to
avoid an excessively long calculation.
7.14. Calculators
143
ASE Manual, Release 3.9.0.3865
Two general options might come in useful to post process the output:
keyword
description
output_template
Base name for the output, in case the calculator is called multiple times within a single
script.
track_output True/False - if True all the output files will be kept, while the number of calls to the
calculator is encoded in the output file name.
List of keywords
This is a non-exclusive list of keywords for the control.in file that can be addresses from within ASE. The
meaning for these keywords is exactly the same as in FHI-aims, please refer to its manual for help on their use.
One thing that should be mentioned is that keywords with more than one option have been implemented as lists, eg.
k_grid=(12,12,12) or relativistic=(’atomic_zora’,’scalar’). In those cases, specifying a
single string containing all the options is also possible.
None of the keywords have any default within ASE,but do check the defaults set by FHI-aims. If there is a keyword
that you would like to set and that is not yet implemented here, it is trivial to add to the first few lines of the aims
calculator in the file ASE/ase/calculators/aims.py .
Describing the basic physics of the system:
keyword
xc
charge
spin
relativistic
use_dipole_correction
vdw_correction_hirshfeld
k_grid
type
str
float
str
list
bool
str
list
Driving relaxations and molecular dynamics:
keyword
relax_geometry
max_relaxation_steps
n_max_pulay
sc_iter_limit
restart_relaxations
MD_run
MD_schedule
MD_segment
type
list
int
int
int
bool
list
list
list
Output options:
keyword
output_level
output
cubes
type
str
list
AimsCube
See below for a description of the volumetric cube file output interface AimsCube
Keywords for accuracy settings:
keyword
sc_accuracy_eev
sc_accuracy_etot
sc_accuracy_forces
sc_accuracy_rho
compute_forces
type
exp
exp
exp
exp
bool
Keywords to adjust the SCF-cycle
144
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
keyword
charge_mix_param
prec_mix_param
spin_mix_param
KS_method
restart
restart_read_only
restart_write_only
preconditioner
mixer
empty_states
ini_linear_mixing
mixer_threshold
occupation_type
type
float
float
float
str
str
str
srt
list
str
int
int
list
list
Note:
Any argument can be changed after the initial construction of the
calculator, simply by setting it with the method
>>> calc.set( keyword=value )
Volumetric Data Output
The class
class ase.calculators.aims.AimsCube(origin=(0,0,0),edges=[(0.1,0.0,0.0),(0.0,0.1,0.0),(0.0,0.0,0.1)],points=(50,50,50)
describes an object that takes care of the volumetric output requests within FHI-aims. An object of this type can
be attached to the main Aims() object as an option.
The possible arguments for AimsCube are:
keyword
origin
edges
points
plots
type
list
3x3-array
list
list
The possible values for the entry of plots are discussed in detail in the FHI-aims manual, see below for an example.
Example
As an example, here is a possible setup to obtain the geometry of a water molecule:
from ase import Atoms
from ase.calculators.aims import Aims, AimsCube
from ase.optimize import QuasiNewton
water = Atoms(’HOH’, [(1, 0, 0), (0, 0, 0), (0, 1, 0)])
water_cube = AimsCube(points=(29, 29, 29),
plots=(’total_density’,
’delta_density’,
’eigenstate 5’,
’eigenstate 6’))
calc=Aims(xc=’PBE’,
output=[’dipole’],
sc_accuracy_etot=1e-6,
sc_accuracy_eev=1e-3,
7.14. Calculators
145
ASE Manual, Release 3.9.0.3865
sc_accuracy_rho=1e-6,
sc_accuracy_forces=1e-4,
cubes=water_cube)
water.set_calculator(calc)
dynamics = QuasiNewton(water,trajectory=’square_water.traj’)
dynamics.run(fmax=0.01)
FLEUR
Introduction
FLEUR is a density-functional theory code which uses the full potential linearized augmented plane-wave
(FLAPW) method. FLEUR can be applied to any element in the periodic table, and the code is well suited
especially to surfaces and magnetic materials.
Environment variables
In order to use FLEUR through ASE, two environment variables have to be set. FLEUR_INPGEN should point to
the simple input generator of FLEUR, and FLEUR to the actual executable. Note that FLEUR has different executables e.g. for cases with and without inversion symmetry, so the environment variable has to be set accordingly.
As an example, the variables could be set like:
$ export FLEUR_INPGEN=$HOME/fleur/v25/inpgen.x
$ export FLEUR=$HOME/fleur/v25/fleur.x
or:
$ export FLEUR="mpirun -np 32 $HOME/fleur/v25/fleur.x"
for parallel calculations.
FLEUR Calculator
Currently, limited number of FLEUR parameters can be set via the ASE interface Below follows a list of supported
parameters
keyword
xc
kpts
convergence
width
kmax
mixer
maxiter
maxrelax
workdir
type
str
seq
dict
float
float
dict
int
int
str
default value
’LDA’
О“-point
{’energy’:
0.0001}
40
20
Current dir
description
XC-functional. Must be one of �LDA’, �PBE’, �RPBE’
k-point sampling
Convergence criteria (meV)
Width of Fermi smearing (eV)
Plane-wave cut-off (a.u.)
Mixing parameters �imix’, �alpha’, and �spinf’
Maximum number of SCF steps
Maximum number of relaxation steps
Working directory for the calculation
seq: A sequence of three int�s. dict: A dictionary
Spin-polarized calculation
If the atoms object has non-zero magnetic moments, a spin-polarized calculation will be performed by default.
146
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Utility functions
As only a subset of FLEUR parameters can currently be specified through ASE interface, the interface defines
some utility functions for cases where manual editing of the FLEUR input file inp is necessary.
FLEUR.write_inp(atoms)
Write the inp input file of FLEUR.
First, the information from Atoms is written to the simple input file and the actual input file inp is then
generated with the FLEUR input generator. The location of input generator is specified in the environment
variable FLEUR_INPGEN.
Finally, the inp file is modified according to the arguments of the FLEUR calculator object.
FLEUR.initialize_density(atoms)
Creates a new starting density.
FLEUR.calculate(atoms)
Converge a FLEUR calculation to self-consistency.
Input files should be generated before calling this function FLEUR performs always fixed number of SCF
steps. This function reduces the number of iterations gradually, however, a minimum of five SCF steps is
always performed.
FLEUR.relax(atoms)
Currently, user has to manually define relaxation parameters (atoms to relax, relaxation directions, etc.) in
inp file before calling this function.
Examples
Lattice constant of fcc Ni
from numpy import linspace
from ase.calculators.fleur import FLEUR
from ase.lattice import bulk
from ase.io.trajectory import PickleTrajectory
atoms = bulk(’Ni’, a=3.52)
calc = FLEUR(xc=’PBE’, kmax=3.6, kpts=(10, 10, 10), workdir=’lat_const’)
atoms.set_calculator(calc)
traj = PickleTrajectory(’Ni.traj’,’w’, atoms)
cell0 = atoms.get_cell()
for s in linspace(0.95, 1.05, 7):
cell = cell0 * s
atoms.set_cell((cell))
ene = atoms.get_potential_energy()
traj.write()
See the equation of states tutorial for analysis of the results.
Gromacs
Introduction
Gromacs is a free classical molecular dynamics package. It is mainly used in modeling of biological systems. It
is part of the ubuntu-linux distribution. http://www.gromacs.org/
Warning:
1. Ase-Gromacs calculator works properly only with gromacs version 4.5.6 or a newer one. (fixed bug
related to .g96 format)
7.14. Calculators
147
ASE Manual, Release 3.9.0.3865
Warning:
2. It only makes sense to use ase-gromacs for qm/mm or for testing. For pure MM production runs the
native gromacs is much much faster (at the moment ase-gromacs has formatted io using .g96 format
which is slow).
Gromacs Calculator
This ASE-interface is a preliminary one and it is VERY SLOW so do not use it for production runs. It is here
because of we’ll have a QM/MM calculator which is using gromacs as the MM part.
For example: (setting for the MM part of a QM/MM run, parameter �-nt 1’ for serial run):
CALC_MM = Gromacs(doing_qmmm = True)
CALC_MM.set_own_params_runs(’extra_mdrun_parameters’, ’ -nt 1 ’)
Here default values for MM input are:: define = �-DFLEXIBLE’, integrator = �cg’, nsteps = �10000’, nstfout =
�10’, nstlog = �10’, nstenergy = �10’, nstlist = �10’, ns_type = �grid’, pbc = �xyz’, rlist = �1.15’, coulombtype
= �PME-Switch’, rcoulomb = �0.8’, vdwtype = �shift’, rvdw = �0.8’, rvdw_switch = �0.75’, DispCorr =
�Ener’
The input values can be changed by::
CALC_MM.set_own_params( �nsteps’,�99999’ �Number of steps’)
The arguments for gromacs programs can be changed by::
CALC_MM.set_own_params_runs( �extra_pdb2gmx_parameters’,’-ignh’)
CALC_MM.set_own_params_runs( �init_structure’,�1GM2.pdb’)
CALC_MM.set_own_params_runs( �extra_mdrun_parameters’, � -nt 1 �)
CALC_MM.set_own_params_runs( �extra_grompp_parameters’, � �)
CALC_MM.set_own_params_runs( �extra_editconf_parameters’, � �)
CALC_MM.set_own_params_runs( �extra_genbox_parameters’, � �)
Parameters
The
description
of
the
parameters
http://www.gromacs.org/Documentation/Manual
can
be
found
in
the
Gromacs
manual:
and extra (ie. non-gromacs) parameter:
do_qmmm: logical (default False) If true we run only single step of gromacs (to get MM forces and energies in
QM/MM)
freeze_qm: logical (default False) If true, the qm atoms will be kept fixed (The list of qm atoms is taken from
file �index_filename’, below)
clean: logical (default True) If true old gromacs files are cleaned
force_field: str (default oplsaa) Name of the force field for gromacs
water_model: str (default tip3p) Name of the water model for gromacs
Environmental variables:
• GMXCMD the name of the main gromacs executable (usually �mdrun’). If GMXCMD is not set gromacs
test is not run, but in the calculator works using �mdrun’.
• GMXCMD_PREF prefix for all gromacs commands (default �’)
148
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
• GMXCMD_POST postfix (ie suffix) for all gromacs commands (default �’)
Example: MM-only geometry optimization of a histidine molecule
THIS IS NOT A PROPER WAY TO SETUP YOUR MD SIMULATION. THIS IS JUST A DEMO THAT DOES
NOT CRASH. (the box size should be iterated by md-NTP, total charge should be 0).
Initial pdb coordinates (file his.pdb):
COMPND
REMARK
REMARK
HETATM
HETATM
HETATM
HETATM
HETATM
HETATM
HETATM
HETATM
HETATM
HETATM
HETATM
REMARK
HIS HISTIDINE
HIS Part of HIC-Up: http://xray.bmc.uu.se/hicup
HIS Extracted from PDB file pdb1wpu.ent
1 N
HIS 4234
0.999 -1.683 -0.097
2 CA HIS 4234
1.191 -0.222 -0.309
3 C
HIS 4234
2.641
0.213 -0.105
4 O
HIS 4234
3.529 -0.651 -0.222
5 CB HIS 4234
0.245
0.546
0.619
6 CG HIS 4234
-1.200
0.349
0.280
7 ND1 HIS 4234
-1.854 -0.849
0.470
8 CD2 HIS 4234
-2.095
1.176 -0.310
9 CE1 HIS 4234
-3.087 -0.752
0.006
10 NE2 HIS 4234
-3.258
0.467 -0.474
11 OXT HIS 4234
2.889
1.404
0.141
HIS ENDHET
1.00
1.00
1.00
1.00
1.00
1.00
1.00
1.00
1.00
1.00
1.00
20.00
20.00
20.00
20.00
20.00
20.00
20.00
20.00
20.00
20.00
20.00
The sample file for relaxation:
""" An example for using gromacs calculator in ase.
Atom positions are relaxed.
A sample call:
python ./gromacs_example_mm_relax.py his.pdb
"""
from ase.calculators.gromacs import Gromacs
import sys
from ase.io import read
infile_name = sys.argv[1]
CALC_MM_RELAX = Gromacs(clean=True)
CALC_MM_RELAX.set_own_params_runs(
’extra_pdb2gmx_parameters’,’-ignh’)
CALC_MM_RELAX.set_own_params_runs(
’init_structure’,infile_name)
CALC_MM_RELAX.generate_topology_and_g96file()
CALC_MM_RELAX.write_input()
CALC_MM_RELAX.set_own_params_runs(
’extra_editconf_parameters’,’-bt cubic -c -d 0.8’)
CALC_MM_RELAX.run_editconf()
CALC_MM_RELAX.set_own_params_runs(
’extra_genbox_parameters’,’-cs spc216.gro’)
CALC_MM_RELAX.run_genbox()
CALC_MM_RELAX.generate_gromacs_run_file()
CALC_MM_RELAX.run()
7.14. Calculators
149
ASE Manual, Release 3.9.0.3865
Jacapo - ASE python interface for Dacapo
Introduction
Jacapo is an ASE interface for Dacapo that is fully compatible with ASE. It replaces the old Dacapo interface
using Numeric python and ASE2. The code was originally developed by John Kitchin and detailed documentation
as well as many examples are available online:
http://gilgamesh.cheme.cmu.edu/doc/software/jacapo/index.html
Jacapo is included as an optional calculator in ASE and small differences to the above documentation may occur,
and the documentation is no longer maintained.
Jacapo calculator
The Jacapo interface is automatically installed with ase and can be imported using:
from ase.calculators.jacapo import Jacapo
(You will need to have a working installation of Dacapo, however.)
class ase.calculators.jacapo.Jacapo
Here is a list of available keywords to initialize the calculator:
keyword
nc
outnc
atoms
pw
dw
xc
type
str
str
object
float
float
str
nbands
ft
kpts
spinpol
fixmagmom
symmetry
stress
dipole
ados
stay_alive
debug
deletenc
int
float
list
boolean
str
boolean
boolean
boolean
dict
boolean
int
boolean
description
Output NetCDF file, or input file if nc already exists.
Output file. By default equal to nc.
ase atoms object
Planewave cutoff in eV
Density cutoff in eV
Exchange-correlation functional. One of
[’PZ’,’VWN’,’PW91’,’PBE’,’RPBE’,’revPBE’]
Number of bands
Fermi temperature
K-point grid, e.g. kpts = (2,2,1)
Turn on/off spin-polarization
Magnetic moment of the unit cell
Turn on/off symmetry reduction
Turn on/off stress calculation
Turn on/off dipole correction
Atom-projected density of states
Turn on/off stay alive
Set debug level (0=off, 10=extreme)
If the nc file exists, delete it (to ensure a fresh run). Default is False.
Example
Here is an example of how to calculate the total energy of a H atom.
Warning: This is an example only - the parameters are not physically meaningful!
from ase import Atoms, Atom
from ase.io import write
from ase.calculators.jacapo import Jacapo
atoms = Atoms([Atom(’H’,[0,0,0])],
cell=(2,2,2),
150
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
pbc=True)
calc = Jacapo(’Jacapo-test.nc’,
pw=200,
nbands=2,
kpts=(1,1,1),
spinpol=False,
dipole=False,
symmetry=False,
ft=0.01)
atoms.set_calculator(calc)
print atoms.get_potential_energy()
write(’Jacapo-test.traj’, atoms)
Note that all calculator parameters should be set in the calculator definition itself. Do not attempt to use the
calc.set_* commands as they are intended to be internal to the calculator. Note also that Dacapo can only operate
with periodic boundary conditions, so be sure that pbc is set to True.
Restarting from an old calculation
If the file you specify to Jacapo with the nc keyword exists, Jacapo will assume you are attempting to restart
an existing calculation. If you do not want this behavior, turn the flag deletenc to True in your calculator
definition.
For example, it is possible to continue a geometry optimization with something like this:
calc = Jacapo(’old.nc’, stay_alive=True)
atoms = calc.get_atoms()
dyn = QuasiNewton(atoms, logfile=’qn.log’)
dyn.run(fmax=0.05)
Note, that the stay_alive flag is not stored in the .nc file and must be set when the calculator instance is created.
Atom-projected density of states
To find the atom-projected density of states with Jacapo, first specify the ados dictionary in your calculator definition, as in:
calc = Jacapo( ... ,
ados={’energywindow’: (-10., 5.),
’energywidth’: 0.2,
’npoints’: 250,
’cutoff’: 1.0})
After this is established, you can use the get_ados command to get the desired ADOS data. For example:
energies, dos = calc.get_ados(atoms=[0],
orbitals=[’d’],
cutoff=’short’,
spin=[0])
LAMMPS Calculators
LAMMPS (Large-scale Atomic/Molecular Massively Parallel Simulator) is a classical molecular dynamics code.
There are two calculators that interface to the LAMMPS molecular dynamics code that can be used to solve an
atoms model for energy, atom forces and cell stresses. They are:
7.14. Calculators
151
ASE Manual, Release 3.9.0.3865
1. LAMMPSrun which interfaces to LAMMPS via writing a controlling input file that is then run automatically
through LAMMPS and the results read back in. These results are currently limited to total energy, atomic forces
and cell stress.
2. LAMMPSlib which uses the python interface that comes with LAMMPS, loads the LAMMPS program as a
python library. The LAMMPSlib calculator then creates a �.lmp’ object which is a running LAMMPS subroutine,
so further commands can be sent to this object and executed until it is explicitly closed. Any additional variables
calculated by LAMMPS can also be extracted. Note however, any mistakes in the code sent to the LAMMPS
routine will cause python to terminate.
ASE is licensed as LGPL and LAMMPS is GPL which �prohibits’ them from being linked together in a distribution
such as ASE. As a result, LAMMPSlib is not distributed with the ASE project but is available separately at
lammpslib . Further explanation of the licensing is constained in License.
It should not matter which code you use, but if you want access to more of LAMMPS internal variables or to
perform a more complicated simulation then use LAMMPSlib. It is important to know which code you are using
because when you make an error in the LAMMPS code, debugging the is difficult and different for both calculators.
Both of these interfaces are still experimental code and any problems should be reported to the ASE developers
mailing list.
LAMMPSrun
Introduction
LAMMPS (Large-scale Atomic/Molecular Massively Parallel Simulator) is a classical molecular dynamics code.
“LAMMPS has potentials for soft materials (biomolecules, polymers) and solid-state materials (metals, semiconductors) and coarse-grained or mesoscopic systems. It can be used to model atoms or,
more generically, as a parallel particle simulator at the atomic, meso, or continuum scale.”
This is LAMMPSrun ASE implementation of the interface to LAMMPS.
Environment variables
The environment variable LAMMPS_COMMAND should contain the path to the lammps binary, or more generally,
a command line possibly also including an MPI-launcher command. For example (in a Bourne-shell compatible
environment):
$ export LAMMPS_COMMAND=/path/to/lmp_binary
or possibly something similar to
$ export LAMMPS_COMMAND="/path/to/mpirun --np 4 lmp_binary"
LAMMPS Calculator
The LAMMPS calculator first appeared in ASE version 3.5.0. At the time of the release of ASE 3.5.0, the
LAMMPS calculator is still in a fairly early stage of development (if you are missing some feature, consider
checking out the source code development tree or some more recent version of ASE).
class ase.calculators.LAMMPSrun.LAMMPS(..., parameters={}, files=[], ...)
Below follows a list with a selection of parameters
152
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
keyword
type default
value
files list[]
parameters
dict{}
description
List of files needed by LAMMPS. Typically a list of potential files.
Dictionary with key-value pairs corresponding to commands and arguments.
Command-argument pairs provided here will be used for overriding the the
calculator defaults.
Example
A simple example.
from ase import Atoms, Atom
from ase.calculators.lammpsrun import LAMMPS
a = [6.5, 6.5, 7.7]
d = 2.3608
NaCl = Atoms([Atom(’Na’, [0, 0, 0]),
Atom(’Cl’, [0, 0, d])],
cell=a, pbc=True)
calc = LAMMPS()
NaCl.set_calculator(calc)
print NaCl.get_stress()
Setting up an OPLS calculation
There are some modules to facilitate the setup of an OPLS force field calculation, see ase.io.opls.
NWChem
NWChem is a computational chemistry code based on gaussian basis functions or plane-waves.
Environment variable
The default command to start NWChem is nwchem PREFIX.nw > PREFIX.out. You can change that by
setting the environment variable ASE_NWCHEM_COMMAND.
Example
Here is an example of how to calculate optimize the geometry of a water molecule using PBE:
$ asec H2O optimize -c nwchem -p xc=PBE
LBFGS:
0 16:17:29
-2064.914841
1.9673
LBFGS:
1 16:17:31
-2064.963074
0.9482
LBFGS:
2 16:17:32
-2064.976603
0.1425
LBFGS:
3 16:17:33
-2064.977216
0.0823
LBFGS:
4 16:17:35
-2064.977460
0.0010
$ ase-gui H2O.traj@-1 -tg "a(1,0,2),d(0,1)"
102.577881445 1.00806894632
7.14. Calculators
153
ASE Manual, Release 3.9.0.3865
SIESTA
Introduction
SIESTA is a density-functional theory code for very large systems based on atomic orbital (LCAO) basis sets.
Environment variables
You need to write a script called run_siesta.py containing something like this:
import os
siesta = ’siesta_2.0’
exitcode = os.system(’%s < %s.fdf > %s.txt’ % (siesta, label, label))
The environment variable SIESTA_SCRIPT must point to that file.
A directory containing the pseudopotential files .vps is also needed, and it is to be put in the environment variable
SIESTA_PP_PATH.
Set both environment variables in your shell configuration file:
$ export SIESTA_SCRIPT=$HOME/siesta/run_siesta.py
$ export SIESTA_PP_PATH=$HOME/mypps
SIESTA Calculator
The default parameters are very close to those that the SIESTA Fortran code uses. These are the exceptions:
class ase.calculators.siesta.Siesta(label=’siesta’, xc=’LDA’, pulay=5, mix=0.1)
Here is a detailed list of all the keywords for the calculator:
keyword
kpts
nbands
meshcutoff
basis
xc
pulay
mix
width
charge
label
type
list
int
float
str
str
int
float
float
float
str
default value
[1,1,1]
None
None
None
’LDA’
5
0.1
None
None
’siesta’
description
Monkhorst-Pack k-point sampling
Number of bands
Mesh cut-off energy in eV
Type of basis set (�sz’, �dz’, �szp’, �dzp’)
Exchange-correlation functional.
Number of old densities to use for Pulay mixing
Pulay mixing weight
Fermi-distribution width in eV
Total charge of the system
Name of the output file
A value of None means that SIESTA’s default value is used.
Extra FDF parameters
The SIESTA code reads the input parameters for any calculation from a .fdf file. This means that you can set
parameters by manually setting entries in this input .fdf file. This is done by the syntax:
>>> calc.set_fdf(’name_of_the_entry’, value)
For example, the EnergyShift can be set using
>>> calc.set_fdf(’PAO.EnergyShift’, 0.01 * Rydberg)
The complete list of the FDF entries can be found in the official SIESTA manual.
154
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Customized basis-set
Standard basis sets can be set by the keyword basis directly in the Siesta calculator object. If a customized basis
is needed, it can be set as an FDF entry, as explained in the previous section.
As an example, we generate a triple-zeta triple-polarized (TZTP) basis for Au. Since the valence states are 6s and
5d, we will have 3 zeta orbitals for l=0 and 3 for l=2 plus 3 polarization orbitals for l=1. The basis can be defined
by
>>> value = ["""Au
2
>>>
0
3
P
>>>
0.00
0.00
>>>
>>>
2
3
>>>
0.00
0.00
split
3
0.00
0.00
0.00"""]
#label, num. of l-shells,type,charge
#l,nzeta,’P’(opt):pol.functions,npolzeta
#rc of basis functions for each zeta function
#0.00 => rc determined by PAO.EnergyShift
#l,nzeta
#rc
>>> calc.set_fdf(’PAO.Basis’,value=value)
The default basis set generation fails for Pt for some versions of Siesta. If this happens, you should specify the
basis set manually. This is exemplified below.
For Pt, using calc.set_fdf(’PAO.EnergyShift’, 0.1 * eV) is usually reasonable, and a single-zeta
polarized basis set can be specified by writing:
# Define SZP basis set for Pt
calc.set_fdf(’PAO.Basis’,
["""\
Pt
2
# Species label, number of l-shells
n=6 0 1 P
# n, l, Nzeta, Polarization, NzetaPol
0.
# 0.0 => default [6.982 \n 1.000]
n=5 2 1
# n, l, zeta
0."""])
# 0.0 => default [5.172 \n 1.000]
A double-zeta polarized basis set for Pt may be specified by:
# Define DZP basis set for Pt
calc.set_fdf(’PAO.Basis’,
["""\
Pt 2 split 0.00 # Species label, number of l-shells
n=6 0 2 P 1
# n, l, Nzeta, Polarization, NzetaPol
0.00 0.00
# 0.0 => default [6.982 5.935 \n 1.000
n=5 2 2
# n, l, zeta
0.00 0.00"""])
# 0.0 => default [5.172 3.060 \n 1.000
1.000]
1.000]
You can also reuse the basis set of a previous calculation, by copying the .ion files to the new location, and set the
User.Basis tag to True:
# Load basis from previous calc (*.ion files)
calc.set_fdf(’User.Basis’, True)
Warning: Specifying a basis set manually in any way will, for some obscure reason, make Siesta crash if you have
ghost atoms!
Pseudopotentials
Pseudopotential files in the .psf or .vps formats are needed. Pseudopotentials generated from the ABINIT
code and converted to the SIESTA format are available in the SIESTA website . A database of user contributed
pseudopotentials is also available there.
You can also find an on-line pseudopotential generator from the OCTOPUS code.
7.14. Calculators
155
ASE Manual, Release 3.9.0.3865
Example
Here is an example of how to calculate the total energy for bulk Silicon, using a double-zeta basis generated by
specifying a given energy-shift:
#!/usr/bin/env python
from ase import *
a0 = 5.43
bulk = Atoms(’Si2’, [(0, 0, 0),
(0.25, 0.25, 0.25)],
pbc=True)
b = a0 / 2
bulk.set_cell([(0, b, b),
(b, 0, b),
(b, b, 0)], scale_atoms=True)
calc = Siesta(label=’Si’,
xc=’PBE’,
meshcutoff=200 * Ry,
basis=’dz’,
mix=0.01,
kpts=[10, 10, 10])
calc.set_fdf(’PAO.EnergyShift’, 0.01 * Ry)
bulk.set_calculator(calc)
e = bulk.get_potential_energy()
Here, the only input information on the basis set is, that it should be double-zeta (basis=’dz’) and that the confinement potential should result in an energy shift of 0.01 Rydberg (the PAO.EnergyShift fdf tag). Sometimes
it can be necessary to specify more information on the basis set. For example, the default basis set generation fails
for Pt for some versions of Siesta. To fix this, you must specify the basis set manually. Manual basis set specifications are described in Customized basis-set.
Restarting from an old Calculation
If you want to rerun an old SIESTA calculation, made using the ASE interface or not, you can set the fdf tag
UseSaveData to True. This is equivalent to setting both DM.UseSaveDM and MD.UseSaveXV to True, i.e.
it will reuse the the density matrix, and the atomic coordinates (and unit cell) of the previous calculation. Note
that the Siesta jobname (the label keyword in the ASE interface) must be identical to the jobname of the old
calculation.
TURBOMOLE
Introduction
TURBOMOLE is a density-functional or Hartree Fock code using atom centered orbitals. This interface makes it
possible to use TURBOMOLE as a calculator in ASE.
Environment variables
Set environment variables in your configuration file:
• bash:
$ TURBODIR=/my_disk/my_name/TURBOMOLE
$ PATH=$TURBODIR/scripts:$PATH
$ PATH=$TURBODIR/bin/sysname:$PATH
156
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
• csh/tcsh:
$ setenv TURBODIR /my_disk/my_name/TURBOMOLE
$ set path=(${TURBODIR}/scripts $path)
$ set path=(${TURBODIR}/bin/sysname $path)
where sysname could be, e.g.: x866 4 в€’ unknown в€’ linux в€’ gnu.
Turbomole Calculator
All usual turbomole input files generated by Turbomole’s define [coord, control, basis, (auxbasis),
mos/alpha+beta] must be present in the current working directory.
Turbomole files are updated during the ASE-run.
Do not use internal coordinates, only cartesians are allowed.
Ase-Turbomole uses turbomole programs �ridft’ and �rdgrad’ if keyword �$ricore’ is present in the Turbomole’s
control file. Otherwise programs �dscf’ and �grad’ are used.
Example1: Single-point energy
Here is an example of how to calculate the total energy of H2 ase/test/turbomole/turbomole_H2.py.
Example2: NEB
Here is an example of how
ase/test/turbomole/turbomole_h3o2m.py.
to
calculate
a
proton
transfer
barrier
in
H3O2-:
VASP
Introduction
VASP is a density-functional theory code using pseudopotentials or the projector-augmented wave method and a
plane wave basis set. This interface makes it possible to use VASP as a calculator in ASE, and also to use ASE as
a post-processor for an already performed VASP calculation.
Environment variables
You need to write a script called run_vasp.py containing something like this:
import os
exitcode = os.system(’vasp’)
The environment variable VASP_SCRIPT must point to that file.
A directory containing the pseudopotential directories potpaw (LDA XC) potpaw_GGA (PW91 XC) and
potpaw_PBE (PBE XC) is also needed, and it is to be put in the environment variable VASP_PP_PATH.
Set both environment variables in your shell configuration file:
$ export VASP_SCRIPT=$HOME/vasp/run_vasp.py
$ export VASP_PP_PATH=$HOME/vasp/mypps
7.14. Calculators
157
ASE Manual, Release 3.9.0.3865
VASP Calculator
The default setting used by the VASP interface is
class ase.calculators.vasp.Vasp(restart=None, xc=’PW91’, setups=None, kpts=(1, 1, 1),
gamma=None)
Below follows a list with a selection of parameters
keyword
restart
xc
setups
kpts
gamma
reciprocal
prec
encut
ediff
nbands
algo
ismear
sigma
nelm
type
bool
str
str
seq
bool
bool
str
float
float
int
str
int
float
int
default value
None
’PW91’
None
О“-point
None
None
description
Restart old calculation or use ASE for post-processing
XC-functional
Additional setup option
k-point sampling
О“-point centered k-point sampling
Use reciprocal units if k-points are specified explicitly
Accuracy of calculation
Kinetic energy cutoff
Convergence break condition for SC-loop.
Number of bands
Electronic minimization algorithm
Type of smearing
Width of smearing
Maximum number of SC-iterations
seq: A sequence of three int�s.
For parameters in the list without default value given, VASP will set the default value. Most of the parameters
used in the VASP INCAR file are allowed keywords. See the official VASP manual for more details.
Note: Parameters can be changed after the calculator has been constructed by using the set() method:
>>> calc.set(prec=’Accurate’, ediff=1E-5)
This would set the precision to Accurate and the break condition for the electronic SC-loop to 1E-5 eV.
Spin-polarized calculation
If the atoms object has non-zero magnetic moments, a spin-polarized calculation will be performed by default.
Here follows an example how to calculate the total magnetic moment of a sodium chloride molecule.
from ase import Atoms, Atom
from ase.calculators.vasp import Vasp
a = [6.5, 6.5, 7.7]
d = 2.3608
NaCl = Atoms([Atom(’Na’, [0, 0, 0], magmom=1.928),
Atom(’Cl’, [0, 0, d], magmom=0.75)],
cell=a)
calc = Vasp(prec = ’Accurate’,
xc = ’PBE’,
lreal = False)
NaCl.set_calculator(calc)
print NaCl.get_magnetic_moment()
In this example the initial magnetic moments are assigned to the atoms when defining the Atoms object. The calculator will detect that at least one of the atoms has a non-zero magnetic moment and a spin-polarized calculation
will automatically be performed. The ASE generated INCAR file will look like:
158
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
INCAR created by Atomic Simulation Environment
PREC = Accurate
LREAL = .FALSE.
ISPIN = 2
MAGMOM = 1*1.9280 1*0.7500
Note: It is also possible to manually tell the calculator to perform a spin-polarized calculation:
>>> calc.set(ispin=2)
This can be useful for continuation jobs, where the initial magnetic moment is read from the WAVECAR file.
Restart old calculation
To continue an old calculation which has been performed without the interface use the restart parameter when
constructing the calculator
>>> calc = Vasp(restart=True)
Then the calculator will read atomic positions from the CONTCAR file, physical quantities from the OUTCAR file,
k-points from the KPOINTS file and parameters from the INCAR file.
Note: Only Monkhorst-Pack and Gamma-centered k-point sampling are supported for restart at the moment.
Some INCAR parameters may not be implemented for restart yet. Please report any problems to the ASE mailing
list.
The restart parameter can be used , as the name suggest to continue a job from where a previous calculation
finished. Furthermore, it can be used to extract data from an already performed calculation. For example, to get the
total potential energy of the sodium chloride molecule in the previous section, without performing any additional
calculations, in the directory of the previous calculation do:
>>> calc = Vasp(restart=True)
>>> atoms = calc.get_atoms()
>>> atoms.get_potential_energy()
-4.7386889999999999
ase_qmmm_manyqm
Introduction
This an general interface to run QM/MM calculations with a ase-QM and ase-MM calculator. Currently QM can
be FHI-aims and MM can be Gromacs.
QM and MM region can be covalently bonded. In principle you can cut wherever you like, but other cutting
schemes are probably better than others. The standard recommendation is to cut only the C-C bonds.
There can be many QM regions embedded in the MM system.
Ase_qmmm_manyqm Calculator
QM/MM interface with QM=FHI-aims, MM=gromacs
QM could be any QM calculator, but you need to read in QM-atom charges from the QM program (in method
�get_qm_charges’).
One can have many QM regions, each with a different calculator. There can be only one MM calculator, which is
calculating the whole system.
7.14. Calculators
159
ASE Manual, Release 3.9.0.3865
Non-bonded interactions:
Generally energies and forces are treated by:
• Within the same QM-QM: by QM calculator
• MM-MM: by MM calculator
• QM-MM: by MM using MM vdw parameters and QM charges.
• Different QM-different QM: by MM using QM and MM charges and MM-vdw parameters
The Hirschfeld charges (or other atomic charges) on QM atoms are calculated by QM in a H terminated cluster in
vacuum. The charge of QM atom next to MM atom (edge-QM-atom) and its H neighbors are set as in the classical
force field.
The extra(missing) charge results from:
• linkH atoms
• The edge-QM atoms, and their singly bonded neighbors (typically -H or =O). These have their original
MM charges.
• From the fact that the charge of the QM fraction is not usually an integer when using the original MM
charges.
• The extra/missing charge is added equally to all QM atoms (not being linkH and not being edge-QMatom or its singly bonded neighbor) so that the total charge of the MM-fragment involving QM atoms
will be the same as in the original MM-description.
Vdw interactions are calculated by MM-gromacs for MM and MM-QM interactions. The QM-QM vdw interaction
s could be done by the FHI-aims if desired (by modifying the input for QM-FHI-aims input accordingly.
Bonded interactions:
E = E_qm(QM-H) + E_mm(ALL ATOMS), where
• E_qm(QM-H): qm energy of H terminated QM cluster(s)
• E_mm(ALL ATOMS): MM energy of all atoms, except for terms in which all MM-interacting atoms
are in the same QM region.
Forces do not act on link atoms but they are positioned by scaling. Forces on link atoms are given to their
QM and MM neighbors by chain rule. (see Top Curr Chem (2007) 268: 173–290, especially pages 192194). At the beginning of a run, the optimal edge-qm-atom-linkH bond length(s) is (are) calculated by QM in
�get_eq_qm_atom_link_h_distances’ or they are read from a file (this is determined by the argument �link_info’).
The covalent bonds between QM and MM are found automatically based on ase-covalent radii in neighbor search.
Link atoms are positioned automatically (according to .
Questions & Comments [email protected]
Interesting applications could be cases when we need two or more QM regions. For instance two redox centers in
a protein, cathode and anode of a fuel cell ... you name it!
Arguments
keyword
type default
value
nqm_regions
int
qm_calculators
list
mm_calculator
Calc
link_infostr ’byQM’
160
description
The number of QM regions
List of members of a Class defining a ase-QM calculator for each QM region
A member of a Class defining a ase-MM calculator
Can be either �byQM’: the edge_qm_atom-link_h_atom distances are
calculated by QM or �byFile’:the edge_qm_atom-link_h_atom distances are
read from a file
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Example
1. Prepare classical input with Gromacs
• Get THE INDEPENDENT STRUCTURE OF THE ANTITRYPTIC REACTIVE SITE LOOP OF
BOWMAN-BIRK INHIBITOR AND SUNFLOWER TRYPSIN INHIBITOR-1 (pdb code 1GM2) from
pdb data bank http://www.rcsb.org/pdb/home/home.do, name it to 1GM2.pdb
• In file 1GM2.pdb take only MODEL1 replace �CYS � by �CYS2’ in order to get deprotonated CYS-CYS
bridge.
• Generate gromacs coordinates and topology
>>> pdb2gmx -ff oplsaa -f 1GM2.pdb -o 1GM2.gro -p 1GM2.top -water tip3p -ignh
• Generate the simulation box (cubic is not the most efficient one...)
>>> editconf -bt cubic -f 1GM2.gro -o 1GM2_box.gro -c -d 0.2
• Solvate the protein in water box
>>> genbox -cp 1GM2_box.gro -cs spc216.gro -o 1GM2_sol.gro -p 1GM2.top
• Generate index file (needed later also for defining QM atoms)
>>> make_ndx -f 1GM2_sol.gro -o index.ndx
>>> select ’q’ <ENTER>
• add to first lines to index.ndx (we define here 3 QM regions, indexing from 1):
[qm_ss]
18 19 20 21 139 140 141 142
[qm_thr]
28 29 30 31 32 33 34 35
[qm_ser]
64 65 66 67 68
2. Relax MM system by fixing QM atoms in their (crystallographic?) positions (see documentation for Gromacs MM calculator).
"""
An example for using gromacs calculator in ase.
Atom positions are relaxed.
If qm atoms are found in index file, they are kept fixed in the relaxation.
QM atoms are defined in index file (numbering from 1)
in sets containing QM or Qm or qm in their name.
A sample call:
./gromacs_example_mm_relax.py 1GM2_sol.gro
"""
from ase.calculators.gromacs import Gromacs
import sys
from ase.io import read
infile_name = sys.argv[1]
CALC_MM_RELAX = Gromacs(
init_structure_file=infile_name,
structure_file = ’gromacs_mm-relax.g96’,
force_field=’oplsaa’,
7.14. Calculators
161
ASE Manual, Release 3.9.0.3865
water_model=’tip3p’,
base_filename = ’gromacs_mm-relax’,
doing_qmmm = False, freeze_qm = True,
index_filename = ’index.ndx’,
extra_mdrun_parameters = ’ -nt 1 ’,
define = ’-DFLEXIBLE’,
integrator = ’cg’,
nsteps = ’10000’,
nstfout = ’10’,
nstlog = ’10’,
nstenergy = ’10’,
nstlist = ’10’,
ns_type = ’grid’,
pbc = ’xyz’,
rlist = ’1.15’,
coulombtype = ’PME-Switch’,
rcoulomb = ’0.8’,
vdwtype = ’shift’,
rvdw = ’0.8’,
rvdw_switch = ’0.75’,
DispCorr = ’Ener’)
CALC_MM_RELAX.generate_topology_and_g96file()
CALC_MM_RELAX.generate_gromacs_run_file()
CALC_MM_RELAX.run()
3. QM/MM relaxation (all atoms are free)
""" demo run for ase_qmmm_manyqm calculator """
#
./test_ase_qmmm_manyqm.py gromacs_mm-relax.g96
from
from
from
from
ase.calculators.gromacs import Gromacs
ase.calculators.aims import Aims
ase.calculators.ase_qmmm_manyqm import AseQmmmManyqm
ase.optimize import BFGS
import sys
from ase.io.gromos import read_gromos
RUN_COMMAND = ’/home/mka/bin/aims.071711_6.serial.x’
SPECIES_DIR = ’/home/mka/Programs/fhi-aims.071711_6/species_defaults/light/’
LOG_FILE = open("ase-qm-mm-output.log","w")
sys.stdout = LOG_FILE
infile_name = sys.argv[1]
CALC_QM1 = Aims(charge = 0,
xc = ’pbe’,
sc_accuracy_etot = 1e-5,
sc_accuracy_eev = 1e-2,
sc_accuracy_rho = 1e-5,
sc_accuracy_forces = 1e-3,
species_dir = SPECIES_DIR,
run_command = RUN_COMMAND)
CALC_QM1.set(output = ’hirshfeld’)
CALC_QM2 = Aims(charge = 0,
xc = ’pbe’,
sc_accuracy_etot = 1e-5,
sc_accuracy_eev = 1e-2,
sc_accuracy_rho = 1e-5,
sc_accuracy_forces = 1e-3,
162
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
species_dir = SPECIES_DIR,
run_command = RUN_COMMAND)
CALC_QM2.set(output = ’hirshfeld’)
CALC_QM3 = Aims(charge = 0,
xc = ’pbe’,
sc_accuracy_etot = 1e-5,
sc_accuracy_eev = 1e-2,
sc_accuracy_rho = 1e-5,
sc_accuracy_forces = 1e-3,
species_dir = SPECIES_DIR,
run_command = RUN_COMMAND)
CALC_QM3.set(output = ’hirshfeld’)
CALC_MM = Gromacs(
init_structure_file = infile_name,
structure_file = ’gromacs_qm.g96’, \
force_field = ’oplsaa’,
water_model = ’tip3p’,
base_filename = ’gromacs_qm’,
doing_qmmm = True, freeze_qm = False,
index_filename = ’index.ndx’,
define = ’-DFLEXIBLE’,
integrator = ’md’,
nsteps = ’0’,
nstfout = ’1’,
nstlog = ’1’,
nstenergy = ’1’,
nstlist = ’1’,
ns_type = ’grid’,
pbc = ’xyz’,
rlist = ’1.15’,
coulombtype = ’PME-Switch’,
rcoulomb = ’0.8’,
vdwtype = ’shift’,
rvdw = ’0.8’,
rvdw_switch = ’0.75’,
DispCorr = ’Ener’)
CALC_MM.generate_topology_and_g96file()
CALC_MM.generate_gromacs_run_file()
CALC_QMMM = AseQmmmManyqm(nqm_regions = 3,
qm_calculators = [CALC_QM1, CALC_QM2, CALC_QM3],
mm_calculator = CALC_MM,
link_info = ’byQM’)
#
link_info = ’byFILE’)
SYSTEM = read_gromos(’gromacs_qm.g96’)
SYSTEM.set_calculator(CALC_QMMM)
DYN = BFGS(SYSTEM)
DYN.run(fmax = 0.05)
print(’exiting fine’)
LOG_FILE.close()
7.14.3 QMMM
For QMMM caculations, see ase.calculators.ase_qmmm_manyqm.
7.14. Calculators
163
ASE Manual, Release 3.9.0.3865
7.14.4 Calculator interface
All calculators must have the following interface:
class ase.calculators.interface.Calculator
ASE calculator.
A calculator should store a copy of the atoms object used for the last calculation. When one of the
get_potential_energy, get_forces, or get_stress methods is called, the calculator should check if anything
has changed since the last calculation and only do the calculation if it’s really needed. Two sets of atoms
are considered identical if they have the same positions, atomic numbers, unit cell and periodic boundary
conditions.
calculation_required(atoms, quantities)
Check if a calculation is required.
Check if the quantities in the quantities list have already been calculated for the atomic configuration
atoms. The quantities can be one or more of: �energy’, �forces’, �stress’, �charges’ and �magmoms’.
This method is used to check if a quantity is available without further calculations. For this reason, calculators should react to unknown/unsupported quantities by returning True, indicating that the quantity
is not available.
get_forces(atoms)
Return the forces.
get_potential_energy(atoms=None, force_consistent=False)
Return total energy.
Both the energy extrapolated to zero Kelvin and the energy consistent with the forces (the free energy)
can be returned.
get_stress(atoms)
Return the stress.
7.14.5 Electronic structure calculators
These calculators have wave functions, electron densities, eigenvalues and many other quantities. Therefore, it
makes sense to have a set of standard methods for accessing those quantities:
class ase.calculators.interface.DFTCalculator
Class for demonstrating the ASE interface to DFT-calculators.
get_bz_k_points()
Return all the k-points in the 1. Brillouin zone.
The coordinates are relative to reciprocal latice vectors.
get_effective_potential(spin=0, pad=True)
Return pseudo-effective-potential array.
get_eigenvalues(kpt=0, spin=0)
Return eigenvalue array.
get_fermi_level()
Return the Fermi level.
get_ibz_k_points()
Return k-points in the irreducible part of the Brillouin zone.
The coordinates are relative to reciprocal latice vectors.
get_k_point_weights()
Weights of the k-points.
The sum of all weights is one.
164
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
get_magnetic_moment(atoms=None)
Return the total magnetic moment.
get_number_of_bands()
Return the number of bands.
get_number_of_grid_points()
Return the shape of arrays.
get_number_of_spins()
Return the number of spins in the calculation.
Spin-paired calculations: 1, spin-polarized calculation: 2.
get_occupation_numbers(kpt=0, spin=0)
Return occupation number array.
get_pseudo_density(spin=None, pad=True)
Return pseudo-density array.
If spin is not given, then the total density is returned. Otherwise, the spin up or down density is
returned (spin=0 or 1).
get_pseudo_wave_function(band=0, kpt=0, spin=0, broadcast=True, pad=True)
Return pseudo-wave-function array.
get_spin_polarized()
Is it a spin-polarized calculation?
get_wannier_localization_matrix(nbands, dirG, kpoint, nextkpoint, G_I, spin)
Calculate integrals for maximally localized Wannier functions.
get_xc_functional()
Return the XC-functional identifier.
�LDA’, �PBE’, ...
initial_wannier(initialwannier, kpointgrid, fixedstates, edf, spin, nbands)
Initial guess for the shape of wannier functions.
Use initial guess for wannier orbitals to determine rotation matrices U and C.
7.15 Constraints
When performing minimizations or dynamics one may wish to keep some degrees of freedom in the system fixed.
One way of doing this is by attaching constraint object(s) directly to the atoms object.
Important: setting constraints will freeze the corresponding atom positions. Changing such atom positions can be
achieved:
• by directly setting the positions attribute (see example of setting Special attributes),
• alternatively, by removing the constraints first:
del atoms.constraints
or:
atoms.set_constraint()
and using the set_positions() method.
7.15. Constraints
165
ASE Manual, Release 3.9.0.3865
7.15.1 The FixAtoms class
This class is used for fixing some of the atoms.
class ase.constraints.FixAtoms(indices=None, mask=None)
You must supply either the indices of the atoms that should be fixed or a mask. The mask is a list of booleans, one
for each atom, being true if the atoms should be kept fixed.
For example, to fix the positions of all the Cu atoms in a simulation with the indices keyword:
>>> c = FixAtoms(indices=[atom.index for atom in atoms if atom.symbol == ’Cu’])
>>> atoms.set_constraint(c)
or with the mask keyword:
>>> c = FixAtoms(mask=[atom.symbol == ’Cu’ for atom in atoms])
>>> atoms.set_constraint(c)
7.15.2 The FixBondLength class
This class is used to fix the distance between two atoms specified by their indices (a1 and a2)
class ase.constraints.FixBondLength(a1, a2)
Example of use:
>>> c = FixBondLength(0, 1)
>>> atoms.set_constraint(c)
In this example the distance between the atoms with indices 0 and 1 will be fixed in all following dynamics and/or
minimizations performed on the atoms object.
This constraint is useful for finding minimum energy barriers for reactions where the path can be described well
by a single bond length (see the Dissociation tutorial tutorial).
Important: If fixing multiple bond lengths, use the FixBondLengths class below, particularly if the same atom is
fixed to multiple partners.
7.15.3 The FixBondLengths class
More than one bond length can be fixed by using this class. Especially for cases in which more than one bond
length constraint is applied on the same atom. It is done by specifying the indices of the two atoms forming the
bond in pairs.
class ase.constraints.FixBondLengths(pairs)
Example of use:
>>> c = FixBondLengths([[0, 1], [0, 2]])
>>> atoms.set_constraint(c)
Here the distances between atoms with indices 0 and 1 and atoms with indices 0 and 2 will be fixed. The constraint
is for the same purpose as the FixBondLength class.
7.15.4 The FixedLine class
class ase.constraints.FixedLine(a, direction)
Constrain an atom a to move on a given line only.
The line is defined by its direction.
166
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
7.15.5 The FixedPlane class
class ase.constraints.FixedPlane(a, direction)
Constrain an atom a to move in a given plane only.
The plane is defined by its normal: direction.
Example of use: Diffusion of gold atom on Al(100) surface (constraint).
7.15.6 The FixedMode class
class ase.constraints.FixedMode(mode)
Constrain atoms to move along directions orthogonal to a given mode only.
A mode is a list of vectors specifying a direction for each atom.
ase.vibrations.Vibrations.get_mode().
It often comes from
7.15.7 The Hookean class
This class of constraints, based on Hooke’s Law, is generally used to conserve molecular identity in optimization
schemes and can be used in three different ways. In the first, it applies a Hookean restorative force between
two atoms if the distance between them exceeds a threshold. This is useful to maintain the identity of molecules
in quenched molecular dynamics, without changing the degrees of freedom or violating conservation of energy.
When the distance between the two atoms is less than the threshold length, this constraint is completely inactive.
The below example tethers atoms at indices 3 and 4 together:
>>> c = Hookean(a1=3, a2=4, rt=1.79, k=5.)
>>> atoms.set_constraint(c)
Alternatively, this constraint can tether a single atom to a point in space, for example to prevent the top layer of
a slab from subliming during a high-temperature MD simulation. An example of tethering atom at index 3 to its
original position:
>>> c = Hookean(a1=3, a2=atoms[3].position, rt=0.94, k=2.)
>>> atoms.set_constraint(c)
Reasonable values of the threshold (rt) and spring constant (k) for some common bonds are below.
Bond
O-H
C-O
C-H
C=O
Pt sublimation
Cu sublimation
rt (Angstroms)
1.40
1.79
1.59
1.58
0.94
0.97
k (eV Angstrom^-2)
5
5
7
10
2
2
A third way this constraint can be applied is to apply a restorative force if an atom crosses a plane in space. For
example:
>>> c = Hookean(a1=3, a2=(0, 0, 1, -7), k=10.)
>>> atoms.set_constraint(c)
This will apply a restorative force on atom 3 in the downward direction of magnitude k * (atom.z - 7) if the atom’s
vertical position exceeds 7 Angstroms. In other words, if the atom crosses to the (positive) normal side of the
plane, the force is applied and directed towards the plane. (The same plane with the normal direction pointing in
the -z direction would be given by (0, 0, -1, 7).)
For an example of use, see the Constrained minima hopping (global optimization) tutorial.
Note: In previous versions of ASE, this was known as the BondSpring constraint.
7.15. Constraints
167
ASE Manual, Release 3.9.0.3865
7.15.8 The FixInternals class
This class allows to fix an arbitrary number of bond lengths, angles and dihedral angles. The defined constraints are
satisfied self consistently. To define the constraints one needs to specify the atoms object on which the constraint
works (needed for atomic masses), a list of bond, angle and dihedral constraints. Those constraint definitions
are always list objects containing the value to be set and a list of atomic indices. The epsilon value specifies the
accuracy to which the constraints are fulfilled.
class ase.constraints.FixInternals(atoms, bonds=[bond1, bond2], angles=[angle1], dihedrals=[dihedral1, dihedral2], epsilon=1.e-7)
Example of use:
>>> bond1 = [1.20, [1, 2]]
>>> angle_indices1 = [2, 3, 4]
>>> dihedral_indices1 = [2, 3, 4, 5]
>>> angle1 = [atoms.get_angle(angle_indices1), angle_indices1]
>>> dihedral1 = [atoms.get_dihedral(dihedral_indices1), \
dihedral_indices1]
>>> c = FixInternals(atoms, bonds=[bonds1], angles=[angles1], \
dihedrals=[dihedral1])
>>> atoms.set_constraint(c)
This example defines a bond an angle and a dihedral angle constraint to be fixed at the same time.
7.15.9 Combining constraints
It is possible to supply several constraints on an atoms object. For example one may wish to keep the distance
between two nitrogen atoms fixed while relaxing it on a fixed ruthenium surface:
>>> pos = [[0.00000, 0.00000, 9.17625],
...
[0.00000, 0.00000, 10.27625],
...
[1.37715, 0.79510, 5.00000],
...
[0.00000, 3.18039, 5.00000],
...
[0.00000, 0.00000, 7.17625],
...
[1.37715, 2.38529, 7.17625]]
>>> unitcell = [5.5086, 4.7706, 15.27625]
>>> atoms = Atoms(positions=pos,
...
symbols=’N2Ru4’,
...
cell=unitcell,
...
pbc=[True,True,False])
>>> fa = FixAtoms(mask=[a.symbol == ’Ru’ for a in atoms])
>>> fb = FixBondLength(0, 1)
>>> atoms.set_constraint([fa, fb])
When applying more than one constraint they are passed as a list in the set_constraint() method, and they
will be applied one after the other.
Important: If wanting to fix the length of more than one bond in the simulation, do not supply a list of
FixBondLength instances; instead, use a single instance of FixBondLengths.
7.15.10 Making your own constraint class
A constraint class must have these two methods:
ase.constraints.adjust_positions(oldpositions, newpositions)
Adjust the newpositions array inplace.
ase.constraints.adjust_forces(positions, forces)
Adjust the forces array inplace.
168
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
A simple example:
import numpy as np
class MyConstraint:
"""Constrain an atom to move along a given direction only."""
def __init__(self, a, direction):
self.a = a
self.dir = direction / sqrt(np.dot(direction, direction))
def adjust_positions(self, oldpositions, newpositions):
step = newpositions[self.a] - oldpositions[self.a]
step = np.dot(step, self.dir)
newpositions[self.a] = oldpositions[self.a] + step * self.dir
def adjust_forces(self, positions, forces):
forces[self.a] = self.dir * np.dot(forces[self.a], self.dir)
A constraint can optionally have two additional methods, which will be ignored if missing:
ase.constraints.adjust_momenta(positions, momenta)
Adjust the momenta array inplace.
ase.constraints.adjust_potential_energy(positions, energy)
Provide the difference in the potential energy due to the constraint. (Note that inplace adjustment is not
possible for energy, which is a float.)
7.15.11 The Filter class
Constraints can also be applied via filters, which acts as a wrapper around an atoms object. A typical use case will
look like this:
----------------------|
|
|
|
|
|
| Atoms |<----| Filter |<----| Dynamics |
|
|
|
|
|
|
-----------------------
and in Python this would be:
>>> atoms = Atoms(...)
>>> filter = Filter(atoms, ...)
>>> dyn = Dynamics(filter, ...)
This class hides some of the atoms in an Atoms object.
class ase.constraints.Filter(atoms, indices=None, mask=None)
You must supply either the indices of the atoms that should be kept visible or a mask. The mask is a list of
booleans, one for each atom, being true if the atom should be kept visible.
Example of use:
>>> from ase import Atoms, Filter
>>> atoms=Atoms(positions=[[ 0
, 0
, 0],
...
[ 0.773, 0.600, 0],
...
[-0.773, 0.600, 0]],
...
symbols=’OH2’)
>>> f1 = Filter(atoms, indices=[1, 2])
>>> f2 = Filter(atoms, mask=[0, 1, 1])
>>> f3 = Filter(atoms, mask=[a.Z == 1 for a in atoms])
>>> f1.get_positions()
[[ 0.773 0.6
0.
]
[-0.773 0.6
0.
]]
7.15. Constraints
169
ASE Manual, Release 3.9.0.3865
In all three filters only the hydrogen atoms are made visible. When asking for the positions only the positions of
the hydrogen atoms are returned.
7.15.12 The UnitCellFilter class
class ase.constraints.UnitCellFilter(atoms, mask=None)
Modify the supercell and the atom positions.
Create a filter that returns the atomic forces and unit cell stresses together, so they can simultaneously be
minimized.
The first argument, atoms, is the atoms object. The optional second argument, mask, is a list of booleans,
indicating which of the six independent components of the strain are relaxed.
•True = relax to zero
•False = fixed, ignore this component
You can still use constraints on the atoms, e.g. FixAtoms, to control the relaxation of the atoms.
>>>
>>>
>>>
>>>
# this should be equivalent to the StrainFilter
atoms = Atoms(...)
atoms.set_constraint(FixAtoms(mask=[True for atom in atoms]))
ucf = UnitCellFilter(atoms)
You should not attach this UnitCellFilter object to a trajectory. Instead, create a trajectory for the atoms,
and attach it to an optimizer like this:
>>>
>>>
>>>
>>>
>>>
>>>
atoms = Atoms(...)
ucf = UnitCellFilter(atoms)
qn = QuasiNewton(ucf)
traj = PickleTrajectory(’TiO2.traj’, ’w’, atoms)
qn.attach(traj)
qn.run(fmax=0.05)
Helpful conversion table:
•0.05 eV/A^3 = 8 GPA
•0.003 eV/A^3 = 0.48 GPa
•0.0006 eV/A^3 = 0.096 GPa
•0.0003 eV/A^3 = 0.048 GPa
•0.0001 eV/A^3 = 0.02 GPa
7.15.13 The StrainFilter class
class ase.constraints.StrainFilter(atoms, mask=None)
Modify the supercell while keeping the scaled positions fixed.
Presents the strain of the supercell as the generalized positions, and the global stress tensor (times the
volume) as the generalized force.
This filter can be used to relax the unit cell until the stress is zero. If MDMin is used for this, the timestep
(dt) to be used depends on the system size. 0.01/x where x is a typical dimension seems like a good choice.
The stress and strain are presented as 6-vectors, the order of the components follow the standard engingeering practice: xx, yy, zz, yz, xz, xy.
Create a filter applying a homogeneous strain to a list of atoms.
The first argument, atoms, is the atoms object.
170
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
The optional second argument, mask, is a list of six booleans, indicating which of the six independent
components of the strain that are allowed to become non-zero. It defaults to [1,1,1,1,1,1].
7.16 Nudged elastic band
The Nudged Elastic Band method is a technique for finding transition paths (and corresponding energy barriers)
between given initial and final states. The method involves constructing a “chain” of “replicas” or “images” of the
system and relaxing them in a certain way.
Relevant literature References:
1. H. Jonsson, G. Mills, and K. W. Jacobsen, in �Classical and Quantum Dynamics in Condensed Phase Systems’, edited by B. J. Berne, G. Cicotti, and D. F. Coker, World Scientific, 1998 [standard formulation]
2. �Improved Tangent Estimate in the NEB method for Finding Minimum Energy Paths and Saddle Points’,
Graeme Henkelman and Hannes Jonsson, J. Chem. Phys. 113, 9978 (2000) [improved tangent estimates]
3. �A Climbing-Image NEB Method for Finding Saddle Points and Minimum Energy Paths’, Graeme Henkelman, Blas P. Uberuaga and Hannes Jonsson, J. Chem. Phys. 113, 9901 (2000)
7.16.1 The NEB class
This module defines one class:
class ase.neb.NEB(images, k=0.1, climb=False, parallel=False, world=None)
Nudged elastic band.
images: list of Atoms objects Images defining path from initial to final state.
k: float or list of floats Spring constant(s) in eV/Ang. One number or one for each spring.
climb: bool Use a climbing image (default is no climbing image).
parallel: bool Distribute images over processors.
Example of use, between initial and final state which have been previously saved in A.traj and B.traj:
from ase import io
from ase.neb import NEB
from ase.optimize import MDMin
# Read initial and final states:
initial = io.read(’A.traj’)
final = io.read(’B.traj’)
# Make a band consisting of 5 images:
images = [initial]
images += [initial.copy() for i in range(3)]
images += [final]
neb = NEB(images)
# Interpolate linearly the potisions of the three middle images:
neb.interpolate()
# Set calculators:
for image in images[1:4]:
image.set_calculator(MyCalculator(...))
# Optimize:
optimizer = MDMin(neb, trajectory=’A2B.traj’)
optimizer.run(fmax=0.04)
Be sure to use the copy method (or similar) to create new instances of atoms within the list of images fed to the
NEB. Do not use something like [initial for i in range(3)], as it will only create references to the original atoms
object.
Notice the use of the interpolate() method to get a good initial guess for the path from A to B.
7.16. Nudged elastic band
171
ASE Manual, Release 3.9.0.3865
NEB.interpolate()
Interpolate path linearly from initial to final state.
Only the internal images (not the endpoints) need have calculators attached.
See Also:
ase.optimize: Information about energy minimization (optimization). Note that you cannot use the default
optimizer, BFGSLineSearch, with NEBs. (This is the optimizer imported when you import QuasiNewton.)
If you would like a quasi-newton optimizer, use BFGS instead.
ase.calculators: How to use calculators.
Tutorials:
• Diffusion of gold atom on Al(100) surface (NEB)
• Dissociation tutorial
Note: If there are M images and each image has N atoms, then the NEB object behaves like one big Atoms
object with M N atoms, so its get_positions() method will return a M N Г— 3 array.
7.16.2 Trajectories
The code:
from ase.optimize import BFGS
optimizer = BFGS(neb, trajectory=’A2B.traj’)
will write all images to one file. The Trajectory object knows about NEB calculations, so it will write M images
with N atoms at every iteration and not one big configuration containing M N atoms.
The result of the latest iteration can now be analysed with this command: ase-gui A2B.traj@-5:.
For the example above, you can write the images to individual trajectory files like this:
for i in range(1, 4):
qn.attach(io.PickleTrajectory(’A2B-%d.traj’ % i, ’w’, images[i]))
The result of the latest iteration can be analysed like this:
$ ase-gui A.traj A2B-?.traj B.traj -n -1
7.16.3 Restarting
Restart the calculation like this:
images = io.read(’A2B.traj@-5:’)
7.16.4 Climbing image
The “climbing image” variation involves designating a specific image to behave differently to the rest of the chain:
it feels no spring forces, and the component of the potential force parallel to the chain is reversed, such that it
moves towards the saddle point. This depends on the adjacent images providing a reasonably good approximation
of the correct tangent at the location of the climbing image; thus in general the climbing image is not turned on
until some iterations have been run without it (generally 20% to 50% of the total number of iterations).
To use the climbing image NEB method, instantiate the NEB object like this:
neb = NEB(images, climb=True)
172
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Note: Quasi-Newton methods, such as BFGS, are not well suited for climbing image NEB calculations. FIRE
have been known to give good results, although convergence is slow.
7.16.5 Parallelization over images
Some calculators can parallelize over the images of a NEB calculation. The script will have to be run with an
MPI-enabled Python interpreter like GPAW�s gpaw-python. All images exist on all processors, but only some of
them have a calculator attached:
from ase.parallel import rank, size
from ase.calculators.emt import EMT
# Number of internal images:
n = len(images) - 2
j = rank * n // size
for i, image in enumerate(images[1:-1]):
if i == j:
image.set_calculator(EMT())
Create the NEB object with NEB(images, parallel=True) and let the master processes write the images:
if rank % (size // n) == 0:
traj = io.PickleTrajectory(’neb%d.traj’ % j, ’w’, images[1 + j],
master=True)
optimizer.attach(traj)
For a complete example using GPAW, see here.
7.17 Vibration analysis
You can calculate the vibrational modes of a an Atoms object in the harmonic approximation using the
Vibrations.
class ase.vibrations.Vibrations(atoms, indices=None, name=’vib’, delta=0.01, nfree=2)
Class for calculating vibrational modes using finite difference.
The vibrational modes are calculated from a finite difference approximation of the Hessian matrix.
The summary(), get_energies() and get_frequencies() methods all take an optional method keyword. Use
method=’Frederiksen’ to use the method described in:
T. Frederiksen, M. Paulsson, M. Brandbyge, A. P. Jauho: “Inelastic transport theory from firstprinciples: methodology and applications for nanoscale devices”, Phys. Rev. B 75, 205413
(2007)
atoms: Atoms object The atoms to work on.
indices: list of int List of indices of atoms to vibrate. Default behavior is to vibrate all atoms.
name: str Name to use for files.
delta: float Magnitude of displacements.
nfree: int Number of displacements per atom and cartesian coordinate, 2 and 4 are supported. Default is 2
which will displace each atom +delta and -delta for each cartesian coordinate.
Example:
7.17. Vibration analysis
173
ASE Manual, Release 3.9.0.3865
>>> from ase import Atoms
>>> from ase.calculators.emt import EMT
>>> from ase.optimize import BFGS
>>> from ase.vibrations import Vibrations
>>> n2 = Atoms(’N2’, [(0, 0, 0), (0, 0, 1.1)],
...
calculator=EMT())
>>> BFGS(n2).run(fmax=0.01)
BFGS:
0 16:01:21
0.440339
3.2518
BFGS:
1 16:01:21
0.271928
0.8211
BFGS:
2 16:01:21
0.263278
0.1994
BFGS:
3 16:01:21
0.262777
0.0088
>>> vib = Vibrations(n2)
>>> vib.run()
Writing vib.eq.pckl
Writing vib.0x-.pckl
Writing vib.0x+.pckl
Writing vib.0y-.pckl
Writing vib.0y+.pckl
Writing vib.0z-.pckl
Writing vib.0z+.pckl
Writing vib.1x-.pckl
Writing vib.1x+.pckl
Writing vib.1y-.pckl
Writing vib.1y+.pckl
Writing vib.1z-.pckl
Writing vib.1z+.pckl
>>> vib.summary()
--------------------#
meV
cm^-1
--------------------0
0.0
0.0
1
0.0
0.0
2
0.0
0.0
3
2.5
20.4
4
2.5
20.4
5 152.6
1230.8
--------------------Zero-point energy: 0.079 eV
>>> vib.write_mode(-1) # write last mode to trajectory file
fold(frequencies, intensities, start=800, end=4000, npts=None, width=4, type=’Gaussian’, normalize=False)
Fold frequencies and intensities within the given range and folding method (Gaussian/Lorentzian).
The energy unit is cm^-1. normalize=True ensures the integral over the peaks to give the intensity.
get_energies(method=’standard’, direction=’central’)
Get vibration energies in eV.
get_frequencies(method=’standard’, direction=’central’)
Get vibration frequencies in cm^-1.
get_mode(n)
Get mode number .
run()
Run the vibration calculations.
This will calculate the forces for 6 displacements per atom +/-x, +/-y, +/-z. Only those calculations
that are not already done will be started. Be aware that an interrupted calculation may produce an
empty file (ending with .pckl), which must be deleted before restarting the job. Otherwise the forces
will not be calculated for that displacement.
Note that the calculations for the different displacements can be done simultaneously by several independent processes. This feature relies on the existence of files and the subsequent creation of the file
174
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
in case it is not found.
summary(method=’standard’, direction=’central’, freq=None, log=<StringIO.StringIO instance at
0x2ad6f80>)
Print a summary of the vibrational frequencies.
Parameters:
method [string] Can be �standard’(default) or �Frederiksen’.
direction: string Direction for finite differences. Can be one of �central’ (default), �forward’, �backward’.
freq [numpy array] Optional. Can be used to create a summary on a set of known frequencies.
log [if specified, write output to a different location than] stdout. Can be an object with a write()
method or the name of a file to create.
write_dos(out=’vib-dos.dat’, start=800, end=4000, npts=None, width=10, type=’Gaussian’,
method=’standard’, direction=’central’)
Write out the vibrational density of states to file.
First column is the wavenumber in cm^-1, the second column the folded vibrational density of states.
Start and end points, and width of the Gaussian/Lorentzian should be given in cm^-1.
write_jmol()
Writes file for viewing of the modes with jmol.
write_mode(n=None, kT=0.025852157076770025, nimages=30)
Write mode number n to trajectory file. If n is not specified, writes all non-zero modes.
name is a string that is prefixed to the names of all the files created. atoms is an Atoms object that is either at a fully
relaxed ground state or at a saddle point. freeatoms is a list of atom indices for which the vibrational modes will
be calculated, the rest of the atoms are considered frozen. displacements is a list of displacements, one for each
free atom that are used in the finite difference method to calculate the Hessian matrix. method is -1 for backward
differences, 0 for centered differences, and 1 for forward differences.
Warning: Using the dacapo calculator you must make sure that the symmetry program in dacapo finds the
same number of symmetries for the displaced configurations in the vibrational modules as found in the ground
state used as input. This is because the wavefunction is reused from one displacement to the next. One way to
ensure this is to tell dacapo not to use symmetries.
This will show op as a python error �Frames are not aligned’. This could be the case for other calculators as
well.
7.18 Phonon calculations
Module for calculating vibrational normal modes for periodic systems using the so-called small displacement
method (see e.g. [Alfe]). So far, space-group symmetries are not exploited to reduce the number of atomic
displacements that must be calculated and subsequent symmetrization of the force constants.
For polar materials the dynamical matrix at the zone center acquires a non-analytical contribution that accounts
for the LO-TO splitting. This contribution requires additional functionality to evaluate and is not included in the
present implementation. Its implementation in conjunction with the small displacement method is described in
[Wang].
7.19 Example
Simple example showing how to calculate the phonon dispersion for bulk aluminum using a 7x7x7 supercell
within effective medium theory:
7.18. Phonon calculations
175
ASE Manual, Release 3.9.0.3865
from
from
from
from
ase.structure import bulk
ase.calculators.emt import EMT
ase.dft.kpoints import ibz_points, get_bandpath
ase.phonons import Phonons
# Setup crystal and EMT calculator
atoms = bulk(’Al’, ’fcc’, a=4.05)
calc = EMT()
# Phonon calculator
N = 7
ph = Phonons(atoms, calc, supercell=(N, N, N), delta=0.05)
ph.run()
# Read forces and assemble the dynamical matrix
ph.read(acoustic=True)
# High-symmetry points in the Brillouin zone
points = ibz_points[’fcc’]
G = points[’Gamma’]
X = points[’X’]
W = points[’W’]
K = points[’K’]
L = points[’L’]
U = points[’U’]
point_names = [’$\Gamma$’, ’X’, ’U’, ’L’, ’$\Gamma$’, ’K’]
path = [G, X, U, L, G, K]
# Band structure in meV
path_kc, q, Q = get_bandpath(path, atoms.cell, 100)
omega_kn = 1000 * ph.band_structure(path_kc)
# Calculate phonon DOS
omega_e, dos_e = ph.dos(kpts=(50, 50, 50), npts=5000, delta=5e-4)
omega_e *= 1000
# Plot the band structure and DOS
import pylab as plt
plt.figure(1, (8, 6))
plt.axes([.1, .07, .67, .85])
for n in range(len(omega_kn[0])):
omega_n = omega_kn[:, n]
plt.plot(q, omega_n, ’k-’, lw=2)
plt.xticks(Q, point_names, fontsize=18)
plt.yticks(fontsize=18)
plt.xlim(q[0], q[-1])
plt.ylabel("Frequency ($\mathrm{meV}$)", fontsize=22)
plt.grid(’on’)
plt.axes([.8, .07, .17, .85])
plt.fill_between(dos_e, omega_e, y2=0, color=’lightgrey’, edgecolor=’k’, lw=1)
plt.ylim(0, 35)
plt.xticks([], [])
plt.yticks([], [])
plt.xlabel("DOS", fontsize=18)
plt.show()
176
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Mode inspection using ase-gui:
# Write modes for specific q-vector to trajectory files
ph.write_modes([l/2 for l in L], branches=[2], repeat=(8, 8, 8), kT=3e-4)
7.19. Example
177
ASE Manual, Release 3.9.0.3865
7.20 Thermochemistry
ASE contains a ase.thermochemistry module that lets the user derive commonly desired thermodynamic
quantities of molecules and crystalline solids from ASE output and some user-specified parameters. Three cases
are currently handled by this module: the ideal-gas limit (in which translational and rotational degrees of freedom
are taken into account), the harmonic limit (generally used for adsorbates, in which all degrees of freedom are
treated harmonically), and a crystalline solid model (in which a lattice of N atoms is treated as a system of
3N independent harmonic oscillators). The first two cases rely on good vibrational energies being fed to the
calculators, which can be calculated with the ase.vibrations module. Likewise, the crystalline solid model
depends on an accurate phonon density of states; this is readily calculated using the ase.phonons module.
7.20.1 Ideal-gas limit
The thermodynamic quantities of ideal gases are calculated by assuming that all spatial degrees of freedom are independent and separable into translational, rotational, and vibrational degrees of freedom. The
IdealGasThermo class supports calculation of enthalpy (H), entropy (S), and Gibbs free energy (G), and
has the interface listed below.
class ase.thermochemistry.IdealGasThermo(vib_energies, geometry, electronicenergy=None,
atoms=None,
symmetrynumber=None,
spin=None, natoms=None)
Class for calculating thermodynamic properties of a molecule based on statistical mechanical treatments in
the ideal gas approximation.
Inputs for enthalpy calculations:
vib_energies [list] a list of the vibrational energies of the molecule (e.g.,
from
ase.vibrations.Vibrations.get_energies). The number of vibrations used is automatically calculated by the geometry and the number of atoms. If more are specified than are needed, then the lowest
numbered vibrations are neglected. If either atoms or natoms is unspecified, then uses the entire list.
Units are eV.
geometry [�monatomic’, �linear’, or �nonlinear’] geometry of the molecule
electronicenergy [float] the electronic energy in eV (if electronicenergy is unspecified, then the methods
of this class can be interpreted as the enthalpy and free energy corrections)
natoms [integer] the number of atoms, used along with �geometry’ to determine how many vibrations to
use. (Not needed if an atoms object is supplied in �atoms’ or if the user desires the entire list of
vibrations to be used.)
Extra inputs needed for for entropy / free energy calculations:
atoms [an ASE atoms object] used to calculate rotational moments of inertia and molecular mass
symmetrynumber [integer] symmetry number of the molecule. See, for example, Table 10.1 and Appendix B of C. Cramer “Essentials of Computational Chemistry”, 2nd Ed.
spin [float] the total electronic spin. (0 for molecules in which all electrons are paired, 0.5 for a free radical
with a single unpaired electron, 1.0 for a triplet with two unpaired electrons, such as O_2.)
get_enthalpy(temperature, verbose=True)
Returns the enthalpy, in eV, in the ideal gas approximation at a specified temperature (K).
get_entropy(temperature, pressure, verbose=True)
Returns the entropy, in eV/K, in the ideal gas approximation at a specified temperature (K) and pressure
(Pa).
get_gibbs_energy(temperature, pressure, verbose=True)
Returns the Gibbs free energy, in eV, in the ideal gas approximation at a specified temperature (K) and
pressure (Pa).
178
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Example
The IdealGasThermo class would generally be called after an energy optimization and a vibrational analysis.
The user needs to supply certain parameters if the entropy or free energy are desired, such as the geometry and
symmetry number. An example on the nitrogen molecule is:
from
from
from
from
from
ase.structure import molecule
ase.calculators.emt import EMT
ase.optimize import QuasiNewton
ase.vibrations import Vibrations
ase.thermochemistry import IdealGasThermo
atoms = molecule(’N2’)
atoms.set_calculator(EMT())
dyn = QuasiNewton(atoms)
dyn.run(fmax=0.01)
electronicenergy = atoms.get_potential_energy()
vib = Vibrations(atoms)
vib.run()
vib_energies = vib.get_energies()
thermo = IdealGasThermo(vib_energies=vib_energies,
electronicenergy=electronicenergy,
atoms=atoms,
geometry=’linear’,
symmetrynumber=2, spin=0)
G = thermo.get_gibbs_energy(temperature=298.15, pressure=101325.)
This will give the thermodynamic summary output:
Enthalpy components at T = 298.15 K:
===============================
E_elec
0.263 eV
E_ZPE
0.076 eV
Cv_trans (0->T)
0.039 eV
Cv_rot (0->T)
0.026 eV
Cv_vib (0->T)
0.000 eV
(C_v -> C_p)
0.026 eV
------------------------------H
0.429 eV
===============================
Entropy components at T = 298.15 K and P = 101325.0 Pa:
=================================================
S
T*S
S_trans (1 atm)
0.0015579 eV/K
0.464 eV
S_rot
0.0004101 eV/K
0.122 eV
S_elec
0.0000000 eV/K
0.000 eV
S_vib
0.0000016 eV/K
0.000 eV
S (1 atm -> P)
-0.0000000 eV/K
-0.000 eV
------------------------------------------------S
0.0019695 eV/K
0.587 eV
=================================================
Free energy components at T = 298.15 K and P = 101325.0 Pa:
=======================
H
0.429 eV
-T*S
-0.587 eV
----------------------G
-0.158 eV
=======================
7.20. Thermochemistry
179
ASE Manual, Release 3.9.0.3865
7.20.2 Harmonic limit
In the harmonic limit, all degrees of freedom are treated harmonically. The HarmonicThermo class supports the calculation of internal energy, entropy, and Gibbs free energy. This class uses all of the energies given to it in the vib_energies list; this is a list as can be generated with the .get_energies() method of
ase.vibrations.Vibrations, but the user should take care that all of these energies are real (nonimaginary). The class HarmonicThermo has the interface described below.
class ase.thermochemistry.HarmonicThermo(vib_energies, electronicenergy=None)
Class for calculating thermodynamic properties in the approximation that all degrees of freedom are treated
harmonically. Often used for adsorbates.
Inputs:
vib_energies [list] a list of the harmonic energies of the adsorbate (e.g.,
from
ase.vibrations.Vibrations.get_energies). The number of energies should match the number of
degrees of freedom of the adsorbate; i.e., 3*n, where n is the number of atoms. Note that this class
does not check that the user has supplied the correct number of energies. Units of energies are eV.
electronicenergy [float] the electronic energy in eV (if electronicenergy is unspecified, then the methods
of this class can be interpreted as the energy corrections)
get_entropy(temperature, verbose=True)
Returns the entropy, in eV/K, in the harmonic approximation at a specified temperature (K).
get_gibbs_energy(temperature, verbose=True)
Returns the Gibbs free energy, in eV, in the harmonic approximation at a specified temperature (K).
get_internal_energy(temperature, verbose=True)
Returns the internal energy, in eV, in the harmonic approximation at a specified temperature (K).
7.20.3 Crystals
In this model a crystalline solid is treated as a periodic system of independent harmonic oscillators. The
CrystalThermo class supports the calculation of internal energy (U ), entropy (S) and Helmholtz free energy
(F ), and has the interface listed below.
class ase.thermochemistry.CrystalThermo(phonon_DOS,
phonon_energies,
formula_units=None, electronicenergy=None)
Class for calculating thermodynamic properties of a crystalline solid in the approximation that a lattice of
N atoms behaves as a system of 3N independent harmonic oscillators.
Inputs:
phonon_DOS [list] a list of the phonon density of states, where each value represents the phonon DOS at
the vibrational energy value of the corresponding index in phonon_energies.
phonon_energies [list] a list of the range of vibrational energies (hbar*omega) over which the phonon density of states has been evaluated. This list should be the same length as phonon_DOS and integrating
phonon_DOS over phonon_energies should yield approximately 3N, where N is the number of atoms
per unit cell. If the first element of this list is zero-valued it will be deleted along with the first element
of phonon_DOS. Units of vibrational energies are eV.
electronicenergy [float] the electronic energy in eV (if electronicenergy is unspecified, then the methods
of this class can be interpreted as the phonon energy corrections.)
formula_units [int] the number of formula units per unit cell. If unspecified, the thermodynamic quantities
calculated will be listed on a per-unit-cell basis.
get_entropy(temperature, verbose=True)
Returns the entropy, in eV/K, of crystalline solid at a specified temperature (K).
get_helmholtz_energy(temperature, verbose=True)
Returns the Helmholtz free energy, in eV, of crystalline solid at a specified temperature (K).
180
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
get_internal_energy(temperature, verbose=True)
Returns the internal energy, in eV, of crystalline solid at a specified temperature (K).
Example
The CrystalThermo class will generally be called after an energy optimization and a phonon vibrational analysis of the crystal. An example for bulk gold is:
from
from
from
from
from
ase.lattice.spacegroup import crystal
ase.calculators.emt import EMT
ase.optimize import QuasiNewton
ase.phonons import Phonons
ase.thermochemistry import CrystalThermo
# Set up gold bulk and attach EMT calculator
a = 4.078
atoms = crystal(’Au’, (0.,0.,0.),
spacegroup = 225,
cellpar = [a, a, a, 90, 90, 90],
pbc = (1, 1, 1))
calc = EMT()
atoms.set_calculator(calc)
qn = QuasiNewton(atoms)
qn.run(fmax = 0.05)
electronicenergy = atoms.get_potential_energy()
# Phonon analysis
N = 5
ph = Phonons(atoms, calc, supercell=(N, N, N), delta=0.05)
ph.run()
ph.read(acoustic=True)
phonon_energies, phonon_DOS = ph.dos(kpts=(40, 40, 40), npts=3000,
delta=5e-4)
# Calculate the Helmholtz free energy
thermo = CrystalThermo(phonon_energies=phonon_energies,
phonon_DOS = phonon_DOS,
electronicenergy = electronicenergy,
formula_units = 4)
F = thermo.get_helmholtz_energy(temperature=298.15)
This will give the thermodynamic summary output:
Internal energy components at T = 298.15 K,
on a per-formula-unit basis:
===============================
E_elec
0.0022 eV
E_ZPE
0.0135 eV
E_phonon
0.0629 eV
------------------------------U
0.0786 eV
===============================
Entropy components at T = 298.15 K,
on a per-formula-unit basis:
=================================================
S
T*S
------------------------------------------------S
0.0005316 eV/K
0.1585 eV
=================================================
Helmholtz free energy components at T = 298.15 K,
7.20. Thermochemistry
181
ASE Manual, Release 3.9.0.3865
on a per-formula-unit basis:
=======================
U
0.0786 eV
-T*S
-0.1585 eV
----------------------F
-0.0799 eV
=======================
7.20.4 Background
Ideal gas. The conversion of electronic structure calculations to thermodynamic properties in the ideal-gas
limit is well documented; see, for example, Chapter 10 of Cramer, 2004. The key equations used in the
IdealGasThermo class are summarized here.
C.J. Cramer. Essentials of Computational Chemistry, Second Edition. Wiley, 2004.
The ideal-gas enthalpy is calculated from extrapolation of the energy at 0 K to the relevant temperature (for an
ideal gas, the enthalpy is not a function of pressure):
T
H(T ) = Eelec + EZPE +
CP dT
0
where the first two terms are the electronic energy and the zero-point energy, and the integral is over the constantpressure heat capacity. The heat capacity is separable into translational, rotational, vibrational, and electronic parts
(plus a term of kB to switch from constant-volume to constant-pressure):
CP = kB + CV ,trans + CV ,rot + CV ,vib + CV ,elec
The translational heat capacity is 3/2 kB for a 3-dimensional gas. The rotational heat capacity is 0 for a monatomic
species, kB for a linear molecule, and 3/2 kB for a nonlinear molecule. In this module, the electronic component
of the heat capacity is assumed to be 0. The vibrational heat capacity contains 3N в€’ 6 degrees of freedom for
nonlinear molecules and 3N в€’ 5 degrees of freedom for linear molecules (where N is the number of atoms). The
integrated form of the vibrational heat capacity is:
vib DOF
T
i
CV,vib dT =
0
where
i
i
e
i /kB T
are the energies associated with the vibrational frequencies,
в€’1
i
= hωi .
The ideal gas entropy can be calculated as a function of temperature and pressure as:
S(T, P ) = S(T, P в—¦ ) в€’ kB ln
P
Pв—¦
= Strans + Srot + Selec + Svib в€’ kB ln
P
Pв—¦
where the translational, rotational, electronic, and vibrational components are calculated as below. (Note that
the translational component also includes components from the Stirling approximation, and that the vibrational
degrees of freedom are enumerated the same as in the above.)
Strans = kB
182
ln
2ПЂM kB T
h2
3/2
kB T
Pв—¦
+
5
2
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Srot
пЈ±
0
пЈґ
пЈґ
пЈґ
пЈІ
kB ln
=
пЈґ
пЈґ
пЈґ
пЈі kB ln
, if monatomic
8ПЂ 2 IkB T
Пѓh2
в€љ
ПЂIA IB IC
Пѓ
+1
, if linear
8ПЂ 2 kB T
h2
3/2
+
3
2
, if nonlinear
vib DOF
i
Svib = kB
kB T e
i
i /kB T
в€’ ln 1 в€’ eв€’
в€’1
i /kB T
Selec = kB ln [2 Г— (spin multiplicity) + 1]
IA through IC are the three principle moments of inertia for a non-linear molecule. I is the degenerate moment of
inertia for a linear molecule. Пѓ is the symmetry number of the molecule.
The ideal-gas Gibbs free energy is then just calculated from the combination of the enthalpy and entropy:
G(T, P ) = H(T ) в€’ T S(T, P )
Harmonic limit. The conversion of electronic structure calculation information into thermodynamic properties is
less established for adsorbates. However, the simplest approach often taken is to treat all 3N degrees of freedom
of the adsorbate harmonically since the adsorbate often has no real translational or rotational degrees of freedom.
This is the approach implemented in the HarmonicThermo class. Thus, the internal energy and entropy of the
adsorbate are calculated as
harm DOF
i
U (T ) = Eelec + EZPE +
i
e
i /kB T
в€’1
harm DOF
i
S = kB
kB T e
i
i /kB T
в€’1
в€’ ln 1 в€’ eв€’
i /kB T
and the Gibbs free energy is calculated as
G(T ) = U (T ) в€’ T S(T )
In this case, the number of harmonic energies ( i ) used in the summation is generally 3N , where N is the number
of atoms in the adsorbate.
Crystalline solid
The derivation of the partition function for a crystalline solid is fairly straight-forward and can be found, for
example, in Chapter 11 of McQuarrie, 2000.
D.A. McQuarrie. Statistical Mechanics. University Science Books, 2000.
The treatment implemented in the CrystalThermo class depends on introducing normal coordinates to the
entire crystal and treating each atom in the lattice as an independent harmonic oscillator. This yields the partition
function
3N
Z=
j=1
7.20. Thermochemistry
1
eв€’ 2 hВЇ П‰j ОІ
1 − e−¯hωj β
eв€’Eelec ОІ
183
ASE Manual, Release 3.9.0.3865
where П‰j are the 3N vibrational frequencies, Eelec is the electronic energy of the crystalline solid, and ОІ = kB1T .
Now, taking the logarithm of the partition function and replacing the resulting sum with an integral (assuming that
the energy level spacing is essentially continuous) gives
в€ћ
ln 1 − e−¯hωβ +
в€’ ln Z = Eelec ОІ +
0
¯hωβ
σ(ω)dω
2
Here Пѓ(П‰) represents the degeneracy or phonon density of states as a function of vibrational frequency. Once
this function has been determined (i.e. using the ase.phonons module), it is a simple matter to calculate the
canonical ensemble thermodynamic quantities; namely the internal energy, the entropy and the Helmholtz free
energy.
U (T ) = в€’
∂ ln Z
∂β
в€ћ
= Eelec +
0
N,V
¯hω
¯hω
+
σ(ω)dω
ehВЇ П‰ОІ в€’ 1
2
U
+ kB ln Z
T
в€ћ
1
hω
ВЇ
− kB ln 1 − e−¯hωβ
=
h
ВЇ П‰ОІ в€’ 1
T
e
0
S(T ) =
σ(ω)dω
F (T ) = U (T ) в€’ T S(T, P )
7.21 Infrared intensities
InfraRed is an extension of Vibrations, in addition to the vibrational modes, also the infrared intensities of
the modes are calculated for an Atoms object.
class ase.infrared.InfraRed(atoms, indices=None, name=’ir’, delta=0.01, nfree=2, directions=None)
Class for calculating vibrational modes and infrared intensities using finite difference.
The vibrational modes are calculated from a finite difference approximation of the Dynamical matrix and
the IR intensities from a finite difference approximation of the gradient of the dipole moment. The method
is described in:
D. Porezag, M. R. Pederson: “Infrared intensities and Raman-scattering activities within densityfunctional theory”, Phys. Rev. B 54, 7830 (1996)
The calculator object (calc) linked to the Atoms object (atoms) must have the attribute:
>>> calc.get_dipole_moment(atoms)
In addition to the methods included in the Vibrations class the InfraRed class introduces two new methods; get_spectrum() and write_spectra().
The summary(), get_energies(),
get_frequencies(), get_spectrum() and write_spectra() methods all take an optional method keyword. Use
method=’Frederiksen’ to use the method described in:
T. Frederiksen, M. Paulsson, M. Brandbyge, A. P. Jauho: “Inelastic transport theory from firstprinciples: methodology and applications for nanoscale devices”, Phys. Rev. B 75, 205413
(2007)
184
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
atoms: Atoms object The atoms to work on.
indices: list of int List of indices of atoms to vibrate. Default behavior is to vibrate all atoms.
name: str Name to use for files.
delta: float Magnitude of displacements.
nfree: int Number of displacements per degree of freedom, 2 or 4 are supported. Default is 2 which will
displace each atom +delta and -delta in each cartesian direction.
directions: list of int Cartesian coordinates to calculate the gradient of the dipole moment in. For example
directions = 2 only dipole moment in the z-direction will be considered, whereas for directions = [0,
1] only the dipole moment in the xy-plane will be considered. Default behavior is to use the dipole
moment in all directions.
Example:
>>> from ase.io import read
>>> from ase.calculators.vasp import Vasp
>>> from ase.infrared import InfraRed
>>> water = read(’water.traj’) # read pre-relaxed structure of water molecule
>>> calc = Vasp(prec=’Accurate’,
...
ediff=1E-8,
...
isym=0,
...
idipol=4,
# calculate the total dipole moment
...
dipol=water.get_center_of_mass(scaled=True),
...
ldipol=True)
>>> water.set_calculator(calc)
>>> ir = InfraRed(water)
>>> ir.run()
>>> ir.summary()
------------------------------------Mode
Frequency
Intensity
#
meV
cm^-1
(D/Г…)^2 amu^-1
------------------------------------0
16.9i
136.2i
1.6108
1
10.5i
84.9i
2.1682
2
5.1i
41.1i
1.7327
3
0.3i
2.2i
0.0080
4
2.4
19.0
0.1186
5
15.3
123.5
1.4956
6 195.5
1576.7
1.6437
7 458.9
3701.3
0.0284
8 473.0
3814.6
1.1812
------------------------------------Zero-point energy: 0.573 eV
Static dipole moment: 1.833 D
Maximum force on atom in �equilibrium�: 0.0026 eV/Å
This interface now also works for calculator �siesta’, (added get_dipole_moment for siesta).
Example:
>>> #!/usr/bin/env python
>>> from ase.io import read
>>> from ase.calculators.siesta import Siesta
>>> from ase.infrared import InfraRed
>>> bud = read(’bud1.xyz’)
>>> calc = Siesta(label=’bud’,
...
meshcutoff=250 * Ry,
7.21. Infrared intensities
185
ASE Manual, Release 3.9.0.3865
...
...
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
basis=’DZP’,
kpts=[1, 1, 1])
calc.set_fdf(’DM.MixingWeight’, 0.08)
calc.set_fdf(’DM.NumberPulay’, 3)
calc.set_fdf(’DM.NumberKick’, 20)
calc.set_fdf(’DM.KickMixingWeight’, 0.15)
calc.set_fdf(’SolutionMethod’,
’Diagon’)
calc.set_fdf(’MaxSCFIterations’, 500)
calc.set_fdf(’PAO.BasisType’, ’split’)
#50 meV = 0.003674931 * Ry
calc.set_fdf(’PAO.EnergyShift’, 0.003674931 * Ry )
calc.set_fdf(’LatticeConstant’, 1.000000 * Ang)
calc.set_fdf(’WriteCoorXmol’,
’T’)
>>> bud.set_calculator(calc)
>>> ir = InfraRed(bud)
>>> ir.run()
>>> ir.summary()
get_spectrum(start=800,
end=4000,
npts=None,
width=4,
type=’Gaussian’,
method=’standard’, direction=’central’, intensity_unit=’(D/A)2/amu’, normalize=False)
Get infrared spectrum.
The method returns wavenumbers in cm^-1 with corresponding absolute infrared intensity. Start and
end point, and width of the Gaussian/Lorentzian should be given in cm^-1. normalize=True ensures
the integral over the peaks to give the intensity.
write_spectra(out=’ir-spectra.dat’,
start=800,
end=4000,
npts=None,
width=10,
type=’Gaussian’,
method=’standard’,
direction=’central’,
intensity_unit=’(D/A)2/amu’, normalize=False)
Write out infrared spectrum to file.
First column is the wavenumber in cm^-1, the second column the absolute infrared intensities, and the
third column the absorbance scaled so that data runs from 1 to 0. Start and end point, and width of the
Gaussian/Lorentzian should be given in cm^-1.
7.22 Molecular dynamics
Typical computer simulations involve moving the atoms around, either to optimize a structure (energy minimization) or to do molecular dynamics. This chapter discusses molecular dynamics, energy minimization algorithms
will be discussed in the ase.optimize section.
A molecular dynamics object will operate on the atoms by moving them according to their forces - it integrates
Newton’s second law numerically. A typical molecular dynamics simulation will use the Velocity Verlet dynamics.
You create the ase.md.verlet.VelocityVerlet object, giving it the atoms and a time step, and then you
perform dynamics by calling its run() method:
dyn = VelocityVerlet(atoms, 5.0 * units.fs)
dyn.run(1000) # take 1000 steps
A number of different algorithms can be used to perform molecular dynamics, with slightly different results.
7.22.1 Choosing the time step
All the dynamics objects need a time step. Choosing it too small will waste computer time, choosing it too large
will make the dynamics unstable, typically the energy increases dramatically (the system “blows up”). If the time
186
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
step is only a little to large, the lack of energy conservation is most obvious in Velocity Verlet dynamics, where
energy should otherwise be conserved.
Experience has shown that 5 femtoseconds is a good choice for most metallic systems. Systems with light atoms
(e.g. hydrogen) and/or with strong bonds (carbon) will need a smaller time step.
All the dynamics objects documented here are sufficiently related to have the same optimal time step.
7.22.2 File output
The time evolution of the system can be saved in a trajectory file, by creating a trajectory object, and attaching it
to the dynamics object. This is documented in the module ase.io.trajectory.
Unlike the geometry optimization classes, the molecular dynamics classes do not support giving a trajectory file
name in the constructor. Instead the trajectory must be attached explicitly to the dynamics, and it is strongly
recommended to use the optional interval argument, so every time step is not written to the file.
7.22.3 Logging
A logging mechanism is provided, printing time; total, potential and kinetic energy; and temperature (calculated
from the kinetic energy). It is enabled by giving the logfile argument when the dynamics object is created,
logfile may be an open file, a filename or the string �-� meaning standard output. Per default, a line is printed
for each timestep, specifying the loginterval argument will chance this to a more reasonable frequency.
The logging can be customized by explicitly attaching a MDLogger object to the dynamics:
from ase.md import MDLogger
dyn = VelocityVerlet(atoms, dt=2*ase.units.fs)
dyn.attach(MDLogger(dyn, atoms, ’md.log’, header=False, stress=False,
peratom=True, mode="a"), interval=1000)
This example will skip the header line and write energies per atom instead of total energies. The parameters are
header: Print a header line defining the columns.
stress: Print the six components of the stress tensor.
peratom: Print energy per atom instead of total energy.
mode: If �a’, append to existing file, if �w’ overwrite existing file.
Despite appearances, attaching a logger like this does not create a cyclic reference to the dynamics.
Note: If building your own logging class, be sure not to attach the dynamics object directly to the logging object.
Instead, create a weak reference using the proxy method of the weakref package. See the ase.md.MDLogger
source code for an example. (If this is not done, a cyclic reference may be created which can cause certain
calculators, such as Jacapo, to not terminate correctly.)
7.22.4 Constant NVE simulations (the microcanonical ensemble)
Newton’s second law preserves the total energy of the system, and a straightforward integration of Newton’s
second law therefore leads to simulations preserving the total energy of the system (E), the number of atoms (N)
and the volume of the system (V). The most appropriate algorithm for doing this is velocity Verlet dynamics, since
it gives very good long-term stability of the total energy even with quite large time steps. Fancier algorithms such
as Runge-Kutta may give very good short-term energy preservation, but at the price of a slow drift in energy over
longer timescales, causing trouble for long simulations.
In a typical NVE simulation, the temperature will remain approximately constant, but if significant structural
changes occurs they may result in temperature changes. If external work is done on the system, the temperature is
likely to rise significantly.
7.22. Molecular dynamics
187
ASE Manual, Release 3.9.0.3865
Velocity Verlet dynamics
class ase.md.verlet.VelocityVerlet(atoms, timestep)
VelocityVerlet is the only dynamics implementing the NVE ensemble. It requires two arguments, the atoms
and the time step. Choosing a too large time step will immediately be obvious, as the energy will increase with
time, often very rapidly.
Example: See the tutorial Molecular dynamics.
7.22.5 Constant NVT simulations (the canonical ensemble)
Since Newton’s second law conserves energy and not temperature, simulations at constant temperature will somehow involve coupling the system to a heat bath. This cannot help being somewhat artificial. Two different approaches are possible within ASE. In Langevin dynamics, each atom is coupled to a heat bath through a fluctuating
force and a friction term. In NosГ©-Hoover dynamics, a term representing the heat bath through a single degree of
freedom is introduced into the Hamiltonian.
Langevin dynamics
class ase.md.langevin.Langevin(atoms, timestep, temperature, friction)
The Langevin class implements Langevin dynamics, where a (small) friction term and a fluctuating force are added
to Newton’s second law which is then integrated numerically. The temperature of the heat bath and magnitude of
the friction is specified by the user, the amplitude of the fluctuating force is then calculated to give that temperature.
This procedure has some physical justification: in a real metal the atoms are (weakly) coupled to the electron gas,
and the electron gas therefore acts like a heat bath for the atoms. If heat is produced locally, the atoms locally
get a temperature that is higher than the temperature of the electrons, heat is transferred to the electrons and then
rapidly transported away by them. A Langevin equation is probably a reasonable model for this process.
A disadvantage of using Langevin dynamics is that if significant heat is produced in the simulation, then the
temperature will stabilize at a value higher than the specified temperature of the heat bath, since a temperature
difference between the system and the heat bath is necessary to get a finite heat flow. Another disadvantage is that
the fluctuating force is stochastic in nature, so repeating the simulation will not give exactly the same trajectory.
When the Langevin object is created, you must specify a time step, a temperature (in energy units) and a friction.
Typical values for the friction are 0.01-0.02 atomic units.
# Room temperature simulation
dyn = Langevin(atoms, 5 * units.fs, units.kB * 300, 0.002)
Both the friction and the temperature can be replaced with arrays giving per-atom values. This is mostly useful
for the friction, where one can choose a rather high friction near the boundaries, and set it to zero in the part of the
system where the phenomenon being studied is located.
NosГ©-Hoover dynamics
In NosГ©-Hoover dynamics, an extra term is added to the Hamiltonian representing the coupling to the heat bath.
From a pragmatic point of view one can regard Nosé-Hoover dynamics as adding a friction term to Newton’s
second law, but dynamically changing the friction coefficient to move the system towards the desired temperature.
Typically the “friction coefficient” will fluctuate around zero.
NosГ©-Hoover dynamics is not implemented as a separate class, but is a special case of NPT dynamics.
Berendsen NVT dynamics
class ase.md.nvtberendsen.NVTBerendsen(atoms, timestep, temperature, taut, fixcm)
188
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
In Berendsen NVT simulations the velocities are scaled to achieve the desired temperature. The speed of the
scaling is determined by the parameter taut.
This method does not result proper NVT sampling but it usually is sufficiently good in practise (with large taut).
For discussion see the gromacs manual at www.gromacs.org.
atoms: The list of atoms.
timestep: The time step.
temperature: The desired temperature, in Kelvin.
taut: Time constant for Berendsen temperature coupling.
fixcm: If True, the position and momentum of the center of mass is kept unperturbed. Default: True.
# Room temperature simulation (300K, 0.1 fs time step)
dyn = NVTBerendsen(atoms, 0.1 * units.fs, 300, taut=0.5*1000*units.fs)
7.22.6 Constant NPT simulations (the isothermal-isobaric ensemble)
class ase.md.npt.NPT(atoms, timestep, temperature, externalstress, ttime, pfactor, mask=None)
Dynamics with constant pressure (or optionally, constant stress) and constant temperature (NPT or N,stress,T
ensemble). It uses the combination of NosГ©-Hoover and Parrinello-Rahman dynamics proposed by Melchionna et
al. [1] and later modified by Melchionna [2]. The differential equations are integrated using a centered difference
method [3]. Details of the implementation are available in the document XXX NPTdynamics.tex, distributed with
the module.
The dynamics object is called with the following parameters:
atoms: The atoms object.
timestep: The timestep in units matching eV, Г…, u. Use the units.fs constant.
temperature: The desired temperature in eV.
externalstress: The external stress in eV/Г…^3. Either a symmetric 3x3 tensor, a 6-vector representing the same, or
a scalar representing the pressure. Note that the stress is positive in tension whereas the pressure is positive
in compression: giving a scalar p is equivalent to giving the tensor (-p. -p, -p, 0, 0, 0).
ttime: Characteristic timescale of the thermostat. Set to None to disable the thermostat.
pfactor: A constant in the barostat differential equation. If a characteristic barostat timescale of ptime is desired,
set pfactor to ptime^2 * B (where B is the Bulk Modulus). Set to None to disable the barostat. Typical
metallic bulk moduli are of the order of 100 GPa or 0.6 eV/Г…^3.
mask=None: Optional argument. A tuple of three integers (0 or 1), indicating if the system can change size along
the three Cartesian axes. Set to (1,1,1) or None to allow a fully flexible computational box. Set to (1,1,0) to
disallow elongations along the z-axis etc.
Useful parameter values:
• The same timestep can be used as in Verlet dynamics, i.e. 5 fs is fine for bulk copper.
• The ttime and pfactor are quite critical[4], too small values may cause instabilites and/or wrong fluctuations
in T / p. Too large values cause an oscillation which is slow to die. Good values for the characteristic
times seem to be 25 fs for ttime, and 75 fs for ptime (used to calculate pfactor), at least for bulk copper
with 15000-200000 atoms. But this is not well tested, it is IMPORTANT to monitor the temperature and
stress/pressure fluctuations.
It has the following methods:
NPT.run(n):
Perform n timesteps.
7.22. Molecular dynamics
189
ASE Manual, Release 3.9.0.3865
NPT.initialize():
Estimates the dynamic variables for time=-1 to start the algorithm. This is automatically called before the
first timestep.
NPT.set_stress():
Set the external stress. Use with care. It is preferable to set the right value when creating the object.
NPT.set_mask():
Change the mask. Use with care, as you may “freeze” a fluctuation in the strain rate.
NPT.set_strainrate(eps):
Set the strain rate. eps must be an upper-triangular matrix. If you set a strain rate along a direction that is
“masked out” (see set_mask), the strain rate along that direction will be maintained constantly.
NPT.get_gibbs_free_energy():
Gibbs free energy is supposed to be preserved by this dynamics. This is mainly intended as a diagnostic
tool.
References:
[1] S. Melchionna, G. Ciccotti and B. L. Holian, Molecular Physics 78, p. 533 (1993).
[2] S. Melchionna, Physical Review E 61, p. 6165 (2000).
[3] B. L. Holian, A. J. De Groot, W. G. Hoover, and C. G. Hoover, Physical Review A 41, p. 4552 (1990).
[4] F. D. Di Tolla and M. Ronchetti, Physical Review E 48, p. 1726 (1993).
See Also:
The API documentation: md
Berendsen NPT dynamics
class ase.md.nptberendsen.NPTBerendsen(atoms, timestep, temperature, taut, pressure, taup,
compressibility, fixcm)
In Berendsen NPT simulations the velocities are scaled to achieve the desired temperature. The speed of the
scaling is determined by the parameter taut.
The atom positions and the simulation cell are scaled in order to achieve the desired pressure.
This method does not result proper NPT sampling but it usually is sufficiently good in practise (with large taut and
taup). For discussion see the gromacs manual at www.gromacs.org. or amber at ambermd.org
atoms: The list of atoms.
timestep: The time step.
temperature: The desired temperature, in Kelvin.
taut: Time constant for Berendsen temperature coupling.
pressure: The desired pressure, in bar (1 bar = 1e5 Pa).
taup: Time constant for Berendsen pressure coupling.
compressibility: The compressibility of the material, water 4.57E-5 bar-1, in bar-1
fixcm: If True, the position and momentum of the center of mass is kept unperturbed. Default: True.
# Room temperature simulation (300K, 0.1 fs time step, atmospheric pressure)
dyn = NPTBerendsen(atoms, timestep=0.1*units.fs, temperature=300,
taut=0.1*1000*units.fs, pressure = 1.01325,
taup=1.0*1000*units.fs, compressibility=4.57e-5)
190
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
7.23 Density Functional Theory
7.23.1 Brillouin zone sampling
The k-points are always given relative to the basis vectors of the reciprocal unit cell.
Monkhorst-Pack
ase.dft.kpoints.monkhorst_pack(size)
Construct a uniform sampling of k-space of given size.
The k-points are given as [MonkhorstPack]:
2ni в€’ Ni в€’ 1
bi ,
2Ni
i=1,2,3
where ni = 1, 2, ..., Ni , size = (N1 , N2 , N3 ) and the bi �s are reciprocal lattice vectors.
ase.dft.kpoints.get_monkhorst_pack_size_and_offset(kpts)
Find Monkhorst-Pack size and offset.
Returns (size, offset), where:
kpts = monkhorst_pack(size) + offset.
The set of k-points must not have been symmetry reduced.
Example:
>>> from ase.dft.kpoints import *
>>> monkhorst_pack((4, 1, 1))
array([[-0.375, 0.
, 0.
],
[-0.125, 0.
, 0.
],
[ 0.125, 0.
, 0.
],
[ 0.375, 0.
, 0.
]])
>>> get_monkhorst_pack_size_and_offset([[0, 0, 0]])
(array([1, 1, 1]), array([ 0., 0., 0.]))
Chadi-Cohen
Predefined sets of k-points:
ase.dft.kpoints.cc6_1x1
ase.dft.kpoints.cc12_2x3
ase.dft.kpoints.cc18_sq3xsq3
ase.dft.kpoints.cc18_1x1
ase.dft.kpoints.cc54_sq3xsq3
ase.dft.kpoints.cc54_1x1
ase.dft.kpoints.cc162_sq3xsq3
ase.dft.kpoints.cc162_1x1
Naming convention: cc18_sq3xsq3 is 18 k-points for a sq(3)xsq(3) cell.
Try this:
7.23. Density Functional Theory
191
ASE Manual, Release 3.9.0.3865
>>> import numpy as np
>>> import pylab as plt
>>> from ase.dft.kpoints import cc162_1x1
>>> B = [(1, 0, 0), (-0.5, 3**0.5 / 2, 0), (0, 0, 1)]
>>> k = np.dot(cc162_1x1, B)
>>> plt.plot(k[:, 0], k[:, 1], ’o’)
[<matplotlib.lines.Line2D object at 0x9b61dcc>]
>>> p.show()
Special points in the Brillouin zone
You can find the special points in the Brillouin zone:
>>> from ase.lattice import bulk
>>> from ase.dft.kpoints import ibz_points, get_bandpath
>>> si = bulk(’Si’, ’diamond’, a=5.459)
>>> points = ibz_points[’fcc’]
>>> G = points[’Gamma’]
>>> X = points[’X’]
>>> W = points[’W’]
>>> K = points[’K’]
>>> L = points[’L’]
>>> kpts, x, X = get_bandpath([W, L, G, X, W, K], si.cell)
>>> print len(kpts), len(x), len(X)
50 50 6
ase.dft.kpoints.get_bandpath(points, cell, npoints=50)
Make a list of kpoints defining the path between the given points.
points: list List of special IBZ point pairs, e.g. points = [W, L, Gamma, X, W, K]. These
should be given in scaled coordinates.
cell: 3x3 ndarray Unit cell of the atoms.
npoints: int Length of the output kpts list.
192
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Return list of k-points, list of x-coordinates and list of x-coordinates of special points.
7.23.2 Maximally localized Wannier functions
This page describes how to construct the Wannier orbitals using the class Wannier. The page is organized as
follows:
• Introduction: A short summary of the basic theory.
• The Wannier class : A description of how the Wannier class is used, and the methods defined within.
Introduction
The point of Wannier functions is the transform the extended Bloch eigenstates of a DFT calculation, into a smaller
set of states designed to facilitate the analysis of e.g. chemical bonding. This is achieved by designing the Wannier
functions to be localized in real space instead of energy (which would be the eigen states).
The standard Wannier transformation is a unitary rotation of the Bloch states. This implies that the Wannier
functions (WF) span the same Hilbert space as the Bloch states, i.e. they have the same eigenvalue spectrum,
and the original Bloch states can all be exactly reproduced from a linear combination of the WF. For maximally
localized Wannier functions (MLWF), the unitary transformation is chosen such that the spread of the resulting
WF is minimized.
The standard choice is to make a unitary transformation of the occupied bands only, thus resulting in as many WF
as there are occupied bands. If you make a rotation using more bands, the localization will be improved, but the
number of wannier functions increase, thus making orbital based analysis harder.
The class defined here allows for construction of partly occupied MLWF. In this scheme the transformation is still
a unitary rotation for the lowest states (the fixed space), but it uses a dynamically optimized linear combination
of the remaining orbitals (the active space) to improve localization. This implies that e.g. the eigenvalues of
the Bloch states contained in the fixed space can be exactly reproduced by the resulting WF, whereas the largest
eigenvalues of the WF will not necessarily correspond to any “real” eigenvalues (this is irrelevant, as the fixed
space is usually chosen large enough, i.e. high enough above the fermilevel, that the remaining DFT eigenvalues
are meaningless anyway).
For the theory behind this method see the paper “Partly Occupied Wannier Functions” Thygesen, Hansen and
Jacobsen, Phys. Rev. Lett, Vol. 94, 26405 (2005).
The Wannier class
Usual invocation:
from ase.dft import Wannier
wan = Wannier(nwannier=18, calc=GPAW(’save.gpw’), fixedstates=15)
wan.localize() # Optimize rotation to give maximal localization
wan.save(’file.pickle’) # Save localization and rotation matrix
# Re-load using saved wannier data
wan = Wannier(nwannier=18, calc=calc, fixedstates=15, file=’file.pickle’)
# Write a cube file
wan.write_cube(index=5, fname=’wannierfunction5.cube’)
For examples of how to use the Wannier class, see the Partly occupied Wannier Functions tutorial.
class ase.dft.wannier.Wannier(nwannier, calc, file=None, nbands=None, fixedenergy=None,
fixedstates=None, spin=0, initialwannier=’random’, seed=None,
verbose=False)
Maximally localized Wannier Functions
Find the set of maximally localized Wannier functions using the spread functional of Marzari and Vanderbilt
(PRB 56, 1997 page 12847).
7.23. Density Functional Theory
193
ASE Manual, Release 3.9.0.3865
Required arguments:
nwannier: The number of Wannier functions you wish to construct. This must be at least
half the number of electrons in the system and at most equal to the number of bands in the
calculation.
calc: A converged DFT calculator class. If file arg. is not provided, the calculator must
provide the method get_wannier_localization_matrix, and contain the wavefunctions (save files with only the density is not enough). If the localization matrix is read
from file, this is not needed, unless get_function or write_cube is called.
Optional arguments:
nbands: Bands to include in localization. The number of bands considered by Wannier can
be smaller than the number of bands in the calculator. This is useful if the highest bands of
the DFT calculation are not well converged.
spin: The spin channel to be considered. The Wannier code treats each spin channel independently.
fixedenergy / fixedstates: Fixed part of Heilbert space. Determine the fixed part of
Hilbert space by either a maximal energy or a number of bands (possibly a list for multiple
k-points). Default is None meaning that the number of fixed states is equated to nwannier.
file: Read localization and rotation matrices from this file.
initialwannier: Initial guess for Wannier rotation matrix. Can be �bloch’ to start from
the Bloch states, �random’ to be randomized, or a list passed to calc.get_initial_wannier.
seed: Seed for random initialwannier.
verbose: True / False level of verbosity.
get_centers(scaled=False)
Calculate the Wannier centers
pos =
L / 2pi * phase(diag(Z))
get_function(index, repeat=None)
Get Wannier function on grid.
Returns an array with the funcion values of the indicated Wannier function on a grid with the size of
the repeated unit cell.
For a calculation using k-points the relevant unit cell for eg. visualization of the Wannier orbitals is
not the original unit cell, but rather a larger unit cell defined by repeating the original unit cell by the
number of k-points in each direction. Note that for a О“-point calculation the large unit cell coinsides
with the original unit cell. The large unitcell also defines the periodicity of the Wannier orbitals.
index can be either a single WF or a coordinate vector in terms of the WFs.
get_functional_value()
Calculate the value of the spread functional.
Tr[|ZI|^2]=sum(I)sum(n) w_i|Z_(i)_nn|^2,
where w_i are weights.
get_hamiltonian(k=0)
Get Hamiltonian at existing k-vector of index k
dag
H(k) = V
k
diag(eps )
k
V
k
get_hamiltonian_kpoint(kpt_c)
Get Hamiltonian at some new arbitrary k-vector
194
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
_
H(k) = >_
R
ik.R
e
H(R)
Warning: This method moves all Wannier functions to cell (0, 0, 0)
get_hopping(R)
Returns the matrix H(R)_nm=<0,n|H|R,m>.
1
_
H(R) = <0,n|H|R,m> = --- >_
Nk k
-ik.R
e
H(k)
where R is the cell-distance (in units of the basis vectors of the small cell) and n,m are indices of the
Wannier functions.
get_pdos(w, energies, width)
Projected density of states (PDOS).
Returns the (PDOS) for Wannier function w. The calculation is performed over the energy grid specified in energies. The PDOS is produced as a sum of Gaussians centered at the points of the energy
grid and with the specified width.
get_radii()
Calculate the spread of the Wannier functions.
-- / L \ 2
2
radius**2 = - >
| --- |
ln |Z|
--d \ 2pi /
initialize(file=None, initialwannier=’random’, seed=None)
Re-initialize current rotation matrix.
Keywords are identical to those of the constructor.
localize(step=0.25, tolerance=1e-08, updaterot=True, updatecoeff=True)
Optimize rotation to give maximal localization
max_spread(directions=[0, 1, 2])
Returns the index of the most delocalized Wannier function together with the value of the spread
functional
save(file)
Save information on localization and rotation matrices to file.
translate(w, R)
Translate the w’th Wannier function
The distance vector R = [n1, n2, n3], is in units of the basis vectors of the small cell.
translate_all_to_cell(cell=[0, 0, 0])
Translate all Wannier functions to specified cell.
Move all Wannier orbitals to a specific unit cell. There exists an arbitrariness in the positions of the
Wannier orbitals relative to the unit cell. This method can move all orbitals to the unit cell specified
by cell. For a О“-point calculation, this has no effect. For a k-point calculation the periodicity of
the orbitals are given by the large unit cell defined by repeating the original unitcell by the number
of k-points in each direction. In this case it is usefull to move the orbitals away from the boundaries
of the large cell before plotting them. For a bulk calculation with, say 10x10x10 k points, one could
move the orbitals to the cell [2,2,2]. In this way the pbc boundary conditions will not be noticed.
translate_to_cell(w, cell)
Translate the w’th Wannier function to specified cell
write_cube(index, fname, repeat=None, real=True)
Dump specified Wannier function to a cube file
7.23. Density Functional Theory
195
ASE Manual, Release 3.9.0.3865
In Dacapo, the inialwannier keyword can be a list as described below:
Setup an initial set of Wannier orbitals. initialwannier can set up a starting guess for the Wannier
functions. This is important to speed up convergence in particular for large systems For transition
elements with d electrons you will always find 5 highly localized d-orbitals centered at the atom.
Placing 5 d-like orbitals with a radius of 0.4 Angstroms and center at atom no. 7, and 3 p-like orbitals
with a radius of 0.4 Angstroms and center at atom no. 27 looks like this:
initialwannier = [[[7],2,0.4],[[27],1,0.4]]
Placing only the l=2, m=-2 and m=-1 orbitals at atom no. 7 looks like this:
initialwannier = [[[7],2,-2,0.4],[[7],2,-1,0.4]]
I.e. if you do not specify the m quantum number all allowed values are used. Instead of placing an
orbital at an atom, you can place it at a specified position. For example the following:
initialwannier = [[[0.5,0.5,0.5],0,0.5]]
places an s orbital with radius 0.5 Angstroms at the position (0.5, 0.5, 0.5) in scaled coordinates of
the unit cell.
Note: For calculations using k-points, make sure that the О“-point is included in the k-point grid. The Wannier
module does not support k-point reduction by symmetry, so you must use the usesymm=False keyword in the
calc, and shift all k-points by a small amount (but not less than 2e-5 in) in e.g. the x direction, before performing
the calculation. If this is not done the symmetry program will still use time-reversal symmetry to reduce the
number of k-points by a factor 2. The shift can be performed like this:
from ase.dft.kpoints import monkhorst_pack
kpts = monkhorst_pack((15, 9, 9)) + [2e-5, 0, 0]
7.23.3 Density of states
Example:
calc = ...
dos = DOS(calc, width=0.2)
d = dos.get_dos()
e = dos.get_energies()
You can plot the result like this:
import pylab as plt
plt.plot(e, d)
plt.xlabel(’energy [eV]’)
plt.ylabel(’DOS’)
plt.show()
196
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Calculations involving moments of a DOS distribution may be
get_distribution_moment() method, as in the following example:
facilitated
by
the
use
of
from ase.dft import get_distribution_moment
volume = get_distribution_moment(e,d)
center, width = get_distribution_moment(e,d,(1,2))
More details
class ase.dft.dos.DOS(calc, width=0.1, window=None, npts=201)
Electronic Density Of States object.
calc: calculator object Any ASE compliant calculator object.
width: float Width of guassian smearing.
window: tuple of two float Use window=(emin, emax). If not specified, a window big enough to
hold all the eigenvalues will be used.
npts: int Number of points.
get_energies()
Return the array of energies used to sample the DOS. The energies are reported relative to the Fermi
level.
get_dos(spin=None)
Get array of DOS values.
The spin argument can be 0 or 1 (spin up or down) - if not specified, the total DOS is returned.
ase.dft.get_distribution_moment(x, y, order=0)
Return the moment of nth order of distribution.
1st and 2nd order moments of a band correspond to the band’s center and width respectively.
For integration, the trapezoid rule is used.
7.23. Density Functional Theory
197
ASE Manual, Release 3.9.0.3865
7.23.4 STM images
The STM is a revolutionary experimental surface probe that has provided direct local insight into the surface
electronic structure. Sometimes the interpretation of STM topographs are not straightforward and therefore theoretically modeled STM images may resolve conflicting possibilities and point to an underlying atomistic model.
ASE includes python modules for generating Tersoff-Hamann STM topographs.
See Also:
• Tutorial using GPAW
• Execise using GPAW
More details:
class ase.dft.stm.STM(atoms, symmetries=None)
Scanning tunneling microscope.
atoms: Atoms object or filename Atoms to scan or name of file to read LDOS from.
symmetries: list of int List of integers 0, 1, and/or 2 indicating which surface symmetries have been used
to reduce the number of k-points for the DFT calculation. The three integers correspond to the following three symmetry operations:
[-1
[ 0
0]
1]
[ 1 0]
[ 0 -1]
[ 0
[ 1
1]
0]
calculate_ldos(bias)
Calculate local density of states for given bias.
get_averaged_current(bias, z)
Calculate avarage current at height z.
Use this to get an idea of what current to use when scanning.
linescan(bias, current, p1, p2, npoints=50, z0=None)
Constant current line scan.
Example:
stm = STM(...)
z = ... # tip position
c = stm.get_averaged_current(-1.0, z)
stm.linescan(-1.0, c, (1.2, 0.0), (1.2, 3.0))
scan(bias, current, z0=None, repeat=(1, 1))
Constant current 2-d scan.
Returns three 2-d arrays (x, y, z) containing x-coordinates, y-coordinates and heights. These three
arrays can be passed to matplotlibs contourf() function like this:
>>>
>>>
>>>
>>>
import matplotlib.pyplot as plt
plt.gca(aspect=’equal’)
plt.contourf(x, y, z)
plt.show()
write(filename=’stm.pckl’)
Write local density of states to pickle file.
7.23.5 Bader Analysis
Henkelman et. al have implemented a fast and robust algorithm for calculating the electronic charges on individual atoms in molecules or crystals, based on the Bader partitioning scheme [Bader]. In that method, the
analysis is based purely on the electron density. The partitioning of the density is determined according to its
zero-flux surfaces. Details of their implementation can be found in [Tang]. The program is freely available at
http://theory.cm.utexas.edu/henkelman/research/bader/ where you will also find a description of the method.
198
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
The algorithm is very well suited for large solid state physical systems, as well as large biomolecular systems.
The computational time depends only on the size of the 3D grid used to represent the electron density, and scales
linearly with the total number of grid points. As the accuracy of the method depends on the grid spacing, it is
recommended to check for convergence in this parameter (which should usually by smaller than the default value).
The program takes cube input files. It does not support units, and assumes atomic units for the density (Bohr^-3).
All ase dft calculators have a get_pseudo_density method, which can be used to get the density. A simple
python script for making a cube file, ready for the Bader program, could be:
>>> from ase import *
>>> density = calc.get_pseudo_density() * Bohr**3
>>> write(’filename.cube’, atoms, data=density)
Some calculators (e.g. gpaw) also have a method called get_all_electron_density, in which case this is
preferable to get_pseudo_density.
Note that it is strongly recommended to use version 0.26b or higher of the program, and the examples below refer
to this version.
Example: The water molecule
The following example shows how to do Bader analysis for a water molecule.
First do a ground state calculation, and save the density as a cube file:
from ase import *
from gpaw import *
atoms = molecule(’H2O’, cell=[7.5, 9, 9], calculator=GPAW(h=.17, xc=’PBE’))
atoms.center()
atoms.get_potential_energy()
rho = atoms.calc.get_all_electron_density(gridrefinement=4) * Bohr**3
write(’water_density.cube’, atoms, data=rho)
Then analyse the density cube file by running (use bader -h for a description of the possible options):
$ bader -p all_atom -p atom_index water_density.cube
This will produce a number of files. The ACF.dat file, contains a summary of the Bader analysis:
|
|
|
|
|
|
|
#
X
Y
Z
CHARGE
MIN DIST
----------------------------------------------------------------1
7.0865
8.5038
9.0672
9.1121
1.3250
2
7.0865
9.9461
7.9403
0.4440
0.2834
3
7.0865
7.0615
7.9403
0.4440
0.2834
----------------------------------------------------------------NUMBER OF ELECTRONS:
9.99999
Revealing that 0.56 electrons have been transferred from each Hydrogen atom to the Oxygen atom.
The BvAtxxxx.dat files, are cube files for each Bader volume, describing the density within that volume. (I.e. it is
just the original cube file, truncated to zero outside the domain of the specific Bader volume).
AtIndex.dat is a cube file with an integer value at each grid point, describing which Bader volume it belongs to.
The plot below shows the dividing surfaces of the Hydrogen Bader volumes. This was achieved by plotting a
contour surface of AtIndex.dat at an isovalue of 1.5.
7.23. Density Functional Theory
199
ASE Manual, Release 3.9.0.3865
You can attach the output charges from the bader program to the atoms for further processing:
from ase import *
from ase.io.bader import attach_charges
# define the molecule as above
atoms = molecule(’H2O’)
atoms.set_cell([7.5, 9, 9])
atoms.center()
# the next two lines are equivalent (only one needed)
attach_charges(atoms)
attach_charges(atoms, ’ACF.dat’)
for atom in atoms:
print ’Atom’, atom.symbol, ’Bader charge’, atom.charge
7.24 Electron transport
The ase.transport module of ASE assumes the generic setup of the system in question sketched below:
...
...
There is a central region (blue atoms plus the molecule) connected to two semi-infinite leads constructed by
infinitely repeated principal layers (red atoms). The entire structure may be periodic in the transverse direction,
which can be effectively sampled using k-points (yellowish atoms).
200
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
The system is described by a Hamiltonian matrix which must be represented in terms of a localized basis set such
that each element of the Hamiltonian can be ascribed to either the left, central, or right region, or the coupling
between these.
The Hamiltonian can thus be decomposed as:
пЈ«
..
пЈ¬ .
V † L
пЈ¬
H=пЈ¬
пЈ¬
пЈ¬
пЈ­
пЈ¶
VL
HL
VL†VL
HC
VR†VR
HR
VR†
пЈ·
пЈ·
пЈ·
пЈ·
пЈ·
VR пЈ·
пЈё
..
.
where HL/R describes the left/right principal layer, and HC the central region. VL/R is the coupling between
principal layers, and from the principal layers into the central region. The central region must contain at least one
principal layer on each side, and more if the potential has not converged to its bulk value at this size. The central
region is assumed to be big enough that there is no direct coupling between the two leads. The principal layer
must be so big that there is only coupling between nearest neighbor layers.
Having defined HL/R , VL/R , and HC , the elastic transmission function can be determined using the Nonequilibrium Green Function (NEGF) method. This is achieved by the class: TransportCalculator (in
ase.transport.calculators) which makes no requirement on the origin of these five matrices.
class ase.transport.calculators.TransportCalculator(energies,
h,
h1,
h2,
s=None, s1=None, s2=None,
align_bf=False)
Determine transport properties of device sandwiched between semi-infinite leads using non-equillibrium
Green function methods.
energies is the energy grid on which the transport properties should be determined.
h1 (h2) is a matrix representation of the Hamiltonian of two principal layers of the left (right) lead, and the
coupling between such layers.
h is a matrix representation of the Hamiltonian of the scattering region. This must include at least on lead
principal layer on each side. The coupling in (out) of the scattering region is assumed to be identical to the
coupling between left (right) principal layers.
s, s1, and s2 are the overlap matrices corresponding to h, h1, and h2. Default is the identity operator.
If align_bf is True, the onsite elements of the Hamiltonians will be shifted to a common fermi level.
This module is stand-alone in the sense that it makes no requirement on the origin of these five matrices. They
can be model Hamiltonians or derived from different kinds of electronic structure codes.
For an example of how to use the ase.transport module, see the GPAW exercise on electron transport
7.25 The data module
7.25.1 Atomic data
This module defines the following variables:
ase.data.atomic_masses
ase.data.atomic_names
ase.data.chemical_symbols
ase.data.covalent_radii
ase.data.cpk_colors
ase.data.reference_states
7.25. The data module
201
ASE Manual, Release 3.9.0.3865
ase.data.vdw_radii
All of these are lists that should be indexed with an atomic number:
>>> from ase.data import *
>>> atomic_names[92]
’Uranium’
>>> atomic_masses[2]
4.0026000000000002
ase.data.atomic_numbers
If you don’t know the atomic number of some element, then you can look it up in the atomic_numbers
dictionary:
>>> atomic_numbers[’Cu’]
29
>>> covalent_radii[29]
1.1699999999999999
The covalent radii are taken from [Cordeo08]. The source of the van der Waals radii is given in vdw.py.
7.25.2 Molecular data
The G1, G2, and G3-databases are available. Example:
>>> from ase.structure import molecule
>>> atoms = molecule(’H2O’)
All molecular members of each database is conveniently contained in a list of strings (g1, g2, g3), ??? and one
can look up the experimental atomization energy for each molecule. This is extrapolated from experimental heats
of formation at room temperature, using calculated zero-point energies and thermal corrections.
Example:
>>> from ase.data.g2 import get_atomization_energy
>>> get_atomization_energy(’H2O’)
232.57990000000001
>>> from ase.units import kcal,mol
>>> get_atomization_energy(’H2O’)*kcal/mol
10.08562144637833
where the last line converts the experimental atomization energy of H2O from units of kcal/mol to eV.
7.25.3 S22, s26, and s22x5 data
The s22, s26, and s22x5 databases are available in the s22 module.
Each weakly bonded complex is identified as an entry in a list of strings (s22, s26, s22x5), and is fully created by
a �create’-function:
>>> from ase.data.s22 import s22, create_s22_system
>>> sys = s22[0]
>>> sys
’Ammonia_dimer’
>>> atoms = create_s22_system(sys)
>>> atoms.get_chemical_symbols()
[’N’, ’H’, ’H’, ’H’, ’N’, ’H’, ’H’, ’H’]
The coupled-cluster interaction energies for the s22 and s26 systems are retrieved like this:
>>> from ase.data.s22 import s22, get_interaction_energy_s22
>>> get_interaction_energy_s22(s22[0])
-0.1375
202
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
in units of eV. For s22 these are not the original energies, but from more recent work where the same (large) basis
set was used for all complexes, yielding more accurate coupled-cluster interaction energies.
The s22x5 database expands on the original s22 data by introducing non-equilibrium geometries for each complex
(0.9, 1.0, 1.2, 1.5, and 2.0 times original intermolecular distance). However, these calculations were done in
accordance with the methods used in the original s22 work, and so is expected to inherit the same problems with
mixed basis set sizes. Assuming the interaction energy error due to this is the same in all 5 geometries for each
complex, the default s22x5 interaction energies are therefore corrected with the energy difference between original
and newer energies at the original separation.
Example:
>>> from ase.data.s22 import *
>>> sys1 = s22[0]
>>> sys1
’Ammonia_dimer’
>>> atoms1 = create_s22_system(sys1)
>>> sys2 = s22x5[0]
>>> sys2
’Ammonia_dimer_0.9’
>>> atoms2 = create_s22_system(sys2)
>>> sys3 = s22x5[1]
>>> sys3
’Ammonia_dimer_1.0’
>>> atoms3 = create_s22_system(sys3)
>>> get_interaction_energy_s22(sys1)
-0.1375
>>> get_interaction_energy_s22(sys2)
-0.1375
>>> get_interaction_energy_s22(sys3)
-0.1375
>>> get_interaction_energy_s22x5(sys2)
-0.10549743024963291
>>> get_interaction_energy_s22x5(sys3)
-0.1375
>>> get_interaction_energy_s22x5(sys3,correct_offset=False)
-0.1362
>>> get_interaction_energy_s22x5(sys1,dist=1.0)
-0.1375
>>> get_interaction_energy_s22x5(sys1,dist=0.9)
-0.10549743024963291
>>> get_interaction_energy_s22x5(sys1,dist=0.9,correct_offset=False)
-0.1045
>>> get_number_of_dimer_atoms(sys1)
[4, 4]
>>> get_s22x5_distance(sys2)
-0.25040236345454536
>>> get_s22x5_distance(sys3)
0.0
where sys1 is an s22 complex in the original geometry, while sys2 and sys3 are two different s22x5 geometries
of the exact same complex. It is seen that the interaction energies for an s22 system and its s22x5 equivalent
(indexed �_1.0’) does not necessarily match when the energy offset-correction is turned off. The last two functions
are convenience functions, giving the number of atoms in the two molecules constituting a dimer and the relative
intermolecular distance in a dimer (relative to the �1.0’ separation, and in Angstrom), respectively.
7.26 Trajectory files
The ase.io.trajectory module defines Trajectory objects, that is objects storing the temporal evolution of
a simulation. A Trajectory file contains one or more Atoms objects, usually to be interpreted as a time series,
although that is not a requirement.
7.26. Trajectory files
203
ASE Manual, Release 3.9.0.3865
The ase.io.trajectory module currently defines two kinds of Trajectory files, the PickleTrajectory and the
BundleTrajectory. PickleTrajectory is the recommended Trajectory format, BundleTrajectory is only intended for
large molecular dynamics simulations (large meaning millions of atoms).
In the future, other kinds of Trajectories may be defined, with similar Python interface but with different underlying
file formats.
7.26.1 PickleTrajectory
The PickleTrajectory has the interface
class ase.io.trajectory.PickleTrajectory(filename, mode=’r’, atoms=None,
ter=None, backup=True)
Reads/writes Atoms objects into a .traj file.
mas-
A PickleTrajectory can be created in read, write or append mode.
Parameters:
filename: The name of the parameter file. Should end in .traj.
mode=’r’: The mode.
�r’ is read mode, the file should already exist, and no atoms argument should be specified.
�w’ is write mode. If the file already exists, it is renamed by appending .bak to the file name. The
atoms argument specifies the Atoms object to be written to the file, if not given it must instead be given
as an argument to the write() method.
�a’ is append mode. It acts a write mode, except that data is appended to a preexisting file.
atoms=None: The Atoms object to be written in write or append mode.
master=None: Controls which process does the actual writing. The default is that process number 0 does
this. If this argument is given, processes where it is True will write.
backup=True: Use backup=False to disable renaming of an existing file.
close()
Close the trajectory file.
open(filename, mode)
Opens the file.
For internal use only.
post_write_attach(function, interval=1, *args, **kwargs)
Attach a function to be called after writing ends.
function: The function or callable object to be called.
interval: How often the function is called. Default: every time (1).
All other arguments are stored, and passed to the function.
pre_write_attach(function, interval=1, *args, **kwargs)
Attach a function to be called before writing begins.
function: The function or callable object to be called.
interval: How often the function is called. Default: every time (1).
All other arguments are stored, and passed to the function.
set_atoms(atoms=None)
Associate an Atoms object with the trajectory.
Mostly for internal use.
204
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
write(atoms=None)
Write the atoms to the file.
If the atoms argument is not given, the atoms object specified when creating the trajectory object is
used.
Note that there is apparently no methods for reading the trajectory. Reading is instead done by indexing the
trajectory, or by iterating over the trajectory: traj[0] and traj[-1] return the first and last Atoms object in
the trajectory.
Examples
Reading a configuration:
from ase.io.trajectory import PickleTrajectory
traj = PickleTrajectory("example.traj")
atoms = traj[-1]
Reading all configurations:
traj = PickleTrajectory("example.traj")
for atoms in traj:
# Analyze atoms
Writing every 100th time step in a molecular dynamics simulation:
# dyn is the dynamics (e.g. VelocityVerlet, Langevin or similar)
traj = PickleTrajectory("example.traj", "w", atoms)
dyn.attach(traj.write, interval=100)
dyn.run(10000)
traj.close()
7.26.2 BundleTrajectory
The BundleTrajectory has the interface
class ase.io.bundletrajectory.BundleTrajectory(filename, mode=’r’,
backup=True)
Reads and writes atoms into a .bundle directory.
atoms=None,
The BundleTrajectory is an alternative way of storing trajectories, intended for large-scale molecular dynamics simulations, where a single flat file becomes unwieldy. Instead, the data is stored in directory, a
�bundle’ (the name bundle is inspired from bundles in Mac OS, which are really just directories the user is
supposed to think of as a single file-like unit).
Parameters:
filename: The name of the directory. Preferably ending in .bundle.
mode (optional): The file opening mode. �r’ means open for reading, �w’ for writing and �a’ for appending.
Default: �r’. If opening in write mode, and the filename already exists, the old file is renamed to .bak
(any old .bak file is deleted), except if the existing file is empty.
atoms (optional): The atoms that will be written. Can only be specified in write or append mode. If not
specified, the atoms must be given as an argument to the .write() method instead.
backup=True: Use backup=False to disable renaming of an existing file.
close()
Closes the trajectory.
classmethod delete_bundle(filename)
Deletes a bundle.
7.26. Trajectory files
205
ASE Manual, Release 3.9.0.3865
static is_bundle(filename)
Check if a filename exists and is a BundleTrajectory.
static is_empty_bundle(filename)
Check if a filename is an empty bundle. Assumes that it is a bundle.
log(text)
Write to the log file in the bundle.
Logging is only possible in write/append mode.
This function is mainly for internal use, but can also be called by the user.
post_write_attach(function, interval=1, *args, **kwargs)
Attach a function to be called after writing ends.
function: The function or callable object to be called.
interval: How often the function is called. Default: every time (1).
All other arguments are stored, and passed to the function.
pre_write_attach(function, interval=1, *args, **kwargs)
Attach a function to be called before writing begins.
function: The function or callable object to be called.
interval: How often the function is called. Default: every time (1).
All other arguments are stored, and passed to the function.
read_extra_data(name, n=0)
Read extra data stored alongside the atoms.
Currently only used to read data stored by an NPT dynamics object. The data is not associated with
individual atoms.
select_data(data, value)
Selects if a given data type should be written.
Data can be written in every frame (specify True), in the first frame only (specify �only’) or not at
all (specify False). Not all data types support the �only’ keyword, if not supported it is interpreted as
True.
The following data types are supported, the letter in parenthesis indicates the default:
positions (T), numbers (O), tags (O), masses (O), momenta (T), forces (T), energy (T), energies (F),
stress (F), magmoms (T)
If a given property is not present during the first write, it will be not be saved at all.
set_extra_data(name, source=None, once=False)
Adds extra data to be written.
Parameters: name: The name of the data.
source (optional): If specified, a callable object returning the data to be written. If not specified it is
instead assumed that the atoms contains the data as an array of the same name.
once (optional): If specified and True, the data will only be written to the first frame.
write(atoms=None)
Write the atoms to the file.
If the atoms argument is not given, the atoms object specified when creating the trajectory object is
used.
206
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
7.26.3 See also
The function ase.io.write() can write a single Atoms object to a Trajectory file.
The function ase.io.read() can read an Atoms object from a Trajectory file, per default it reads the last one.
7.27 Utillity functions and classes
ase.utils.opencew(filename, world=None)
Create and open filename exclusively for writing.
If master cpu gets exclusive write access to filename, a file descriptor is returned (a dummy file descriptor
is returned on the slaves). If the master cpu does not get write access, None is returned on all processors.
ase.utils.gcd(a, b)
Greatest common divisor of a and b.
7.27.1 Equation of state
The EquationOfState class can be used to find equilibrium volume, energy, and bulk modulus for solids:
class ase.utils.eos.EquationOfState(volumes, energies, eos=’sjeos’)
Fit equation of state for bulk systems.
The following equation is used:
sjeos (default)
A third order inverse polynomial fit 10.1103/PhysRevB.67.026103
2
3
E(V) = c + c t + c t + c t ,
0
1
2
3
-1/3
t = V
taylor
A third order Taylor series expansion about the minimum volume
murnaghan
PRB 28, 5480 (1983)
birch
Intermetallic compounds: Principles and Practice,
Vol I: Principles. pages 195-210
birchmurnaghan
PRB 70, 224107
pouriertarantola
PRB 70, 224107
vinet
PRB 70, 224107
antonschmidt
Intermetallics 11, 23-32 (2003)
p3
A third order polynomial fit
Use:
7.27. Utillity functions and classes
207
ASE Manual, Release 3.9.0.3865
eos = EquationOfState(volumes, energies, eos=’sjeos’)
v0, e0, B = eos.fit()
eos.plot()
See Also:
The Equation of state tutorial.
7.27.2 Symmetry analysis
http://spglib.sourceforge.net/pyspglibForASE/
7.27.3 Phonons
http://phonopy.sourceforge.net/
7.28 Building neighbor-lists
The ase.calculators.emt.EMT potential and the GPAW DFT calculator both make use of ASE’s built-in
neighbor-list class:
class ase.calculators.neighborlist.NeighborList(cutoffs,
skin=0.3,
sorted=False,
self_interaction=True,
bothways=False)
Neighbor list object.
cutoffs: list of float List of cutoff radii - one for each atom. If the spheres (defined by their cutoff radii) of
two atoms overlap, they will be counted as neighbors.
skin: float If no atom has moved more than the skin-distance since the last call to the update() method,
then the neighbor list can be reused. This will save some expensive rebuilds of the list, but extra
neighbors outside the cutoff will be returned.
self_interaction: bool Should an atom return itself as a neighbor?
bothways: bool Return all neighbors. Default is to return only “half” of the neighbors.
Example:
nl = NeighborList([2.3, 1.7])
nl.update(atoms)
indices, offsets = nl.get_neighbors(0)
build(atoms)
Build the list.
get_neighbors(a)
Return neighbors of atom number a.
A list of indices and offsets to neighboring atoms is returned. The positions of the neighbor atoms can
be calculated like this:
indices, offsets = nl.get_neighbors(42)
for i, offset in zip(indices, offsets):
print atoms.positions[i] + dot(offset, atoms.get_cell())
Notice that if get_neighbors(a) gives atom b as a neighbor, then get_neighbors(b) will not return a as
a neighbor - unless bothways=True was used.
update(atoms)
Make sure the list is up to date.
208
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
7.29 Setting up an OPLS force field calculation
In order to facilitate the definition of structures for the use of OPLS force fields, there are some helper classes.
7.29.1 Modified xyz
Suppose, we define the ethanal molecule as an modified xyz file (172_mod.xyz):
7
# ethanal from ChemSpider
O
1.613900000000000
CT
-0.327900000000000
C
0.392400000000000
HC
-0.960000000000000
HC
-0.960000000000000
HC
0.346400000000000
H1
-0.104900000000000
-0.762100000000000
0.522700000000000
-0.722900000000000
0.580900000000000
0.580900000000000
1.382000000000000
-1.581400000000000
-0.000000000000000
0.000000000000000
-0.000000000000000
0.887500000000000
-0.887500000000000
0.000000000000000
-0.000000000000000
Then we can read and view the structure using:
from ase.visualize import view
from ase.io.opls import OPLSStructure
s = OPLSStructure(’172_mod.xyz’) # 172_mod.xyz if the file name for the structure above
view(s) # view with real elements
elements = { ’CT’ : ’Si’, ’HC’ : ’H’, ’H1’ : ’He’ }
view(s.colored(elements)) # view with fake elements
7.29.2 Defining the force field
The definitions of the force field can be stored in an Amber like style (172_defs.par):
# the blocks are separated by empty lines
# comments are allowed
#
# one body - LJ-parameters and charge
CT 0.0028619844 3.50 0.000
C 0.0028619844 3.50 0.000
O 0.0073717780 3.12 -0.683
HC 0.0013009018 2.50 0.000
H1 0 0 0
# bonds
C -CT 317.0
C -O
570.0
CT-HC 340.0
C -H1 340.0
# angles
CT-C -O
HC-CT-HC
CT-C -H1
# dihedrals
O -C -CT-HC
1.522
1.229
1.090
1.090
80.0
35.0
70.0
JCC,7,(1986),230; AA
JCC,7,(1986),230; AA,CYT,GUA,THY,URA
changed from 331 bsd on NMA nmodes; AA, SUGARS
120.40
109.50
117.00
0.00000 6.02496E-01
-3
# cutoffs
C -CT 2.0
C -O 1.8
CT-HC 1.4
7.29. Setting up an OPLS force field calculation
209
ASE Manual, Release 3.9.0.3865
C -H1 1.4
C3-O1 1.8 # extra stuff, should not bother
We can write LAMMPS input using the information above:
from ase.io.opls import OPLSff, OPLSStructure
s = OPLSStructure(’172_mod.xyz’)
opls = OPLSff(’172_defs.par’)
opls.write_lammps(s, prefix=’lmp’)
which writes the LAMMPS input files lmp_atoms defining atoms, bonds, etc., and lmp_opls defining the
corresponding OPLS force field. A rudimentary lmp_in is also written.
7.30 A database for atoms
ASE has its own database that can be used for storing and retrieving atoms and associated data in a compact and
convenient way.
Note: This is work in progress. Use at your own risk!
There are currently three back-ends:
JSON: Simple human-readable text file with a .json extension.
SQLite3: Self-contained, server-less, zero-configuration database. Lives in a file with a .db extension.
PostgreSQL: Server based database.
The JSON and SQLite3 back-ends work “out of the box”, whereas PostgreSQL requires a server.
There is a command-line tool called ase-db that can be used to query and manipulate databases and also a Python
interface.
Contents
• A database for atoms
– What’s in the database?
– Command-line tool
– Integration with other parts of ASE
– Python Interface
* Extracting Atoms objects from the database
* Add additional data
* More details
7.30.1 What’s in the database?
Every row in the database contains:
• all the information stored in the Atoms object (positions, atomic numbers, ...)
• calculator name and parameters (if a calculator is present)
• already calculated properties such as energy and forces (if a calculator is present)
• keywords and key-value pairs (for finding the calculation again)
• an integer ID (unique for each database) starting with 1 and always increasing for each new row
210
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
• a unique ID which is a 128 bit random number which should be globally unique (at least in the lifetime of
our universe)
• constraints (if present)
• user-name
• creation and modification time
7.30.2 Command-line tool
The ase-db command can be used to query databases and for manipulating keywords and key-value pairs. Try:
$ ase-db --help
Example: Show all rows of SQLite database abc.db:
$ ase-db abc.db
id|age|user |formula|calc|energy| fmax|pbc|keywords|keyvals
| mass
1|6s |jensj|H2
|emt | 1.419|9.803|000|molecule|relaxed=False|2.016
2|5s |jensj|H2
|emt | 1.071|0.000|000|molecule|relaxed=True |2.016
3|5s |jensj|H
|emt | 3.210|0.000|000|
|
|1.008
Show all details for a single row:
$ ase-db abc.db id=3 -l
id: 3
formula: H
user: jensj
age: 174s
calculator: emt
energy: 3.210 eV
maximum atomic force: 0.000 eV/Ang
magnetic moment: 0
periodic boundary conditions: [False False False]
unit cell [Ang]:
1.000
0.000
0.000
0.000
1.000
0.000
0.000
0.000
1.000
volume: 1.000 Ang^3
mass: 1.008 au
Here are some example query strings:
v3
abc=H
v3,abc=H
calculator=nwchem
2.2<bandgap<3.0
natoms>=10
H<3
id=2345
age<1h
age>1y
has �v3’ keyword
has key �abc’ with value �H’
both of the above
calculations done with NWChem
�bandgap’ key has value between 2.2 and 3.0
10 or more atoms
less than 3 hydrogen atoms
specific id
not older than 1 hour
older than 1 year
These names are special:
7.30. A database for atoms
211
ASE Manual, Release 3.9.0.3865
id
natoms
energy
charge
magmom
calculator
user
age
integer identifier
number of atoms
potential energy
total charge
total magnetic moment
name of calculator
who did it
age of calculation (use s, m, h, d, w, M and y for second, minute, hour, day, week, month and year
respectively)
7.30.3 Integration with other parts of ASE
ASE’s ase.io.read() function can also read directly from databases:
>>>
>>>
>>>
>>>
from ase.io import read
a = read(’abc.db@42’)
a = read(’abc.db@id=42’) # same thing
b = read(’abc.db@v3,abc=H’)
Also the ase-gui program can read from databases using the same syntax.
7.30.4 Python Interface
First, we connect() to the database:
>>> from ase.db import connect
>>> c = connect(’abc.db’)
or
>>> import ase.db
>>> c = ase.db.connect(’abc.db’)
Let’s do a calculation for a hydrogen molecule and write some results to a database:
>>> from ase import Atoms
>>> from ase.calculators.emt import EMT
>>> h2 = Atoms(’H2’, [(0, 0, 0), (0, 0, 0.7)])
>>> h2.calc = EMT()
>>> h2.get_forces()
array([[ 0.
, 0.
, -9.80290573],
[ 0.
, 0.
, 9.80290573]])
Write a row to the database with keyword ’molecule’ and a key-value pair (’relaxed’, False):
>>> c.write(h2, [’molecule’], relaxed=False)
1
The write() method returns an integer id.
Do one more calculation and write results:
>>> from ase.optimize import BFGS
>>> BFGS(h2).run(fmax=0.01)
BFGS:
0 12:49:25
1.419427
9.8029
BFGS:
1 12:49:25
1.070582
0.0853
BFGS:
2 12:49:25
1.070544
0.0236
BFGS:
3 12:49:25
1.070541
0.0001
>>> c.write(h2, [’molecule’], relaxed=True)
2
212
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
Loop over selected rows using the select() method:
>>> for d in c.select(’molecule’):
...
print d.forces[0, 2], d.relaxed
...
-9.8029057329 False
-9.2526347333e-05 True
The select() method will generate dictionaries that one can loop over. The dictionaries are special in the sense
that keys can be accessed as attributes also (d.relaxed == d[’relaxed’]).
Write the energy of an isolated hydrogen atom to the database:
>>> h = Atoms(’H’)
>>> h.calc = EMT()
>>> h.get_potential_energy()
3.21
>>> c.write(h)
3
Select a single row with the get() method:
>>> d = c.get(relaxed=1, calculator=’emt’)
>>> for k, v in d.items():
...
print ’%-25s: %s’ % (k, v)
...
user
: jensj
key_value_pairs
: {u’relaxed’: True}
ctime
: 14.0195850909
mtime
: 14.0195850909
energy
: 1.07054126233
relaxed
: True
calculator_parameters
: {}
cell
: [[ 1. 0. 0.] [ 0. 1. 0.] [ 0.
numbers
: [1 1]
forces
: [[ ... ]]
positions
: [[ ... ]]
keywords
: [u’molecule’]
pbc
: [False False False]
id
: 2
unique_id
: 22e4a2d64800987dd8d398c6cc9fd085
calculator
: emt
0.
1.]]
Calculate the atomization energy and update() a row in the database:
>>> e2 = d.energy
>>> e1 = c.get(H=1).energy
>>> ae = 2 * e1 - e2
>>> print ae
5.34945873767
>>> id = c.get(relaxed=1).id
>>> c.update(id, atomization_energy=ae)
(0, 1)
Delete a single row:
>>> del c[c.get(relaxed=0).id]
or use the delete() method to delete several rows.
Extracting Atoms objects from the database
If you want an Atoms object insted of a dictionary, you should use the get_atoms() method:
7.30. A database for atoms
213
ASE Manual, Release 3.9.0.3865
>>> h2 = c.get_atoms(H=2)
or if you want the original EMT calculator attached:
>>> h2 = c.get_atoms(H=2, attach_calcuolator=True)
Add additional data
When you write a row to a database using the write() method, you can add string keywords and key-value pairs
where the values can be strings, floating point numbers, integers and booleans:
>>> c.write(atoms, [’project42’, ’ABC’], functional=’LDA’, distance=7.2)
More complicated data can be written like this:
>>> c.write(atoms, ..., data={’parents’: [7, 34, 14], ’stuff’: ...})
and accessed like this:
>>> d = c.get(...)
>>> d.data.parents
[7, 34, 14]
More details
ase.db.core.connect(name,
type=’extract_from_name’,
use_lock_file=True)
Create connection to database.
create_indices=True,
name: str Filename or address of database.
type: str One of �json’, �db’ or �pg’ (JSON, SQLite, PostgreSQL). Default is �extract_from_name’, which
will ... guess the type from the name.
use_lock_file: bool You can turn this off if you know what you are doing ...
class ase.db.core.Database(filename=None, create_indices=True, use_lock_file=False)
Base class for all databases.
write(*args, **kwargs)
Write atoms to database with keywords and key-value pairs.
atoms: Atoms object Write atomic numbers, positions, unit cell and boundary conditions. If a calculator is attached, write also already calculated properties such as the energy and forces.
keywords: list of str List of keywords.
key_value_pairs: dict Dictionary of key-value pairs. Values must be strings or numbers.
data: dict Extra stuff (not for searching).
Key-value pairs can also be set using keyword arguments:
connection.write(atoms, name=’ABC’, frequency=42.0)
reserve(*args, **kwargs)
Write empty row if not already present.
Usage:
id = conn.reserve(’keyword1’, ’keyword2’, ...,
key1=value1, key2=value2, ...)
Write an empty row with the given keywords and key-value pairs and return the integer id. If such a
row already exists, don’t write anything and return None.
214
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
get_atoms(selection=None,
**kwargs)
Get Atoms object.
attach_calculator=False,
add_additional_information=False,
selection: int, str or list See the select() method.
attach_calculator: bool Attach calculator object to Atoms object (default value is False).
add_additional_information: bool Put keywords, key-value pairs and data into Atoms.info dictionary.
In addition, one can use keyword arguments to select specific key-value pairs.
get(selection=None, fancy=True, **kwargs)
Select a single row and return it as a dictionary.
selection: int, str or list See the select() method.
fancy: bool return fancy dictionary with keys as attributes (this is the default).
select(selection=None, fancy=True, filter=None, explain=False, verbosity=1, limit=None,
**kwargs)
Select rows.
Return iterator with results as dictionaries. Selection is done using key-value pairs, keywords and the
special keys:
age, user, calculator, natoms, energy, magmom and/or charge.
selection: int, str or list Can be:
• an integer id
• a string like �key=value’, where �=’ can also be one of �<=’, �<’, �>’, �>=’ or �!=’.
• a string like �keyword’
• comma separated strings like �key1<value1,key2=value2,keyword’
• list of strings or tuples: [(�charge’, �=’, 1)].
fancy: bool return fancy dictionary with keys as attributes (this is the default).
filter: function A function that takes as input a dictionary and returns True or False.
explain: bool Explain query plan.
verbosity: int Possible values: 0, 1 or 2.
limit: int or None Limit selection.
update(*args, **kwargs)
Update row(s).
ids: int or list of int ID’s of rows to update.
add_keywords: list of str List of keyword strings to add to rows.
add_key_value_pairs: dict Key-value pairs to add.
returns number of keywords and key-value pairs added.
delete_keywords_and_key_value_pairs(*args, **kwargs)
Delete keywords and/or key_value_pairs from row(s).
ids: int or list of int ID’s of rows to delete from.
delete_keywords: list of str List of keyword strings to remove to rows.
delete_key_value_pairs: list of str Key-value pairs to remove.
returns number of keywords and key-value pairs removed.
7.30. A database for atoms
215
ASE Manual, Release 3.9.0.3865
delete(ids)
Delete rows.
7.31 Genetic Algorithm
Genetic algorithms (GA) have proven a good alternative to Monte Carlo type optimization methods for global
structure and materials properties optimization. A GA has recently been implemented into ase.
The use of the GA is best learned through tutorials:
7.31.1 Optimization with a Genetic Algorithm
A genetic algorithm (GA) has been implemented for global structure optimization within ase. The optimizer
consists of its own module ase.ga which includes all classes needed for the optimizer.
Details about the implemented method is described in the supplemental material of
L. B. Vilhelmsen and B. Hammer
Systematic Study of Au6 to Au12 Gold Clusters on MgO(100) F Centers Using Density-Functional
Theory
Physical Review Letters, Vol. 108 (Mar 2012), 126101
and in the main text of
L. B. Vilhelmsen, K. S. Walton and D. S. Sholl
Structure and Mobility of Metal Clusters in MOFs: Au, Pd, and AuPd Clusters in MOF-74
Journal of the American Chemical Society, Vol. 134, No. 30, pp. 12807-12816
Any questions about how to use the GA can be asked at the mailing list.
A Brief Overview of the Implementation
The GA relies on the ase.db module for tracking which structures have been found. Before the GA optimization
starts the user therefore needs to prepare this database and appropriate folders. This is done trough an initialization
script as the one described in the next section. In this initialization the starting population is generated and added
to the database.
After initialization the main script is run. This script defines objects responsible for the different parts of the GA
and then creates and locally relaxes new candidates. It is up to the user to define when the main script should
terminate. An example of a main script is given in the next section. Notice that because of the persistent data
storage the main script can be executed multiple times to generate new candidates.
The GA implementation generally follows a responsibility driven approach. This means that each part of the GA
is isolated into individual classes making it possible to put together an optimizer satisfying the needs of a specific
optimization problem.
This tutorial will use the following parts of the GA:
• A population responsible for proposing new candidates to pair together.
• A paring operator which combines two candidates.
• A set of mutations.
• A comparator which determines if two structures are different.
• A starting population generator.
Each of the above components are described in the supplemental material of the first reference given above and
will not be discussed here. The example will instead focus on the technical aspect of executing the GA.
216
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
A Basic Example
The user needs to specify the following three properties about the structure that needs to be optimized.
• A list of atomic numbers for the structure to be optimized
• A super cell in which to do the optimization. If the structure to optimize resides on a surface or in a support
this supercell contains the atoms which should not be considered explicitly by the GA.
• A box defining the volume of the super cell in which to randomly distribute the starting population.
As an example we will find the structure of a Ag2 Au2 cluster on a Au(111) surface using the EMT optimizer.
The script doing all the initialisations should be run in the folder in which the GA optimisation is to take place.
The script looks as follows:
from ase.ga.data import PrepareDB
from ase.ga.startgenerator import StartGenerator
from ase.ga.utilities import closest_distances_generator
from ase.ga.utilities import get_all_atom_types
from ase.constraints import FixAtoms
import numpy as np
from ase.lattice.surface import fcc111
db_file = ’gadb.db’
# create the surface
slab = fcc111(’Au’, size=(4, 4, 1), vacuum=10.0, orthogonal=True)
slab.set_constraint(FixAtoms(mask=len(slab) * [True]))
# define the volume in which the adsorbed cluster is optimized
# the volume is defined by a corner position (p0)
# and three spanning vectors (v1, v2, v3)
pos = slab.get_positions()
cell = slab.get_cell()
p0 = np.array([0., 0., max(pos[:, 2]) + 2.])
v1 = cell[0, :] * 0.8
v2 = cell[1, :] * 0.8
v3 = cell[2, :]
v3[2] = 3.
# Define the composition of the atoms to optimize
atom_numbers = 2 * [47] + 2 * [79]
# define the closest distance two atoms of a given species can be to each other
unique_atom_types = get_all_atom_types(slab, atom_numbers)
cd = closest_distances_generator(atom_numbers=unique_atom_types,
ratio_of_covalent_radii=0.7)
# create the starting population
sg = StartGenerator(slab=slab,
atom_numbers=atom_numbers,
closest_allowed_distances=cd,
box_to_place_in=[p0, [v1, v2, v3]])
# generate the starting population
population_size = 20
starting_population = [sg.get_new_candidate() for i in xrange(population_size)]
# from ase.visualize import view
# view(starting_population)
# uncomment these lines
# to see the starting population
# create the database to store information in
d = PrepareDB(db_file_name=db_file,
simulation_cell=slab,
7.31. Genetic Algorithm
217
ASE Manual, Release 3.9.0.3865
stoichiometry=atom_numbers,)
# population_size=population_size)
for a in starting_population:
d.add_unrelaxed_candidate(a)
Having initialized the GA optimization we now need to actually run the GA. The main script running the GA
consists of first an initialization part, and then a loop proposing new structures and locally optimizing them. The
main script can look as follows:
from
from
from
from
random import random
ase.io import write
ase.optimize import BFGS
ase.calculators.emt import EMT
from
from
from
from
from
from
from
from
from
from
ase.ga.data import DataConnection
ase.ga.population import Population
ase.ga.standard_comparators import InteratomicDistanceComparator
ase.ga.cutandsplicepairing import CutAndSplicePairing
ase.ga.utilities import closest_distances_generator
ase.ga.utilities import get_all_atom_types
ase.ga.offspring_creator import OperationSelector
ase.ga.standardmutations import MirrorMutation
ase.ga.standardmutations import RattleMutation
ase.ga.standardmutations import PermutationMutation
# Change the following three parameters to suit your needs
population_size = 20
mutation_probability = 0.3
n_to_test = 20
# Initialize the different components of the GA
da = DataConnection(’gadb.db’)
atom_numbers_to_optimize = da.get_atom_numbers_to_optimize()
n_to_optimize = len(atom_numbers_to_optimize)
slab = da.get_slab()
all_atom_types = get_all_atom_types(slab, atom_numbers_to_optimize)
blmin = closest_distances_generator(all_atom_types,
ratio_of_covalent_radii=0.7)
comp = InteratomicDistanceComparator(n_top=n_to_optimize,
pair_cor_cum_diff=0.015,
pair_cor_max=0.7,
dE=0.02,
mic=False)
pairing = CutAndSplicePairing(slab, n_to_optimize, blmin)
mutations = OperationSelector([1., 1., 1.],
[MirrorMutation(blmin, n_to_optimize),
RattleMutation(blmin, n_to_optimize),
PermutationMutation(n_to_optimize)])
# Relax all unrelaxed structures (e.g. the starting population)
while da.get_number_of_unrelaxed_candidates() > 0:
a = da.get_an_unrelaxed_candidate()
a.set_calculator(EMT())
print(’Relaxing starting candidate {0}’.format(a.info[’confid’]))
dyn = BFGS(a, trajectory=None, logfile=None)
dyn.run(fmax=0.05, steps=100)
a.set_raw_score(-a.get_potential_energy())
da.add_relaxed_step(a)
# create the population
218
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
population = Population(data_connection=da,
population_size=population_size,
comparator=comp)
# test n_to_test new candidates
for i in xrange(n_to_test):
print(’Now starting configuration number {0}’.format(i))
a1, a2 = population.get_two_candidates()
a3, desc = pairing.get_new_individual([a1, a2])
if a3 == None:
continue
da.add_unrelaxed_candidate(a3, description=desc)
# Check if we want to do a mutation
if random() < mutation_probability:
a3_mut, desc = mutations.get_new_individual([a3])
if a3_mut != None:
da.add_unrelaxed_step(a3_mut, desc)
a3 = a3_mut
# Relax the new candidate
a3.set_calculator(EMT())
dyn = BFGS(a3, trajectory=None, logfile=None)
dyn.run(fmax=0.05, steps=100)
a3.set_raw_score(-a3.get_potential_energy())
da.add_relaxed_step(a3)
population.update()
write(’all_candidates.traj’, da.get_all_relaxed_candidates())
The above script proposes and locally relaxes 20 new candidates. To speed up the execution of this sample the
local relaxations are limited to 100 steps. This restriction should not be set in a real application. Note it is
important to set the the raw_score, as it is what is being optimized (maximized). It is really an input in the
atoms.info[’key_value_pairs’] dictionary.
The GA progress can be monitored by running the tool ase/ga/tools/get_all_candidates in the same
folder as the GA. This will create a trajectory file all_candidates.traj which includes all locally relaxed
candidates the GA has tried. This script can be run at the same time as the main script is running. This is possible
because the ase.db database is being updated as the GA progresses.
Running the GA in Parallel
One of the great advantages of a GA is that many structures can be relaxed in parallel. This GA implementation
includes two classes which facilitates running the GA in parallel. One class can be used for running several single
threaded optimizations simultaneously on the same compute node, and the other class integrates the GA into the
PBS queuing system used at many high performance computer clusters.
Relaxations in Parallel on the Same Computer
In order to relax several structures simultaneously on the same computer a seperate script relaxing one structure
needs to be created. Continuing the example from above we therefore create a script taking as input the filename of
the structure to relax and which as output saves a trajectory file with the locally optimized structure. It is important
that the relaxed structure is named as in this script, since the parallel integration assumes this file naming scheme.
For the example described above this script could look like
from
from
from
from
from
ase.optimize import BFGS
ase.io import read, write
ase.calculators.emt import EMT
ase.ga.relax_attaches import VariansBreak
ase.ga.atoms_attach import enable_raw_score_methods
7.31. Genetic Algorithm
219
ASE Manual, Release 3.9.0.3865
import sys
fname = sys.argv[1]
print(’Now relaxing {}’.format(fname))
a = read(fname)
a.set_calculator(EMT())
dyn = BFGS(a, trajectory=None, logfile=None)
vb = VariansBreak(a, dyn)
dyn.attach(vb.write)
dyn.run(fmax=0.05)
enable_raw_score_methods(a)
a.set_raw_score(-a.get_potential_energy())
write(fname[:-5] + ’_done.traj’, a)
print(’Done relaxing {}’.format(fname))
The main script needs to initialize the parallel controller and then the script needs to be changed the two places
where structures are relaxed. The changed main script now looks like
from random import random
from ase.io import write
import time
from ase.ga.data import DataConnection
from ase.ga.population import Population
from ase.ga.standard_comparators import InteratomicDistanceComparator
from ase.ga.cutandsplicepairing import CutAndSplicePairing
from ase.ga.offspring_creator import OperationSelector
from ase.ga.standardmutations import MirrorMutation
from ase.ga.standardmutations import RattleMutation
from ase.ga.standardmutations import PermutationMutation
from ase.ga.utilities import closest_distances_generator
from ase.ga.utilities import get_all_atom_types
from ase.ga.parallellocalrun import ParallelLocalRun
population_size = 20
mutation_probability = 0.3
n_to_test = 100
# Initialize the different components of the GA
da = DataConnection(’gadb.db’)
tmp_folder = ’tmp_folder/’
# An extra object is needed to handle the parallel execution
parallel_local_run = ParallelLocalRun(data_connection=da,
tmp_folder=tmp_folder,
n_simul=4,
calc_script=’calc.py’)
atom_numbers_to_optimize = da.get_atom_numbers_to_optimize()
n_to_optimize = len(atom_numbers_to_optimize)
slab = da.get_slab()
all_atom_types = get_all_atom_types(slab, atom_numbers_to_optimize)
blmin = closest_distances_generator(all_atom_types,
ratio_of_covalent_radii=0.7)
comp = InteratomicDistanceComparator(n_top=n_to_optimize,
pair_cor_cum_diff=0.015,
220
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
pair_cor_max=0.7,
dE=0.02,
mic=False)
pairing = CutAndSplicePairing(slab, n_to_optimize, blmin)
mutations = OperationSelector([1., 1., 1.],
[MirrorMutation(blmin, n_to_optimize),
RattleMutation(blmin, n_to_optimize),
PermutationMutation(n_to_optimize)])
# Relax all unrelaxed structures (e.g. the starting population)
while da.get_number_of_unrelaxed_candidates() > 0:
a = da.get_an_unrelaxed_candidate()
parallel_local_run.relax(a)
# Wait until the starting population is relaxed
while parallel_local_run.get_number_of_jobs_running() > 0:
time.sleep(5.)
# create the population
population = Population(data_connection=da,
population_size=population_size,
comparator=comp)
# test n_to_test new candidates
for i in xrange(n_to_test):
print(’Now starting configuration number {0}’.format(i))
a1, a2 = population.get_two_candidates()
a3, desc = pairing.get_new_individual([a1, a2])
if a3 is None:
continue
da.add_unrelaxed_candidate(a3, description=desc)
# Check if we want to do a mutation
if random() < mutation_probability:
a3_mut, desc = mutations.get_new_individual([a3])
if a3_mut is not None:
da.add_unrelaxed_step(a3_mut, desc)
a3 = a3_mut
# Relax the new candidate
parallel_local_run.relax(a3)
population.update()
# Wait until the last candidates are relaxed
while parallel_local_run.get_number_of_jobs_running() > 0:
time.sleep(5.)
write(’all_candidates.traj’, da.get_all_relaxed_candidates())
Notice how the main script is not cluttered by the local optimization logic and is therefore now also easier to read.
n_simul controls the number of simultaneous relaxations, and can of course also be set to 1 effectively giving
the same result as in the non parallel situation.
The relax method on the ParallelLocalRun class only returns control to the main script when there is an
execution thread available. In the above example the relax method immediately returns control to the main script
the first 4 times it is called, but the fifth time control is first returned when one of the first four relaxations have
been completed.
Running the GA together with a queing system
The GA has been implemented with first principles structure optimization in mind. When using for instance DFT
calculations for the local relaxations relaxing one structure can take many hours. For this reason the GA has been
7.31. Genetic Algorithm
221
ASE Manual, Release 3.9.0.3865
made so that it can work together with queing systems where each candidate is relaxed in a separate job. With this
in mind the main script of the GA can thus also be considered a controller script which every time it is invoked
gathers the current population, checks with a queing system for the number of jobs submitted, and submits new
jobs. For a typical application the main script can thus be invoked by a crontab once every hour.
To run the GA together with a queing system the user needs to specify a function which takes as input a job name
and the path to the trajectory file that needs to be submitted (the jtg function in the sample script below). From
this the function generates a PBS job file which is submitted to the queing system. The calculator script specified
in the jobfile needs to obey the same naming scheme as the sample calculator script in the previous section. The
sample relaxation script given in the previous can be used as starting point for a relaxation script.
Handling of the parallel logic is in this case in the main script. The parameter n_simul given to the PBSQueueRun
object determines how many relaxations should be in the queuing system simultaneously. The main script now
looks the following:
from
from
from
from
from
from
from
from
from
from
from
from
from
random import random
ase.io import write
ase.ga.data import DataConnection
ase.ga.population import Population
ase.ga.standard_comparators import InteratomicDistanceComparator
ase.ga.cutandsplicepairing import CutAndSplicePairing
ase.ga.offspring_creator import OperationSelector
ase.ga.standardmutations import MirrorMutation
ase.ga.standardmutations import RattleMutation
ase.ga.standardmutations import PermutationMutation
ase.ga.utilities import closest_distances_generator
ase.ga.utilities import get_all_atom_types
ase.ga.pbs_queue_run import PBSQueueRun
def jtg(job_name, traj_file):
s = ’#!/bin/sh\n’
s += ’#PBS -l nodes=1:ppn=12\n’
s += ’#PBS -l walltime=48:00:00\n’
s += ’#PBS -N {0}\n’.format(job_name)
s += ’#PBS -q q12\n’
s += ’cd $PBS_O_WORKDIR\n’
s += ’python calc.py {0}\n’.format(traj_file)
return s
population_size = 20
mutation_probability = 0.3
# Initialize the different components of the GA
da = DataConnection(’gadb.db’)
tmp_folder = ’tmp_folder/’
# The PBS queing interface is created
pbs_run = PBSQueueRun(da,
tmp_folder=tmp_folder,
job_prefix=’Ag2Au2_opt’,
n_simul=5,
job_template_generator=jtg)
atom_numbers_to_optimize = da.get_atom_numbers_to_optimize()
n_to_optimize = len(atom_numbers_to_optimize)
slab = da.get_slab()
all_atom_types = get_all_atom_types(slab, atom_numbers_to_optimize)
blmin = closest_distances_generator(all_atom_types,
ratio_of_covalent_radii=0.7)
comp = InteratomicDistanceComparator(n_top=n_to_optimize,
pair_cor_cum_diff=0.015,
pair_cor_max=0.7,
222
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
dE=0.02,
mic=False)
pairing = CutAndSplicePairing(slab, n_to_optimize, blmin)
mutations = OperationSelector([1., 1., 1.],
[MirrorMutation(blmin, n_to_optimize),
RattleMutation(blmin, n_to_optimize),
PermutationMutation(n_to_optimize)])
# Relax all unrelaxed structures (e.g. the starting population)
while (da.get_number_of_unrelaxed_candidates() > 0
and not pbs_run.enough_jobs_running()):
a = da.get_an_unrelaxed_candidate()
pbs_run.relax(a)
# create the population
population = Population(data_connection=da,
population_size=population_size,
comparator=comp)
# Submit new candidates until enough are running
while (not pbs_run.enough_jobs_running()
and len(population.get_current_population()) > 2):
a1, a2 = population.get_two_candidates()
a3, desc = pairing.get_new_individual([a1, a2])
if a3 is None:
continue
da.add_unrelaxed_candidate(a3, description=desc)
if random() < mutation_probability:
a3_mut, desc = mutations.get_new_individual([a3])
if a3_mut is not None:
da.add_unrelaxed_step(a3_mut, desc)
a3 = a3_mut
pbs_run.relax(a3)
write(’all_candidates.traj’, da.get_all_relaxed_candidates())
7.31.2 GA Search for stable FCC alloys
In this tutorial we will emulate an older paper [JГіhannesson] and determine the most stable FCC alloy using the
genetic algorithm. Since the purpose is only the tutorial we will limit the phase space to the elements supported
by the EMT potential. The search is also equivalent to the recent search for mixed metal ammines with superior
properties for ammonia storage described here:
P. B. Jensen, S. Lysgaard, U. J. Quaade and T. Vegge
Designing Mixed Metal Halide Ammines for Ammonia Storage Using Density Functional Theory
and Genetic Algorithms
Physical Chemistry Chemical Physics, Vol 16, No. 36, pp. 19732-19740, (2014)
7.31. Genetic Algorithm
223
ASE Manual, Release 3.9.0.3865
Contents
• GA Search for stable FCC alloys
– Basic outline of the search
– Setting up reference database
– Initial population
– Run the algorithm
– Extending the algorithm
* Extra mutation operators
* Prevent identical calculations from being performed
* Reuse of calculations between algorithm runs
Basic outline of the search
1. Choose the phase space of your problem. Is the number of possible individuals large enough to prevent a
full screening and is the fitness function too discontinuous for a traditional optimization by derivation? If
so continue.
2. Choose model structures and calculate references in those structures. Put the results somewhere accesible
for a script initiated by the genetic algorithm.
3. Choose suitable parameters like population size (general rule of thumb for the population size: log2 (N) <
pop size < 2log2 (N), where N is the size of the phase space), convergence criteria etc.
4. Create the initial population.
5. Choose procreation operators, i.e. how should offspring be produced. New operators can easily be created
by modifying the existing operators.
6. Run the algorithm.
Here we would like to predict the most stable fcc alloys. In this tutorial we only have the EMT potential available
thus we are limited to the supported metal elements: Al, Ni, Cu, Pd, Ag, Pt and Au. We limit ourselves to at most
4 different metals in one structure, thereby having only 74 = 2401 candidates in the phase space, symmetry would
make this number even lower but the number is fitting for this tutorial.
For a real application of the algorithm it is necessary to use a more sophisticated calculator, in that case each
individual calculation is performed on a cluster by submitting to a queuing system. How this is achieved in the
algorithm is covered in Optimization with a Genetic Algorithm.
Setting up reference database
Now we need to set up a database in which reference calculations can be stored. This can either be in a central
database server where keywords distinguish between different references or dedicated separate databases for each
different type of reference calculations.
In the following script, ga_fcc_references.py, we put the references in the database file refs.db. Our
model structure is fcc which is loaded with ase.lattice.cubic.FaceCenteredCubic(). We perform
a volume relaxation to find the optimal lattice constant and lowest energy, which we save in the database as
key-value pairs for quick retrieval.
import numpy as np
from
from
from
from
ase.lattice.cubic import FaceCenteredCubic
ase.calculators.emt import EMT
ase.utils.eos import EquationOfState
ase.db import connect
db = connect(’refs.db’)
metals = [’Al’, ’Au’, ’Cu’, ’Ag’, ’Pd’, ’Pt’, ’Ni’]
224
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
for m in metals:
atoms = FaceCenteredCubic(m)
atoms.set_calculator(EMT())
e0 = atoms.get_potential_energy()
a = atoms.cell[0][0]
eps = 0.05
volumes = (a * np.linspace(1 - eps, 1 + eps, 9))**3
energies = []
for v in volumes:
atoms.set_cell([v**(1. / 3)] * 3, scale_atoms=True)
energies.append(atoms.get_potential_energy())
eos = EquationOfState(volumes, energies)
v1, e1, B = eos.fit()
atoms.set_cell([v1**(1. / 3)] * 3, scale_atoms=True)
ef = atoms.get_potential_energy()
db.write(atoms, metal=m,
latticeconstant=v1**(1. / 3),
energy_per_atom=ef / len(atoms))
Initial population
We choose a population size of 10 individuals and create the initial population by randomly selecting four elements
for each starting individual.
import random
from ase import Atoms
from ase.ga.data import PrepareDB
metals = [’Al’, ’Au’, ’Cu’, ’Ag’, ’Pd’, ’Pt’, ’Ni’]
population_size = 10
# Create database
db = PrepareDB(’fcc_alloys.db’,
population_size=population_size,
metals=metals)
# Create starting population
for i in xrange(population_size):
atoms_string = [random.choice(metals) for _ in xrange(4)]
db.add_unrelaxed_candidate(Atoms(atoms_string),
atoms_string=’’.join(atoms_string))
Note how we add the population size and metals as extra key-value pairs when we create the database
fcc_alloys.db. We can then retrieve these parameters later when running the main script to avoid having to input the same parameters twice.
We can study our initial population by doing (on the command-line):
$ ase-db fcc_alloys.db -c +atoms_string
the term atoms_string determines the order in which the elements are put into the model structure. So it is
possible to fully describe an individual by just providing the atoms_string.
7.31. Genetic Algorithm
225
ASE Manual, Release 3.9.0.3865
Run the algorithm
from
from
from
from
from
from
ase.ga.data import DataConnection
ase.ga.element_mutations import RandomElementMutation
ase.ga.element_crossovers import OnePointElementCrossover
ase.ga.offspring_creator import OperationSelector
ase.ga.population import Population
ase.ga.convergence import GenerationRepetitionConvergence
from ga_fcc_alloys_relax import relax
# Specify the number of generations this script will run
num_gens = 40
db = DataConnection(’fcc_alloys.db’)
ref_db = ’refs.db’
# Retrieve saved parameters
population_size = db.get_param(’population_size’)
metals = db.get_param(’metals’)
# Specify the procreation operators for the algorithm
# Try and play with the mutation operators that move to nearby
# places in the periodic table
oclist = ([1, 1], [RandomElementMutation(metals),
OnePointElementCrossover(metals)])
operation_selector = OperationSelector(*oclist)
# Pass parameters to the population instance
pop = Population(data_connection=db,
population_size=population_size)
# We form generations in this algorithm run and can therefore set
# a convergence criteria based on generations
cc = GenerationRepetitionConvergence(pop, 3)
# Relax the starting population
while db.get_number_of_unrelaxed_candidates() > 0:
a = db.get_an_unrelaxed_candidate()
relax(a, ref_db)
db.add_relaxed_step(a)
pop.update()
# Run the algorithm
for _ in xrange(num_gens):
if cc.converged():
print(’converged’)
break
for i in xrange(population_size):
a1, a2 = pop.get_two_candidates(with_history=False)
op = operation_selector.get_operator()
a3, desc = op.get_new_individual([a1, a2])
db.add_unrelaxed_candidate(a3, description=desc)
relax(a3, ref_db)
db.add_relaxed_step(a3)
pop.update()
# Print the current population to monitor the evolution
print([’-’.join(p.get_chemical_symbols()) for p in pop.pop])
226
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
In this script we run a generational GA as opposed to the pool GA outlined in Optimization with a Genetic
Algorithm. This is achieved by having two for-loops; the innermost loop runs the number of times specified by
the population size it corresponds to one generation. The outermost loop runs as many generations as specified in
num_gens. The function pop.update() is called after the innermost loop has finished thereby only adding
individuals to the population after a whole generation is calculated.
After each generation is finished the population is printed to the screen so we can follow the evolution. The
calculated individuals are continuously added to fcc_alloys.db, we can evaluate them directly by doing from
the command line (in another shell instance if the GA is still running):
$ ase-db fcc_alloys.db -c +atoms_string,raw_score,generation,hof -s raw_score
To prevent clutter we import the relax function from the following script:
import numpy as np
from
from
from
from
ase.lattice.cubic import FaceCenteredCubic
ase.calculators.emt import EMT
ase.utils.eos import EquationOfState
ase.db import connect
def relax(input_atoms, ref_db):
atoms_string = input_atoms.get_chemical_symbols()
# Open connection to the database with reference data
db = connect(ref_db)
# Load our model structure which is just FCC
atoms = FaceCenteredCubic(’X’, latticeconstant=1.)
atoms.set_chemical_symbols(atoms_string)
# Compute the average lattice constant of the metals in this individual
# and the sum of energies of the constituent metals in the fcc lattice
# we will need this for calculating the heat of formation
a = 0
ei = 0
for m in set(atoms_string):
dct = db.get(metal=m)
count = atoms_string.count(m)
a += count * dct.latticeconstant
ei += count * dct.energy_per_atom
a /= len(atoms_string)
atoms.set_cell([a, a, a], scale_atoms=True)
# Since calculations are extremely fast with EMT we can also do a volume
# relaxation
atoms.set_calculator(EMT())
eps = 0.05
volumes = (a * np.linspace(1 - eps, 1 + eps, 9))**3
energies = []
for v in volumes:
atoms.set_cell([v**(1. / 3)] * 3, scale_atoms=True)
energies.append(atoms.get_potential_energy())
eos = EquationOfState(volumes, energies)
v1, ef, B = eos.fit()
latticeconstant = v1**(1. / 3)
# Calculate the heat of formation by subtracting ef with ei
hof = (ef - ei) / len(atoms)
# Place the calculated parameters in the info dictionary of the
# input_atoms object
7.31. Genetic Algorithm
227
ASE Manual, Release 3.9.0.3865
input_atoms.info[’key_value_pairs’][’hof’] = hof
# Raw score must always be set
input_atoms.info[’key_value_pairs’][’raw_score’] = -hof
input_atoms.info[’key_value_pairs’][’latticeconstant’] = latticeconstant
# Setting the atoms_string directly for easier analysis
atoms_string = ’’.join(input_atoms.get_chemical_symbols())
input_atoms.info[’key_value_pairs’][’atoms_string’] = atoms_string
The relaxation script is naturally similar to the script we used to calculate the references.
Note that the global optimum is PtNi3 with a -0.11 eV heat of formation, whereas the second worst alloy is AlNi3
heat of formation 0.26 eV. This result is in complete contrast to the conclusion obtained in [JГіhannesson], where
AlNi3 is the most stable alloy within the phase space chosen here. Obviously there is a limit to the predictive
power of EMT!
Extending the algorithm
There are different ways one can extend the algorithm and make it more complex and sophisticated, all employed
in [Jensen]:
Extra mutation operators
Instead of only using random operations we can include some that mutates elements to other elements nearby in
the periodic table:
from
from
from
from
from
from
ase.ga.element_mutations import RandomElementMutation
ase.ga.element_mutations import MoveDownMutation
ase.ga.element_mutations import MoveUpMutation
ase.ga.element_mutations import MoveLeftMutation
ase.ga.element_mutations import MoveRightMutation
ase.ga.element_crossovers import OnePointElementCrossover
...
oclist = ([4,1,1,1,1,8], [RandomElementMutation([metals]),
MoveDownMutation([metals]),
MoveUpMutation([metals]),
MoveLeftMutation([metals]),
MoveRightMutation([metals]),
OnePointElementCrossover([metals])
mut_selector = MutationSelector(*oclist)
These operators takes advantage of the fact that chemically like elements (close in the periodic table) exhibit
similar properties and the substitution of one to a chemically similar elements could refine the properties of an
alloy in the population. A natural extension of these operators would be to use a different ordering of the elements
than the periodic table; e.g. Pettifor chemical scale, electronegativity, etc.
Note how we have set the probabilities for selecting operators differently.
The probability for
RandomElementMutation is equal to the sum of the move mutations. Similarly the probability of
OnePointElementCrossover is equal to the sum of all the mutation operators. This is to prevent the search
from being purely local.
Prevent identical calculations from being performed
In the current main script there is no check to determine whether an identical calculation has been performed, this
is easy to check in this regime where model structures are used and we can just use the atoms_string. We
insert the following in the inner loop:
228
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
for i in xrange(population_size):
dup = True
while dup:
a1, a2 = pop.get_two_candidates(with_history=False)
op = operation_selector.get_operator()
a3, desc = op.get_new_individual([a1, a2])
dup = db.is_duplicate(atoms_string=’’.join(a3.get_chemical_symbols()))
Since the fcc model structure is completely symmetric we could compare sorted versions of the atoms_string,
thereby ruling out individuals containing the same elements in different order.
Reuse of calculations between algorithm runs
Since genetic algorithms are inherently random in nature one can never be sure to obtain the global minimum with
only one algorithm run, it is customary to perform more runs and check that the results agree. In this case it is
vital to be able to reuse identical calculations between runs.
We do the following from the command line to create a new database file containing only the relaxed structures:
$ ase-db fcc_alloys.db relaxed=1 -i all_relaxed.db
We subsequently add this to the relaxation script:
def relax(input_atoms, ref_db):
atoms_string = input_atoms.get_chemical_symbols()
relaxed_db = connect(’all_relaxed.db’)
save_relax = True
try:
dct = relaxed_db.get(atoms_string=’’.join(atoms_string))
except KeyError:
# Open connection to the database with reference data
db = connect(ref_db)
# Omitting lines up to the point where hof has been calculated
...
else:
hof = dct.hof
latticeconstant = dct.latticeconstant
save_relax = False
# Place the calculated parameters in the info dictionary of the
# input_atoms object
...
# Put this at the very end
if save_relax:
relaxed_db.write(input_atoms,relaxed=1,
key_value_pairs=input_atoms.info[’key_value_pairs’])
Before the actual calculation is performed all_relaxed.db is checked to see if it has been calculated before; if
so we just collect the heat of formation, but if not we do the calculation and save it directly to all_relaxed.db.
Note: this addition assumes that Prevent identical calculations from being performed.
The GA implementation is diverse. It (or previous versions of it) has been used in publications with differing
subjects such as structure of gold clusters on surfaces, composition of alloy nanoparticles, ammonia storage in
mixed metal ammines and more. The implementation is structured such that it can be tailored to the specific
problem investigated and to the computational resources available (single computer or a large computer cluster).
The method is described in detail in the following publications:
For small clusters on/in support material in:
7.31. Genetic Algorithm
229
ASE Manual, Release 3.9.0.3865
L. B. Vilhelmsen and B. Hammer
A genetic algorithm for first principles global structure optimization of supported nano structures
The Journal of chemical physics, Vol. 141 (2014), 044711
For medium sized alloy clusters in:
S. Lysgaard, D. D. Landis, T. Bligaard and T. Vegge
Genetic Algorithm Procreation Operators for Alloy Nanoparticle Catalysts
Topics in Catalysis, Vol 57, No. 1-4, pp. 33-39, (2014)
A search for mixed metal ammines for ammonia storage have been performed using the GA in:
P. B. Jensen, S. Lysgaard, U. J. Quaade and T. Vegge
Designing Mixed Metal Halide Ammines for Ammonia Storage Using Density Functional Theory
and Genetic Algorithms
Physical Chemistry Chemical Physics, Vol 16, No. 36, pp. 19732-19740, (2014)
A simple tutorial explaining how to set up a database and perform a similar search can be found here: GA Search
for stable FCC alloys
7.32 Dimer method
The dimer method is a means of finding a saddle point on a potential energy surface starting from a single point
(as opposed to a NEB calculation, which requires an initial and final state). You can read about this method here:
1. �A dimer method for finding saddle points on high dimensional potential surfaces using only first derivatives’, G. Henkelman and H. Jonsson, J. Chem. Phys. 111, 7010, 1999.
An example is shown below.
from
from
from
from
ase.lattice.surface import fcc100, add_adsorbate
ase.constraints import FixAtoms
ase.calculators.emt import EMT
ase.dimer import DimerControl, MinModeAtoms, MinModeTranslate
# Set up a small "slab" with an adatoms
atoms = fcc100(’Pt’, size = (2, 2, 1), vacuum = 10.0)
add_adsorbate(atoms, ’Pt’, 1.611, ’hollow’)
# Freeze the "slab"
mask = [atom.tag > 0 for atom in atoms]
atoms.set_constraint(FixAtoms(mask = mask))
# Calculate using EMT
atoms.set_calculator(EMT())
relaxed_energy = atoms.get_potential_energy()
# Set up the dimer
d_control = DimerControl(initial_eigenmode_method = ’displacement’, \
displacement_method = ’vector’, logfile = None, \
mask = [0, 0, 0, 0, 1])
d_atoms = MinModeAtoms(atoms, d_control)
# Displace the atoms
displacement_vector = [[0.0]*3]*5
displacement_vector[-1][1] = -0.1
d_atoms.displace(displacement_vector = displacement_vector)
# Converge to a saddle point
dim_rlx = MinModeTranslate(d_atoms, trajectory = ’dimer_method.traj’, \
logfile = None)
dim_rlx.run(fmax = 0.001)
230
Chapter 7. Documentation for modules in ASE
ASE Manual, Release 3.9.0.3865
The module contains several classes.
class ase.dimer.DimerControl(logfile=’-�, eigenmode_logfile=None, **kwargs)
A class that takes care of the parameters needed for a Dimer search.
Parameters:
eigenmode_method: str The name of the eigenmode search method.
f_rot_min: float Size of the rotational force under which no rotation will be performed.
f_rot_max: float Size of the rotational force under which only one rotation will be performed.
max_num_rot: int Maximum number of rotations per optimizer step.
trial_angle: float Trial angle for the finite difference estimate of the rotational angle in radians.
trial_trans_step: float Trial step size for the MinModeTranslate optimizer.
maximum_translation: float Maximum step size and forced step size when the curvature is still positive
for the MinModeTranslate optimizer.
cg_translation: bool Conjugate Gradient for the MinModeTranslate optimizer.
use_central_forces: bool Only calculate the forces at one end of the dimer and extrapolate the forces to
the other.
dimer_separation: float Separation of the dimer’s images.
initial_eigenmode_method: str How to construct the initial eigenmode of the dimer. If an eigenmode is
given when creating the MinModeAtoms object, this will be ignored. Possible choices are: �gauss’
and �displacement’
extrapolate_forces: bool When more than one rotation is performed, an extrapolation scheme can be used
to reduce the number of force evaluations.
displacement_method: str How to displace the atoms. Possible choices are �gauss’ and �vector’.
gauss_std: float The standard deviation of the gauss curve used when doing random displacement.
order: int How many lowest eigenmodes will be inverted.
mask: list of bool Which atoms will be moved during displacement.
displacement_center: int or [float, float, float] The center of displacement, nearby atoms will be displaced.
displacement_radius: float When choosing which atoms to displace with the displacement_center keyword, this decides how many nearby atoms to displace.
number_of_displacement_atoms: int The amount of atoms near displacement_center to displace.
class ase.dimer.MinModeAtoms(atoms, control=None, eigenmodes=None, random_seed=None,
**kwargs)
Wrapper for Atoms with information related to minimum mode searching.
Contains an Atoms object and pipes all unknown function calls to that object. Other information that is
stored in this object are the estimate for the lowest eigenvalue, curvature, and its corresponding eigenmode, eigenmode. Furthermore, the original configuration of the Atoms object is stored for use in multiple
minimum mode searches. The forces on the system are modified by inverting the component along the
eigenmode estimate. This eventually brings the system to a saddle point.
Parameters:
atoms [Atoms object] A regular Atoms object
control [MinModeControl object] Contains the parameters necessary for the eigenmode search. If no control object is supplied a default DimerControl will be created and used.
mask: list of bool Determines which atoms will be moved when calling displace()
7.32. Dimer method
231
ASE Manual, Release 3.9.0.3865
random_seed: int The seed used for the random number generator. Defaults to modified version the current time.
References:
class ase.dimer.MinModeTranslate(atoms, logfile=’-�, trajectory=None)
An Optimizer specifically tailored to minimum mode following.
class ase.dimer.DimerEigenmodeSearch(atoms, control=None, eigenmode=None, basis=None,
**kwargs)
An implementation of the Dimer’s minimum eigenvalue mode search.
This class implements the rotational part of the dimer saddle point searching method.
Parameters:
atoms: MinModeAtoms object MinModeAtoms is an extension to the Atoms object, which includes information about the lowest eigenvalue mode.
control: DimerControl object Contains the parameters necessary for the eigenmode search. If no control
object is supplied a default DimerControl will be created and used.
basis: list of xyz-values Eigenmode. Must be an ndarray of shape (n, 3). It is possible to constrain the
eigenmodes to be orthogonal to this given eigenmode.
Notes:
The code is inspired, with permission, by code written by the Henkelman group, which can be found at
http://theory.cm.utexas.edu/vtsttools/code/
References:
•Henkelman and Jonsson, JCP 111, 7010 (1999)
•Olsen, Kroes, Henkelman, Arnaldsson, and Jonsson, JCP 121, 9776 (2004).
•Heyden, Bell, and Keil, JCP 123, 224101 (2005).
•Kastner and Sherwood, JCP 128, 014106 (2008).
232
Chapter 7. Documentation for modules in ASE
CHAPTER
EIGHT
FREQUENTLY ASKED QUESTIONS
8.1 ASE-GUI
See also the documentation for ase-gui.
8.1.1 How do I export images from a trajectory to png or pov files?
With ase-gui, you can choose File в†’ Save, but this is not fun if you need to do it for many images. Here is how to
do it on the command line for a number of images:
ase-gui images.traj@0 -o image0.pov
ase-gui images.traj@1 -o image1.pov
ase-gui images.traj@2 -o image2.pov
If you have many images, it will be easier to do it using the Python interpreter:
>>> from ase import *
>>> for n, image in enumerate(read(’images.traj@:3’)):
...
write(’image%d.pov’ % n, image, run_povray=True, pause=False,
...
rotation=’-90x,10z’)
Here, we also:
• run povray to generate png files
• disable pausing between the images
• set a rotation (choose View → Rotate ... in ase-gui to select the best rotation angles)
Try:
>>> help(write)
to see all possibilities or read more here.
8.2 General
8.2.1 Citation: how should I cite ASE?
If you find ASE useful in your research please cite:
S. R. Bahn and K. W. Jacobsen
An object-oriented scripting interface to a legacy electronic structure code
Comput. Sci. Eng., Vol. 4, 56-66, 2002
BibTex (doc/ASE.bib):
233
ASE Manual, Release 3.9.0.3865
@Article{ISI:000175131400009,
Author = {S. R. Bahn and K. W. Jacobsen},
Title = {An object-oriented scripting interface to a legacy electronic structure code},
JournalFull = {COMPUTING IN SCIENCE \& ENGINEERING},
Year = {2002},
Volume = {4},
Number = {3},
Pages = {56-66},
Month = {MAY-JUN},
Abstract = {The authors have created an object-oriented scripting interface to a mature density fu
code. The interface gives users a high-level, flexible handle on the code without rewriting the
underlying number-crunching code. The authors also discuss the design issues and advantages of
homogeneous interfaces},
Publisher = {IEEE COMPUTER SOC},
Address = {10662 LOS VAQUEROS CIRCLE, PO BOX 3014, LOS ALAMITOS, CA 90720-1314 USA},
Type = {Article},
Language = {English},
Affiliation = {Bahn, SR (Reprint Author), Tech Univ Denmark, Dept Phys, CAMP, Bldg 307, DK-2800 Ly
Tech Univ Denmark, Dept Phys, CAMP, DK-2800 Lyngby, Denmark.},
ISSN = {1521-9615},
Keywords-Plus = {MULTISCALE SIMULATION; GOLD ATOMS},
Subject-Category = {Computer Science, Interdisciplinary Applications},
Author-Email = {[email protected] [email protected]},
Number-of-Cited-References = {19},
Journal-ISO = {Comput. Sci. Eng.},
Journal = {Comput. Sci. Eng.},
Doc-Delivery-Number = {543YL},
Unique-ID = {ISI:000175131400009},
DOI = {10.1109/5992.998641},
}
8.3 Download
Trying to checkout the code via SVN resulted:
[~]$ svn checkout "https://svn.fysik.dtu.dk/projects/ase/trunk"
svn: Unrecognized URL scheme ’https://svn.fysik.dtu.dk/projects/ase/trunk’
This error is diplayed in case the library �libsvn_ra_dav’ is missing on your system. The library is used by SVN,
but is not installed by default.
234
Chapter 8. Frequently Asked Questions
CHAPTER
NINE
GLOSSARY
API Application Programming Interface. Automatically generated documentation from docstrings in the source
code using Epydoc. See here.
ASE Atomic Simulation Environment.
Class XXX
Constructor XXX
Docstring XXX
DFT Density Functional Theory.
EMT Effective Medium Theory.
HF Hartree-Fock approximation XXX ...
Instance XXX
LAPW In the linearized augmented plane wave (LAPW) method the unit cell of the crystal is divided into two
different types of regions. The first one, called the muffin-tin region, consists of spheres centered around
the atoms, while the second one, called the interstitial region consists of the remaining part of the unit cell.
In the muffin-tin spheres the basis consists of atomic like functions to account for the rapid changes of the
wave function in this area, whereas in the interstitial region the basis functions are plane waves, since the
wave function changes only slowly at some distance from the atomic sites.
Namespace An abstract container of the current scope�s variables.
ndarray NumPy�s n-dimensional array. See Numeric arrays in Python.
NumPy XXX See Numeric arrays in Python.
Method XXX
Python XXX What is Python?.
Scope An enclosing context where values and expressions are associated.
235
ASE Manual, Release 3.9.0.3865
236
Chapter 9. Glossary
CHAPTER
TEN
MAILING LISTS
There is a mailing list for discussing ASE:
• ase-users
The mailing lists below are of interest for active ASE developers only:
• ase-developers
• ase-svncheckins
or (mainly) dacapo / ASE-2 users / developers:
• campos
• campos-devel
10.1 Internet Relay Chat
We have the IRC channel #campos on FreeNode. Please join us if you have any questions. For easy access, you
can use this webclient.
237
ASE Manual, Release 3.9.0.3865
238
Chapter 10. Mailing Lists
CHAPTER
ELEVEN
LICENSE
Contents
• License
– Human-readable version
– Legal version of the license
– What happens when ASE Calculators are under another license?
11.1 Human-readable version
ASE is released under the GNU Lesser General Public License (LGPL). In short, this means
• NO WARRANTY: We provide the code free of charge. You cannot sue us if it does not work, gives wrong
results, or even if it damages your computer and/or scientific reputation.
• You may use the code for whatever you like. You may study and modify it.
• You may distribute distribute modified or unmodified versions of ASE as long as you do it under the LGPL
(or GPL) licence. You may distribute unmodified versions of ASE together with software under other
licences (even commercial) as long as ASE itself is clearly identified as being under the LGPL, but if you
modify ASE for such purposes you are required to make the modifications available under the LGPL.
Note that we appreciate that you send modifications, bug fixes and improvements back to us instead of just distributing them, but the license has no such requirements.
You can read more about the LGPL on Wikipedia.
11.2 Legal version of the license
Please read the full text of the GNU Lesser General Public License (as published by the Free Software Foundation).
11.3 What happens when ASE Calculators are under another license?
We are sometimes asked if it is problematic to use ASE together with calculators under other licenses, for example
GPL. It is clear that a program under the GPL can use a library under the LGPL, whereas a program under the
LGPL cannot be derived from (and link) a library under the GPL. Does this cause a problem if someone uses ASE
with a calculator such as GPAW licensed under the GPL? We do not think so, for the following reasons:
1. The LGPL and GPL do not limit how you use the codes, only how you distribute them.
239
ASE Manual, Release 3.9.0.3865
2. ASE does not require any specific calculator to function, but many calculators require ASE to function,
supporting the interpretation that ASE is a library for the calculator.
3. Although ASE includes a few cases where it imports calculators such as GPAW and Asap, these can be
regarded as “hooks” helping ASE to support these calculators, ASE does not depend on these calculators
for its functionality.
4. The LGPL / GPL concept of “derived work” relies on the concept of “linking” which only makes sense
in compiled languages. It is generally agreed that it is unproblematic when an interpreted language uses
different modules under different licenses. See e.g. this statement by Fedora: Mere use of independent
modules in a true interpreted language environment (like Perl or Python) is not a situation where Fedora
is generally concerned about license compatibility, as long as those multiply licensed modules are not
compiled together into a single binary and there is no code copying between the two.
5. The actual executable doing the linkage is not ASE, but Python. However, nobody doubts that it is OK for
Python (which has a very permissible license) to load modules licensed under the GPL. Probably because
of point 1 above.
6. Point 5 is not valid when running parallel GPAW or Asap calculations. In these cases GPAW and Asap
provide specially built Python executables with the GPAW or Asap code built-in, i.e. derived work based on
Python but licensed under the GPL (or LGPL for Asap). In these cases it is absolutely clear that it is GPAW
or Asap loading ASE, not the other way around; so there are no problems.
240
Chapter 11. License
CHAPTER
TWELVE
ASE DEVELOPMENT
As a developer, you should subscribe to all ASE related Mailing Lists.
12.1 Development topics
12.1.1 Release notes
Development version in trunk
trunk.
• Genetic algorithm implemented; ase.ga. This can be used for the optimization of: atomic cluster structure, materials properties by use of template structures. Extension to other projects related to atomic simulations should be straightforward.
• The ase.lattice.bulk() function can now build the Wurtzite structure.
Version 3.8.0
22 October 2013: tags/3.8.0.
• ASE’s gui renamed from ag to ase-gui.
• New STM module.
• Python 2.6 is now a requirement.
• The old ase.structure.bulk() function is now deprecated.
(ase.lattice.bulk()).
Use the new one instead
• We’re now using BuildBot for continous integration: https://ase-buildbot.fysik.dtu.dk/waterfall
• New interface to the JDFTx code.
Version 3.7.0
13 May 2013: tags/3.7.0.
• ASE’s GUI can now be configured to be more friendly to visually impaired users: High contrast settings
for ase-gui.
• The ase.neb.NEB object now accepts a list of spring constants.
• Important backwards incompatible change: The ase.lattice.surface.surface() function now
returns a right-handed unit cell.
• Mopac, NWChem and Gaussian interfaces and EAM potential added.
241
ASE Manual, Release 3.9.0.3865
• New set_initial_charges() and get_initial_charges() methods. The get_charges()
method will now ask the calculator to calculate the atomic charges.
• The Calculator interface proposal has been implemented and 6 ASE calculators are now based on the new
base classes.
• ASE now runs on Windows and Mac.
• Constrained minima hopping (global optimization) added to ASE.
Version 3.6.0
24 Feb 2012: tags/3.6.0.
• ASE GUI translations added, available: da_DK, en_GB, es_ES.
• New function for making surfaces with arbitrary Miller indices with the smallest possible surface unit cell:
ase.lattice.surface.surface()
• New ase.lattice.bulk() function. Will replace old ase.structure.bulk() function. The new one will produce
a more natural hcp lattice and it will use experimental data for crystal structure and lattice constants if not
provided explicitely.
• New values for ase.data.covalent_radii from Cordeo et al..
• New command line tool: Command line tool and tests based on it: abinit, elk, fleur, nwchem.
• New crystal builder for ase-gui
• Van der Waals radii in ase.data
• ASE’s GUI (ase-gui) now supports velocities for both graphs and coloring
• Cleaned up some name-spaces:
– ase now contains only Atoms and Atom
– ase.calculators is now empty
Version 3.5.1
24 May 2011: tags/3.5.1.
• Problem with parallel vibration calculations fixed: Ticket #80.
Version 3.5.0
13 April 2011: tags/3.5.0.
• Improved EMT potential: uses a NeighborList object and is now ASAP compatible.
• BFGSLineSearch is now the default (QuasiNewton==BFGSLineSearch).
• There is a new interface to the LAMMPS molecular dynamics code.
• New phonons module.
• Van der Waals corrections for DFT, see GPAW usage.
• New BundleTrajectory added.
• Updated GUI interface:
– Stability and usability improvements.
– Povray render facility.
– Updated expert user mode.
242
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
– Enabled customization of colours and atomic radii.
– Enabled user default settings via ~/.ase/gui.py.
• Database library expanded to include:
– The s22, s26 and s22x5 sets of van der Waals bonded dimers and complexes by the Hobza group.
– The DBH24 set of gas-phase reaction barrier heights by the Truhlar group.
• Implementation of the Dimer method.
Version 3.4.1
11 August 2010: tags/3.4.1.
12.1.2 How to contribute
Discussion of ASE development takes place on the ase-developer mailing list, and also sometimes on the #gpaw
IRC channel on freenode.
We welcome new developers who would like to help work on improving ASE. If you would like to contribute,
your should first tell us what you want to work on. Use the mailing list for that.
SVN access
We don’t give new contributers write access to our SVN repository from day one. So, you will have to create a
patch and send it to the mailing list:
$
$
$
$
svn checkout https://svn.fysik.dtu.dk/projects/ase/trunk myase
cd myase
# do your thing ...
svn diff > patch.txt
Before you send the patch, please read our Coding Conventions and learn how to use pep8.py, pylint and epydoc:
• Run pep8.py on your code
• Using pylint to check your code
• Run epydoc on your code
One of the current committers will look at the patch and give you some feedback. Maybe the patch is fine and the
committer will commit it to trunk. There could also be some more work to do like:
• make it compatible with all supported pythons (see Installation requirements).
• write more comments
• fix docstrings
• write a test
• add some documentation
Once everyone is happy, the patch can be applied. This patch-feedback loop is not something we have invented to
prevent you from contributing - it should be viewed as an opportunity for you to learn how to write code that fits
into the ASE codebase.
After a couple of contributions, we will probably trust you enough to add you as a committer.
Committers
Here is the list of current committers:
12.1. Development topics
243
ASE Manual, Release 3.9.0.3865
user name
anpet
askhl
bjork
dlandis
dulak
eojons
ehermes
gdonval
getri
grabow
hahansen
ivca
jakobb
jber
jblomqvist
jensj
jesperf
jesswe
jingzhe
jkitchin
jussie
kkaa
kleis
kwj
lassebv
markus
miwalter
moses
mvanin
pastewka
s032082
schenkst
schiotz
slabanja
strange
tjiang
tolsen
real name
Andrew Peterson
Ask Hjorth Larsen
Jonas Bjork
David Landis
Marcin Dulak
Elvar Г–rn JГіnsson
Eric Hermes
GaГ«l Donval
George Tritsaris
Lars Grabow
Heine Anton Hansen
Ivano Eligio Castelli
Jakob Blomquist
Jon Bergmann Maronsson
Janne Blomqvist
Jens JГёrgen Mortensen
Jesper Friis
Jess Wellendorff Pedersen
Jingzhe Chen
John Kitchin
Jussi Enkovaara
Kristen Kaasbjerg
Jesper Kleis
Karsten Wedel Jacobsen
Lasse Vilhelmsen
Markus Kaukonen
Michael Walter
Poul Georg Moses
Marco Vanin
Lars Pastewka
Christian Glinsvad
Stephan Schenk
Jakob Schiotz
Mattias Slabanja
Mikkel Strange
Tao Jiang
Thomas Olsen
andrew_peterson:brown,edu
asklarsen:gmail,com
jonbj:ifm,liu,se
dlandis:fysik,dtu,dk
dulak:fysik,dtu,dk
elvar,jonsson:fysik,dtu,dk
ehermes:chem,wisc,edu
gael,donval:cnrs-imn,fr
gtritsaris:seas,harvard,edu
grabow:uh,edu
hahansen:fysik,dtu,dk
ivca:fysik,dtu,dk
jakobb:fysik,dtu,dk
jber:fysik,dtu,dk
Janne,Blomqvist:tkk,fi
jensj:fysik,dtu,dk
jesper,friis:sintef,no
jesswe:fysik,dtu,dk
jingzhe:fysik,dtu,dk
jkitchin:andrew,cmu,edu
jussi,enkovaara:csc,fi
kkaa:fysik,dtu,dk
kleis:fysik,dtu,dk
kwj:fysik,dtu,dk
lassebv:phys,au,dk
markus,kaukonen:iki,fi
Michael,Walter:fmf,uni-freiburg,de
poulgeorgmoses:gmail,com
mvanin:fysik,dtu,dk
lars,pastewka:iwm,fraunhofer,de
s032082:fysik,dtu,dk
stephan,schenk:basf,com
schiotz:fysik,dtu,dk
slabanja:chalmers,se
mikkel,strange:gmail,com
tjiang:fysik,dtu,dk
tolsen:fysik,dtu,dk
Former committers:
anro
carstenr
hanke
s042606
s052580
Anthony Goodrow
Carsten Rostgaard
Felix Hanke
Janosch Michael Rauba
Troels Kofoed Jacobsen
anro:fysik,dtu,dk
carstenr:fysik,dtu,dk
F,Hanke:liverpool,ac,uk
s042606:fysik,dtu,dk
s052580:fysik,dtu,dk
12.1.3 Using version control (SVN)
The version control system used in ASE development is subversion. A thorough subversion manual can be found
at http://svnbook.red-bean.com/, here is a brief overview of the most basic features needed when developing ASE.
• perform svn checkout of ase.
Place it, for example, in ase-svn directory:
244
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
cd
svn checkout https://svn.fysik.dtu.dk/projects/ase/trunk ase-svn
This retrieves the code tree from the subversion repository. Prepend PYTHONPATH and PATH environment
variables as described at Manual installation.
• Updating the working copy of the code (in the directory ase-svn):
svn update
After each (important) update, remove ase/svnrevision.py* files, and run:
python setup.py sdist
to keep the ase/svnrevision.py file up-to-date.
• Checking the status of the working copy (in the directory ase-svn):
svn stat
The status about the files which are not in version control can be surpassed with the -q flag, and the status
with respect to latest additions in server can be checked with the -u flag.
• Committing the changes to the repository
Before sending the changes in the working copy to the repository, working copy should be updated. After
that, the changes can be send with:
svn commit -m "Message to describe the committed changes"
If the -m option is omitted and appropriate environment variable SVN_EDITOR is set, an editor is opened
for writing the log message.
• Adding files or directories to version control:
svn add filename
If filename is directory, also all the files within the directory are added. Note that svn commit is
required before the new files are actually included in version control.
• ASE documentation resides under doc directory, and is also under subversion control. See more at Writing
documentation.
12.1.4 Coding Conventions
Importing modules
In code, like the implementation of ASE, we must not use the import * syntax. Import everything explicitly
from exactly the place where it’s defined:
from ase.io import read, write
We distinguish between scripts and code. In your own scripts, it’s OK to use:
from ase.all import *
which will give you the most used symbols.
Python Coding Conventions
Please run pep8.py and pylint on your code before committing.
The rules for the Python part are almost identical to those used by the Docutils project:
12.1. Development topics
245
ASE Manual, Release 3.9.0.3865
Contributed code will not be refused merely because it does not strictly adhere to these conditions; as long as it’s
internally consistent, clean, and correct, it probably will be accepted. But don’t be surprised if the “offending”
code gets fiddled over time to conform to these conventions.
The project shall follow the generic coding conventions as specified in the Style Guide for Python Code and
Docstring Conventions PEPs, summarized, clarified, and extended as follows:
• 4 spaces per indentation level. No hard tabs.
• Very important: Read the Whitespace in Expressions and Statements section of PEP8.
• Avoid introducing trailing whitespaces.
• Try to use only 7-bit ASCII, no 8-bit strings.
• No one-liner compound statements (i.e., no if x: return: use two lines & indentation), except for
degenerate class or method definitions (i.e., class X: pass is OK.).
• Lines should be no more than 78 characters long.
• Use “StudlyCaps” for class names.
• Use “lowercase” or “lowercase_with_underscores” for function, method, and variable names. For short
names, maximum two words, joined lowercase may be used (e.g. “tagname”). For long names with three or
more words, or where it’s hard to parse the split between two words, use lowercase_with_underscores (e.g.,
“note_explicit_target”, “explicit_target”). If in doubt, use underscores.
• Avoid lambda expressions, which are inherently difficult to understand. Named functions are preferable
and superior: they’re faster (no run-time compilation), and well-chosen names serve to document and aid
understanding.
• Avoid functional constructs (filter, map, etc.). Use list comprehensions instead.
• Avoid from __future__ import constructs. They are inappropriate for production code.
• Use �single quotes’ for string literals, and “”“triple double quotes”“” for docstrings. Double quotes are OK
for something like "don’t".
Attention: Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the
number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent,
nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.
Georg Brandl
General advice
• Get rid of as many break and continue statements as possible.
Writing documentation in the code
Here is an example of how to write good docstrings:
https://github.com/numpy/numpy/blob/master/doc/example.py
Run pep8.py on your code
The pep8.py program is installed together with ASE tools/pep8.py. It will check the PEP8 conventions for you.
Try:
$ pep8.py --help
246
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
Using pylint to check your code
A pylintrc trying to follow ASE Coding Conventions can be found here: doc/development/pylintrc
Running pylint yourself
Run pylint on a single file like this:
[~]$ pylint mypythonfile.py
Run pylint on a module like this:
[~]$ pylint path/to/module/root/dir
Run epydoc on your code
Run:
$ epydoc --docformat restructuredtext --parse-only --show-imports -v dir
12.1.5 Writing documentation
We use the Sphinx tool to generate the documentation (both HTML and PDF). The documentation is stored in
SVN as text files in the doc directory using the reStructuredText markup language.
Installing Docutils and Sphinx
The reStructuredText parser that Sphinx needs, is part of the Docutils project. So, we need to install docutils and
sphinx (version>= 0.5).
Other requirements
When building the documentation, a number of png-files are generated. For that to work, you need the following
installed:
• matplotlib
• povray
• dvipng
• pdflatex
• bibtex
• AUCTex
• convert (ImageMagick)
Using Sphinx
First, you should take a look at the documentation for Sphinx and reStructuredText.
If you don’t already have your own copy of the ASE package, then get the Latest development release and install
it.
Then cd to the doc directory and build the html-pages:
12.1. Development topics
247
ASE Manual, Release 3.9.0.3865
$ cd ~/ase/doc
$ sphinx-build . _build
Note: Make sure that you build the Sphinx documentation using the corresponding ASE version by setting the
environment variables $PYTHONPATH and $PATH.
Make your changes to the .rst files, run the sphinx-build command again, check the results and if things looks
ok, commit:
$
$
$
$
emacs index.rst
sphinx-build . _build
firefox _build/index.html
svn ci -m "..." index.rst
To build a pdf-file, you do this:
$ sphinx-build -b latex . _build
$ cd _build
$ make ase-manual.pdf
Extensions to Sphinx
We have a couple of extensions to Sphinx:
:mol:
Use :mol:�CH_3OH� to get CH3 OH.
:svn:
A role for creating a link to a file in SVN. If you write :svn:�ase/atoms.py�, you will get:
ase/atoms.py.
:trac:
A role for creating a link to a file in Trac. If you write :trac:�ase/atoms.py�, you will get:
ase/atoms.py.
:epydoc:
A role for creating a link to the API-documentation generated with epydoc.
:epydoc:�ase.atoms.Atoms�, you will get: Atoms.
If you write
:math:
This role is for inline LaTeX-style math. Example: :math:�\sin(x_n^2)� gives you sin(x2n ).
This role is actually the default for ASE’s documentation, so you can leave out the :math: part like
here: �\sin(x_n^2)�.
.. math::
Write displayed LaTeX-style math. Example:
.. math:: \frac{1}{1+x^2}
gives you:
1
1 + x2
248
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
Running Python code to create figures
If you want to include a picture in your page, you should not check in the png-file to our SVN repositoy! Instead,
you should check in the Python script you used to generate the picture (you can also generate csv-files or pdf-files
like this). The first line of the script should look like this:
# creates: fig1.png fig2.png table1.csv
Sphinx will run the script and generate the files that you can then use in your rst-file. Examples:
• Equation of state. Source: doc/tutorials/eos/eos.py, doc/tutorials/eos/eos.rst
• Finding lattice constants. Source: doc/tutorials/lattice_constant.py, doc/tutorials/lattice_constant.rst
reStructedText in emacs
For people using emacs, the reStructuredText extension is highly recommended. The intallation procedure is
described in the top of the file, but for most people, it is enough to place it in your emacs load-path (typically
.emacs.d/) and add the lines:
(add-to-list ’load-path "~/.emacs.d")
(require ’rst)
somewhere in your .emacs file.
To make the mode auto load for relevant file extension, you can write something like:
(setq auto-mode-alist
(append ’(("\\.rst$" . rst-mode)
("\\.rest$" . rst-mode)) auto-mode-alist))
In your .emacs file.
Updating Sphinx
Starting a new project with sphinx requires an initial configuration. This is achieved by running sphinxquickstart. When updating from a very old sphinx you may consider generating new configuration files and
updating the old files accordingly.
Note that the current project is configured up-to-date, so if you are “simply” writing the documentation you must
skip the sphinx-quickstart step and focus on Using Sphinx.
Here is how do you setup the GPAW project with sphinx:
• cd to the doc directory,
• run sphinx-quickstart and answer the questions (example given for GPAW):
> Root path for the documentation [.]:
> Separate source and build directories (y/N) [n]:
> Name prefix for templates and static dir [.]: _
> Project name: GPAW
> Author name(s): 2008, CAMd et al.
> Project version: 0.5
> Project release [0.5]:
> Source file suffix [.rst]:
> Name of your master document (without suffix) [index]: contents
12.1. Development topics
249
ASE Manual, Release 3.9.0.3865
> autodoc: automatically insert docstrings from modules (y/N) [n]: y
> doctest: automatically test code snippets in doctest blocks (y/N) [n]:
> intersphinx: link between Sphinx documentation of different projects (y/N) [n]: y
This will create doc/conf.py and doc/contents.rst. Both these files need to be edited further
(doc/conf.py may for example include options for sphinx.ext.pngmath)
12.1.6 Adding new calculators
Adding an ASE interface to your favorite force-calculator is very simple. Take a look at the Calculator and
FileIOCalculator classes below (the code is here: ase/calculators/calculator.py). You should inherit from
the FileIOCalculator and implement the read(), read_results() and write_input() methods.
The methods set(), check_state() and set_label() may also need to be implemented.
See Also:
• The code for our Abinit interface: ase/calculators/abinit.py
• Calculator interface proposal
• ase.calculators
Description of base-classes
The Calculator base-class
class ase.calculators.calculator.Calculator(restart=None,
ignore_bad_restart_file=False, label=None,
atoms=None, **kwargs)
Base-class for all ASE calculators.
A calculator must raise NotImplementedError if asked for a property that it can’t calculate. So, if calculation
of the stress tensor has not been implemented, get_stress(atoms) should raise NotImplementedError. This
can be achieved simply by not including the string �stress’ in the list implemented_properties which is a class
member. These are the names of the standard properties: �energy’, �forces’, �stress’, �dipole’, �charges’,
�magmom’ and �magmoms’.
Basic calculator implementation.
restart: str Prefix for restart file. May contain a directory. Default is None: don’t restart.
ignore_bad_restart_file: bool Ignore broken or missing restart file. By default, it is an error if the restart
file is missing or broken.
label: str Name used for all files. May contain a directory.
atoms: Atoms object Optional Atoms object to which the calculator will be attached. When restarting,
atoms will get its positions and unit-cell updated from file.
implemented_properties = []
Properties calculator can handle (energy, forces, ...)
default_parameters = {}
Default parameters
set_label(label)
Set label and convert label to directory and prefix.
Examples:
•label=’abc’: (directory=’.’, prefix=’abc’)
•label=’dir1/abc’: (directory=’dir1’, prefix=’abc’)
250
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
Calculators that must write results to files with fixed names can overwrite this method so that the
directory is set to all of label.
reset()
Clear all information from old calculation.
read(label)
Read atoms, parameters and calculated properties from output file.
Read result from self.label file. Raise ReadError if the file is not there. If the file is corrupted or
contains an error message from the calculation, a ReadError should also be raised. In case of succes,
these attributes must set:
atoms: Atoms object The state of the atoms from last calculation.
parameters: Parameters object The parameter dictionary.
results: dict Calculated properties like energy and forces.
The FileIOCalculator.read() method will typically read atoms and parameters and get the results dict
by calling the read_results() method.
set(**kwargs)
Set parameters like set(key1=value1, key2=value2, ...).
A dictionary containing the parameters that have been changed is returned.
Subclasses must implement a set() method that will look at the chaneged parameters and decide if a
call to reset() is needed. If the changed parameters are harmless, like a change in verbosity, then there
is no need to call reset().
The special keyword �parameters’ can be used to read parameters from a file.
check_state(atoms, tol=1e-15)
Check for system changes since last calculation.
calculate(atoms=None, properties=[’energy’], system_changes=[’positions’, �numbers’, �cell’,
�pbc’, �initial_charges’, �initial_magmoms’])
Do the calculation.
properties: list of str List of what needs to be calculated. Can be any combination of �energy’,
�forces’, �stress’, �dipole’, �charges’, �magmom’ and �magmoms’.
system_changes: list of str List of what has changed since last calculation. Can be any combination
of these five: �positions’, �numbers’, �cell’, �pbc’, �initial_charges’ and �initial_magmoms’.
Subclasses need to implement this, but can ignore properties and system_changes if they want. Calculated properties should be inserted into results dictionary like shown in this dummy example:
self.results = {’energy’: 0.0,
’forces’: np.zeros((len(atoms), 3)),
’stress’: np.zeros(6),
’dipole’: np.zeros(3),
’charges’: np.zeros(len(atoms)),
’magmom’: 0.0,
’magmoms’: np.zeros(len(atoms))}
The subclass implementation should first call this implementation to set the atoms attribute.
calculate_numerical_forces(atoms, d=0.001)
Calculate numerical forces using finite difference.
All atoms will be displaced by +d and -d in all directions.
12.1. Development topics
251
ASE Manual, Release 3.9.0.3865
The FileIOCalculator class
class ase.calculators.calculator.FileIOCalculator(restart=None,
ignore_bad_restart_file=False,
label=None, atoms=None, command=None, **kwargs)
Base class for calculators that write/read input/output files.
File-IO calculator.
command: str Command used to start calculation.
command = None
Command used to start calculation
write_input(atoms, properties=None, system_changes=None)
Write input file(s).
Call this method first in subclasses so that directories are created automatically.
read_results()
Read energy, forces, ... from output file(s).
12.1.7 Making movies
using recordmydesktop
A video tutorial can be produced in the following way:
• change the screen resolution to 1280x1024,
• record the movie of the screen (without sound) using recordmydesktop (gtk-recordMyDesktop),
• convert the resulting ogv into avi using mencoder:
mencoder video.ogv -o video.avi -oac copy -ovc lavc
• record and edit the sound track using audacity:
– use 44100 Hz for recording and save the final file as sound.wav,
– make sure not to keep the microphone to close to avoid signal peaks,
– cut microphone signal peaks, insert silences, ...
• edit the movie using avidemux (to match the sound track):
– load the video.avi: File → Open, make sure to use the following options when editing and saving:
Video в†’ Copy, Audio в†’ Copy, Format в†’ AVI,
– add the sound.avi: Audio → Main Track → Audio Source → External WAV,
– cut video frames (or copy and insert still frames to extend the video) to match the sound track. Set
beginning mark and end mark - the cut or copy/paste operation applies to the selected region,
– make sure to save intermediate stages when working on the video File → Save → Save Video (as AVI):
* avidemux caches the audio track so to match the audio to a freshly cut video you can copy the
audio file into another name, and add the sound track from that name,
* sometimes when cutting frames avidemux does not allow to set the markers correctly, and there
is no undo the last step in avidemux!
– save the video_final.avi (that matches the sound track), and encode it into mpeg4 format using mencoder, using two passes:
252
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
opt="vbitrate=550:mbd=2:dc=10 -vf unsharp=l:0.4:c:0.0:hqdn3d"
mencoder -ovc lavc -lavcopts vcodec=msmpeg4v2:vpass=1 -nosound -o /dev/null video_final.a
mencoder video_final.avi -oac mp3lame -af resample=32000:0:2 -lameopts vbr=3:br=80:mode=3
-ovc lavc -lavcopts acodec=mp3lame:vcodec=msmpeg4v2:vpass=2:$opt \
-info name="Overview and installation of ASE":artist=CAMd:copyright="CAMd 2009" -
– convert video_final.avi into a 800x600 swf file for streaming:
ffmpeg -i video_final.avi -pass 1 -s
-vcodec flv -b:v 1200k -g 160
ffmpeg -i video_final.avi -pass 2 -s
-vcodec flv -b:v 1200k -g 160
800x600 -b:a 256k -ar 44100 -ac 1 \
-mbd 2 oi_en_800x600.swf
800x600 -b:a 256k -ar 44100 -ac 1 \
-mbd 2 -y oi_en_800x600.swf
using avconf to collect png files
Load the trajectory and write the images out as single png files, e. g.:
from ase import io, visualize
t = io.read(’mytrajectory.traj’)
for i, s in enumerate(t):
# rotate to the desired direction
s.rotate(’z’, ’x’, rotate_cell=True)
# repeat with keeping old cell
cell = s.get_cell()
s = s.repeat((1,3,3))
s.set_cell(cell)
ofname = str(i) + ’.png’
print ’writing’, ofname
io.write(ofname, s,
show_unit_cell=True,
bbox=[-3, -5, 50, 22], # set bbox by hand, try and error
)
In case you do not have avconv, install it (ubuntu):
sudo apt-get install libav-tools libavcodec-extra-53 libavdevice-extra-53 libavformat-extra-53 lib
Convert the png files to a movie (img.mov):
avconv -i "%d.png" -r 25 -c:v libx264 -crf 20
-pix_fmt yuv420p img.mov
the options are:
-i “img%d.png” uses these files as the input, %d is a placeholder for the number
-r 25 the desired frame rate, 25 FPS in this case
-c:v libx264 use the h264 codec x264
-crf 20 the video quality, 20 is pretty high, the default is 23
-pix_fmt yuv420p a compatible pixel format
12.1.8 New release
When it is time for a new release of the code, here is what you have to do:
** Warning: use only three digits release numbers, e.g. 3.1.0,
• Checkout the Latest development release.
12.1. Development topics
253
ASE Manual, Release 3.9.0.3865
• Run the tests.
• Make sure version.py has the correct version number.
• Make a tag in svn, using the current version number (to make sure not to include changes done by other
developers in the meantime!):
svn copy -r 845 https://svn.fysik.dtu.dk/projects/ase/trunk https://svn.fysik.dtu.dk/projects
Note the resulting tag’s revision tags_revision.
• Checkout the source, specyfing the version number in the directory name:
svn co -r tags_revision https://svn.fysik.dtu.dk/projects/ase/tags/3.1.0 ase-3.1.0
• Create the tar file:
cd ase-3.1.0
rm -f MANIFEST ase/svnversion.py*; python setup.py sdist
Note that the tags_revision is put into the name of the tar file automatically. Make sure that you are
getting only tags_revision in the tar file name! Any changes to the source will be reflected as a mixed
or modified revision tag!
• Put the tar file on webX (set it read-able for all):
scp dist/python-ase-3.1.0."tags_revision".tar.gz root@webX:/var/www/wiki/ase-files
• Add a link on News and update the information on the Installation requirements page and the Release notes
page.
• Add the new release on https://pypi.python.org/pypi/python-ase/:
– under the edit menu increase the version number to 3.1.0
– under the files menu add the tar file as File Type Source
• Increase the version number in ase/version.py, and commit the change:
cd ~/ase
svn ci -m "Version 3.2.0"
Now the trunk is ready for work on the new version.
• Send announcement email to the ase-users mailing list (see Mailing Lists).
12.1.9 Testing the code
All additions and modifications to ASE should be tested.
Test scripts should be put in the ase/test directory. Run all tests with:
python -c "from ase.test import test; test(2)"
It is using the function:
test.test(verbosity=1, dir=None)
Runs the test scripts in ase/test.
Important: When you fix a bug, add a test to the test suite checking that it is truly fixed. Bugs sometimes come
back, do not give it a second chance!
254
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
How to fail successfully
The test suite provided by test.test() automatically runs all test scripts in the ase/test directory and summarizes the results.
Note: Test scripts are run from within Python using the execfile() function. Among other things, this
provides the test scripts with an specialized global namespace, which means they may fail or behave differently if
you try to run them directly e.g. using python testscript.py.
If a test script causes an exception to be thrown, or otherwise terminates in an unexpected way, it will show up in
this summary. This is the most effective way of raising awareness about emerging conflicts and bugs during the
development cycle of the latest revision.
Remember, great tests should serve a dual purpose:
Working interface To ensure that the class�es and method�s in ASE are functional and provide the expected
interface. Empirically speaking, code which is not covered by a test script tends to stop working over time.
Replicable results Even if a calculation makes it to the end without crashing, you can never be too sure that the
numerical results are consistent. Don’t just assume they are, assert() it!
ase.test.assert(expression)
Raises an AssertionError if the expression does not evaluate to True.
Example:
from ase import molecule
atoms = molecule(’C60’)
atoms.center(vacuum=4.0)
result = atoms.get_positions().mean(axis=0)
expected = 0.5*atoms.get_cell().diagonal()
tolerance = 1e-4
assert (abs(result - expected) < tolerance).all()
Using functions to repeat calculations with different parameters:
def test(parameter):
# setup atoms here...
atoms.set_something(parameter)
# calculations here...
assert everything_is_going_to_be_alright
if __name__ in [’__main__’, ’__builtin__’]:
test(0.1)
test(0.3)
test(0.7)
Important: Unlike normally, the module __name__ will be set to ’__builtin__’ when a test script is run
by the test suite.
12.1.10 Buildbot
buildbot is a continuous integration system. The server called buildmaster defines and schedules processes
of building and testing of software to be performed by so called builders on machines called buildslaves
(or buildbots). One buildslave can have several builders associated (for example a given operating system version buildslave performs testing of several software branches builders). One builder can also be associated with several buildslaves (several, “identical” machines running the same operating system), in which
case buildmaster will schedule the given builder to switch periodically between the buildslaves. At the
time of writing (2012) buildbot does not offer satisfactory security mechanisms, and due to clear text passwords
12.1. Development topics
255
ASE Manual, Release 3.9.0.3865
stored/transferred both on buildmaster and buildslaves external security measures like firewall, proxy,
ssh/stunnel should be used.
The sections below describe the configuration of buildmaster and buildslaves.
Configuration of buildmaster
The buildmaster should be running as unprivileged user (usually called buildmaster). The user and group
need to be created.
In order to install buildbot on RHEL6 system you need:
yum install python-twisted python-jinja2 python-tempita
Additional dependencies + buildbot itself need to be installed manually:
wget https://downloads.sourceforge.net/project/sqlalchemy/sqlalchemy/0.7.9/SQLAlchemy-0.7.9.tar.gz
wget http://sqlalchemy-migrate.googlecode.com/files/sqlalchemy-migrate-0.7.2.tar.gz
It is sufficient to unpack the files and set PYTHONPATH, and PATH accordingly. Buildbot may need to
be patched for twisted compatibility http://www.npcglib.org/~stathis/blog/2012/10/20/bug-buildbot-dies-withexceptions-importerror-cannot-import-name-noresource/
Proceed with buildbot configuration:
• create the master:
buildbot create-master --relocatable python-ase
• reconfigure the master with doc/development/master.cfg:
cp master.cfg python-ase
buildbot checkconfig python-ase/master.cfg
buildbot start python-ase
• consider setting up a crontab which starts buildmaster after the server reboot (this solution is not reliable, deploy rather init scripts - see below):
# run every 5 minutes
*/5 * * * * sh ~/python-ase-restart.sh
with the following python-ase-restart.sh:
bot=python-ase
# no pid file - assume buildbot is not running
if ! test -f $bot/twistd.pid;
then
buildbot restart $bot || buildbot start $bot
else
# pid file exists but buildbot is not running
pid=�cat $bot/twistd.pid�
if test -z �ps -p $pid -o pid=�;
then
buildbot restart $bot
fi
fi
• or create a system V init script under /etc/init.d
#!/bin/sh
#
# python-ase:
#
# chkconfig:
# description:
256
python-ase buildmaster
345 98 02
python-ase buildmaster
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
# LSB init-info
### BEGIN INIT INFO
# Provides:
# Required-Start:
# Required-Stop:
# Default-Start:
# Default-Stop:
# Short-Description:
### END INIT INFO
python-ase
$network
$network
2 3 4 5
0 1 6
python-ase buildmaster
# Source function library.
if [ -e /etc/init.d/functions ]; then
. /etc/init.d/functions
fi
# LSB functions
. /lib/lsb/init-functions
# Check that networking is configured.
[ "${NETWORKING}" = "no" ] && exit 0
RUN_AS=buildmaster-username
PYTHON_ASE_HOME=/home/$RUN_AS/python-ase
test -d $PYTHON_ASE_HOME || exit 5
LOGFILE=$PYTHON_ASE_HOME/../python-ase.log
PIDFILE=$PYTHON_ASE_HOME/../python-ase.pid
LOCKFILE=$PYTHON_ASE_HOME/../python-ase.lock
start() {
echo -n $"Starting python-ase buildmaster: "
dostatus > /dev/null 2>&1
if [ $RETVAL -eq 0 ]
then
echo -n $"python-ase buildmaster already running"
log_failure_msg
RETVAL=1
return
fi
#su - $RUN_AS -s /bin/sh -c "exec nohup /bin/sh $PYTHON_ASE_HOME/../python-ase-start.
# don’t produce log
su - $RUN_AS -s /bin/sh -c "exec nohup /bin/sh $PYTHON_ASE_HOME/../python-ase-start.s
RETVAL=$?
if [ $RETVAL -eq 0 ]
then
sleep 5
su - $RUN_AS -s /bin/sh -c "cat $PYTHON_ASE_HOME/twistd.pid > $PIDFILE"
su - $RUN_AS -s /bin/sh -c "touch $LOCKFILE"
log_success_msg
else
log_failure_msg
fi
return $RETVAL
}
stop() {
echo -n $"Shutting down python-ase buildmaster: "
kill $(su - $RUN_AS -s /bin/sh -c "cat $PIDFILE 2>/dev/null") > /dev/null 2>&1
RETVAL=$?
sleep 5
if [ $RETVAL -eq 0 ]
then
12.1. Development topics
257
ASE Manual, Release 3.9.0.3865
su - $RUN_AS -s /bin/sh -c "rm -f $PIDFILE $LOCKFILE"
log_success_msg
else
log_failure_msg
fi
return $RETVAL
}
restart() {
stop
start
}
condrestart() {
[ -f $LOCKFILE ] && restart || :
}
dostatus() {
kill -0 $(cat $PIDFILE 2>/dev/null) > /dev/null 2>&1
RETVAL=$?
if [ $RETVAL -eq 0 ]
then
echo "python-ase buildmaster (pid $(cat $PIDFILE 2>/dev/null)) is running..."
else
if [ -f $PIDFILE ]
then
echo "python-ase buildmaster dead but pid file exists"
RETVAL=1
return
fi
if [ -f $LOCKFILE ]
then
echo "python-ase buildmaster dead but subsys locked"
RETVAL=2
return
fi
echo "python-ase buildmaster is stopped"
RETVAL=3
fi
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
dostatus
;;
restart|reload)
restart
;;
condrestart)
condrestart
;;
*)
echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
exit 1
esac
258
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
exit $RETVAL
The service is added with:
chkconfig --add python-ase-buildmaster
started with:
service python-ase-buildmaster start
end enabled for boot time with:
chkconfig python-ase-buildmaster on
See also an example of systemd script in the section below.
• consider protecting the buildmaster web interface by, e.g.
apache reverse proxy
(http://httpd.apache.org/docs/2.4/mod/mod_proxy.html). The basic configuration file may look like
# EEE.EEE.EEE.EEE is the IP of your External apache server:
# ase-buildbot.fysik.dtu.dk
<VirtualHost EEE.EEE.EEE.EEE:80>
ServerName ase-buildbot.fysik.dtu.dk
ServerAlias ase-buildbot ase-buildbot.fysik.dtu.dk
Redirect / https://ase-buildbot.fysik.dtu.dk/
</VirtualHost>
<VirtualHost EEE.EEE.EEE.EEE:443>
ServerName ase-buildbot.fysik.dtu.dk
ServerAlias ase-buildbot ase-buildbot.fysik.dtu.dk
# important http://httpd.apache.org/docs/current/mod/mod_proxy.html
ProxyRequests Off
# III.III.III.III:8080 the IP and port of the Internal buildbot web server
ProxyPass / http://III.III.III.III:8080/
ProxyPassReverse / http://III.III.III.III:8080/
<Proxy http://III.III.III.III:8080/*>
Options -Indexes
Order deny,allow
Deny from all
Allow from 127.0.0.1
Allow from ::1
#Allow from all
</Proxy>
SSLProxyEngine on
# provide an authority signed certificate
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
</VirtualHost>
# vim: filetype=apache shiftwidth=4 tabstop=4 wrap!
Installation and configuration of buildslaves
Some examples are given below. The configuration should be performed under an unprivileged buildslave,
or buildbot user account.
12.1. Development topics
259
ASE Manual, Release 3.9.0.3865
Installation
Fedora Install with:
yum install buildbot-slave
You can configure systemd service by creating python-ase-fedora-18-x86_64-gcc-2.7.service
file under /usr/lib/systemd/system.
[Unit]
Description=buildslave python-ase-fedora+18+x86_64+gcc+2.7 stock
After=network.target
[Service]
Type=forking
User=buildslave-username
Group=buildslave-groupname
ExecStart=/usr/bin/sh /home/buildslave-username/python-ase-fedora+18+x86_64+gcc+2.7-start.sh
Restart=always
[Install]
WantedBy=multi-user.target
python-ase-fedora+18+x86_64+gcc+2.7-start.sh simply exports the necessary environment variables (if needed) and starts buildslave (use the full path), e.g.:
#!/bin/sh
bot=/home/buildslave-username/python-ase-fedora+18+x86_64+gcc+2.7
buildslave start $bot
Choose User and Group under which buildslave will be running. The service is started with:
systemctl start python-ase-fedora-18-x86_64-gcc-2.7.service
In order to force the service to be started at boot time create a link:
cd /etc/systemd/system/multi-user.target.wants
ln -s /usr/lib/systemd/system/python-ase-fedora-18-x86_64-gcc-2.7.service .
OS X Configure Homebrew, and:
brew install subversion
Configure a virtualenv, and then:
pip install numpy
pip install buildbot-slave
RHEL5 Install recent python-setuptools in order to get easy_install:
mkdir ~/buildbot-slave-el5
export PATH=$HOME/buildbot-slave-el5:${PATH}
export PYTHONPATH=$HOME/buildbot-slave-el5:${PYTHONPATH}
wget http://pypi.python.org/packages/2.4/s/setuptools/setuptools-0.6c11-py2.4.egg
sh setuptools-0.6c11-py2.4.egg --install-dir=$HOME/buildbot-slave-el5
then:
easy_install --install-dir=$HOME/buildbot-slave-el5 zope.interface==3.6.7
easy_install --install-dir=$HOME/buildbot-slave-el5 twisted==9.0.0 # ignore errors
easy_install --install-dir=$HOME/buildbot-slave-el5 buildbot-slave
260
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
RHEL6 Install build-slave and dependencies:
mkdir ~/buildbot-slave-el6
export PATH=$HOME/buildbot-slave-el6:${PATH}
export PYTHONPATH=$HOME/buildbot-slave-el6:${PYTHONPATH}
easy_install --install-dir=$HOME/buildbot-slave-el6 buildbot-slave
Windows build-slave can be installed and configured to start as a service on Windows
http://trac.buildbot.net/wiki/RunningBuildbotOnWindows. This involves several steps:
1. install Python(x,y) from https://code.google.com/p/pythonxy/wiki/Downloads
2. configure distutils to use mingw. First enable showing file extensions:
Open a folder with IE -> Folder and search options-> View -> Folder Options:
Check: Show hidden files, ...; uncheck: Hide extensions for known file types.
Then, in notepad, create C:\python27\lib\distutils\distutils.cfg, containing:
[build]
compiler=mingw32
3. install build-slave on the command line:
C:\python27\scripts\easy_install.exe buildbot-slave
4. create a local (domain computer-name) user that will run the buildbot service:
control panel->administrative tools->computer management->local users and groups->users->new
Click the created user: member of: administrators->check names
5. grant buildslave-username the ability to run the services.
Login as
computer-name\buildslave-username: Run secpol.msc on the command line as administrator (task bar->cmd->right click: run as administrator):
• Select the “Local Policies” folder
• Select the “User Rights Assignment” folder
• Double click “Log on as a service”
• Use “Add User or Group...” to add your user here.
Select the correct “from this location” (may require login as the current domain administrator) and Enter
the object names: computer-name\buildslave-username.
6. on the command line install the buildbot service:
buildbot_service.py --user computer-name\buildslave-username --password thepassword --startup
7. start the service (for the moment it does not start any buildslave, because they are not configured yet):
Start->Control Panel> Administrative Tools->Services->Buildbot (Start)
There are additional steps mentioned in the buildbot wiki, but it seems just to work on Windows 7.
8. run regedit as administrator (type “regedit” on the command line) and add “directories” parameter of the
String Value type, containing paths to all your buildslave instances (they will be configured in the
Configuration section below):
HKEY_LOCAL_MACHINE\System\CurrentControlSet\services\Buildbot->paramaters->new (String Value)
9. configure buildslave instance as described in the Configuration section below and start the service again
(point 7.). Test that buildslave comes online, and verify that the service starts after reboot.
12.1. Development topics
261
ASE Manual, Release 3.9.0.3865
Configuration
After having installed the buildbot create a name which will identify your buildslave. Obtain the first part of
the name for your buildslave by running doc/development/master.cfg:
python master.cfg
This will return a string like redhat+6+x86_64+gcc+2.6 (OS+OSversion+Bitness+Ccompiler+PythonVersion).
Append it with something that identifies your buildslave, for example gpu. For a very special system you can
use a name like mycluster+x86_64+open64+2.5 gpu. Note that ASE buildbot will perform verification
of python version based on the buildslave name so stay consistent!
Generate a strong buildslave password with Creating an encrypted password for SVN access. Don’t reuse
any valuable passwords. You don’t need to remember it, buildbot stores it plain text!
Create the buildslave with:
buildslave create-slave python-ase-redhat+6+x86_64+gcc+2.6 buildbot.fysik.dtu.dk:ASE_BB_PORT "redh
ASE_BB_PORT is the port ASE buildbot uses for communication with the buildslave. You will have to tell
us the name and password of your buildslave. Please contact ase-developers list Mailing Lists, but don’t send
the name and password there!
Edit the python-ase-redhat+6+x86_64+gcc+2.6/info/{admin,info} files:
buildslave configuration relevant for the builder process in the info file.
describe your
Note that before starting the slave you need to perform an temporary svn checkout of ASE in order to accept the
certificate permanently.
Start the buildslave with:
buildslave start python-ase-redhat+6+x86_64+gcc+2.6
Don’t forget to configure a crontab job or a service as described in the previous sections.
By default all slaves run the continuous integration for the trunk. If you prefer your buildslave works also on
one of the branches, write this in the email to ase-developers Mailing Lists.
12.1.11 Translate ASE
You can contribute by translating the ASE GUI, ase-gui, into your language.
How to translate
If any of the below steps prove difficult, be sure to ask on the developer mailing list. These steps should work on
GNU/Linux.
• Download ASE.
• Go to ase/gui/po. There is a directory of the form ll or ll_LL for each language, where ll is the
language code and LL the country code. The latter is necessary only if variants of the same language are
spoken in multiple countries.
• If your language is not there already, run LANG=ll make init, substituting the desired language code.
If necessary append the country code as well: LANG=ll_LL ....
• There should now be a template file for your language, ll/LC_MESSAGES/ag.po, which can be filled
out.
You can edit the po-file with any text editor. It is easiest with a dedicated po-editor such as gtranslator, poedit or
the gettext mode in EMACS (the package “gettext-el”). Fill out the missing msgstr entries like this:
262
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
#: ../energyforces.py:61
msgid "Calculate potential energy and the force on all atoms"
msgstr "Beregn potentiel energi og kræfter på alle atomer"
Your editor may wholly or partially hide some of the difficult formatting syntax. This next example shows a more
syntactically complex case in case you need it:
#: ../calculator.py:107
msgid ""
"GPAW implements Density Functional Theory using a\n"
"<b>G</b>rid-based real-space representation of the wave\n"
"functions, and the <b>P</b>rojector <b>A</b>ugmented <b>W</b>ave\n"
"method for handling the core regions. \n"
msgstr ""
"GPAW implementerer tæthedsfunktionalteori med en <b>G</b>itterbaseret\n"
"repræsentation af bølgefunktioner i det reelle rum, samt\n"
"<b>P</b>rojector <b>A</b>ugmented <b>W</b>ave-metoden til behandling\n"
"af regionen omkring atomkerner. \n"
If you are maintaining an existing translation, there may be some “fuzzy” messages. These are translations that
were written previously but now need to be reviewed, maybe because the original string has been slightly modified.
Edit them as appropriate and remove the “fuzzy” flag.
There will be a few special constructs such as string substitution codes %(number)d or %s. These should remain
unchanged in the translation as they are replaced by numbers or text at runtime. An underscore like in msgid
"_File" indicates that F is a shortcut key. Conflicting shortcut keys are not a big problem, but avoid them if
you see them. Finally, some messages may have a lot of whitespace in them. This is due to bad programming
style; just try to get approximately the same spacing in your translation.
Already after writing a few translations, you can check that the translation works as expected by following the
instructions in the next section.
Check and commit your translation
• You can check the syntax by running msgfmt -cv ag.po. This will report any syntax errors.
• You can test your translation in ase-gui directly. First issue the command make in ase/gui/po,
then reinstall ASE using the usual procedure. The translations will then be in the newly installed ASE. If
you translate into the same language as your computer’s locale, you should see the translations when you
start ase-gui normally. If you translate ASE into another language, then run LANG=ll_LL.UTF-8
ase-gui. On some operating systems you may need to run LANGUAGE=ll_LL.UTF-8 ase-gui
instead.
Depending on your operating system, you may need to install gettext or locales.
Send the partially or completely translated po-file to the developers mailing list and ask to have it committed. In
fact, we will be quite thrilled if you send an e-mail even before you start, and be sure to send one whenever you
have questions.
Note: Certain uncommon languages such as Lojban, Anglo-Saxon or Klingon may not be compatible with our
current build system. Please let us know if you want to translate ASE into such languages.
Maintaining translations
Messages will once in a while be added or changed in the ASE. Running make in ase/gui/po automatically
synchronizes all templates with the messages in the current source tree while maximally reusing the existing
translations. Some strings may be marked “fuzzy”, indicating that they need review by translators (this happens
e.g. if an English message is changed only slightly). One can then update the few fuzzy or untranslated messages.
The obvious time to do this is shortly before a new stable release.
12.1. Development topics
263
ASE Manual, Release 3.9.0.3865
If you are a committer, please run make before committing and briefly check by running the translated ase-gui
that nothing is obviously horrible.
12.1.12 To do
Check our issue tracker.
Documentation
• Put example of Verlet dynamics in ase/md
• talk about writing files - pos, py and pckl
• Write more about the parameters of the supported elements of the EMT calculator.
Code
• Could the directions argument of ase.lattice.FaceCenteredCubic etc. have default values?
12.1.13 Python 3 strategy
• One codebase for both 2 and 3.
• Use print(...) and add this line as the fist line:
from __future__ import print_function
• Don’t do this: print >> f, .... Use f.write(...
+ ’\n’) or print(..., file=f).
• More help here: http://packages.python.org/six/
12.1.14 ASE enhancement proposals
Calculator interface proposal
All ASE calculators should behave similarly if there is no good reason for them not to. This should make it simpler
for both users and developers.
This proposal tries to define how a good ASE calculator should behave. The goal is to have ASE calculators:
• that share more code
• are more uniform to use
• are better tested
• are portable
Setting some standards is a good thing, but we should also be careful not to set too strict rules that could limit each
calculator to the lowest common denominator.
Behavior
When a calculator calculates the energy, forces, stress tensor, total magnetic moment, atomic magnetic moments
or dipole moment, it should store a copy of the system (atomic numbers, atomic positions, unit cell and boundary
conditions). When asked again, it should return the value already calculated if the system hasn’t been changed.
If calculational parameters such as plane wave cutoff or XC-functional has been changed the calculator should
throw away old calculated values.
264
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
Standards parameters
The standard keywords that all calculators must use (if they make sense) are: xc, kpts, smearing, charge
and nbands. Each calculator will have its own default values for these parameters — see recommendations
below. In addition, calculators will typically have many other parameters. The units are eV and Г….
Initial magnetic moments are taken from the Atoms object.
xc It is recommended that ’LDA’ and ’PBE’ are valid options.
kpts
• (1,1,1): Gamma-point
• (n1,n2,n3): Monkhorst-Pack grid
• (n1,n2,n3,’gamma’): Shifted Monkhorst-Pack grid that includes Γ
• [(k11,k12,k13),(k21,k22,k23),...]: Explicit list in units of the reciprocal
lattice vectors
• kpts=3.5: k-point density as in 3.5 k-points per Å−1
smearing The smearing parameter must be given as a tuple:
• (’Fermi-Dirac’, width)
• (’Gaussian’, width)
• (’Methfessel-Paxton’, width, n), where n is the order (n = 0 is the same as
’Gaussian’)
Lower-case strings are also allowed. The width parameter used for the chosen smearing
method is in eV units.
charge Charge of the system in units of |e| (charge=1 means one electron has been removed).
nbands Each band can be occupied by two electrons.
ABC calculator example
The constructor will look like this:
ABC(restart=None, ignore_bad_restart=False, label=None,
atoms=None, **kwargs)
A calculator should be able to prefix all output files with a given label or run the calculation in a directory with a
specified name. This is handled by the label argument. There are three possibilities:
• Name of a file containing all results of a calculation (possibly containing a directory).
• A prefix used for several files containing results. The label may have both a directory part and a prefix part
like ’LDA/mol1’.
• Name of a directory containing result files with fixed names.
Each calculator can decide what the default value is: None for no output, ’-’ for standard output or something
else.
If the restart argument is given, atomic configuration, input parameters and results will be read from a previous
calculation from the file(s) pointed to by the restart argument. It is an error if those files don’t exist and are
corrupted. This error can be ignored bu using ignore_bad_restart=True.
The atoms argument is discussed below. All additional parameters are given as keyword arguments.
Example: Do a calculation with ABC calculator and write results to si.abc:
12.1. Development topics
265
ASE Manual, Release 3.9.0.3865
>>> atoms = ...
>>> atoms.calc = ABC(label=’si.abc’, xc=’LDA’, kpts=3.0)
>>> atoms.get_potential_energy()
-1.2
Read atoms with ABC calculator attaced from a previous calculation:
>>> atoms = ABC.read_atoms(’si.abc’)
>>> atoms.calc
<ABC-calculator>
>>> atoms.get_potential_energy()
-1.2
The ABC.read_atoms(’si.abc’) statement is equivalent to:
ABC(restart=’si.abc’, label=’si.abc’).get_atoms()
If we do:
>>> atoms = ABC.read_atoms(’si.abc’)
>>> atoms.rattle()
# change positions and/or
>>> atoms.calc.set(xc=’PBE’) # change a calculator-parameter
>>> atoms.get_potential_energy()
-0.7
then the si.abc will be overwritten or maybe appended to.
An alternative way to connect atoms and calculator:
>>> atoms = ...
>>> calc = ABC(restart=’si.abc’, label=’si.abc’, atoms=atoms)
>>> atoms.get_potential_energy()
-0.7
This will automatically attach the calculator to the atoms and the atoms will be updated form the file. If you
add ignore_bad_restart=True, you will be able to use the same script to do the initial calculation where
si.abc does not exist and following calculations where atoms may have been moved arround by an optimization
algorithm.
The command used to start the ABC code can be given in an environment variable called ASE_ABC_COMMAND
or as a command keyword. The command can look like this:
mpiexec abc PREFIX.input > PREFIX.output
or like this:
~/bin/start_abc.py PREFIX
The PREFIX strings will be substituted by the label keyword.
Implementation
• Portability (Linux/Windows): os.system(’Linux commands’) not allowed.
• Common base class for all calculators: Calculator. Takes care of restart from file logic, handles setting
of parameters and checks for state changes.
• A FileIOCalculator for the case where we need to:
– write input file(s)
– run Fortran/C/C++ code
– read output file(s)
• Helper function to deal with kpts keyword.
266
Chapter 12. ASE development
ASE Manual, Release 3.9.0.3865
Command line tools
This proposal tries to clean up the command line tools that we distribute with ASE.
Current status
ASE currently has 7 command line tools that we install in /usr/bin:
command
ag
ASE2ase
testase
ase
asec
foldtrajectory
trajectoryinfo
description
ASE’s GUI
Translate old ASE-2 code to ASE-3 style
Run tests
First attempt to create a command that can do everything
Second attempt
Wrap atoms outside simulation box to inside box
Write information about trajectory file
Proposed set of command line tools
In the future things will look like this:
command
ase-gui
ase-info
ase-test
ase-build
ase-run
ase-db
description
ASE’s GUI
Write information about files
Run tests
Build simple molecule or bulk structure
Run calculations with ASE’s calculators
Put stuff into or query database
Comments
ag:
Renamed to ase-gui.
ASE2ase:
Removed — no longer needed.
testase:
Renamed to ase-test. Alternative:
python setup.py test
ase and asec:
Replaced by new commands ase-build and ase-run. The old ase command is documented here and
is hopefully not used a lot since we propose to get rid of it.
foldtrajectory:
Too specialized to deserve its own command. Use:
python -m ase.md.foldtrajectory
instead.
trajectoryinfo:
Replaced by new more general command ase-info that can pull out information from anything that
ASE can read.
12.1. Development topics
267
ASE Manual, Release 3.9.0.3865
Naming convention
Any suggestions for better names or are the proposed ones OK? The good thing about using ase-something for
all is that it is consistent and if you know one command, you will maybe discover the other ones when you do
tab-completion.
Implementation details
• Should we use the very nice argparse module, which is the future but only available in Python 2.7, or
should we stick with the old and deprecated optparse module?
12.2 Creating an encrypted password for SVN access
Use this command:
htpasswd -nm <your-desired-user-name>
and type a good password twice. The encrypted password will be printed on the screen.
Alternatively, you can use:
openssl passwd -apr1
followed by your password (twice).
268
Chapter 12. ASE development
CHAPTER
THIRTEEN
BUGS!
If you find a bug in the ASE software, please report it to the developers so it can be fixed. We need that feedback
from the community to maintain the quality of the code.
13.1 Bug report
• If you are unsure if it is a real bug, or a usage problem, it is probably best to report the problem on the
ase-users mailing list (see Mailing Lists).
Please provide the failing script as well as the information about your environment (processor architecture,
versions of python and numpy). Then we (or other users) can help you to find out if it is a bug.
Another advantage of reporting bugs on the mailing list: often other users will tell you how to work around
the bug (until it is solved).
• If you think it is a bug, you can also report it directly on our bug tracking system. The advantage of reporting
bugs here is that it is not forgotten (which may be a risk on the mailing list).
We do not guarantee to fix all bugs, but we will do our best.
13.2 Known bugs
A list of known bugs (tickets) is on our Trac.
269
ASE Manual, Release 3.9.0.3865
270
Chapter 13. Bugs!
CHAPTER
FOURTEEN
PORTING OLD ASE-2 CODE TO
VERSION 3
The old Numeric-Python based ASE-2 can coexist with the new numpy-based ASE-3, because the two packages
have different names: ASE and ase respectively. Here is an example of combining both:
from ASE.Trajectories.NetCDFTrajectory import NetCDFTrajectory
traj = NetCDFTrajectory(’a.nc’)
loa = traj.GetListOfAtoms(-1)
# Convert to new style Atoms object:
from ase import *
a = Atoms(loa)
The new ASE can actually read old NetCDF trajectory files, so this would be simpler:
from ase import *
a = read(’a.nc’)
Note:
Reading old NetCDF files in the new ASE, works even without having the libnetcdf and
Scientific.IO.NetCDF libraries installed.
14.1 The ASE2ase tool
Use the ASE2ase tool (source code tools/ASE2ase) to convert old scripts:
$ ASE2ase oldscript.py
$ diff -u oldscript.py.bak oldscript.py
Check that the differences look OK. The conversion tool isn’t clever enough to get everything right, so you will
have to do some conversion manually also. If you have any problems doing this, then you should not hesitate to
contact the campos-devel mailing list (see Mailing Lists) and ask for help.
271
ASE Manual, Release 3.9.0.3865
272
Chapter 14. Porting old ASE-2 code to version 3
BIBLIOGRAPHY
[JГіhannesson] G. JГіhannesson, T. Bligaard, A. Ruban, H. Skriver, K. Jacobsen and J. NГёrskov. Combined Electronic Structure and Evolutionary Search Approach to Materials Design, Phys. Rev. Lett., Vol 88, No. 25, pp.
1-5 (2002)
[Jensen] P. B. Jensen, S. Lysgaard, U. J. Quaade and T. Vegge. Designing Mixed Metal Halide Ammines for
Ammonia Storage Using Density Functional Theory and Genetic Algorithms Phys. Chem. Chem. Phys., Vol
16, No. 36, pp. 19732-19740, (2014)
[Alfe] D. Alfe, PHON: A program to calculate phonons using the small displacement method, Comput. Phys.
Commun. 180, 2622 (2009)
[Wang] Y. Wang et al., A mixed-space approach to first-principles calculations of phonon frequencies for polar
materials, J. Phys.: Cond. Matter 22, 202201 (2010)
[MonkhorstPack] Hendrik J. Monkhorst and James D. Pack: Special points for Brillouin-zone integrations, Phys.
Rev. B 13, 5188–5192 (1976)
[Bader] R. F. W. Bader. Atoms in Molecules: A Quantum Theory. Oxford University Press, New York, 1990.
[Tang] W. Tang, E. Sanville, G. Henkelman. A grid-based Bader analysis algorithm without lattice bias. J. Phys.:
Compute Mater. 21, 084204 (2009).
[Cordeo08] Covalent radii revisited, Beatriz Cordero, VerГіnica GГіmez, Ana E. Platero-Prats, Marc RevГ©s,
Jorge EcheverrГ­a, Eduard Cremades, Flavia BarragГЎn and Santiago Alvarez, Dalton Trans., 2008, 2832-2838
DOI:10.1039/B801115J
[JГіhannesson] G. JГіhannesson, T. Bligaard, A. Ruban, H. Skriver, K. Jacobsen and J. NГёrskov. Combined Electronic Structure and Evolutionary Search Approach to Materials Design, Phys. Rev. Lett., Vol 88, No. 25, pp.
1-5 (2002)
[Jensen] P. B. Jensen, S. Lysgaard, U. J. Quaade and T. Vegge. Designing Mixed Metal Halide Ammines for
Ammonia Storage Using Density Functional Theory and Genetic Algorithms Phys. Chem. Chem. Phys., Vol
16, No. 36, pp. 19732-19740, (2014)
273
ASE Manual, Release 3.9.0.3865
274
Bibliography
PYTHON MODULE INDEX
a
ase, 67
ase.atom, 81
ase.atoms, 69
ase.calculators, 128
ase.calculators.abinit, 134
ase.calculators.aims, 143
ase.calculators.ase_qmmm_manyqm, 159
ase.calculators.castep, 135
ase.calculators.dftb, 139
ase.calculators.eam, 130
ase.calculators.emt, 134
ase.calculators.exciting, 141
ase.calculators.fleur, 146
ase.calculators.gromacs, 147
ase.calculators.jacapo, 149
ase.calculators.lammps, 151
ase.calculators.LAMMPSrun, 152
ase.calculators.nwchem, 153
ase.calculators.siesta, 153
ase.calculators.turbomole, 156
ase.calculators.vasp, 157
ase.constraints, 165
ase.data, 201
ase.db, 210
ase.db.core, 212
ase.dft, 190
ase.dft.dos, 196
ase.dft.kpoints, 191
ase.dft.wannier, 193
ase.dimer, 230
ase.ga, 216
ase.gui, 88
ase.infrared, 184
ase.io, 83
ase.io.opls, 209
ase.io.trajectory, 203
ase.lattice, 111
ase.lattice.spacegroup, 29
ase.lattice.surface, 102
ase.md, 186
ase.md.langevin, 188
ase.md.npt, 189
ase.md.nptberendsen, 190
ase.md.nvtberendsen, 188
ase.md.verlet, 188
ase.neb, 171
ase.optimize, 115
ase.optimize.basin, 119
ase.optimize.bfgslinesearch, 118
ase.optimize.fire, 117
ase.optimize.lbfgs, 117
ase.optimize.mdmin, 117
ase.optimize.qn, 116
ase.optimize.sciopt, 118
ase.parallel, 120
ase.phonons, 175
ase.structure, 100
ase.test, 254
ase.thermochemistry, 177
ase.transport, 200
ase.units, 83
ase.utils, 207
ase.vibrations, 173
ase.visualize, 120
ase.visualize.mlab, 121
ase.visualize.vtk, 121
b
basics, 89
c
calculate, 95
e
edit, 91
s
setup, 95
t
tools, 92
v
view, 92
vtk, 126
275
ASE Manual, Release 3.9.0.3865
276
Python Module Index
INDEX
Symbols
ase.calculators.gromacs (module), 147
ase.calculators.jacapo (module), 149
$HOME, 11
ase.calculators.lammps (module), 151
$PATH, 248
ase.calculators.LAMMPSrun (module), 152
$PYTHONPATH, 248
ase.calculators.nwchem (module), 153
ase.calculators.siesta (module), 153
A
ase.calculators.turbomole (module), 156
add_adsorbate() (in module ase.lattice.surface), 107
add_axes() (ase.visualize.vtk.atoms.vtkAtoms method), ase.calculators.vasp (module), 157
ase.constraints (module), 165
126
add_cell() (ase.visualize.vtk.atoms.vtkAtoms method), ase.data (module), 201
ase.db (module), 210
126
add_forces()
(ase.visualize.vtk.atoms.vtkAtoms ase.db.core (module), 212
ase.dft (module), 190
method), 126
ase.dft.dos (module), 196
add_scalar_property() (ase.visualize.vtk.grid.vtkAtomicPositions
ase.dft.kpoints (module), 191
method), 127
ase.dft.wannier (module), 193
add_vacuum() (in module ase.lattice.surface), 107
ase.dimer (module), 230
add_vector_property() (ase.visualize.vtk.grid.vtkAtomicPositions
ase.ga (module), 216
method), 127
add_velocities()
(ase.visualize.vtk.atoms.vtkAtoms ase.gui (module), 88
ase.infrared (module), 184
method), 126
ase.io (module), 83
adjust_forces() (in module ase.constraints), 168
ase.io.opls (module), 209
adjust_momenta() (in module ase.constraints), 169
ase.io.trajectory (module), 203
adjust_positions() (in module ase.constraints), 168
adjust_potential_energy() (in module ase.constraints), ase.lattice (module), 111
ase.lattice.spacegroup (module), 29
169
ase.lattice.surface (module), 102
ag, 88
ase.md (module), 186
Aims (class in ase.calculators.aims), 143
ase.md.langevin (module), 188
AimsCube (class in ase.calculators.aims), 145
ase.md.npt (module), 189
API, 235
ase.md.nptberendsen (module), 190
append() (ase.atoms.Atoms method), 75
ase.md.nvtberendsen (module), 188
ASE, 235
ase.md.verlet (module), 188
ase, 96
ase.neb (module), 171
ase (module), 67
ase.optimize (module), 115
ase-gui, 88
ase.optimize.basin (module), 119
ase.atom (module), 81
ase.optimize.bfgslinesearch (module), 118
ase.atoms (module), 69
ase.optimize.fire (module), 117
ase.calculators (module), 128
ase.optimize.lbfgs (module), 117
ase.calculators.abinit (module), 134
ase.optimize.mdmin (module), 117
ase.calculators.aims (module), 143
ase.optimize.qn (module), 116
ase.calculators.ase_qmmm_manyqm (module), 159
ase.optimize.sciopt (module), 118
ase.calculators.castep (module), 135
ase.parallel (module), 120
ase.calculators.dftb (module), 139
ase.phonons (module), 175
ase.calculators.eam (module), 130
ase.structure (module), 100
ase.calculators.emt (module), 134
ase.test (module), 254
ase.calculators.exciting (module), 141
ase.thermochemistry (module), 177
ase.calculators.fleur (module), 146
277
ASE Manual, Release 3.9.0.3865
ase.transport (module), 200
ase.transport.calculators.TransportCalculator (class in
ase.transport), 201
ase.units (module), 83
ase.utils (module), 207
ase.vibrations (module), 173
ase.visualize (module), 120
ase.visualize.mlab (module), 121
ase.visualize.vtk (module), 121
ASE2ase, 271
ASE_ABC_COMMAND, 130, 266
ASE_NWCHEM_COMMAND, 153
assert() (in module ase.test), 255
Atom (class in ase.atom), 81
atomic_masses (in module ase.data), 201
atomic_names (in module ase.data), 201
atomic_numbers (in module ase.data), 202
Atoms (class in ase.atoms), 74
B
basics (module), 89
bcc100() (in module ase.lattice.surface), 103
bcc110() (in module ase.lattice.surface), 104
bcc111() (in module ase.lattice.surface), 104
build()
(ase.calculators.neighborlist.NeighborList
method), 208
Bulk modulus, 207
bulk() (in module ase.lattice), 100
BundleTrajectory (class in ase.io.bundletrajectory), 205
C
Class, 235
close()
(ase.io.bundletrajectory.BundleTrajectory
method), 205
close() (ase.io.trajectory.PickleTrajectory method), 204
command (ase.calculators.calculator.FileIOCalculator
attribute), 252
connect() (in module ase.db.core), 214
constraints (ase.atoms.Atoms attribute), 75
Constructor, 235
copy() (ase.atoms.Atoms method), 75
covalent_radii (in module ase.data), 201
cpk_colors (in module ase.data), 201
CrystalThermo (class in ase.thermochemistry), 180
D
Database (class in ase.db.core), 214
default_parameters (ase.calculators.calculator.Calculator
attribute), 250
delete() (ase.db.core.Database method), 215
delete_bundle() (ase.io.bundletrajectory.BundleTrajectory
class method), 205
delete_keywords_and_key_value_pairs()
(ase.db.core.Database method), 215
DFT, 235
DFTCalculator (class in ase.calculators.interface), 164
diamond100() (in module ase.lattice.surface), 103
diamond111() (in module ase.lattice.surface), 105
DimerControl (class in ase.dimer), 231
DimerEigenmodeSearch (class in ase.dimer), 232
Docstring, 235
DOS (class in ase.dft.dos), 197
calc (ase.atoms.Atoms attribute), 75
E
calculate (module), 95
calculate()
(ase.calculators.calculator.Calculator edit (module), 91
edit() (ase.atoms.Atoms method), 75
method), 251
calculate() (ase.calculators.fleur.FLEUR method), 147 EMT, 235
EMT (class in ase.calculators.emt), 134
calculate_ldos() (ase.dft.stm.STM method), 198
environment variable
calculate_numerical_forces()
$HOME, 11
(ase.calculators.calculator.Calculator
$PATH, 248
method), 251
$PYTHONPATH, 248
calculation_required() (ase.calculators.interface.Calculator
ABINIT_PP_PATH, 134
method), 164
ASE_ABC_COMMAND, 130, 266
Calculator (class in ase.calculators.calculator), 250
ASE_ABINIT_COMMAND, 134
Calculator (class in ase.calculators.interface), 164
ASE_NWCHEM_COMMAND, 153
Castep (class in ase.calculators.castep), 135
FLEUR, 146
cc12_2x3 (in module ase.dft.kpoints), 191
FLEUR_INPGEN, 146
cc162_1x1 (in module ase.dft.kpoints), 191
HOME, 15
cc162_sq3xsq3 (in module ase.dft.kpoints), 191
LAMMPS_COMMAND, 152
cc18_1x1 (in module ase.dft.kpoints), 191
PATH, 15, 245, 256
cc18_sq3xsq3 (in module ase.dft.kpoints), 191
PYTHONPATH, 15, 20, 245, 256
cc54_1x1 (in module ase.dft.kpoints), 191
PYTHONSTARTUP, 18
cc54_sq3xsq3 (in module ase.dft.kpoints), 191
SIESTA_PP_PATH, 154
cc6_1x1 (in module ase.dft.kpoints), 191
SIESTA_SCRIPT, 154
cell (ase.atoms.Atoms attribute), 75
SVN_EDITOR, 245
center() (ase.atoms.Atoms method), 75
VASP_PP_PATH, 157
check_state()
(ase.calculators.calculator.Calculator
VASP_SCRIPT, 157
method), 251
EquationOfState (class in ase.utils.eos), 207
chemical_symbols (in module ase.data), 201
278
Index
ASE Manual, Release 3.9.0.3865
Exciting (class in ase.calculators.exciting), 141, 143
extend() (ase.atoms.Atoms method), 75
get_eigenvalues() (ase.calculators.interface.DFTCalculator
method), 164
get_energies() (ase.dft.dos.DOS method), 197
F
get_energies() (ase.vibrations.Vibrations method), 174
get_enthalpy() (ase.thermochemistry.IdealGasThermo
fcc100() (in module ase.lattice.surface), 103
method), 178
fcc110() (in module ase.lattice.surface), 103
get_entropy()
(ase.thermochemistry.CrystalThermo
fcc111() (in module ase.lattice.surface), 104
method), 180
fcc211() (in module ase.lattice.surface), 104
get_entropy() (ase.thermochemistry.HarmonicThermo
FieldPlotter (class in ase.visualize.fieldplotter), 124
method), 180
FileIOCalculator (class in ase.calculators.calculator),
get_entropy() (ase.thermochemistry.IdealGasThermo
252
method), 178
Filter (class in ase.constraints), 169
get_fermi_level() (ase.calculators.interface.DFTCalculator
FixAtoms (class in ase.constraints), 166
method), 164
FixBondLength (class in ase.constraints), 166
get_forces() (ase.atoms.Atoms method), 77
FixBondLengths (class in ase.constraints), 166
get_forces()
(ase.calculators.interface.Calculator
FixedLine (class in ase.constraints), 166
method), 164
FixedMode (class in ase.constraints), 167
get_frequencies() (ase.vibrations.Vibrations method),
FixedPlane (class in ase.constraints), 167
174
FixInternals (class in ase.constraints), 168
get_function() (ase.dft.wannier.Wannier method), 194
FLEUR, 146
get_functional_value()
(ase.dft.wannier.Wannier
FLEUR_INPGEN, 146
method), 194
fold() (ase.vibrations.Vibrations method), 174
get_gibbs_energy() (ase.thermochemistry.HarmonicThermo
method), 180
G
get_gibbs_energy()
(ase.thermochemistry.IdealGasThermo
gcd() (in module ase.utils), 207
method),
178
get() (ase.db.core.Database method), 215
get_actor() (ase.visualize.vtk.module.vtkGlyphModule get_hamiltonian() (ase.dft.wannier.Wannier method),
194
method), 128
get_hamiltonian_kpoint()
(ase.dft.wannier.Wannier
get_all_distances() (ase.atoms.Atoms method), 75
method),
194
get_angle() (ase.atoms.Atoms method), 76
get_angular_momentum() (ase.atoms.Atoms method), get_helmholtz_energy()
(ase.thermochemistry.CrystalThermo
76
method), 180
get_array() (ase.atoms.Atoms method), 76
get_hopping()
(ase.dft.wannier.Wannier method), 195
get_atomic_numbers() (ase.atoms.Atoms method), 76
get_ibz_k_points()
(ase.calculators.interface.DFTCalculator
get_atoms() (ase.db.core.Database method), 214
method),
164
get_averaged_current() (ase.dft.stm.STM method), 198
get_initial_charges()
(ase.atoms.Atoms method), 77
get_bandpath() (in module ase.dft.kpoints), 192
get_initial_magnetic_moments()
(ase.atoms.Atoms
get_bz_k_points() (ase.calculators.interface.DFTCalculator
method),
77
method), 164
get_calculation_done() (ase.atoms.Atoms method), 76 get_internal_energy() (ase.thermochemistry.CrystalThermo
method), 180
get_calculator() (ase.atoms.Atoms method), 76
get_internal_energy()
(ase.thermochemistry.HarmonicThermo
get_cell() (ase.atoms.Atoms method), 76
method),
180
get_celldisp() (ase.atoms.Atoms method), 76
get_k_point_weights() (ase.calculators.interface.DFTCalculator
get_center_of_mass() (ase.atoms.Atoms method), 76
method), 164
get_centers() (ase.dft.wannier.Wannier method), 194
get_kinetic_energy()
(ase.atoms.Atoms method), 77
get_charges() (ase.atoms.Atoms method), 76
get_magnetic_moment()
(ase.atoms.Atoms method),
get_chemical_formula() (ase.atoms.Atoms method), 76
77
get_chemical_symbols() (ase.atoms.Atoms method),
get_magnetic_moment()
76
(ase.calculators.interface.DFTCalculator
get_dihedral() (ase.atoms.Atoms method), 76
method), 164
get_dipole_moment() (ase.atoms.Atoms method), 76
get_magnetic_moments()
(ase.atoms.Atoms method),
get_distance() (ase.atoms.Atoms method), 77
77
get_distances() (ase.atoms.Atoms method), 77
get_masses() (ase.atoms.Atoms method), 77
get_distribution_moment() (in module ase.dft), 197
get_mode() (ase.vibrations.Vibrations method), 174
get_dos() (ase.dft.dos.DOS method), 197
get_momenta() (ase.atoms.Atoms method), 77
get_effective_potential()
get_moments_of_inertia() (ase.atoms.Atoms method),
(ase.calculators.interface.DFTCalculator
77
method), 164
Index
279
ASE Manual, Release 3.9.0.3865
get_monkhorst_pack_size_and_offset() (in module H
ase.dft.kpoints), 191
HarmonicThermo (class in ase.thermochemistry), 180
get_neighbors() (ase.calculators.neighborlist.NeighborListhas() (ase.atoms.Atoms method), 78
method), 208
hcp0001() (in module ase.lattice.surface), 104
get_number_of_atoms() (ase.atoms.Atoms method), 77 hcp10m10() (in module ase.lattice.surface), 103
get_number_of_bands()
HF, 235
(ase.calculators.interface.DFTCalculator
HOME, 15
method), 165
get_number_of_grid_points()
I
(ase.calculators.interface.DFTCalculator
IdealGasThermo (class in ase.thermochemistry), 178
method), 165
implemented_properties
get_number_of_spins()
(ase.calculators.calculator.Calculator
at(ase.calculators.interface.DFTCalculator
tribute), 250
method), 165
InfraRed (class in ase.infrared), 184
get_occupation_numbers()
initial_wannier() (ase.calculators.interface.DFTCalculator
(ase.calculators.interface.DFTCalculator
method), 165
method), 165
initialize() (ase.dft.wannier.Wannier method), 195
get_pbc() (ase.atoms.Atoms method), 77
initialize_density()
(ase.calculators.fleur.FLEUR
get_pdos() (ase.dft.wannier.Wannier method), 195
method), 147
get_points() (ase.visualize.vtk.grid.vtkAtomicPositions Instance, 235
method), 127
interpolate() (ase.neb.NEB method), 171
get_positions() (ase.atoms.Atoms method), 77
is_bundle() (ase.io.bundletrajectory.BundleTrajectory
get_potential_energies() (ase.atoms.Atoms method), 77
static method), 205
get_potential_energy() (ase.atoms.Atoms method), 77
is_empty_bundle() (ase.io.bundletrajectory.BundleTrajectory
get_potential_energy() (ase.calculators.interface.Calculator
static method), 206
method), 164
get_pseudo_density() (ase.calculators.interface.DFTCalculator
J
method), 165
Jacapo (class in ase.calculators.jacapo), 150
get_pseudo_wave_function()
(ase.calculators.interface.DFTCalculator
L
method), 165
LAMMPS (class in ase.calculators.LAMMPSrun), 152
get_radii() (ase.dft.wannier.Wannier method), 195
LAMMPS_COMMAND, 152
get_reciprocal_cell() (ase.atoms.Atoms method), 78
Langevin (class in ase.md.langevin), 188
get_scaled_positions() (ase.atoms.Atoms method), 78
LAPW, 235
get_spectrum() (ase.infrared.InfraRed method), 186
linescan() (ase.dft.stm.STM method), 198
get_spin_polarized() (ase.calculators.interface.DFTCalculator
localize() (ase.dft.wannier.Wannier method), 195
method), 165
log()
(ase.io.bundletrajectory.BundleTrajectory
get_stress() (ase.atoms.Atoms method), 78
method),
206
get_stress()
(ase.calculators.interface.Calculator
log()
(ase.visualize.fieldplotter.FieldPlotter
method),
method), 164
124
get_stresses() (ase.atoms.Atoms method), 78
log() (ase.visualize.primiplotter.PrimiPlotter method),
get_tags() (ase.atoms.Atoms method), 78
123
get_temperature() (ase.atoms.Atoms method), 78
get_total_energy() (ase.atoms.Atoms method), 78
M
get_unstructured_grid()
max_spread() (ase.dft.wannier.Wannier method), 195
(ase.visualize.vtk.grid.vtkAtomicPositions
Method, 235
method), 127
MinModeAtoms (class in ase.dimer), 231
get_velocities() (ase.atoms.Atoms method), 78
MinModeTranslate (class in ase.dimer), 232
get_volume() (ase.atoms.Atoms method), 78
molecule() (in module ase.structure), 100
get_wannier_localization_matrix()
monkhorst_pack() (in module ase.dft.kpoints), 191
(ase.calculators.interface.DFTCalculator
method), 165
N
get_xc_functional() (ase.calculators.interface.DFTCalculator
Namespace, 235
method), 165
nanotube() (in module ase.structure), 101
graphene_nanoribbon() (in module ase.structure), 101
ndarray, 235
gui, 88
NEB (class in ase.neb), 171
NeighborList (class in ase.calculators.neighborlist), 208
280
Index
ASE Manual, Release 3.9.0.3865
new_array() (ase.atoms.Atoms method), 78
NPT (class in ase.md.npt), 189
NPTBerendsen (class in ase.md.nptberendsen), 190
numbers (ase.atoms.Atoms attribute), 78
NumPy, 235
NVTBerendsen (class in ase.md.nvtberendsen), 188
S
save() (ase.dft.wannier.Wannier method), 195
scan() (ase.dft.stm.STM method), 198
SciPyFminBFGS (class in ase.optimize.sciopt), 118
SciPyFminCG (class in ase.optimize.sciopt), 118
Scope, 235
select() (ase.db.core.Database method), 215
O
select_data() (ase.io.bundletrajectory.BundleTrajectory
open() (ase.io.trajectory.PickleTrajectory method), 204
method), 206
opencew() (in module ase.utils), 207
set() (ase.calculators.calculator.Calculator method),
251
P
set() (in module ase.calculators), 130
set_actor() (ase.visualize.vtk.module.vtkGlyphModule
paropen() (in module ase.parallel), 120
method), 128
parprint() (in module ase.parallel), 120
set_angle() (ase.atoms.Atoms method), 79
PATH, 15, 245, 256
set_array() (ase.atoms.Atoms method), 79
pbc (ase.atoms.Atoms attribute), 78
set_atomic_numbers() (ase.atoms.Atoms method), 79
PickleTrajectory (class in ase.io.trajectory), 204
(ase.io.trajectory.PickleTrajectory
plot() (ase.visualize.fieldplotter.FieldPlotter method), set_atoms()
method), 204
124
plot() (ase.visualize.primiplotter.PrimiPlotter method), set_background() (ase.visualize.fieldplotter.FieldPlotter
method), 125
124
set_background_color()
plot() (in module ase.visualize.mlab), 121
(ase.visualize.fieldplotter.FieldPlotter
pop() (ase.atoms.Atoms method), 78
method), 125
positions (ase.atoms.Atoms attribute), 78
set_black_white_colors()
post_write_attach() (ase.io.bundletrajectory.BundleTrajectory
(ase.visualize.fieldplotter.FieldPlotter
method), 206
method), 125
post_write_attach() (ase.io.trajectory.PickleTrajectory
set_calculator() (ase.atoms.Atoms method), 79
method), 204
set_cell() (ase.atoms.Atoms method), 79
pre_write_attach() (ase.io.bundletrajectory.BundleTrajectory
set_chemical_symbols() (ase.atoms.Atoms method), 80
method), 206
pre_write_attach() (ase.io.trajectory.PickleTrajectory set_color_function() (ase.visualize.fieldplotter.FieldPlotter
method), 125
method), 204
set_color_function()
(ase.visualize.primiplotter.PrimiPlotter
PrimiPlotter (class in ase.visualize.primiplotter), 122
method),
124
Python, 235
set_colors()
(ase.visualize.primiplotter.PrimiPlotter
PYTHONPATH, 15, 20, 245, 256
method),
124
PYTHONSTARTUP, 18
set_constraint() (ase.atoms.Atoms method), 80
R
set_data_range() (ase.visualize.fieldplotter.FieldPlotter
method), 125
rattle() (ase.atoms.Atoms method), 78
set_dihedral()
(ase.atoms.Atoms method), 80
read() (ase.calculators.calculator.Calculator method),
set_dimensions()
(ase.visualize.fieldplotter.FieldPlotter
251
method),
125
read() (in module ase.io), 83
set_dimensions()
(ase.visualize.primiplotter.PrimiPlotter
read_cube_data() (in module ase.io), 86
method), 124
read_extra_data() (ase.io.bundletrajectory.BundleTrajectory
set_distance()
(ase.atoms.Atoms method), 80
method), 206
set_extra_data()
(ase.io.bundletrajectory.BundleTrajectory
read_results() (ase.calculators.calculator.FileIOCalculator
method),
206
method), 252
set_initial_charges()
(ase.atoms.Atoms method), 80
reference_states (in module ase.data), 201
set_initial_magnetic_moments()
(ase.atoms.Atoms
relax() (ase.calculators.fleur.FLEUR method), 147
method),
80
repeat() (ase.atoms.Atoms method), 78
set_invisibility_function()
reserve() (ase.db.core.Database method), 214
(ase.visualize.fieldplotter.FieldPlotter
reset() (ase.calculators.calculator.Calculator method),
method), 125
251
set_invisibility_function()
rotate() (ase.atoms.Atoms method), 79
(ase.visualize.primiplotter.PrimiPlotter
rotate_dihedral() (ase.atoms.Atoms method), 79
method), 124
rotate_euler() (ase.atoms.Atoms method), 79
set_invisible()
(ase.visualize.fieldplotter.FieldPlotter
run() (ase.vibrations.Vibrations method), 174
method), 125
Index
281
ASE Manual, Release 3.9.0.3865
set_invisible() (ase.visualize.primiplotter.PrimiPlotter update()
(ase.calculators.neighborlist.NeighborList
method), 124
method), 208
set_label()
(ase.calculators.calculator.Calculator update() (ase.db.core.Database method), 215
method), 250
update()
(ase.visualize.fieldplotter.FieldPlotter
set_log()
(ase.visualize.fieldplotter.FieldPlotter
method), 125
method), 125
update()
(ase.visualize.primiplotter.PrimiPlotter
set_log()
(ase.visualize.primiplotter.PrimiPlotter
method), 124
method), 124
V
set_masses() (ase.atoms.Atoms method), 80
set_momenta() (ase.atoms.Atoms method), 80
Vasp (class in ase.calculators.vasp), 158
set_output()
(ase.visualize.fieldplotter.FieldPlotter VASP_PP_PATH, 157
method), 125
VASP_SCRIPT, 157
set_output()
(ase.visualize.primiplotter.PrimiPlotter vdw_radii (in module ase.data), 201
method), 124
VelocityVerlet (class in ase.md.verlet), 188
set_pbc() (ase.atoms.Atoms method), 80
Vibrations (class in ase.vibrations), 173
set_plot_plane() (ase.visualize.fieldplotter.FieldPlotter view (module), 92
method), 125
view() (in module ase.visualize), 120
set_positions() (ase.atoms.Atoms method), 80
vtk, 126
set_property() (ase.visualize.vtk.module.vtkGlyphModulevtk (module), 126
method), 128
vtkAtomicPositions (class in ase.visualize.vtk.grid),
set_radii()
(ase.visualize.fieldplotter.FieldPlotter
127
method), 125
vtkAtoms (class in ase.visualize.vtk.atoms), 126
set_radii()
(ase.visualize.primiplotter.PrimiPlotter vtkGlyphModule (class in ase.visualize.vtk.module),
method), 124
127
set_red_yellow_colors()
W
(ase.visualize.fieldplotter.FieldPlotter
method), 125
Wannier (class in ase.dft.wannier), 193
set_rotation()
(ase.visualize.fieldplotter.FieldPlotter write() (ase.atoms.Atoms method), 81
method), 125
write() (ase.db.core.Database method), 214
set_rotation() (ase.visualize.primiplotter.PrimiPlotter write() (ase.dft.stm.STM method), 198
method), 124
write()
(ase.io.bundletrajectory.BundleTrajectory
set_scaled_positions() (ase.atoms.Atoms method), 81
method), 206
set_tags() (ase.atoms.Atoms method), 81
write() (ase.io.trajectory.PickleTrajectory method), 204
set_velocities() (ase.atoms.Atoms method), 81
write() (in module ase.io), 85
setup (module), 95
write_cube() (ase.dft.wannier.Wannier method), 195
Siesta (class in ase.calculators.siesta), 154
write_dos() (ase.vibrations.Vibrations method), 175
SIESTA_PP_PATH, 154
write_inp() (ase.calculators.fleur.FLEUR method), 147
SIESTA_SCRIPT, 154
write_input() (ase.calculators.calculator.FileIOCalculator
STM (class in ase.dft.stm), 198
method), 252
StrainFilter (class in ase.constraints), 170
write_jmol() (ase.vibrations.Vibrations method), 175
summary() (ase.vibrations.Vibrations method), 175
write_mode() (ase.vibrations.Vibrations method), 175
surface() (in module ase.lattice.surface), 107
write_spectra() (ase.infrared.InfraRed method), 186
SVN_EDITOR, 245
T
test, 15
test.test() (in module ase.test), 254
testase, 254
tools (module), 92
translate() (ase.atoms.Atoms method), 81
translate() (ase.dft.wannier.Wannier method), 195
translate_all_to_cell()
(ase.dft.wannier.Wannier
method), 195
translate_to_cell() (ase.dft.wannier.Wannier method),
195
U
UnitCellFilter (class in ase.constraints), 170
282
Index