Codebase list python-ase / a83331c
Imported Upstream version 3.16.0 Graham Inggs 6 years ago
252 changed file(s) with 13718 addition(s) and 5549 deletion(s). Raw diff Collapse all Expand all
99
1010 #editor backup files
1111 *.py~
12 *.rst~
13
14 # Ignore PyCharm settings
15 .idea/
16
17 # Vim swap files:
18 .*.sw?
19
20 # Translation template
21 ase/gui/po/ag.pot
00
11 python_2_7_tests:
2 image: python:2.7
23 script:
3 - apt-get update -qy
4 - apt-get install -qy python-pip python-numpy python-scipy pyflakes libhdf5-dev libnetcdf-dev cython
5 - pip install --upgrade setuptools
6 - pip install --user netCDF4
7 - pwd
8 - echo $HOME
9 - cd ..
10 - echo $PWD
11 # using 'install from source' instructions
4 # manually install ase deps
5 - pip install numpy scipy matplotlib flask
6 # extra packages for testing
7 - pip install pyflakes netCDF4
8 # using "install from source" instructions
129 - export PATH=$PATH:$CI_PROJECT_DIR/bin
1310 - echo $PATH
1411 - export PYTHONPATH=$CI_PROJECT_DIR
1613 # tests
1714 - python --version
1815 - ase info
19 - ase test
20 # pyflakes code check
16 - ase test -v
17 # pyflakes code check (Python 2 version)
2118 - cd $CI_PROJECT_DIR
22 - PYTHONPATH=$PWD python ase/test/__init__.py
19 - python ase/test/__init__.py
2320
2421 python_3_tests:
22 image: python:3
2523 script:
26 - apt-get update -qy
27 - apt-get install -qy python3-pip python3-numpy python3-scipy pyflakes gettext libhdf5-dev libnetcdf-dev cython3
28 - pip3 install --upgrade setuptools
29 - pip3 install --user netCDF4
30 # install ase into current python environment to ensure
31 # any shebang lines in scripts point to python3
32 - pip3 install --user .
33 # script path when installing with --user
34 - export PATH=$HOME/.local/bin:$PATH
35 # Running from a temporary directory to avoid import errors
36 - mkdir -p /tmp/test/ && cd /tmp/test && echo $PWD
24 # manually install extra deps
25 - pip install netCDF4 pyflakes
26 # 'pip install' pulls in all required packages
27 - pip install .
3728 # Run tests
38 - python3 --version
29 - python --version
3930 - ase info
4031 - ase test -v
41 # pyflakes code check
32 # pyflakes code check (Python 3 version)
4233 - cd $CI_PROJECT_DIR
43 - python3 ase/test/__init__.py
34 - python ase/test/__init__.py
35
36 conda_tests:
37 image: continuumio/anaconda3
38 script:
39 # manually install extra deps
40 - conda install -yq pip wheel numpy scipy pyflakes matplotlib flask
41 # 'pip install' pulls in all required packages
42 - pip install .
43 # Run tests
44 - python --version
45 - ase info
46 - ase test -v
47
48 docs_test:
49 image: python:3
50 script:
51 # 'pip install' pulls in all required packages (include docs)
52 - pip install .[docs]
53 # build the docs
54 - ase info
55 - which sphinx-build
56 - cd $CI_PROJECT_DIR/doc
57 - sphinx-build -W . build
58
0 Adam J. Jackson <a.j.jackson@physics.org> Adam J. Jackson <a.j.jackson@bath.ac.uk>
1 Adam Arvidsson <adamar@chalmers.se>
2 addman <mail@example.com> addman <addman@Bobor>
3 addman <mail@example.com> addman <addman@X201>
4 addman <mail@example.com> addman <pravod@gmail.com>
5 Alejandro Pérez Paz <alejandroperezpaz@yahoo.com>
6 Alexander Sougaard Tygesen <atygesen@hotmail.com>
7 Alin M Elena <alin@elena.space>
8 Andrew Peterson <andrew_peterson@brown.edu> Andrew Peterson <Andrew Peterson andrew_peterson@brown.edu>
9 Andrew Peterson <andrew_peterson@brown.edu> anpet <anpet@5af997e4-4c3d-0410-961e-ac0512e437d9>
10 Andrew Rosen <rosen@u.northwestern.edu>
11 Andrey Sobolev <andrey.n.sobolev@gmail.com>
12 anro <anro@5af997e4-4c3d-0410-961e-ac0512e437d9>
13 Antoni Macià <antoni.macia@ub.edu>
14 Anubhab Haldar <jinxhaldar@gmail.com>
15 Ask Hjorth Larsen <asklarsen@gmail.com> askhl <askhl@5af997e4-4c3d-0410-961e-ac0512e437d9>
16 Asmus O. Dohn <asod@hi.is> Asmus O. Dohn <asmus.od@gmail.com>
17 Asmus O. Dohn <asod@hi.is> Asmus Ougaard Dohn <asmus.od@gmail.com>
18 Ben Blaiszik <blaiszik@uchicago.edu>
19 Bismarrck <Bismarrck@me.com>
20 Jonas Bjork <J.Bjork@liverpool.ac.uk> bjork <bjork@5af997e4-4c3d-0410-961e-ac0512e437d9>
21 Pedro Brandimarte <brandimarte@gmail.com> brandimarte <brandimarte@gmail.com>
22 Brandon Cook <brandongc@gmail.com>
23 Carsten Rostgaard <mail@example.com> carstenr <carstenr@5af997e4-4c3d-0410-961e-ac0512e437d9>
24 chripa <chripa@5af997e4-4c3d-0410-961e-ac0512e437d9>
25 Christoph Schober <christoph.schober@ch.tum.de> Christoph <christoph.schober@ch.tum.de>
26 David Landis <mail@example.com> dlandis <dlandis@5af997e4-4c3d-0410-961e-ac0512e437d9>
27 Marcin Dułak <mail@example.com> dulak <dulak@5af997e4-4c3d-0410-961e-ac0512e437d9>
28 Edward Tait <ewt23@cam.ac.uk>
29 Eric Hermes <erichermes@gmail.com> ehermes <ehermes@5af997e4-4c3d-0410-961e-ac0512e437d9>
30 Eric Hermes <erichermes@gmail.com> Eric hermes <ehermes@wisc.edu>
31 Eric Hermes <erichermes@gmail.com> Eric Hermes <ehermes@wisc.edu>
32 Eric Hermes <erichermes@gmail.com> ehermes <ehermes@wisc.edu>
33 Emmanuel FARHI <farhi@ill.fr>
34 Eric Dill <edill@bnl.gov>
35 Eric Prestat <eric.prestat@gmail.com>
36 Erik Fransson <karl.erik.fransson@gmail.com>
37 Esben Leonhard Kolsbjerg <esb@phys.au.dk> Esben Leonhard Kolsbjerg <esb@s81n11.grendel.cscaa.dk>
38 Esben Leonhard Kolsbjerg <esb@phys.au.dk> Esben Leonhard Kolsbjerg <esb@st-d05496.local>
39 fras <fras@5af997e4-4c3d-0410-961e-ac0512e437d9>
40 Gaël Donval <gdonval+gitlab@gmail.com>
41 Jeppe Gavnholt <mail@example.com> gavnholt <gavnholt@5af997e4-4c3d-0410-961e-ac0512e437d9>
42 George Tritsaris <mail@example.com> getri <getri@5af997e4-4c3d-0410-961e-ac0512e437d9>
43 Geun Ho Gu <ggu@login000.(none)>
44 Gianluca Levi <giale@kemi.dtu.dk>
45 GitLab <gitlab@gitlab.com>
46 Glen R. Jenness <glenjenness@gmail.com> Glen Richard Jenness <gjenness@login000.(none)>
47 Glen R. Jenness <glenjenness@gmail.com> gjenness <gjenness@5af997e4-4c3d-0410-961e-ac0512e437d9>
48 googhgoo <googhgoo@hotmail.com>
49 Lars Grabow <mail@example.com> grabow <grabow@5af997e4-4c3d-0410-961e-ac0512e437d9>
50 Graham Inggs <graham@nerve.org.za> Graham Inggs <graham.inggs+gitlab@gmail.com>
51 Grigory Smirnov <grsmirnov@gmail.com>
52 Heine Anton Hansen <mail@example.com> hahansen <hahansen@5af997e4-4c3d-0410-961e-ac0512e437d9>
53 Felix Hanke <mail@example.com> hanke <hanke@5af997e4-4c3d-0410-961e-ac0512e437d9>
54 Hong Li <hongli520@gmail.com>
55 Igor Mosyagin <@Hannelore c6h10o5@gmail.com>
56 ithod <thod_@gmx.de>
57 Ivan Kondov <ivan.kondov@kit.edu>
58 Ivano Castelli <ivano@chem.ku.dk>
59 Jacob Madsen <jamad@fysik.dtu.dk>
60 Jakob Blomquist <knjakob.blomquist@gmail.com> jakobb <jakobb@5af997e4-4c3d-0410-961e-ac0512e437d9>
61 Jakob Blomquist <knjakob.blomquist@gmail.com> knjakob-blomquist <knjakob.blomquist@gmail.com>
62 Jakob Schiotz <schiotz@fysik.dtu.dk> schiotz <schiotz@5af997e4-4c3d-0410-961e-ac0512e437d9>
63 James Kermode <james.kermode@gmail.com> kermode <kermode@5af997e4-4c3d-0410-961e-ac0512e437d9>
64 jber <jber@5af997e4-4c3d-0410-961e-ac0512e437d9>
65 Janne Blomqvist <mail@example.com> jblomqvist <jblomqvist@5af997e4-4c3d-0410-961e-ac0512e437d9>
66 Jens Jørgen Mortensen <jensj@fysik.dtu.dk> jensj <jensj@5af997e4-4c3d-0410-961e-ac0512e437d9>
67 Jens Jørgen Mortensen <jensj@fysik.dtu.dk> Jens Jørgen Mortensen <jensj@jordan.fysik.dtu.dk>
68 Jens Jørgen Mortensen <jensj@fysik.dtu.dk> Jens Jorgen Mortensen <jensj@surt.fysik.dtu.dk>
69 Jens Jørgen Mortensen <jensj@fysik.dtu.dk> Jens Jørgen Mortensen <jjmo@dtu.dk>
70 Jesper Friis <jesper.friis@sintef.no> jesperf <jesperf@5af997e4-4c3d-0410-961e-ac0512e437d9>
71 Jess Wellendorff <mail@example.com> jesswe <jesswe@5af997e4-4c3d-0410-961e-ac0512e437d9>
72 jg <jag@psibox.dk>
73 Jin Chang <jchang@dtu.dk>
74 Jingzhe Chen <mail@example.com> jingzhe <jingzhe@5af997e4-4c3d-0410-961e-ac0512e437d9>
75 John Kitchin <jkitchin@cmu.edu> jk7683@kit.edu <jk7683@uc1n996.localdomain>
76 John Kitchin <jkitchin@cmu.edu> jk7683@kit.edu <jk7683@uc1n997.localdomain>
77 John Kitchin <jkitchin@cmu.edu> jkitchin <jkitchin@5af997e4-4c3d-0410-961e-ac0512e437d9>
78 Joakim Löfgren <joalof@chalmers.se> joalof <joalof@chalmers.se>
79 Joshua Lansford <lansford.jl@gmail.com> Joshua Lansford <Joshua Lansford>
80 Joshua Lansford <lansford.jl@gmail.com> JLans <lansford.jl@gmail.com>
81 Juan M. Lorenzi <jmlorenzi@gmail.com>
82 Jussi Enkovaara <mail@example.com> jussie <jussie@5af997e4-4c3d-0410-961e-ac0512e437d9>
83 Jun Yan <mail@example.com> juya <juya@5af997e4-4c3d-0410-961e-ac0512e437d9>
84 Keenan Lyon <klyon@uwaterloo.ca>
85 Kristen Kaasbjerg <mail@example.com> kkaa <kkaa@5af997e4-4c3d-0410-961e-ac0512e437d9>
86 Jesper Kleis <mail@example.com> kleis <kleis@5af997e4-4c3d-0410-961e-ac0512e437d9>
87 Korina Kuhar <kokuha@fysik.dtu.dk>
88 krbt <krbt@5af997e4-4c3d-0410-961e-ac0512e437d9>
89 Karsten Wedel Jacobsen <kwj@fysik.dtu.dk> kwj <kwj@5af997e4-4c3d-0410-961e-ac0512e437d9>
90 Lars Pastewka <lars.pastewka@imtek.uni-freiburg.de> Lars Pastewka <lars.pastewka@kit.edu>
91 Lars Pastewka <lars.pastewka@imtek.uni-freiburg.de> pastewka <pastewka@5af997e4-4c3d-0410-961e-ac0512e437d9>
92 Lasse Vilhelmsen <mail@example.com> lassebv <lassebv@5af997e4-4c3d-0410-961e-ac0512e437d9>
93 Leon Avakyan <laavakyan@sfedu.ru>
94 Letif Mones <letif.mones@gmail.com>
95 Logan Ward <ward.logan.t@gmail.com>
96 Lukasz Mentel <lmmentel@gmail.com>
97 Lynza Sprowl <lynza.sprowl@gmail.com> Lynza Halberstadt <halbersl@oregonstate.edu>
98 Mads Engelund <mail@example.com> Mads Engelund <mads_engelund001@ehu.es>
99 Mads Engelund <mail@example.com> mads.engelund <mads.engelund@5af997e4-4c3d-0410-961e-ac0512e437d9>
100 Magnus Nord <Magnus.Nord@glasgow.ac.uk> Magnus Nord <magnunor@gmail.com>
101 Maja Lenz <lenz@fhi-berlin.mpg.de> Maja-Olivia Lenz <lenz@fhi-berlin.mpg.de>
102 Marc Barbry <marc.barbarosa@gmail.com> marc barbry <marc.barbarosa@gmail.com>
103 Marc Barbry <marc.barbarosa@gmail.com> marc barbry <marc.barbry@mailoo.org>
104 Marko Melander <marmela@dtu.dk>
105 markus <markus@5af997e4-4c3d-0410-961e-ac0512e437d9>
106 Martin Hangaard Hansen <mhah@surt.fysik.dtu.dk> mhah <mhah@5af997e4-4c3d-0410-961e-ac0512e437d9>
107 Mathias Ljungberg <mathias.ljungberg@gmail.com> Mathias Ljungberg <mathias@captiveportal-10-100-14-106.local.su.se>
108 Mathias Ljungberg <mathias.ljungberg@gmail.com> Mathias Ljungberg <mathias@captiveportal-10-100-17-25.local.su.se>
109 Mathias Ljungberg <mathias.ljungberg@gmail.com> mathiasljungberg <mathias.ljungberg@gmail.com>
110 Mathias Ljungberg <mathias.ljungberg@gmail.com> Mathias Ljungberg <mathias@Mathiass-MacBook-Pro.local>
111 Mathias Ljungberg <mathias.ljungberg@gmail.com> Mathias Ljungberg <mathias@u020031.sw.ehu.es>
112 Mathias Ljungberg <mathias.ljungberg@gmail.com> Mathias <mathias.ljungberg@gmail.com>
113 Mazay <mazay0@gmail.com> mazay <mazay@mzh>
114 Michael Walter <Michael.Walter@fmf.uni-freiburg.de> Michael Walter <mcoywalter@gmail.com>
115 Michael Walter <Michael.Walter@fmf.uni-freiburg.de> Michael Walter <@ PC-L192 mcoywalter@gmail.com>
116 Michael Walter <Michael.Walter@fmf.uni-freiburg.de> miwalter <miwalter@5af997e4-4c3d-0410-961e-ac0512e437d9>
117 Miguel Caro <mcaroba@gmail.com>
118 Mikael Kuisma <mikael.j.kuisma@jyu.fi>
119 Mikkel Strange <mikst@fysik.dtu.dk> Mikkel Strange <strange@chem.ku.dk>
120 Mikkel Strange <mikst@fysik.dtu.dk> Strange, Mikkel (smikk) <mikst@fysik.dtu.dk>
121 Mikkel Strange <mikst@fysik.dtu.dk> strange <strange@5af997e4-4c3d-0410-961e-ac0512e437d9>
122 Morten Gjerding <mogje@fysik.dtu.dk> mogje <mogje@5af997e4-4c3d-0410-961e-ac0512e437d9>
123 mohpa <mohpa@5af997e4-4c3d-0410-961e-ac0512e437d9>
124 Morten Gjerding <mogje@fysik.dtu.dk> mortengjerding <mogje@fysik.dtu.dk>
125 Morten Gjerding <mogje@fysik.dtu.dk> Morten Gjerding <mogje@fysik.dtu.dk>
126 Morten Nagel <morten.nagel@helsinki.fi>
127 Poul Georg Moses <mail@example.com> moses <moses@5af997e4-4c3d-0410-961e-ac0512e437d9>
128 Marco Vanin <mail@example.com> mvanin <mvanin@5af997e4-4c3d-0410-961e-ac0512e437d9>
129 mvdb <maxime.cp.vandenbossche@gmail.com>
130 Nicki Frank Hinsche <nickih@surt.fysik.dtu.dk>
131 Ole Schütt <ole.schuett@empa.ch> Ole Schuett <ole.schuett@empa.ch>
132 Ole Schütt <ole.schuett@empa.ch> Ole Schütt <oschuett@cp2k.org>
133 Ole Schütt <ole.schuett@empa.ch> oschuett <oschuett@5af997e4-4c3d-0410-961e-ac0512e437d9>
134 Oliver Brügner <oliver-bruegner@web.de>
135 Otto Kohulak <kohulak@Maxwell00> Otto Kohulák <pravod@gmail.com>
136 Markus Kaukonen <markus.kaukonen@iki.fi> paapu68 <markus.kaukonen@iki.fi>
137 Paul C. Jennings <jennings.p.c@gmail.com> Paul C. Jennings <pcje@surt.fysik.dtu.dk>
138 Paul Erhart <erhart@chalmers.se>
139 Paweł T. Jochym <pawel.jochym@ifj.edu.pl> Paweł T. Jochym <jochym@wolf.ifj.edu.pl>
140 Paweł T. Jochym <pawel.jochym@ifj.edu.pl> Pawel T. Jochym <pawel.jochym@ifj.edu.pl>
141 Pedro Brandimarte <brandimarte@gmail.com>
142 Per S. Schmidt <psisc@fysik.dtu.dk> psisc <psisc@5af997e4-4c3d-0410-961e-ac0512e437d9>
143 prtkm <prateekm@cmu.edu>
144 pvstishenko <pavelstishenko@yandex.ru>
145 pvst <pvst@localhost.localdomain>
146 Rasmus K <shandolad@gmail.com>
147 refreshx2 <jjmaldonis@gmail.com>
148 Robert Warmbier <Robert.Warmbier@wits.ac.za> rowue <rowue@5af997e4-4c3d-0410-961e-ac0512e437d9>
149 Christian Glinsvad <mail@example.com> s032082 <s032082@5af997e4-4c3d-0410-961e-ac0512e437d9>
150 s042606 <s042606@5af997e4-4c3d-0410-961e-ac0512e437d9>
151 s052580 <s052580@5af997e4-4c3d-0410-961e-ac0512e437d9>
152 Santiago Cingolani <santiago.cingolani@gmail.com>
153 schenkst <schenkst@5af997e4-4c3d-0410-961e-ac0512e437d9>
154 shrx <differenxe@gmail.com>
155 Simon Brodersen <mail@example.com> sihb <sihb@5af997e4-4c3d-0410-961e-ac0512e437d9>
156 Simone Sturniolo <wml08325@scpc044.esc.rl.ac.uk> Simone Sturniolo <simonesturniolo@gmail.com>
157 Simone Sturniolo <wml08325@scpc044.esc.rl.ac.uk> Simone Sturniolo <simone.sturniolo@stfc.ac.uk>
158 Simone Sturniolo <wml08325@scpc044.esc.rl.ac.uk> Simone Sturniolo <wml08325@faraday.esc.rl.ac.uk>
159 Simone Sturniolo <wml08325@scpc044.esc.rl.ac.uk> Simone Sturniolo <wml08325@scpc044.esc.rl.ac.uk>
160 Simone Sturniolo <wml08325@scpc044.esc.rl.ac.uk> Simone <wml08325@scpc044.esc.rl.ac.uk>
161 Simone Sturniolo <wml08325@scpc044.esc.rl.ac.uk> stur86 <simonesturniolo@gmail.com>
162 Simon Rittmeyer <simon.rittmeyer@tum.de>
163 Matthias Slabanja <mail@example.com> slabanja <slabanja@5af997e4-4c3d-0410-961e-ac0512e437d9>
164 Steen Lysgaard <stly@dtu.dk> Steen Lysgaard <stly@surt.fysik.dtu.dk>
165 Steen Lysgaard <stly@dtu.dk> stly <stly@5af997e4-4c3d-0410-961e-ac0512e437d9>
166 Steen Lysgaard <stly@dtu.dk> stly <stly@dtu.dk>
167 Sten Haastrup <sthaa@mott.fysik.dtu.dk> Sten Haastrup <sten.haastrup@gmail.com>
168 tdd20@cam.ac.uk <tdd20@cam.ac.uk>
169 Thorsten Deilmann <thorsten.deilmann@uni-muenster.de>
170 Tiziano Müller <tiziano.mueller@chem.uzh.ch>
171 Tao Jiang <mail@example.com> tjiang <tjiang@5af997e4-4c3d-0410-961e-ac0512e437d9>
172 Thomas Olsen <mail@example.com> tolsen <tolsen@5af997e4-4c3d-0410-961e-ac0512e437d9>
173 Toma Susi <toma.susi@iki.fi>
174 Tom Daff <tdd20@cam.ac.uk>
175 Tristan Maxson <tgmaxson@gmail.com> Tristan G Maxson <tgmaxson@gmail.com>
176 Tristan Maxson <tgmaxson@gmail.com> tgmaxson <tgmaxson@5af997e4-4c3d-0410-961e-ac0512e437d9>
177 Tristan Maxson <tgmaxson@gmail.com> tgmaxson <tgmaxson@gmail.com>
178 Tuomas Rossi <tuomas.rossi@aalto.fi>
179 Yingchun Zhang <yczhang@smail.nju.edu.cn>
180 Yinjia Zhang <yz144@login001.oscar.ccv.brown.edu>
181 Zhenhua Zeng <zeng46@purdue.edu> zeng <zeng@5af997e4-4c3d-0410-961e-ac0512e437d9>
00 include MANIFEST.in
11 include COPYING* LICENSE README.rst CONTRIBUTING.rst CHANGELOG.rst
22 include requirements.txt
3 include bin/ase
4 include bin/ase3
35 include ase/spacegroup/spacegroup.dat
46 include ase/collections/*.json
57 include ase/db/static/*
68 include ase/db/templates/*
7 include ase/gui/po/ag.pot
89 include ase/gui/po/Makefile
910 include ase/gui/po/??_??/LC_MESSAGES/ag.po
1011 include ase/gui/po/??/LC_MESSAGES/ag.po
11 matrix:
22 # For Python versions available on Appveyor, see
33 # http://www.appveyor.com/docs/installed-software#python
4 # Use Anaconda as SciPy is a headache with Windows.
5 # 2.7
6 - PYTHON: "C:\\Miniconda"
7 # 2.7 64-bit
8 - PYTHON: "C:\\Miniconda-x64"
9 # 3.4
10 - PYTHON: "C:\\Miniconda3"
11 # 3.4 64-bit
12 - PYTHON: "C:\\Miniconda3-x64"
13 # 3.5
14 - PYTHON: "C:\\Miniconda35"
15 # 3.5 64-bit
16 - PYTHON: "C:\\Miniconda35-x64"
17 # 3.6
18 - PYTHON: "C:\\Miniconda36"
19 # 3.6 64-bit
20 - PYTHON: "C:\\Miniconda36-x64"
4 # # Python 2.7
5 #- PYTHON: "C:\\Python27"
6 # # Python 2.7 - 64-bit
7 #- PYTHON: "C:\\Python27-x64"
8 # # Python 3.6
9 #- PYTHON: "C:\\Python36"
10 # Python 3.6 - 64-bit
11 - PYTHON: "C:\\Python36-x64"
12 # # Conda 2.7
13 #- PYTHON: "C:\\Miniconda"
14 # # Conda 2.7 64-bit
15 #- PYTHON: "C:\\Miniconda-x64"
16 # # Conda 3.6
17 #- PYTHON: "C:\\Miniconda36"
18 # # Conda 3.6 64-bit
19 #- PYTHON: "C:\\Miniconda36-x64"
2120
2221 install:
2322 # Prepend chosen Python to the PATH of this build
2524 # Check that we have the expected version and architecture for Python
2625 - "python --version"
2726 - "python -c \"import struct; print(struct.calcsize('P') * 8)\""
28 # Install the conda supplied packages; msvc_runtime needed for py34
29 - "conda update -y conda"
30 - "conda install -y pip wheel numpy scipy pyflakes msvc_runtime"
27 # Install the conda supplied packages if using conda, otherwise use pip
28 # The wheel package is needed for 'pip wheel'
29 # Turn off progressbars '-q' otherwise PowerShell thinks there are errors
30 - ps: |
31 if($env:PYTHON -match "conda")
32 {
33 conda update -yq conda
34 conda install -yq pip wheel numpy scipy pyflakes matplotlib flask
35 }
36 else
37 {
38 pip install --upgrade pip
39 pip install wheel
40 }
3141 # install ase into the current python
3242 - "echo %cd%"
3343 - "where pip"
3949 # run tests from temp dir so source tree doesn't interfere
4050 - "cd %TEMP%"
4151 - "ase info"
42 - "ase test"
52 - "ase test -v"
4353
4454 after_test:
4555 # This step builds distribution.
1010 from ase.atoms import Atoms
1111
1212 __all__ = ['Atoms', 'Atom']
13 __version__ = '3.15.0'
13 __version__ = '3.16.0'
1414
1515 # import ase.parallel early to avoid circular import problems when
1616 # ase.parallel does "from gpaw.mpi import world":
1919 from ase.data import atomic_numbers, chemical_symbols, atomic_masses
2020 from ase.utils import basestring, formula_hill, formula_metal
2121 from ase.geometry import (wrap_positions, find_mic, cellpar_to_cell,
22 cell_to_cellpar, complete_cell, is_orthorhombic)
22 cell_to_cellpar, complete_cell, is_orthorhombic,
23 get_angles, get_distances)
2324
2425
2526 class Atoms(object):
360361 First three are unit cell vector lengths and second three
361362 are angles between them::
362363
363 [len(a), len(b), len(c), angle(a,b), angle(a,c), angle(b,c)]
364 [len(a), len(b), len(c), angle(b,c), angle(a,c), angle(a,b)]
364365
365366 in degrees.
366367 """
470471 self.set_array('numbers', symbols2numbers(symbols), int, ())
471472
472473 def get_chemical_formula(self, mode='hill'):
473 """Get the chemial formula as a string based on the chemical symbols.
474 """Get the chemical formula as a string based on the chemical symbols.
474475
475476 Parameters:
476477
477478 mode: str
478479 There are three different modes available:
479480
480 'all': The list of chemical symbols are contracted to at string,
481 'all': The list of chemical symbols are contracted to a string,
481482 e.g. ['C', 'H', 'H', 'H', 'O', 'H'] becomes 'CHHHOH'.
482483
483484 'reduce': The same as 'all' where repeated elements are contracted
489490 first), e.g. 'CHHHOCHHH' is reduced to 'C2H6O' and 'SOOHOHO' to
490491 'H2O4S'. This is default.
491492
492 'metal': The list of checmical symbols (alphabetical metals,
493 'metal': The list of chemical symbols (alphabetical metals,
493494 and alphabetical non-metals)
494495 """
495496 if len(self) == 0:
14781479 start = self.get_dihedral(a1)
14791480 self.set_dihedral(a1, angle + start, mask)
14801481
1481 def get_angle(self, a1, a2=None, a3=None, mic=False):
1482 def get_angle(self, a1, a2, a3, mic=False):
14821483 """Get angle formed by three atoms.
14831484
14841485 calculate angle in degrees between the vectors a2->a1 and
14881489 angle across periodic boundaries.
14891490 """
14901491
1491 if a2 is None:
1492 # old API (uses radians)
1493 warnings.warn(
1494 'Please use new API (which will return the angle in degrees): '
1495 'atoms_obj.get_angle(a1,a2,a3)*pi/180 instead of '
1496 'atoms_obj.get_angle([a1,a2,a3])')
1497 assert a3 is None
1498 a1, a2, a3 = a1
1499 f = 1
1500 else:
1501 f = 180 / pi
1502
1503 # normalized vector 1->0, 1->2:
1504 v10 = self.positions[a1] - self.positions[a2]
1505 v12 = self.positions[a3] - self.positions[a2]
1492 indices = np.array([[a1, a2, a3]])
1493
1494 a1s = self.positions[indices[:, 0]]
1495 a2s = self.positions[indices[:, 1]]
1496 a3s = self.positions[indices[:, 2]]
1497
1498 v12 = a1s - a2s
1499 v32 = a3s - a2s
1500
1501 cell = None
1502 pbc = None
1503
15061504 if mic:
1507 v10, v12 = find_mic([v10, v12], self._cell, self._pbc)[0]
1508 v10 /= np.linalg.norm(v10)
1509 v12 /= np.linalg.norm(v12)
1510 angle = np.vdot(v10, v12)
1511 angle = np.arccos(angle)
1512 return angle * f
1505 cell = self._cell
1506 pbc = self._pbc
1507
1508 return get_angles(v12, v32, cell=cell, pbc=pbc)[0]
1509
1510
1511 def get_angles(self, indices, mic=False):
1512 """Get angle formed by three atoms for multiple groupings.
1513
1514 calculate angle in degrees between vectors between atoms a2->a1
1515 and a2->a3, where a1, a2, and a3 are in each row of indices.
1516
1517 Use mic=True to use the Minimum Image Convention and calculate
1518 the angle across periodic boundaries.
1519 """
1520
1521 indices = np.array(indices)
1522
1523 a1s = self.positions[indices[:, 0]]
1524 a2s = self.positions[indices[:, 1]]
1525 a3s = self.positions[indices[:, 2]]
1526
1527 v12 = a1s - a2s
1528 v32 = a3s - a2s
1529
1530 cell = None
1531 pbc = None
1532
1533 if mic:
1534 cell = self._cell
1535 pbc = self._pbc
1536
1537 return get_angles(v12, v32, cell=cell, pbc=pbc)
1538
15131539
15141540 def set_angle(self, a1, a2=None, a3=None, angle=None, mask=None):
15151541 """Set angle (in degrees) formed by three atoms.
15731599 """
15741600
15751601 R = self.arrays['positions']
1576 D = np.array([R[a1] - R[a0]])
1602 p1 = [R[a0]]
1603 p2 = [R[a1]]
1604
1605 cell = None
1606 pbc = None
1607
15771608 if mic:
1578 D, D_len = find_mic(D, self._cell, self._pbc)
1579 else:
1580 D_len = np.array([np.sqrt((D**2).sum())])
1609 cell = self._cell
1610 pbc = self._pbc
1611
1612 D, D_len = get_distances(p1, p2, cell=cell, pbc=pbc)
1613
15811614 if vector:
1582 return D[0]
1583
1584 return D_len[0]
1615 return D[0, 0]
1616 else:
1617 return D_len[0, 0]
1618
15851619
15861620 def get_distances(self, a, indices, mic=False, vector=False):
15871621 """Return distances of atom No.i with a list of atoms.
15911625 """
15921626
15931627 R = self.arrays['positions']
1594 D = R[indices] - R[a]
1628 p1 = [R[a]]
1629 p2 = R[indices]
1630
1631 cell = None
1632 pbc = None
1633
15951634 if mic:
1596 D, D_len = find_mic(D, self._cell, self._pbc)
1597 else:
1598 D_len = np.sqrt((D**2).sum(1))
1635 cell = self._cell
1636 pbc = self._pbc
1637
1638 D, D_len = get_distances(p1, p2, cell=cell, pbc=pbc)
1639
1640 if vector:
1641 D.shape = (-1, 3)
1642 return D
1643 else:
1644 D_len.shape = (-1,)
1645 return D_len
1646
1647
1648 def get_all_distances(self, mic=False, vector=False):
1649 """Return distances of all of the atoms with all of the atoms.
1650
1651 Use mic=True to use the Minimum Image Convention.
1652 """
1653 R = self.arrays['positions']
1654
1655 cell = None
1656 pbc = None
1657
1658 if mic:
1659 cell = self._cell
1660 pbc = self._pbc
1661
1662 D, D_len = get_distances(R, cell=cell, pbc=pbc)
1663
15991664 if vector:
16001665 return D
1601 return D_len
1602
1603 def get_all_distances(self, mic=False):
1604 """Return distances of all of the atoms with all of the atoms.
1605
1606 Use mic=True to use the Minimum Image Convention.
1607 """
1608 L = len(self)
1609 R = self.arrays['positions']
1610
1611 D = []
1612 for i in range(L - 1):
1613 D.append(R[i + 1:] - R[i])
1614 D = np.concatenate(D)
1615
1616 if mic:
1617 D, D_len = find_mic(D, self._cell, self._pbc)
1618 else:
1619 D_len = np.sqrt((D**2).sum(1))
1620
1621 results = np.zeros((L, L), dtype=float)
1622 start = 0
1623 for i in range(L - 1):
1624 results[i, i + 1:] = D_len[start:start + L - i - 1]
1625 start += L - i - 1
1626 return results + results.T
1666 else:
1667 return D_len
1668
16271669
16281670 def set_distance(self, a0, a1, distance, fix=0.5, mic=False):
16291671 """Set the distance between two atoms.
18101852 from ase.io import write
18111853 write(filename, self, format, **kwargs)
18121854
1813 def _images_(self):
1855 def iterimages(self):
18141856 yield self
18151857
18161858 def edit(self):
439439 newatoms = atoms.copy()
440440 for index, order in enumerate(orders):
441441 newatoms[index].position = atoms[order[0]].position.copy()
442
443 # Add empty 'sites' dictionary for consistency with other functions
444 newatoms.info['adsorbate_info'] = {'sites': {}}
442445 return newatoms
443446
444447
11
22 Felix Hanke hanke@liverpool.ac.uk
33 Jonas Bjork j.bjork@liverpool.ac.uk
4 Simon P. Rittmeyer simon.rittmeyer@tum.de
45 """
56
67 import os
78
89 import numpy as np
10 import warnings
11 import time
912
1013 from ase.units import Hartree
1114 from ase.io.aims import write_aims, read_aims
115118
116119
117120 class Aims(FileIOCalculator):
118 command = 'aims.version.serial.x > aims.out'
121 # was "command" before the refactoring to dynamical commands
122 __command_default = 'aims.version.serial.x > aims.out'
123 __outfilename_default = 'aims.out'
124
119125 implemented_properties = ['energy', 'forces', 'stress', 'dipole', 'magmom']
120126
121127 def __init__(self, restart=None, ignore_bad_restart_file=False,
122128 label=os.curdir, atoms=None, cubes=None, radmul=None,
123 tier=None, **kwargs):
124 """Construct FHI-aims calculator.
125
129 tier=None, aims_command=None,
130 outfilename=None, **kwargs):
131 """Construct the FHI-aims calculator.
132
126133 The keyword arguments (kwargs) can be one of the ASE standard
127134 keywords: 'xc', 'kpts' and 'smearing' or any of FHI-aims'
128135 native keywords.
129
130 Additional arguments:
136
137 .. note:: The behavior of command/run_command has been refactored ase X.X.X
138 It is now possible to independently specify the command to call
139 FHI-aims and the outputfile into which stdout is directed. In
140 general, we replaced
141
142 <run_command> = <aims_command> + " > " + <outfilename
143
144 That is,what used to be, e.g.,
145
146 >>> calc = Aims(run_command = "mpiexec -np 4 aims.x > aims.out")
147
148 can now be achieved with the two arguments
149
150 >>> calc = Aims(aims_command = "mpiexec -np 4 aims.x"
151 >>> outfilename = "aims.out")
152
153 Backward compatibility, however, is provided. Also, the command
154 actually used to run FHI-aims is dynamically updated (i.e., the
155 "command" member variable). That is, e.g.,
156
157 >>> calc = Aims()
158 >>> print(calc.command)
159 aims.version.serial.x > aims.out
160 >>> calc.outfilename = "systemX.out"
161 >>> print(calc.command)
162 aims.version.serial.x > systemX.out
163 >>> calc.aims_command = "mpiexec -np 4 aims.version.scalapack.mpi.x"
164 >>> print(calc.command)
165 mpiexec -np 4 aims.version.scalapack.mpi > systemX.out
166
167
168 Arguments:
131169
132170 cubes: AimsCube object
133171 Cube file specification.
172
134173 radmul: int
135174 Set radial multiplier for the basis set of all atomic species.
175
136176 tier: int or array of ints
137177 Set basis set tier for all atomic species.
178
179 aims_command : str
180 The full command as executed to run FHI-aims *without* the
181 redirection to stdout. For instance "mpiexec -np 4 aims.x". Note
182 that this is not the same as "command" or "run_command".
183 .. note:: Added in ase X.X.X
184
185 outfilename : str
186 The file (incl. path) to which stdout is redirected. Defaults to
187 "aims.out"
188 .. note:: Added in ase X.X.X
189
190 run_command : str, optional (default=None)
191 Same as "command", see FileIOCalculator documentation.
192 .. note:: Deprecated in ase X.X.X
193
194 outfilename : str, optional (default=aims.out)
195 File into which the stdout of the FHI aims run is piped into. Note
196 that this will be only of any effect, if the <run_command> does not
197 yet contain a '>' directive.
198
199 kwargs : dict
200 Any of the base class arguments.
201
138202 """
139 try:
140 self.outfilename = kwargs.get('run_command').split()[-1]
141 except:
142 self.outfilename = 'aims.out'
143
203 # yes, we pop the key and run it through our legacy filters
204 command = kwargs.pop('command', None)
205
206 # Check for the "run_command" (deprecated keyword)
207 # Consistently, the "command" argument should be used as suggested by the FileIO base class.
208 # For legacy reasons, however, we here also accept "run_command"
209 run_command = kwargs.pop('run_command', None)
210 if run_command:
211 # this warning is debatable... in my eyes it is more consistent to
212 # use 'command'
213 warnings.warn('Argument "run_command" is deprecated and will be replaced with "command". Alternatively, use "aims_command" and "outfile". See documentation for more details.')
214 if command:
215 warnings.warn('Caution! Argument "command" overwrites "run_command.')
216 else:
217 command=run_command
218
219 # this is the fallback to the default value for empty init
220 if np.all([i is None for i in (command, aims_command, outfilename)]):
221 # we go for the FileIOCalculator default way (env variable) with the former default as fallback
222 command = os.environ.get('ASE_AIMS_COMMAND', Aims.__command_default)
223
224
225 # filter the command and set the member variables "aims_command" and "outfilename"
226 self.__init_command(command=command,
227 aims_command=aims_command,
228 outfilename=outfilename)
229
144230 FileIOCalculator.__init__(self, restart, ignore_bad_restart_file,
145231 label, atoms,
146 command=kwargs.get('run_command'),
232 # well, this is not nice, but cannot work around it...
233 command=self.command,
147234 **kwargs)
235
148236 self.cubes = cubes
149237 self.radmul = radmul
150238 self.tier = tier
151239
152 def set_label(self, label):
240 # handling the filtering for dynamical commands with properties,
241 @property
242 def command(self):
243 return self.__command
244 @command.setter
245 def command(self, x):
246 self.__update_command(command=x)
247
248 @property
249 def aims_command(self):
250 return self.__aims_command
251
252 @aims_command.setter
253 def aims_command(self, x):
254 self.__update_command(aims_command=x)
255
256 @property
257 def outfilename(self):
258 return self.__outfilename
259
260 @outfilename.setter
261 def outfilename(self, x):
262 self.__update_command(outfilename=x)
263
264 def __init_command(self, command=None, aims_command=None,
265 outfilename=None):
266 """
267 Create the private variables for which properties are defines and set
268 them accordingly.
269 """
270 # new class variables due to dynamical command handling
271 self.__aims_command = None
272 self.__outfilename = None
273 self.__command = None
274
275 # filter the command and set the member variables "aims_command" and "outfilename"
276 self.__update_command(command=command,
277 aims_command=aims_command,
278 outfilename=outfilename)
279
280 # legacy handling of the (run_)command behavior a.k.a. a universal setter routine
281 def __update_command(self, command=None, aims_command=None,
282 outfilename=None):
283 """
284 Abstracted generic setter routine for a dynamic behavior of "command".
285
286 The command that is actually called on the command line and enters the
287 base class, is <command> = <aims_command> > <outfilename>.
288
289 This new scheme has been introduced in order to conveniently change the
290 outfile name from the outside while automatically updating the
291 <command> member variable.
292
293 Obiously, changing <command> conflicts with changing <aims_command>
294 and/or <outfilename>, which thus raises a <ValueError>. This should,
295 however, not happen if this routine is not used outside the property
296 definitions.
297
298 Parameters
299 ----------
300 command : str
301 The full command as executed to run FHI-aims. This includes
302 any potential mpiexec call, as well as the redirection of stdout.
303 For instance "mpiexec -np 4 aims.x > aims.out".
304
305 aims_command : str
306 The full command as executed to run FHI-aims *without* the
307 redirection to stdout. For instance "mpiexec -np 4 aims.x"
308
309 outfilename : str
310 The file (incl. path) to which stdout is redirected.
311 """
312 # disentangle the command if given
313 if command:
314 if aims_command:
315 raise ValueError('Cannot specify "command" and "aims_command" simultaneously.')
316 if outfilename:
317 raise ValueError('Cannot specify "command" and "outfilename" simultaneously.')
318
319 # check if the redirection of stdout is included
320 command_spl = command.split('>')
321 if len(command_spl) > 1:
322 self.__aims_command = command_spl[0].strip()
323 self.__outfilename = command_spl[-1].strip()
324 else:
325 # this should not happen if used correctly
326 # but just to ensure legacy behavior of how "run_command" was handled
327 self.__aims_command = command.strip()
328 self.__outfilename = Aims.__outfilename_default
329 else:
330 if aims_command is not None:
331 self.__aims_command = aims_command
332 elif outfilename is None:
333 # nothing to do here, empty call with 3x None
334 return
335 if outfilename is not None:
336 self.__outfilename = outfilename
337 else:
338 # default to 'aims.out'
339 if not self.outfilename:
340 self.__outfilename = Aims.__outfilename_default
341
342 self.__command = '{0:s} > {1:s}'.format(self.aims_command, self.outfilename)
343
344 def set_atoms(self, atoms):
345 self.atoms = atoms
346
347 def set_label(self, label, update_outfilename=False):
153348 self.label = label
154349 self.directory = label
155350 self.prefix = ''
351 # change outfile name to "<label.out>"
352 if update_outfilename:
353 self.outfilename="{}.out".format(os.path.basename(label))
156354 self.out = os.path.join(label, self.outfilename)
157355
158356 def check_state(self, atoms):
168366 kwargs['xc'] = {'LDA': 'pw-lda', 'PBE': 'pbe'}.get(xc, xc)
169367
170368 changed_parameters = FileIOCalculator.set(self, **kwargs)
171
369
172370 if changed_parameters:
173371 self.reset()
174372 return changed_parameters
175373
176 def write_input(self, atoms, scaled = False, properties=None, system_changes=None,
177 ghosts=None):
374 def write_input(self, atoms, properties=None, system_changes=None,
375 ghosts=None, scaled=False):
178376 FileIOCalculator.write_input(self, atoms, properties, system_changes)
179377
180378 have_lattice_vectors = atoms.pbc.any()
189387 self.write_species(atoms, os.path.join(self.directory, 'control.in'))
190388 self.parameters.write(os.path.join(self.directory, 'parameters.ase'))
191389
390 def prepare_input_files(self):
391 """
392 Wrapper function to prepare input filesi, e.g., to a run on a remote
393 machine
394 """
395 if self.atoms is None:
396 raise ValueError('No atoms object attached')
397 self.write_input(self.atoms)
398
192399 def write_control(self, atoms, filename):
400 lim = '#' + '='*79
193401 output = open(filename, 'w')
194 for line in ['=====================================================',
195 'FHI-aims file: ' + filename,
402 output.write(lim + '\n')
403 for line in ['FHI-aims file: ' + filename,
196404 'Created using the Atomic Simulation Environment (ASE)',
405 time.asctime(),
197406 '',
198407 'List of parameters used to initialize the calculator:',
199 '=====================================================']:
200 output.write('#' + line + '\n')
408 ]:
409 output.write('# ' + line + '\n')
410 for p,v in self.parameters.iteritems():
411 s = '# {} : {}\n'.format(p, v)
412 output.write(s)
413 output.write(lim + '\n')
414
201415
202416 assert not ('kpts' in self.parameters and 'k_grid' in self.parameters)
203417 assert not ('smearing' in self.parameters and
237451 output.write('%-35s%r\n' % (key, value))
238452 if self.cubes:
239453 self.cubes.write(output)
240 output.write(
241 '#=======================================================\n\n')
454 output.write(lim + '\n\n')
242455 output.close()
243456
244457 def read(self, label):
245458 FileIOCalculator.read(self, label)
246459 geometry = os.path.join(self.directory, 'geometry.in')
247460 control = os.path.join(self.directory, 'control.in')
248
461
249462 for filename in [geometry, control, self.out]:
250463 if not os.path.isfile(filename):
251464 raise ReadError
640853 self.edges = edges
641854 self.points = points
642855 self.plots = plots
643
856
644857 def ncubes(self):
645858 """returns the number of cube files to output """
646859 if self.plots:
1313 import ase.units as units
1414 from scipy.io import netcdf
1515
16 # SPC/Fw charge on H
17 qH = 0.410
1618
1719 class Amber(FileIOCalculator):
1820 """Class for doing Amber classical MM calculations.
235237 f = netcdf.netcdf_file(filename, 'r')
236238 forces = f.variables['forces']
237239 self.results['forces'] = forces[-1, :, :] \
238 / units.Ang * units.kJ / units.mol
240 / units.Ang * units.kcal / units.mol
239241 f.close()
240242
241243 def set_charges(self, selection, charges, parmed_filename=None):
265267 raise RuntimeError('%s returned an error: %d' %
266268 (self.label, errorcode))
267269
270 def get_virtual_charges(self, atoms):
271 charges = np.empty(len(atoms))
272 charges[:] = qH
273 if atoms.numbers[0] == 8:
274 charges[::3] = -2 * qH
275 else:
276 charges[2::3] = -2 * qH
277 return charges
278
279 def add_virtual_sites(self, positions):
280 return positions # no virtual sites
281
282 def redistribute_forces(self, forces):
283 return forces
268284
269285 def map(atoms, top):
270286 p = np.zeros((2, len(atoms)), dtype="int")
1515 pass
1616
1717
18 def compare_atoms(atoms1, atoms2, tol=1e-15):
19 """Check for system changes since last calculation."""
20 if atoms1 is None:
21 system_changes = all_changes[:]
22 else:
23 system_changes = []
24 if not equal(atoms1.positions, atoms2.positions, tol):
25 system_changes.append('positions')
26 if not equal(atoms1.numbers, atoms2.numbers):
27 system_changes.append('numbers')
28 if not equal(atoms1.cell, atoms2.cell, tol):
29 system_changes.append('cell')
30 if not equal(atoms1.pbc, atoms2.pbc):
31 system_changes.append('pbc')
32 if not equal(atoms1.get_initial_magnetic_moments(),
33 atoms2.get_initial_magnetic_moments(), tol):
34 system_changes.append('initial_magmoms')
35 if not equal(atoms1.get_initial_charges(),
36 atoms2.get_initial_charges(), tol):
37 system_changes.append('initial_charges')
38
39 return system_changes
40
41
1842 all_properties = ['energy', 'forces', 'stress', 'dipole',
1943 'charges', 'magmom', 'magmoms', 'free_energy']
2044
2448
2549
2650 # Recognized names of calculators sorted alphabetically:
27 names = ['abinit', 'aims', 'amber', 'asap', 'castep', 'cp2k', 'demon', 'dftb',
28 'dmol', 'eam', 'elk', 'emt', 'espresso', 'exciting', 'fleur',
29 'gaussian', 'gpaw', 'gromacs', 'gulp', 'hotbit', 'jacapo', 'lammps',
51 names = ['abinit', 'aims', 'amber', 'asap', 'castep', 'cp2k', 'crystal',
52 'demon', 'dftb', 'dmol', 'eam', 'elk', 'emt', 'espresso',
53 'exciting', 'fleur', 'gaussian', 'gpaw', 'gromacs', 'gulp',
54 'hotbit', 'jacapo', 'lammpsrun',
3055 'lammpslib', 'lj', 'mopac', 'morse', 'nwchem', 'octopus', 'onetep',
3156 'siesta', 'tip3p', 'turbomole', 'vasp']
3257
3661 'eam': 'EAM',
3762 'elk': 'ELK',
3863 'emt': 'EMT',
64 'crystal': 'CRYSTAL',
3965 'fleur': 'FLEUR',
4066 'gulp': 'GULP',
41 'lammps': 'LAMMPS',
67 'lammpsrun': 'LAMMPS',
4268 'lammpslib': 'LAMMPSlib',
4369 'lj': 'LennardJones',
4470 'mopac': 'MOPAC',
233259 file.close()
234260
235261
236 class Calculator:
262 class Calculator(object):
237263 """Base-class for all ASE calculators.
238264
239265 A calculator must raise PropertyNotImplementedError if asked for a
415441
416442 def check_state(self, atoms, tol=1e-15):
417443 """Check for system changes since last calculation."""
418 if self.atoms is None:
419 system_changes = all_changes[:]
420 else:
421 system_changes = []
422 if not equal(self.atoms.positions, atoms.positions, tol):
423 system_changes.append('positions')
424 if not equal(self.atoms.numbers, atoms.numbers):
425 system_changes.append('numbers')
426 if not equal(self.atoms.cell, atoms.cell, tol):
427 system_changes.append('cell')
428 if not equal(self.atoms.pbc, atoms.pbc):
429 system_changes.append('pbc')
430 if not equal(self.atoms.get_initial_magnetic_moments(),
431 atoms.get_initial_magnetic_moments(), tol):
432 system_changes.append('initial_magmoms')
433 if not equal(self.atoms.get_initial_charges(),
434 atoms.get_initial_charges(), tol):
435 system_changes.append('initial_charges')
436
437 return system_changes
444 return compare_atoms(self.atoms, atoms)
438445
439446 def get_potential_energy(self, atoms=None, force_consistent=False):
440447 energy = self.get_property('energy', atoms)
55 Authors:
66 Max Hoffmann, max.hoffmann@ch.tum.de
77 Joerg Meyer, joerg.meyer@ch.tum.de
8 Simon P. Rittmeyer, simon.rittmeyer@tum.de
89
910 Contributors:
1011 Juan M. Lorenzi, juan.lorenzi@tum.de
1112 Georg S. Michelitsch, georg.michelitsch@tch.tum.de
1213 Reinhard J. Maurer, reinhard.maurer@yale.edu
13 Simon P. Rittmeyer, simon.rittmeyer@tum.de
1414 """
1515
1616 from copy import deepcopy
2727 import ase
2828 import ase.units as units
2929 from ase.calculators.general import Calculator
30 from ase.calculators.calculator import compare_atoms
3031 from ase.constraints import FixCartesian
3132 from ase.parallel import paropen
3233 from ase.utils import basestring
143144
144145 ``label`` The prefix of .param, .cell, .castep, etc. files.
145146
147 ``castep_command`` Command to run castep. Can also be set via the bash
148 environment variable ``CASTEP_COMMAND``. If none is
149 given or found, will default to ``castep``
150
151 ``check_castep_version`` Boolean whether to check if the installed castep
152 version matches the version from which the available
153 options were deduced. Defaults to ``False``.
154
155 ``castep_pp_path`` The path where the pseudopotentials are stored. Can
156 also be set via the bash environment variables
157 ``PSPOT_DIR`` (preferred) and ``CASTEP_PP_PATH``.
158 Will default to the current working directory if
159 none is given or found. Note that pseudopotentials
160 may be generated on-the-fly if they are not found.
161
162 ``find_pspots`` Boolean whether to search for pseudopotentials in
163 ``<castep_pp_path>`` or not. If activated, files in
164 this directory will be checked for typical names. If
165 files are not found, they will be generated on the
166 fly, depending on the ``_build_missing_pspots``
167 value. A RuntimeError will be raised in case
168 multiple files per element are found. Defaults to
169 ``False``.
146170 ========================= ====================================================
147171
148172
173197 *Note:* This option has no effect if ``copy_pspots``
174198 is True..
175199
200 ``_build_missing_pspots`` (``=True``): if set to True, castep will generate
201 missing pseudopotentials on the fly. If not, a
202 RuntimeError will be raised if not all files were
203 found.
204
176205 ``_export_settings`` (``=True``): if this is set to
177206 True, all calculator internal settings shown here
178207 will be included in the .param in a comment line (#)
192221
193222 ``_castep_pp_path`` (``='.'``) : the place where the calculator
194223 will look for pseudo-potential files.
224
225 ``_find_pspots`` (``=False``): if set to True, the calculator will
226 try to find the respective pseudopotentials from
227 <_castep_pp_path>. As long as there are no multiple
228 files per element in this directory, the auto-detect
229 feature should be very robust. Raises a RuntimeError
230 if required files are not unique (multiple files per
231 element). Non existing pseudopotentials will be
232 generated, though this could be dangerous.
195233
196234 ``_rename_existing_dir`` (``=True``) : when using a new instance
197235 of the calculator, this will move directories out of
230268 single-point calculations. Regular reuse for *e.g.*
231269 a geometry-optimization can be achieved by setting
232270 ``calc.param.reuse = True``.
271
233272 ``_pedantic`` (``=False``) if set to true, the calculator will
234273 inform about settings probably wasting a lot of CPU
235274 time or causing numerical inconsistencies.
259298
260299 ``.set_pspot('<library>')``
261300 This automatically sets the pseudo-potential for all present species to
262 *<Species>_<library>.usp*. Make sure that ``_castep_pp_path`` is set
263 correctly.
301 ``<Species>_<library>.usp``. Make sure that ``_castep_pp_path`` is set
302 correctly. Note that there is no check, if the file actually exists. If it
303 doesn't castep will crash! You may want to use ``find_pspots()`` instead.
304
305 ``.find_pspots(pspot=<library>, suffix=<suffix>)``
306 This automatically searches for pseudopotentials of type
307 ``<Species>_<library>.<suffix>`` or ``<Species>-<library>.<suffix>`` in
308 ``castep_pp_path` (make sure this is set correctly). Note that ``<Species>``
309 will be searched for case insensitive. Regular expressions are accepted, and
310 arguments ``'*'`` will be regarded as bash-like wildcards. Defaults are any
311 ``<library>`` and any ``<suffix>`` from ``['usp', 'UPF', 'recpot']``. If you
312 have well-organized folders with pseudopotentials of one kind, this should
313 work with the defaults.
264314
265315 ``print(calc)``
266316 Prints a short summary of the calculator settings and atoms.
323373 'forces',
324374 'nbands',
325375 'positions',
326 'stress']
376 'stress',
377 'pressure']
327378
328379 internal_keys = [
329380 '_castep_command',
330381 '_check_checkfile',
331382 '_copy_pspots',
332383 '_link_pspots',
384 '_find_pspots',
385 '_build_missing_pspots',
333386 '_directory',
334387 '_export_settings',
335388 '_force_write',
344397
345398 def __init__(self, directory='CASTEP', label='castep',
346399 castep_command=None, check_castep_version=False,
347 castep_pp_path=None,
400 castep_pp_path=None, find_pspots=False,
348401 **kwargs):
349402
350403 self.__name__ = 'Castep'
387440 self._check_checkfile = True
388441 self._copy_pspots = False
389442 self._link_pspots = True
443 self._find_pspots = find_pspots
444 self._build_missing_pspots = True
390445 self._directory = os.path.abspath(directory)
391446 self._export_settings = True
392447 self._force_write = True
412467 self._energy_total = None
413468 self._energy_free = None
414469 self._energy_0K = None
470 self._energy_total_corr = None
415471
416472 # dispersion corrections
417473 self._dispcorr_energy_total = None
422478 self._spins = None
423479 self._hirsh_volrat = None
424480
481 # Mulliken charges
482 self._mulliken_charges = None
483 # Hirshfeld charges
484 self._hirshfeld_charges = None
485
425486 self._number_of_cell_constraints = None
426487 self._output_verbosity = None
427488 self._stress = None
489 self._pressure = None
428490 self._unit_cell = None
429491 self._kpoints = None
430492
456518 self.__setattr__('cut_off_energy', str(value))
457519 else: # the general case
458520 self.__setattr__(keyword, value)
521
522 def todict(self, skip_default=True):
523 """Create dict with settings of .param and .cell"""
524 dct = {}
525 dct['param'] = self.param.get_attr_dict()
526 dct['cell'] = self.cell.get_attr_dict()
527
528 return dct
529
530 def check_state(self, atoms, tol=1e-15):
531 """Check for system changes since last calculation."""
532 return compare_atoms(self._old_atoms, atoms)
459533
460534 def _castep_find_last_record(self, castep_file):
461535 """Checks wether a given castep file has a regular
605679 # Hirshfeld volumes are calculated
606680 spin_polarized = False
607681 calculate_hirshfeld = False
682 mulliken_analysis = False
683 hirshfeld_analysis = False
684 kpoints = None
608685
609686 positions_frac_list = []
610687
620697 line = out.readline()
621698 if not line or out.tell() > record_end:
622699 break
700 elif 'Hirshfeld Analysis' in line:
701 hirshfeld_charges = []
702
703 hirshfeld_analysis = True
704 # skip the separating line
705 line = out.readline()
706 # this is the headline
707 line = out.readline()
708
709 if 'Charge' in line:
710 # skip the next separator line
711 line = out.readline()
712 while True:
713 line = out.readline()
714 fields = line.split()
715 if len(fields) == 1:
716 break
717 else:
718 hirshfeld_charges.append(float(fields[-1]))
719 elif 'stress calculation' in line:
720 if line.split()[-1].strip() == 'on':
721 self.param.calculate_stress = True
722 elif 'plane wave basis set cut-off' in line:
723 cutoff = float(line.split()[-2])
724 self.param.cut_off_energy = cutoff
725 elif 'total energy / atom convergence tol.' in line:
726 elec_energy_tol = float(line.split()[-2])
727 self.param.elec_energy_tol = elec_energy_tol
728 elif 'convergence tolerance window' in line:
729 elec_convergence_win = int(line.split()[-2])
730 self.param.elec_convergence_win = elec_convergence_win
731 elif re.match('\sfinite basis set correction\s*:', line):
732 finite_basis_corr = line.split()[-1]
733 fbc_possibilities = {'none': 0, 'manual': 1, 'automatic': 2}
734 fbc = fbc_possibilities[finite_basis_corr]
735 self.param.finite_basis_corr = fbc
736 elif 'Treating system as non-metallic' in line:
737 self.param.fix_occupancy = True
738 elif 'max. number of SCF cycles:' in line:
739 max_no_scf = float(line.split()[-1])
740 self.param.max_scf_cycles = max_no_scf
741 elif 'density-mixing scheme' in line:
742 mixing_scheme = line.split()[-1]
743 self.param.mixing_scheme = mixing_scheme
744 elif 'dump wavefunctions every' in line:
745 no_dump_cycles = float(line.split()[-3])
746 self.param.num_dump_cycles = no_dump_cycles
747 elif 'optimization strategy' in line:
748 if 'memory' in line:
749 self.param.opt_strategy = 'Memory'
750 if 'speed' in line:
751 self.param.opt_strategy = 'Speed'
752 elif 'calculation limited to maximum' in line:
753 calc_limit = float(line.split()[-2])
754 self.param.run_time = calc_limit
755 elif 'type of calculation' in line:
756 calc_type = line.split(":")[-1]
757 calc_type = re.sub(r'\s+', ' ', calc_type)
758 calc_type = calc_type.strip()
759 if calc_type != 'single point energy':
760 calc_type_possibilities = {
761 'geometry optimization': 'GeometryOptimization',
762 'band structure': 'BandStructure',
763 'molecular dynamics': 'MolecularDynamics',
764 'optical properties': 'Optics',
765 'phonon calculation': 'Phonon',
766 'E-field calculation': 'Efield',
767 'Phonon followed by E-field': 'Phonon+Efield',
768 'transition state search': 'TransitionStateSearch',
769 'Magnetic Resonance': 'MagRes',
770 'Core level spectra': 'Elnes',
771 'Electronic Spectroscopy': 'ElectronicSpectroscopy'
772 }
773 ctype = calc_type_possibilities[calc_type]
774 self.param.task = ctype
775 elif 'using functional' in line:
776 used_functional = line.split(":")[-1]
777 used_functional = re.sub('\s+', ' ', used_functional)
778 used_functional = used_functional.strip()
779 if used_functional != 'Local Density Approximation':
780 used_functional_possibilities = {
781 'Perdew Wang (1991)': 'PW91',
782 'Perdew Burke Ernzerhof': 'PBE',
783 'revised Perdew Burke Ernzerhof': 'RPBE',
784 'PBE with Wu-Cohen exchange': 'WC',
785 'PBE for solids (2008)': 'PBESOL',
786 'Hartree-Fock': 'HF',
787 'Hartree-Fock +': 'HF-LDA',
788 'Screened Hartree-Fock': 'sX',
789 'Screened Hartree-Fock + ': 'sX-LDA',
790 'hybrid PBE0': 'PBE0',
791 'hybrid B3LYP': 'B3LYP',
792 'hybrid HSE03': 'HSE03',
793 'hybrid HSE06': 'HSE06'
794 }
795 used_func = used_functional_possibilities[used_functional]
796 self.param.xc_functional = used_func
623797 elif 'output verbosity' in line:
624798 iprint = int(line.split()[-1][1])
625799 if int(iprint) != 1:
626800 self.param.iprint = iprint
627801 elif 'treating system as spin-polarized' in line:
628802 spin_polarized = True
803 self.param.spin_polarized = spin_polarized
629804 elif 'treating system as non-spin-polarized' in line:
630805 spin_polarized = False
806 elif 'Number of kpoints used' in line:
807 kpoints = int(line.split('=')[-1].strip())
631808 elif 'Unit Cell' in line:
632809 lattice_real = []
633810 lattice_reci = []
718895 self._energy_free = float(line.split()[-2])
719896 elif 'NB est. 0K energy' in line:
720897 self._energy_0K = float(line.split()[-2])
898 # check if we had a finite basis set correction
899 elif 'Total energy corrected for finite basis set' in line:
900 self._energy_total_corr = float(line.split()[-2])
721901
722902 # Add support for dispersion correction
723903 # filtering due to SEDC is done in get_potential_energy
805985 stress.append([float(s) for s in fields[2:5]])
806986 line = out.readline()
807987 fields = line.split()
988 line = out.readline()
989 if "Pressure:" in line:
990 self._pressure = float(line.split()[-2]) * units.GPa
808991 elif ('BFGS: starting iteration' in line or
809992 'BFGS: improving iteration' in line):
810993 if n_cell_const < 6:
811994 lattice_real = []
812995 lattice_reci = []
996 # backup previous configuration first:
997 # for highly symmetric systems (where essentially only the
998 # stress is optimized, but the atomic positions) positions
999 # are only printed once.
1000 if species:
1001 prev_species = deepcopy(species)
1002 if positions_frac:
1003 prev_positions_frac = deepcopy(positions_frac)
8131004 species = []
8141005 positions_frac = []
8151006 forces = []
8191010 # stress = []
8201011 stress = np.zeros([3, 3])
8211012
822 elif 'BFGS: Final Configuration:' in line:
823 break
1013 # extract info from the Mulliken analysis
1014 elif 'Atomic Populations' in line:
1015 # sometimes this appears twice in a castep file
1016 mulliken_charges = []
1017 spins = []
1018
1019 mulliken_analysis = True
1020 # skip the separating line
1021 line = out.readline()
1022 # this is the headline
1023 line = out.readline()
1024
1025 if 'Charge' in line:
1026 # skip the next separator line
1027 line = out.readline()
1028 while True:
1029 line = out.readline()
1030 fields = line.split()
1031 if len(fields) == 1:
1032 break
1033
1034 # the check for len==7 is due to CASTEP 18 outformat changes
1035 if spin_polarized:
1036 if len(fields) != 7:
1037 spins.append(float(fields[-1]))
1038 mulliken_charges.append(float(fields[-2]))
1039 else:
1040 mulliken_charges.append(float(fields[-1]))
1041
1042 # There is actually no good reason to get out of the loop
1043 # already at this point... or do I miss something?
1044 #elif 'BFGS: Final Configuration:' in line:
1045 # break
8241046 elif 'warn' in line.lower():
8251047 self._warnings.append(line)
1048
8261049 except Exception as exception:
827 print(line, end=' ')
828 print('|-> line triggered exception: ' + str(exception))
1050 sys.stderr.write(line + '|-> line triggered exception: ' +
1051 str(exception))
8291052 raise
8301053
831 # get the spins in a separate run over the file as we
832 # do not want to break the BFGS-break construct
833 # probably one can implement it in a more convenient
834 # way, but this constructon does the job.
835
836 if spin_polarized:
837 spins = []
838 out.seek(record_start)
839 while True:
840 try:
841 line = out.readline()
842 if not line or out.tell() > record_end:
843 break
844 elif 'Atomic Populations' in line:
845 # skip the separating line
846 line = out.readline()
847 # this is the headline
848 line = out.readline()
849 if 'Spin' in line:
850 # skip the next separator line
851 line = out.readline()
852 while True:
853 line = out.readline()
854 fields = line.split()
855 if len(fields) == 1:
856 break
857 spins.append(float(fields[-1]))
858 break
859
860 except Exception as exception:
861 print(line + '|-> line triggered exception: ' +
862 str(exception))
863 raise
864 else:
1054 if _close:
1055 out.close()
1056
1057 # in highly summetric crystals, positions and symmetry are only printed
1058 # upon init, hence we here restore these original values
1059 if not positions_frac:
1060 positions_frac = prev_positions_frac
1061 if not species:
1062 species = prev_species
1063
1064 if not spin_polarized:
8651065 # set to zero spin if non-spin polarized calculation
8661066 spins = np.zeros(len(positions_frac))
867
868 if _close:
869 out.close()
8701067
8711068 positions_frac_atoms = np.array(positions_frac)
8721069 forces_atoms = np.array(forces)
8731070 spins_atoms = np.array(spins)
1071
1072 if mulliken_analysis:
1073 mulliken_charges_atoms = np.array(mulliken_charges)
1074 else:
1075 mulliken_charges_atoms = np.zeros(len(positions_frac))
1076
1077 if hirshfeld_analysis:
1078 hirshfeld_charges_atoms = np.array(hirshfeld_charges)
1079 else:
1080 hirshfeld_charges_atoms = None
8741081
8751082 if calculate_hirshfeld:
8761083 hirsh_atoms = np.array(hirsh_volrat)
8911098 forces_castep = np.array(forces)
8921099 hirsh_castep = np.array(hirsh_volrat)
8931100 spins_castep = np.array(spins)
1101 mulliken_charges_castep = np.array(mulliken_charges_atoms)
8941102
8951103 # go through the atoms position list and replace
8961104 # with the corresponding one from the
9071115 if spin_polarized:
9081116 # reordering not necessary in case all spins == 0
9091117 spins_atoms[iase] = np.array(spins_castep[icastep])
1118 mulliken_charges_atoms[iase] = np.array(mulliken_charges_castep[icastep])
9101119 atoms_assigned[icastep] = True
9111120 break
9121121
9441153 if self.param.spin_polarized:
9451154 # only set magnetic moments if this was a spin polarized
9461155 # calculation
1156 # this one fails as is
9471157 atoms.set_initial_magnetic_moments(magmoms=spins_atoms)
9481158
1159 if mulliken_analysis:
1160 atoms.set_initial_charges(charges=mulliken_charges_atoms)
9491161 atoms.set_calculator(self)
9501162
1163 self._kpoints = kpoints
9511164 self._forces = forces_atoms
9521165 # stress in .castep file is given in GPa:
9531166 self._stress = np.array(stress) * units.GPa
9541167 self._hirsh_volrat = hirsh_atoms
9551168 self._spins = spins_atoms
1169 self._mulliken_charges = mulliken_charges_atoms
1170 self._hirshfeld_charges = hirshfeld_charges_atoms
1171
9561172
9571173 if self._warnings:
9581174 print('WARNING: %s contains warnings' % castep_file)
9721188 if isinstance(castep_castep, basestring):
9731189 if not os.path.isfile(castep_castep):
9741190 print('Warning: CASTEP file %s not found!' % castep_castep)
975 f = paropen(castep_castep, 'a')
1191 f = paropen(castep_castep, 'r')
9761192 _close = True
9771193 else:
9781194 # in this case we assume that we have a fileobj already, but check
10041220 if 'Symmetry and Constraints' in line:
10051221 break
10061222
1007 if self.param.iprint is None or self.param.iprint < 2:
1223 if self.param.iprint.value is None or self.param.iprint < 2:
10081224 self._interface_warnings.append(
10091225 'Warning: No symmetry'
10101226 'operations could be read from %s (iprint < 2).' % f.name)
10571273 """
10581274 return self._spins
10591275
1276 def get_mulliken_charges(self):
1277 """
1278 Return the charges from a plane-wave Mulliken analysis.
1279 """
1280 return self._mulliken_charges
1281
1282 def get_hirshfeld_charges(self):
1283 """
1284 Return the charges from a Hirshfeld analysis.
1285 """
1286 return self._hirshfeld_charges
1287
10601288 def set_label(self, label):
10611289 """The label is part of each seed, which in turn is a prefix
10621290 in each CASTEP related file.
10801308 - notelems (None): do not set the elements
10811309 - clear (True): clear previous settings
10821310 - suffix (usp): PP file suffix
1083
1084
1085
10861311 """
1312 if self._find_pspots:
1313 if self._pedantic:
1314 print('Warning: <_find_pspots> = True')
1315 print('Do you really want to use `set_pspots()`')
1316 print('This does not check whether the PP files exist.')
1317 print('You may rather want to use `find_pspots()` with the same <pspot>.')
10871318
10881319 if clear and not elems and not notelems:
10891320 self.cell.species_pot.clear()
10941325 continue
10951326 self.cell.species_pot = (elem, '%s_%s.%s' % (elem, pspot, suffix))
10961327
1328 def find_pspots(self, pspot='.+', elems=None,
1329 notelems=None, clear=True, suffix='(usp|UPF|recpot)'):
1330 """Quickly find and set all pseudo-potentials by searching in
1331 castep_pp_path:
1332
1333 This one is more flexible than set_pspots, and also checks if the files
1334 are actually available from the castep_pp_path.
1335
1336 Essentially, the function parses the filenames in <castep_pp_path> and
1337 does a regex matching. The respective pattern is:
1338
1339 r"^(<elem>|<elem.upper()>|elem.lower()>(_|-)<pspot>\.<suffix>$"
1340
1341 In most cases, it will be sufficient to not specify anything, if you
1342 use standard CASTEP USPPs with only one file per element in the
1343 <castep_pp_path>.
1344
1345 The function raises a `RuntimeError` if there is some ambiguity
1346 (multiple files per element).
1347
1348 Parameters ::
1349
1350 - pspots ('.+') : as defined above, will be a wildcard if not
1351 specified.
1352 - elems (None) : set only these elements
1353 - notelems (None): do not set the elements
1354 - clear (True): clear previous settings
1355 - suffix (usp|UPF|recpot): PP file suffix
1356 """
1357 if clear and not elems and not notelems:
1358 self.cell.species_pot.clear()
1359
1360 if not os.path.isdir(self._castep_pp_path):
1361 if self._pedantic:
1362 print('Cannot search directory:\n {}\nFolder does not exist'.format(self._castep_pp_path))
1363 return
1364
1365 # translate the bash wildcard syntax to regex
1366 if pspot == '*':
1367 pspot = '.*'
1368 if suffix == '*':
1369 suffix = '.*'
1370 if pspot == '*':
1371 pspot = '.*'
1372
1373 # GBRV USPPs have a strnage naming schme
1374 pattern = r'^({elem}|{elem_upper}|{elem_lower})(_|-){pspot}\.{suffix}$'
1375
1376 for elem in set(self.atoms.get_chemical_symbols()):
1377 if elems is not None and elem not in elems:
1378 continue
1379 if notelems is not None and elem in notelems:
1380 continue
1381 p = pattern.format(elem=elem, elem_upper=elem.upper(), elem_lower=elem.lower(),
1382 pspot=pspot, suffix=suffix)
1383 pps = []
1384 for f in os.listdir(self._castep_pp_path):
1385 if re.match(p, f):
1386 pps.append(f)
1387 if not pps:
1388 if self._pedantic:
1389 print('Pseudopotential for species {} not found!'.format(elem))
1390 elif not len(pps) == 1:
1391 raise RuntimeError('Pseudopotential for species {} not unique!\n'.format(elem)
1392 + 'Found the following files in {}\n'.format(self._castep_pp_path)
1393 + '\n'.join([' {}'.format(pp) for pp in pps])
1394 + '\nConsider a stricter search pattern in `find_pspots()`.')
1395 else:
1396 self.cell.species_pot = (elem, pps[0])
1397
1398 @property
1399 def name(self):
1400 """Return the name of the calculator (string). """
1401 return self.__name__
1402
10971403 @_self_getter
10981404 def get_forces(self, atoms):
10991405 """Run CASTEP calculation if needed and return forces."""
11051411 """Run CASTEP calculation if needed and return total energy."""
11061412 self.update(atoms)
11071413 return self._energy_total
1414
1415 @_self_getter
1416 def get_total_energy_corrected(self, atoms):
1417 """Run CASTEP calculation if needed and return total energy."""
1418 self.update(atoms)
1419 return self._energy_total_corr
11081420
11091421 @_self_getter
11101422 def get_free_energy(self, atoms):
11491461 def get_stress(self, atoms):
11501462 """Return the stress."""
11511463 self.update(atoms)
1152 return self._stress
1464 # modification: we return the Voigt form directly to get rid of the
1465 # annoying user warnings
1466 stress = np.array([self._stress[0, 0], self._stress[1, 1], self._stress[2, 2],
1467 self._stress[1, 2], self._stress[0, 2], self._stress[0, 1]])
1468 #return self._stress
1469 return stress
1470
1471 @_self_getter
1472 def get_pressure(self, atoms):
1473 """Return the pressure."""
1474 self.update(atoms)
1475 return self._pressure
11531476
11541477 @_self_getter
11551478 def get_unit_cell(self, atoms):
11681491 """Return the number of cell constraints."""
11691492 self.update(atoms)
11701493 return self._number_of_cell_constraints
1171
1494
1495 @_self_getter
1496 def get_charges(self, atoms):
1497 """Run CASTEP calculation if needed and return Mulliken charges."""
1498 self.update(atoms)
1499 return np.array(self._mulliken_charges)
1500
1501 @_self_getter
1502 def get_magnetic_moments(self, atoms):
1503 """Run CASTEP calculation if needed and return Mulliken charges."""
1504 self.update(atoms)
1505 return np.array(self._spins)
1506
11721507 def set_atoms(self, atoms):
11731508 """Sets the atoms for the calculator and vice versa."""
11741509 atoms.pbc = [True, True, True]
12851620 # if self._calls == 0:
12861621 self._fetch_pspots()
12871622
1288 cwd = os.getcwd()
1289 os.chdir(self._directory)
1290
12911623 # if _try_reuse is requested and this
12921624 # is not the first run, we try to find
12931625 # the .check file from the previous run
12941626 # this is only necessary if _track_output
12951627 # is set to true
12961628 if self._try_reuse and self._calls > 0:
1297 if os.path.exists(self._check_file):
1629 if os.path.exists(self._abs_path(self._check_file)):
12981630 self.param.reuse = self._check_file
1299 elif os.path.exists(self._castep_bin_file):
1631 elif os.path.exists(self._abs_path(self._castep_bin_file)):
13001632 self.param.reuse = self._castep_bin_file
13011633 self._seed = self._build_castep_seed()
13021634 self._check_file = '%s.check' % self._seed
13031635 self._castep_bin_file = '%s.castep_bin' % self._seed
1304 self._castep_file = os.path.abspath('%s.castep' % self._seed)
1636 self._castep_file = self._abs_path('%s.castep' % self._seed)
13051637
13061638 # write out the input file
1307 self._write_cell('%s.cell' % self._seed,
1639 self._write_cell(self._abs_path('%s.cell' % self._seed),
13081640 self.atoms, castep_cell=self.cell,
13091641 force_write=force_write)
13101642
13121644 interface_options = self._opt
13131645 else:
13141646 interface_options = None
1315 write_param('%s.param' % self._seed, self.param,
1647 write_param(self._abs_path('%s.param' % self._seed), self.param,
13161648 check_checkfile=self._check_checkfile,
13171649 force_write=force_write,
13181650 interface_options=interface_options,)
1319 os.chdir(cwd)
13201651
13211652 def _build_castep_seed(self):
13221653 """Abstracts to construction of the final castep <seed>
13271658 else:
13281659 return '%s' % (self._label)
13291660
1661 def _abs_path(self, path):
1662 # Create an absolute path for a file to put in the working directory
1663 return os.path.join(self._directory, path)
1664
13301665 def run(self):
13311666 """Simply call castep. If the first .err file
13321667 contains text, this will be printed to the screen.
13331668 """
13341669 # change to target directory
1335 cwd = os.getcwd()
1336 os.chdir(self._directory)
13371670 self._calls += 1
13381671
13391672 # run castep itself
13401673 stdout, stderr = shell_stdouterr('%s %s' % (self._castep_command,
1341 self._seed))
1674 self._seed),
1675 cwd=self._directory)
13421676 if stdout:
13431677 print('castep call stdout:\n%s' % stdout)
13441678 if stderr:
13481682 # self.push_oldstate()
13491683
13501684 # check for non-empty error files
1351 err_file = '%s.0001.err' % self._seed
1685 err_file = self._abs_path('%s.0001.err' % self._seed)
13521686 if os.path.exists(err_file):
13531687 err_file = open(err_file)
13541688 self._error = err_file.read()
13551689 err_file.close()
1356 os.chdir(cwd)
13571690 if self._error:
13581691 raise RuntimeError(self._error)
13591692
15901923 from ase.io.castep import write_param
15911924
15921925 temp_dir = tempfile.mkdtemp()
1593 curdir = os.getcwd()
1594 self._fetch_pspots(temp_dir)
1595 os.chdir(temp_dir)
15961926 self._fetch_pspots(temp_dir)
15971927 seed = 'dryrun'
15981928
1599 self._write_cell('%s.cell' % seed, self.atoms,
1600 castep_cell=self.cell)
1929 self._write_cell(os.path.join(temp_dir, '%s.cell' % seed),
1930 self.atoms, castep_cell=self.cell)
16011931 # This part needs to be modified now that we rely on the new formats.py
16021932 # interface
1603 if not os.path.isfile('%s.cell' % seed):
1933 if not os.path.isfile(os.path.join(temp_dir, '%s.cell' % seed)):
16041934 print('%s.cell not written - aborting dryrun' % seed)
16051935 return
1606 write_param('%s.param' % seed, self.param, )
1936 write_param(os.path.join(temp_dir, '%s.param' % seed), self.param, )
16071937
16081938 stdout, stderr = shell_stdouterr(('%s %s %s' % (self._castep_command,
16091939 seed,
1610 dryrun_flag)))
1940 dryrun_flag)),
1941 cwd=temp_dir)
16111942
16121943 if stdout:
16131944 print(stdout)
16141945 if stderr:
16151946 print(stderr)
1616 result_file = open('%s.castep' % seed)
1947 result_file = open(os.path.join(temp_dir, '%s.castep' % seed))
16171948
16181949 txt = result_file.read()
16191950 ok_string = r'.*DRYRUN finished.*No problems found with input files.*'
16201951 match = re.match(ok_string, txt, re.DOTALL)
16211952
1622 try:
1623 self._kpoints_used = int(
1624 re.search(
1625 r'Number of kpoints used = *([0-9]+)', txt).group(1))
1626 except:
1953 m = re.search(r'Number of kpoints used =\s*([0-9]+)', txt)
1954 if m:
1955 self._kpoints = int(m.group(1))
1956 else:
16271957 print('Couldn\'t fetch number of kpoints from dryrun CASTEP file')
16281958
1629 err_file = '%s.0001.err' % seed
1959 err_file = os.path.join(temp_dir, '%s.0001.err' % seed)
16301960 if match is None and os.path.exists(err_file):
16311961 err_file = open(err_file)
16321962 self._error = err_file.read()
16331963 err_file.close()
16341964
16351965 result_file.close()
1636 os.chdir(curdir)
16371966 shutil.rmtree(temp_dir)
16381967
16391968 # re.match return None is the string does not match
16892018 if not os.path.isdir(self._castep_pp_path):
16902019 print('PSPs directory %s not found' % self._castep_pp_path)
16912020 pspots = {}
2021 if self._find_pspots:
2022 self.find_pspots()
16922023 if self.cell.species_pot.value is not None:
16932024 for line in self.cell.species_pot.value.split('\n'):
16942025 line = line.split()
16962027 pspots[line[0]] = line[1]
16972028 for species in self.atoms.get_chemical_symbols():
16982029 if not pspots or species not in pspots.keys():
1699 if self._pedantic:
1700 print('Warning: you have no PP specified for %s.' %
1701 species)
1702 print('CASTEP will now generate an on-the-fly potentials.')
1703 print('For sake of numerical consistency and efficiency')
1704 print('this is discouraged.')
2030 if self._build_missing_pspots:
2031 if self._pedantic:
2032 print('Warning: you have no PP specified for %s.' %
2033 species)
2034 print('CASTEP will now generate an on-the-fly potentials.')
2035 print('For sake of numerical consistency and efficiency')
2036 print('this is discouraged.')
2037 else:
2038 raise RuntimeError('Warning: you have no PP specified for %s.' %
2039 species)
17052040 if self.cell.species_pot.value:
17062041 for (species, pspot) in pspots.items():
17072042 orig_pspot_file = os.path.join(self._castep_pp_path, pspot)
20912426 raise RuntimeError('Caught unhandled option: %s = %s'
20922427 % (attr, value))
20932428
2429 def get_attr_dict(self):
2430 """Settings that go into .param file in a traditional dict"""
2431
2432 return {k : o.value for k, o in self._options.items() if o.value is not None}
2433
20942434
20952435 class CastepCell(object):
20962436
22982638 raise RuntimeError('Caught unhandled option: %s = %s'
22992639 % (attr, value))
23002640
2641 def get_attr_dict(self):
2642 """Settings that go into .cell file in a traditional dict"""
2643
2644 return {k : o.value for k, o in self._options.items() if o.value is not None}
2645
23012646
23022647 class ConversionError(Exception):
23032648
23232668 """Abstract the quest for a CASTEP PSP directory."""
23242669 if castep_pp_path:
23252670 return os.path.abspath(os.path.expanduser(castep_pp_path))
2671 elif 'PSPOT_DIR' in os.environ:
2672 return os.environ['PSPOT_DIR']
23262673 elif 'CASTEP_PP_PATH' in os.environ:
23272674 return os.environ['CASTEP_PP_PATH']
23282675 else:
23392686 return 'castep'
23402687
23412688
2342 def shell_stdouterr(raw_command):
2689 def shell_stdouterr(raw_command, cwd=None):
23432690 """Abstracts the standard call of the commandline, when
23442691 we are only interested in the stdout and stderr
23452692 """
23472694 stdout=subprocess.PIPE,
23482695 stderr=subprocess.PIPE,
23492696 universal_newlines=True,
2350 shell=True).communicate()
2697 shell=True, cwd=cwd).communicate()
23512698 return stdout.strip(), stderr.strip()
23522699
23532700
362362 root.add_keyword('FORCE_EVAL/DFT/LS_SCF', 'MAX_SCF %d' % p.max_scf)
363363
364364 if p.xc:
365 if p.xc.startswith("XC_"):
365 legacy_libxc = ""
366 for functional in p.xc.split():
367 functional = functional.replace("LDA", "PADE") # resolve alias
368 xc_sec = root.get_subsection('FORCE_EVAL/DFT/XC/XC_FUNCTIONAL')
369 # libxc input section changed over time
370 if functional.startswith("XC_") and self._shell.version < 3.0:
371 legacy_libxc += " " + functional # handled later
372 elif functional.startswith("XC_"):
373 s = InputSection(name='LIBXC')
374 s.keywords.append('FUNCTIONAL ' + functional)
375 xc_sec.subsections.append(s)
376 else:
377 s = InputSection(name=functional.upper())
378 xc_sec.subsections.append(s)
379 if legacy_libxc:
366380 root.add_keyword('FORCE_EVAL/DFT/XC/XC_FUNCTIONAL/LIBXC',
367 'FUNCTIONAL ' + p.xc)
368 else:
369 root.add_keyword('FORCE_EVAL/DFT/XC/XC_FUNCTIONAL',
370 '_SECTION_PARAMETERS_ ' + p.xc)
381 'FUNCTIONAL ' + legacy_libxc)
371382
372383 if p.uks:
373384 root.add_keyword('FORCE_EVAL/DFT', 'UNRESTRICTED_KOHN_SHAM ON')
0 """This module defines an ASE interface to CRYSTAL14
1
2 http://www.crystal.unito.it/
3
4 Written by:
5
6 Daniele Selli, daniele.selli@unimib.it
7 Gianluca Fazio, g.fazio3@campus.unimib.it
8
9 The file 'fort.34' contains the input and output geometry
10 and it will be updated during the crystal calculations.
11 The wavefunction is stored in 'fort.20' as binary file.
12
13 The keywords are given, for instance, as follows:
14
15 guess = True,
16 xc = 'PBE',
17 kpts = (2,2,2),
18 otherkeys = [ 'scfdir', 'anderson', ['maxcycles','500'],
19 ['fmixing','90']],
20 ...
21
22 """
23
24 from ase.units import Hartree, Bohr
25 from ase.io import write
26 import numpy as np
27 import os
28
29 from ase.calculators.calculator import FileIOCalculator
30
31
32 class CRYSTAL(FileIOCalculator):
33 """ A crystal calculator with ase-FileIOCalculator nomenclature
34 """
35
36 implemented_properties = ['energy', 'forces', 'stress', 'charges',
37 'dipole']
38
39 def __init__(self, restart=None, ignore_bad_restart_file=False,
40 label='cry', atoms=None, **kwargs):
41 """Construct a crystal calculator.
42
43 """
44 # default parameters
45 self.default_parameters = dict(
46 xc='HF',
47 spinpol=False,
48 guess=True,
49 kpts=None,
50 isp=1,
51 basis='custom',
52 smearing=None,
53 otherkeys=[])
54
55 self.pcpot = None
56 self.lines = None
57 self.atoms = None
58 self.atoms_input = None
59 self.outfilename = 'cry.out'
60
61 FileIOCalculator.__init__(self, restart, ignore_bad_restart_file,
62 label, atoms,
63 **kwargs)
64
65 def write_crystal_in(self, filename):
66 """ Write the input file for the crystal calculation.
67 Geometry is taken always from the file 'fort.34'
68 """
69
70 # write BLOCK 1 (only SP with gradients)
71 outfile = open(filename, 'w')
72 outfile.write('Single point + Gradient crystal calculation \n')
73 outfile.write('EXTERNAL \n')
74 if self.pcpot:
75 outfile.write('POINTCHG \n')
76 self.pcpot.write_mmcharges('POINTCHG.INP')
77
78 # write BLOCK 2 from file (basis sets)
79 p = self.parameters
80 if p.basis == 'custom':
81 outfile.write('END \n')
82 basisfile = open(os.path.join(self.directory, 'basis'))
83 basis_ = basisfile.readlines()
84 for line in basis_:
85 outfile.write(line)
86 outfile.write('99 0 \n')
87 outfile.write('END \n')
88 else:
89 outfile.write('BASISSET \n')
90 outfile.write(p.basis.upper() + '\n')
91
92 # write BLOCK 3 according to parameters set as input
93 # ----- write hamiltonian
94
95 if self.atoms.get_initial_magnetic_moments().any():
96 p.spinpol = True
97
98 if p.xc == 'HF':
99 if p.spinpol:
100 outfile.write('UHF \n')
101 else:
102 outfile.write('RHF \n')
103 elif p.xc == 'MP2':
104 outfile.write('MP2 \n')
105 outfile.write('ENDMP2 \n')
106 else:
107 outfile.write('DFT \n')
108 # Standalone keywords and LDA are given by a single string.
109 if isinstance(p.xc, str):
110 xc = {'LDA': 'EXCHANGE\nLDA\nCORRELAT\nVWN',
111 'PBE': 'PBEXC'}.get(p.xc, p.xc)
112 outfile.write(xc.upper() + '\n')
113 # Custom xc functional are given by a tuple of string
114 else:
115 x, c = p.xc
116 outfile.write('EXCHANGE \n')
117 outfile.write(x + ' \n')
118 outfile.write('CORRELAT \n')
119 outfile.write(c + ' \n')
120 if p.spinpol:
121 outfile.write('SPIN \n')
122 outfile.write('END \n')
123 # When guess=True, wf is read.
124 if p.guess:
125 # wf will be always there after 2nd step.
126 if os.path.isfile('fort.20'):
127 outfile.write('GUESSP \n')
128
129 # smearing
130 if p.smearing is not None:
131 if p.smearing[0] != 'Fermi-Dirac':
132 raise ValueError('Only Fermi-Dirac smearing is allowed.')
133 else:
134 outfile.write('SMEAR \n')
135 outfile.write(str(p.smearing[1] / Hartree) + ' \n')
136
137 # ----- write other CRYSTAL keywords
138 # ----- in the list otherkey = ['ANDERSON', ...] .
139
140 for keyword in p.otherkeys:
141 if isinstance(keyword, str):
142 outfile.write(keyword.upper() + '\n')
143 else:
144 for key in keyword:
145 outfile.write(key.upper() + '\n')
146
147 ispbc = self.atoms.get_pbc()
148 self.kpts = p.kpts
149
150 # if it is periodic, gamma is the default.
151 if any(ispbc):
152 if self.kpts is None:
153 self.kpts = (1, 1, 1)
154 else:
155 self.kpts = None
156
157 # explicit lists of K-points, shifted Monkhorst-
158 # Pack net and k-point density definition are
159 # not allowed.
160 if self.kpts is not None:
161 if isinstance(self.kpts, float):
162 raise ValueError('K-point density definition not allowed.')
163 if isinstance(self.kpts, list):
164 raise ValueError('Explicit K-points definition not allowed.')
165 if isinstance(self.kpts[-1], str):
166 raise ValueError('Shifted Monkhorst-Pack not allowed.')
167 outfile.write('SHRINK \n')
168 # isp is by default 1, 2 is suggested for metals.
169 outfile.write('0 ' + str(p.isp * max(self.kpts)) + ' \n')
170 if ispbc[2]:
171 outfile.write(str(self.kpts[0])
172 + ' ' + str(self.kpts[1])
173 + ' ' + str(self.kpts[2]) + ' \n')
174 elif ispbc[1]:
175 outfile.write(str(self.kpts[0])
176 + ' ' + str(self.kpts[1])
177 + ' 1 \n')
178 elif ispbc[0]:
179 outfile.write(str(self.kpts[0])
180 + ' 1 1 \n')
181
182 # GRADCAL command performs a single
183 # point and prints out the forces
184 # also on the charges
185 outfile.write('GRADCAL \n')
186 outfile.write('END \n')
187
188 outfile.close()
189
190 def write_input(self, atoms, properties=None, system_changes=None):
191 FileIOCalculator.write_input(
192 self, atoms, properties, system_changes)
193 self.write_crystal_in(os.path.join(self.directory, 'INPUT'))
194 write(os.path.join(self.directory, 'fort.34'), atoms)
195 # self.atoms is none until results are read out,
196 # then it is set to the ones at writing input
197 self.atoms_input = atoms
198 self.atoms = None
199
200 def read_results(self):
201 """ all results are read from OUTPUT file
202 It will be destroyed after it is read to avoid
203 reading it once again after some runtime error """
204
205 with open(os.path.join(self.directory, 'OUTPUT'), 'r') as myfile:
206 self.lines = myfile.readlines()
207
208 self.atoms = self.atoms_input
209 # Energy line index
210 estring1 = 'SCF ENDED'
211 estring2 = 'TOTAL ENERGY + DISP'
212 for iline, line in enumerate(self.lines):
213 if line.find(estring1) >= 0:
214 index_energy = iline
215 pos_en = 8
216 break
217 else:
218 raise RuntimeError('Problem in reading energy')
219 # Check if there is dispersion corrected
220 # energy value.
221 for iline, line in enumerate(self.lines):
222 if line.find(estring2) >= 0:
223 index_energy = iline
224 pos_en = 5
225 energy = float(self.lines[index_energy].split()[pos_en]) * Hartree
226 self.results['energy'] = energy
227
228 # Force line indexes
229 fstring = 'CARTESIAN FORCES'
230 gradients = []
231 for iline, line in enumerate(self.lines):
232 if line.find(fstring) >= 0:
233 index_force_begin = iline + 2
234 break
235 else:
236 raise RuntimeError('Problem in reading forces')
237 for j in range(index_force_begin, index_force_begin + len(self.atoms)):
238 word = self.lines[j].split()
239 gradients.append([float(word[k + 2]) for k in range(0, 3)])
240 forces = np.array(gradients) * Hartree / Bohr
241
242 self.results['forces'] = forces
243
244 # stress stuff begins
245 sstring = 'STRESS TENSOR, IN'
246 have_stress = False
247 stress = []
248 for iline, line in enumerate(self.lines):
249 if sstring in line:
250 have_stress = True
251 start = iline + 4
252 end = start + 3
253 for i in range(start, end):
254 cell = [float(x) for x in self.lines[i].split()]
255 stress.append(cell)
256 if have_stress:
257 stress = -np.array(stress) * Hartree / Bohr**3
258 self.results['stress'] = stress
259
260 # stress stuff ends
261
262 # Get partial charges on atoms.
263 # In case we cannot find charges
264 # they are set to None
265 qm_charges = []
266
267 # ----- this for cycle finds the last entry of the
268 # ----- string search, which corresponds
269 # ----- to the charges at the end of the SCF.
270 for n, line in enumerate(self.lines):
271 if 'TOTAL ATOMIC CHARGE' in line:
272 chargestart = n + 1
273 lines1 = self.lines[chargestart:(chargestart
274 + (len(self.atoms) - 1) // 6 + 1)]
275 atomnum = self.atoms.get_atomic_numbers()
276 words = []
277 for line in lines1:
278 for el in line.split():
279 words.append(float(el))
280 i = 0
281 for atn in atomnum:
282 qm_charges.append(-words[i] + atn)
283 i = i + 1
284 charges = np.array(qm_charges)
285 self.results['charges'] = charges
286
287 # Read dipole moment.
288
289 dipole = np.zeros([1, 3])
290 for n, line in enumerate(self.lines):
291 if 'DIPOLE MOMENT ALONG' in line:
292 dipolestart = n + 2
293 dipole = np.array([float(f) for f in
294 self.lines[dipolestart].split()[2:5]])
295 break
296 # debye to e*Ang
297 self.results['dipole'] = dipole * 0.2081943482534
298
299 def embed(self, mmcharges=None, directory='./'):
300 """Embed atoms in point-charges (mmcharges)
301 """
302 self.pcpot = PointChargePotential(mmcharges, self.directory)
303 return self.pcpot
304
305
306 class PointChargePotential:
307 def __init__(self, mmcharges, directory='./'):
308 """Point-charge potential for CRYSTAL.
309 """
310 self.mmcharges = mmcharges
311 self.directory = directory
312 self.mmpositions = None
313 self.mmforces = None
314
315 def set_positions(self, mmpositions):
316 self.mmpositions = mmpositions
317
318 def set_charges(self, mmcharges):
319 self.mmcharges = mmcharges
320
321 def write_mmcharges(self, filename='POINTCHG.INP'):
322 """ mok all
323 write external charges as monopoles for CRYSTAL.
324
325 """
326 if self.mmcharges is None:
327 print("CRYSTAL: Warning: not writing external charges ")
328 return
329 charge_file = open(os.path.join(self.directory, filename), 'w')
330 charge_file.write(str(len(self.mmcharges)) + ' \n')
331 for [pos, charge] in zip(self.mmpositions, self.mmcharges):
332 [x, y, z] = pos
333 charge_file.write('%12.6f %12.6f %12.6f %12.6f \n'
334 % (x, y, z, charge))
335 charge_file.close()
336
337 def get_forces(self, calc, get_forces=True):
338 """ returns forces on point charges if the flag get_forces=True """
339 if get_forces:
340 return self.read_forces_on_pointcharges()
341 else:
342 return np.zeros_like(self.mmpositions)
343
344 def read_forces_on_pointcharges(self):
345 """Read Forces from CRYSTAL output file (OUTPUT)."""
346 from ase.units import Hartree, Bohr
347 infile = open(os.path.join(self.directory, 'OUTPUT'), 'r')
348 lines = infile.readlines()
349 infile.close()
350
351 external_forces = []
352 for n, line in enumerate(lines):
353 if ('RESULTANT FORCE' in line):
354 chargeend = n - 1
355 break
356 else:
357 raise RuntimeError(
358 'Problem in reading forces on MM external-charges')
359 lines1 = lines[(chargeend - len(self.mmcharges)):chargeend]
360 for line in lines1:
361 external_forces.append(
362 [float(i) for i in line.split()[2:]])
363 return np.array(external_forces) * Hartree / Bohr
00 from ase.calculators.demon.demon import Demon
1 #from ase.calculators.demon.demon_io import *
2
13 __all__ = ['Demon']
11 """This module defines an ASE interface to deMon.
22
33 http://www.demon-software.com
4
45 """
56 import os
67 import os.path as op
1617 from ase.calculators.calculator import Parameters, all_changes
1718 from ase.calculators.calculator import equal
1819 import ase.io
20 from .demon_io import parse_xray
1921
2022 m_e_to_amu = 1822.88839
2123
2527 Documented in Base_deMon.__init__
2628
2729 The options here are the most important ones that the user needs to be
28 aware of. Further options accepted by deMon can be set in the dictionary
30 aware of. Further options accepted by deMon can be set in the dictionary
2931 input_arguments.
3032
3133 """
5759
5860
5961 class Demon(FileIOCalculator):
60 """Calculator interface to the deMon code."""
62 """Calculator interface to the deMon code. """
6163
6264 implemented_properties = (
6365 'energy',
6769
6870 def __init__(self, **kwargs):
6971 """ASE interface to the deMon code.
72
73 The deMon2k code can be obtained from http://www.demon-software.com
74
75 The DEMON_COMMAND environment variable must be set to run the executable, in bash it would be set along the lines of
76 export DEMON_COMMAND="deMon.4.3.6.std > deMon_ase.out 2>&1"
7077
7178 Parameters:
72 label : str. relative path to the run directory
73 atoms : The Atoms onject
74 command : str. Command to run deMon. If not present the environment varable DEMON_COMMAND will be used
75 restart : str. Relative path to ASE restart directory for parameters and atoms object and results
76 basis_path : str. Relative path to the directory containing BASIS, AUXIS, ECPS, MCPS and AUGMENT
77 ignore_bad_restart_file : bool. Ignore broken or missing ASE restart files
78 By default, it is an error if the restart
79 file is missing or broken.
80 deMon_restart_path : str. Relative path to the deMon restart dir
81 title : str. Title in the deMon input file.
82 scftype : str. Type of scf
83 forces : bool. If True a force calculation will be enforced.
84 dipole : bool. If True a dipole calculation will be enforced
85 xc : str. xc-functional
86 guess : str. guess for initial density and wave functions
87 print_out : str|list. Options for the printing in deMon
88 basis : dict. Definition of basis sets.
89 ecps : dict. Definition of ECPs.
90 mcps : dict. Definition of MCPs.
91 auxis : dict. Definition of AUXIS,
92 augment : dict. Definition of AUGMENT.
93 input_arguments: dict. Explicitly given input arguments. The key is the input keyword
94 and the value is either a str, a list of str (will be written on the same line as the keyword),
95 or a list of lists of str (first list is written on the first line, the others on following lines.)
96
97
98 """
79
80 label : str
81 relative path to the run directory
82 atoms : Atoms object
83 the atoms object
84 command : str
85 Command to run deMon. If not present the environment varable DEMON_COMMAND will be used
86 restart : str
87 Relative path to ASE restart directory for parameters and atoms object and results
88 basis_path : str
89 Relative path to the directory containing BASIS, AUXIS, ECPS, MCPS and AUGMENT
90 ignore_bad_restart_file : bool
91 Ignore broken or missing ASE restart files
92 By default, it is an error if the restart
93 file is missing or broken.
94 deMon_restart_path : str
95 Relative path to the deMon restart dir
96 title : str
97 Title in the deMon input file.
98 scftype : str
99 Type of scf
100 forces : bool
101 If True a force calculation will be enforced.
102 dipole : bool
103 If True a dipole calculation will be enforced
104 xc : str
105 xc-functional
106 guess : str
107 guess for initial density and wave functions
108 print_out : str | list
109 Options for the printing in deMon
110 basis : dict
111 Definition of basis sets.
112 ecps : dict
113 Definition of ECPs
114 mcps : dict
115 Definition of MCPs
116 auxis : dict
117 Definition of AUXIS
118 augment : dict
119 Definition of AUGMENT
120 input_arguments : dict
121 Explicitly given input arguments. The key is the input keyword
122 and the value is either a str, a list of str (will be written on the same line as the keyword),
123 or a list of lists of str (first list is written on the first line, the others on following lines.)
124
125 For example usage, see the tests h2o.py and h2o_xas_xes.py in the directory ase/test/demon
126
127 """
128
99129 parameters = Parameters_deMon(**kwargs)
100130
101131 # Setup the run command
147177 self.parameters[key] = value
148178
149179 return changed_parameters
180
181 def link_file(self, fromdir, todir, filename):
182
183 if op.exists(todir + '/' + filename):
184 os.remove(todir + '/' + filename)
185
186 if op.exists(fromdir + '/' + filename):
187 os.symlink(fromdir + '/' + filename,
188 todir + '/' + filename)
189 else:
190 raise RuntimeError(
191 "{0} doesn't exist".format(fromdir + '/' + filename))
192
193
194
150195
151196 def calculate(self,
152197 atoms=None,
184229 value = self.parameters['guess']
185230 if value.upper() == 'RESTART':
186231 value2 = self.parameters['deMon_restart_path']
232
187233 if op.exists(self.directory + '/deMon.rst')\
188234 or op.islink(self.directory + '/deMon.rst'):
189235 os.remove(self.directory + '/deMon.rst')
198244 raise RuntimeError(
199245 "{0} doesn't exist".format(abspath + '/deMon.rst'))
200246
247
248 abspath = op.abspath(basis_path)
249
201250 # link basis
202 abspath = op.abspath(basis_path)
203
204 if op.exists(self.directory + '/BASIS')\
205 or op.islink(self.directory + '/BASIS'):
206 os.remove(self.directory + '/BASIS')
207
208 if op.exists(abspath + '/BASIS')\
209 or op.islink(abspath + '/BASIS'):
210 os.symlink(abspath + '/BASIS',
211 self.directory + '/BASIS')
212 else:
213 raise RuntimeError(
214 "{0} doesn't exist".format(abspath + '/BASIS'))
251 self.link_file(abspath, self.directory, 'BASIS')
215252
216253 # link auxis
217 if op.exists(self.directory + '/AUXIS')\
218 or op.islink(self.directory + '/AUXIS'):
219 os.remove(self.directory + '/AUXIS')
220
221 if op.exists(abspath + '/AUXIS')\
222 or op.islink(abspath + '/AUXIS'):
223 os.symlink(abspath + '/AUXIS',
224 self.directory + '/AUXIS')
225 else:
226 raise RuntimeError(
227 "{0} doesn't exist".format(abspath + '/AUXIS'))
254 self.link_file(abspath, self.directory, 'AUXIS')
228255
229256 # link ecps
230 if op.exists(self.directory + '/ECPS')\
231 or op.islink(self.directory + '/ECPS'):
232 os.remove(self.directory + '/ECPS')
233
234 if op.exists(abspath + '/ECPS')\
235 or op.islink(abspath + '/ECPS'):
236 os.symlink(abspath + '/ECPS',
237 self.directory + '/ECPS')
238 else:
239 raise RuntimeError(
240 "{0} doesn't exist".format(abspath + '/ECPS'))
257 self.link_file(abspath, self.directory, 'ECPS')
241258
242259 # link mcps
243 if op.exists(self.directory + '/MCPS')\
244 or op.islink(self.directory + '/MCPS'):
245 os.remove(self.directory + '/MCPS')
246
247 if op.exists(abspath + '/MCPS')\
248 or op.islink(abspath + '/ECPS'):
249 os.symlink(abspath + '/MCPS',
250 self.directory + '/MCPS')
251 else:
252 raise RuntimeError(
253 "{0} doesn't exist".format(abspath + '/MCPS'))
260 self.link_file(abspath, self.directory, 'MCPS')
261
262 # link ffds
263 self.link_file(abspath, self.directory, 'FFDS')
254264
255265 # go to directory and run calculation
256266 os.chdir(self.directory)
273283 print(line.strip())
274284 print('##### end of deMon.out')
275285 raise RuntimeError
286
287
288
276289
277290 def set_label(self, label):
278291 """Set label directory """
292305 atoms : The Atoms object to write.
293306 properties : The properties which should be calculated.
294307 system_changes : List of properties changed since last run.
308
295309 """
296310 # Call base calculator.
297311 FileIOCalculator.write_input(
396410 if not op.exists(restart_path + '/deMon.inp'):
397411 raise ReadError('The restart_path file {0} does not exist'
398412 .format(restart_path))
399
400 parameters = pickle.load(open(restart_path +
401 '/deMon_parameters.pckl', 'rb'))
402 self.parameters = parameters
413
414 if op.exists(restart_path + '/deMon_parameters.pckl'):
415 parameters = pickle.load(open(restart_path +
416 '/deMon_parameters.pckl', 'r'))
417 self.parameters = parameters
403418
404419 self.atoms = self.deMon_inp_to_atoms(restart_path + '/deMon.inp')
405420
657672 lines = f.readlines()
658673
659674 for i in range(len(lines)):
660 if lines[i].rfind('DIPOLE') > -1:
675 if lines[i].rfind('DIPOLE') > -1 and lines[i].rfind('XAS') == -1:
661676 dipole[0] = float(lines[i + 1].split()[3])
662677 dipole[1] = float(lines[i + 2].split()[3])
663678 dipole[2] = float(lines[i + 3].split()[3])
670685 def read_xray(self):
671686 """Read deMon.xry if present."""
672687
673 filename = self.label + '/deMon.xry'
688
689 # try to read core IP from, .out file
690 filename = self.label + '/deMon.out'
691 core_IP = None
674692 if op.isfile(filename):
675693 with open(filename, 'r') as f:
676694 lines = f.readlines()
677
678 mode = lines[0].split()[0]
679 ntrans = int(lines[0].split()[1])
680
681 E_trans = []
682 osc_strength = []
683 trans_dip = []
684 for i in range(1, ntrans + 1):
685 E_trans.append(float(lines[i].split()[0]))
686 osc_strength.append(
687 float(lines[i].split()[1].replace('D', 'e')))
688
689 dip1 = float(lines[i].split()[3].replace('D', 'e'))
690 dip2 = float(lines[i].split()[4].replace('D', 'e'))
691 dip3 = float(lines[i].split()[5].replace('D', 'e'))
692 trans_dip.append([dip1, dip2, dip3])
693
695
696 for i in range(len(lines)):
697 if lines[i].rfind('IONIZATION POTENTIAL') > -1:
698 core_IP = float(lines[i].split()[3])
699
700 try:
701 mode, ntrans, E_trans, osc_strength, trans_dip = parse_xray(self.label + '/deMon.xry')
702 except ReadError:
703 pass
704 else:
694705 xray_results = {'xray_mode': mode,
695706 'ntrans': ntrans,
696 'E_trans': np.array(E_trans) * Hartree,
697 'osc_strength': np.array(osc_strength), # units?
698 'trans_dip': np.array(trans_dip)} # units?
699
707 'E_trans': E_trans,
708 'osc_strength': osc_strength, # units?
709 'trans_dip': trans_dip, # units?
710 'core_IP':core_IP}
711
700712 self.results['xray'] = xray_results
701
713
714
715
702716 def deMon_inp_to_atoms(self, filename):
703717 """Routine to read deMon.inp and convert it to an atoms object."""
718
704719 with open(filename, 'r') as f:
705720 lines = f.readlines()
706721
722737 for i in range(ii + 1, len(lines)):
723738 try:
724739 line = lines[i].split()
725
726 for symbol in ase.data.chemical_symbols:
727 found = None
728 if line[0].upper().rfind(symbol.upper()) > -1:
729 found = symbol
730 break
731
732 if found is not None:
733 chemical_symbols.append(found)
734 else:
735 break
736
737 xyz.append([float(line[1]), float(line[2]), float(line[3])])
740
741 if(len(line) > 0):
742 for symbol in ase.data.chemical_symbols:
743 found = None
744 if line[0].upper().rfind(symbol.upper()) > -1:
745 found = symbol
746 break
747
748 if found is not None:
749 chemical_symbols.append(found)
750 else:
751 break
752
753 xyz.append([float(line[1]), float(line[2]), float(line[3])])
738754
739755 if len(line) > 4:
740756 atomic_numbers.append(int(line[4]))
0 from ase.calculators.calculator import ReadError
1 import os.path as op
2 import numpy as np
3 from ase.units import Hartree
4
5 def parse_xray(filename):
6 #filename = self.label + '/deMon.xry'
7 if op.isfile(filename):
8 with open(filename, 'r') as f:
9 lines = f.readlines()
10
11 mode = lines[0].split()[0]
12 ntrans = int(lines[0].split()[1])
13
14 E_trans = []
15 osc_strength = []
16 trans_dip = []
17 for i in range(1, ntrans + 1):
18 tokens = lines[i].split()
19
20 E_trans.append(float(tokens[0]))
21 osc_strength.append(
22 float(tokens[1].replace('D', 'e')))
23
24 dip1 = float(tokens[3].replace('D', 'e'))
25 dip2 = float(tokens[4].replace('D', 'e'))
26 dip3 = float(tokens[5].replace('D', 'e'))
27 trans_dip.append([dip1, dip2, dip3])
28
29 return mode, ntrans, np.array(E_trans) * Hartree, np.array(osc_strength), np.array(trans_dip)
30
31 else:
32 raise ReadError('The file {0} does not exist'
33 .format(filename))
99 from ase.units import Bohr, Hartree
1010 from ase.io.xyz import write_xyz
1111 from ase.io.vasp import write_vasp
12 from ase.parallel import paropen, world, broadcast
12 from ase.parallel import world, broadcast
1313
1414
1515 class DFTD3(FileIOCalculator):
214214 # If a parameter file exists in the working directory, delete it
215215 # first. If we need that file, we'll recreate it later.
216216 localparfile = os.path.join(self.directory, '.dftd3par.local')
217 if os.path.isfile(localparfile):
217 if world.rank == 0 and os.path.isfile(localparfile):
218218 os.remove(localparfile)
219219
220220 # Write XYZ or POSCAR file and .dftd3par.local file if we are using
223223 command = self._generate_command()
224224
225225 # Finally, call dftd3 and parse results.
226 with paropen(self.label + '.out', 'w') as f:
227 if world.rank == 0:
228 # DFTD3 does not run in parallel
229 # so we only need it to run on 1 core
226 # DFTD3 does not run in parallel
227 # so we only need it to run on 1 core
228 errorcode = None
229 if world.rank == 0:
230 with open(self.label + '.out', 'w') as f:
230231 errorcode = subprocess.call(command,
231232 cwd=self.directory, stdout=f)
232 else:
233 errorcode = None
234 world.barrier() # Wait for the call() to complete on the master node
233
235234 errorcode = broadcast(errorcode, root=0)
236235
237236 if errorcode:
299298 damppars.append('6')
300299
301300 damp_fname = os.path.join(self.directory, '.dftd3par.local')
302 with paropen(damp_fname, 'w') as f:
303 f.write(' '.join(damppars))
301 if world.rank == 0:
302 with open(damp_fname, 'w') as f:
303 f.write(' '.join(damppars))
304304
305305 def read_results(self):
306306 # parse the energy
307307 outname = os.path.join(self.directory, self.label + '.out')
308 with open(outname, 'r') as f:
309 for line in f:
310 if line.startswith(' program stopped'):
311 if 'functional name unknown' in line:
312 raise RuntimeError('Unknown DFTD3 functional name '
313 '"{}". Please check the dftd3.f '
314 'source file for the list of '
315 'known functionals and their '
316 'spelling.'
317 ''.format(self.parameters['xc']))
318 raise RuntimeError('dftd3 failed! Please check the {} '
319 'output file and report any errors '
320 'to the ASE developers.'
321 ''.format(outname))
322 if line.startswith(' Edisp'):
323 e_dftd3 = float(line.split()[3]) * Hartree
324 self.results['energy'] = e_dftd3
325 self.results['free_energy'] = e_dftd3
326 break
327 else:
328 raise RuntimeError('Could not parse energy from dftd3 output, '
329 'see file {}'.format(outname))
308 self.results['energy'] = None
309 self.results['free_energy'] = None
310 if world.rank == 0:
311 with open(outname, 'r') as f:
312 for line in f:
313 if line.startswith(' program stopped'):
314 if 'functional name unknown' in line:
315 message = 'Unknown DFTD3 functional name "{}". ' \
316 'Please check the dftd3.f source file ' \
317 'for the list of known functionals ' \
318 'and their spelling.' \
319 ''.format(self.parameters['xc'])
320 else:
321 message = 'dftd3 failed! Please check the {} ' \
322 'output file and report any errors ' \
323 'to the ASE developers.' \
324 ''.format(outname)
325 raise RuntimeError(message)
326
327 if line.startswith(' Edisp'):
328 e_dftd3 = float(line.split()[3]) * Hartree
329 self.results['energy'] = e_dftd3
330 self.results['free_energy'] = e_dftd3
331 break
332 else:
333 raise RuntimeError('Could not parse energy from dftd3 '
334 'output, see file {}'.format(outname))
335
336 self.results['energy'] = broadcast(self.results['energy'], root=0)
337 self.results['free_energy'] = broadcast(self.results['free_energy'],
338 root=0)
339
330340 # FIXME: Calculator.get_potential_energy() simply inspects
331341 # self.results for the free energy rather than calling
332342 # Calculator.get_property('free_energy'). For example, GPAW does
341351 self.results['free_energy'] += efree
342352 except PropertyNotImplementedError:
343353 pass
354
344355 if self.parameters['grad']:
345356 # parse the forces
346357 forces = np.zeros((len(self.atoms), 3))
347358 forcename = os.path.join(self.directory, 'dftd3_gradient')
348 with open(forcename, 'r') as f:
349 for i, line in enumerate(f):
350 forces[i] = np.array([float(x) for x in line.split()])
351 self.results['forces'] = -forces * Hartree / Bohr
359 self.results['forces'] = None
360 if world.rank == 0:
361 with open(forcename, 'r') as f:
362 for i, line in enumerate(f):
363 forces[i] = np.array([float(x) for x in line.split()])
364 self.results['forces'] = -forces * Hartree / Bohr
365 self.results['forces'] = broadcast(self.results['forces'], root=0)
352366
353367 if any(self.atoms.pbc):
354368 # parse the stress tensor
355369 stress = np.zeros((3, 3))
356370 stressname = os.path.join(self.directory, 'dftd3_cellgradient')
357 with open(stressname, 'r') as f:
358 for i, line in enumerate(f):
359 stress[i] = np.array([float(x) for x in line.split()])
360
361 stress *= Hartree / Bohr / self.atoms.get_volume()
362 stress = np.dot(stress, self.atoms.cell.T)
363 self.results['stress'] = stress.flat[[0, 4, 8, 5, 2, 1]]
371 self.results['stress'] = None
372 if world.rank == 0:
373 with open(stressname, 'r') as f:
374 for i, line in enumerate(f):
375 for j, x in enumerate(line.split()):
376 stress[i, j] = float(x)
377
378 stress *= Hartree / Bohr / self.atoms.get_volume()
379 stress = np.dot(stress, self.atoms.cell.T)
380 self.results['stress'] = stress.flat[[0, 4, 8, 5, 2, 1]]
381 self.results['stress'] = broadcast(self.results['stress'],
382 root=0)
364383
365384 def get_property(self, name, atoms=None, allow_calculation=True):
366385 dft_result = None
524524 B[3:, :] = atoms2.positions
525525
526526 # Solve least square problem Ax = B
527 lstsq_fit = np.linalg.lstsq(A, B)
527 lstsq_fit = np.linalg.lstsq(A, B, rcond=-1)
528528 x = lstsq_fit[0]
529529 error = np.linalg.norm(np.dot(A, x) - B)
530530
88 EigenvalOccupationMixin)
99
1010 elk_parameters = {'swidth': Hartree}
11
1112
1213 class ELK(FileIOCalculator, EigenvalOccupationMixin):
1314 command = 'elk > elk.out'
5859 if 'kpts' in self.parameters:
5960 raise RuntimeError("You can't use both 'autokpt' and 'kpts'!")
6061 if 'ngridk' in self.parameters:
61 raise RuntimeError("You can't use both 'autokpt' and 'ngridk'!")
62 raise RuntimeError(
63 "You can't use both 'autokpt' and 'ngridk'!")
6264 if 'ngridk' in self.parameters:
6365 if 'kpts' in self.parameters:
6466 raise RuntimeError("You can't use both 'ngridk' and 'kpts'!")
6567
6668 if self.parameters.get('autoswidth'):
6769 if 'smearing' in self.parameters:
68 raise RuntimeError("You can't use both 'autoswidth' and 'smearing'!")
70 raise RuntimeError(
71 "You can't use both 'autoswidth' and 'smearing'!")
6972 if 'swidth' in self.parameters:
70 raise RuntimeError("You can't use both 'autoswidth' and 'swidth'!")
73 raise RuntimeError(
74 "You can't use both 'autoswidth' and 'swidth'!")
7175
7276 fd = open(os.path.join(self.directory, 'elk.in'), 'w')
7377
7781
7882 if self.parameters.get('rmt', None) is not None:
7983 self.rmt = self.parameters['rmt'].copy()
80 assert len(self.rmt.keys()) == len(list(set(self.rmt.keys()))), 'redundant rmt definitions'
81 self.parameters.pop('rmt') # this is not an elk keyword!
84 assert len(self.rmt.keys()) == len(list(set(self.rmt.keys()))), \
85 'redundant rmt definitions'
86 self.parameters.pop('rmt') # this is not an elk keyword!
8287 else:
8388 self.rmt = None
8489
8691 inp.update(self.parameters)
8792
8893 if 'xc' in self.parameters:
89 xctype = {'LDA': 3, # PW92
94 xctype = {'LDA': 3, # PW92
9095 'PBE': 20,
9196 'REVPBE': 21,
9297 'PBESOL': 22,
153158 species[symbol] = [(a, m)]
154159 symbols.append(symbol)
155160 fd.write('atoms\n%d\n' % len(species))
156 #scaled = atoms.get_scaled_positions(wrap=False)
161 # scaled = atoms.get_scaled_positions(wrap=False)
157162 scaled = np.linalg.solve(atoms.cell.T, atoms.positions.T).T
158163 for symbol in symbols:
159164 fd.write("'%s.in' : spfname\n" % symbol)
160165 fd.write('%d\n' % len(species[symbol]))
161166 for a, m in species[symbol]:
162167 fd.write('%.14f %.14f %.14f 0.0 0.0 %.14f\n' %
163 (tuple(scaled[a])+ (m,)))
168 (tuple(scaled[a]) + (m,)))
164169 # species
165170 species_path = self.parameters.get('species_dir')
166171 if species_path is None:
185190 # use default rmt for undefined species
186191 self.rmt.update({s: 0.0})
187192 # write custom species into elk.in
188 skeys = list(set(self.rmt.keys())) # unique
193 skeys = list(set(self.rmt.keys())) # unique
189194 skeys.sort()
190195 for s in skeys:
191196 found = False
193198 if line.find("'" + s + "'") > -1:
194199 begline = n - 1
195200 for n, line in enumerate(slines[begline:]):
196 if not line.strip(): # first empty line
201 if not line.strip(): # first empty line
197202 endline = n
198203 found = True
199204 break
201206 fd.write("species\n")
202207 # set rmt on third line
203208 rmt = self.rmt[s]
204 assert isinstance(rmt, (float,int))
205 if rmt <= 0.0: # relative
209 assert isinstance(rmt, (float, int))
210 if rmt <= 0.0: # relative
206211 # split needed because H is defined with comments
207 newrmt = float(slines[begline + 3].split()[0].strip()) + rmt
212 newrmt = (float(slines[begline + 3].split()[0].strip()) +
213 rmt)
208214 else:
209215 newrmt = rmt
210216 slines[begline + 3] = '%6s\n' % str(newrmt)
211217 for l in slines[begline: begline + endline]:
212218 fd.write('%s' % l)
213 fd.write("\n")
219 fd.write('\n')
214220 else:
215221 # use default species
216222 # if sppath is present in elk.in it overwrites species blocks!
224230
225231 for filename in [totenergy, eigval, kpoints, self.out]:
226232 if not os.path.isfile(filename):
227 raise ReadError('ELK output file '+filename+' is missing.')
233 raise ReadError('ELK output file ' + filename + ' is missing.')
228234
229235 # read state from elk.in because *.OUT do not provide enough digits!
230236 self.atoms = read_elk(os.path.join(self.directory, 'elk.in'))
268274 forces = []
269275 for line in lines:
270276 if line.rfind('total force') > -1:
271 forces.append(np.array([float(f) for f in line.split(':')[1].split()]))
277 forces.append(np.array([float(f)
278 for f in line.split(':')[1].split()]))
272279 self.results['forces'] = np.array(forces) * Hartree / Bohr
273280
274281 def read_convergence(self):
281288
282289 # more methods
283290 def get_electronic_temperature(self):
284 return self.width*Hartree
291 return self.width * Hartree
285292
286293 def get_number_of_bands(self):
287294 return self.nbands
326333 def read_kpts(self, mode='ibz_k_points'):
327334 """ Returns list of kpts weights or kpts coordinates. """
328335 values = []
329 assert mode in ['ibz_k_points' , 'k_point_weights'], 'mode not in [\'ibz_k_points\' , \'k_point_weights\']'
336 assert mode in ['ibz_k_points', 'k_point_weights']
330337 kpoints = os.path.join(self.directory, 'KPOINTS.OUT')
331338 lines = open(kpoints).readlines()
332339 kpts = None
334341 if line.rfind(': nkpt') > -1:
335342 kpts = int(line.split(':')[0].strip())
336343 break
337 assert not kpts is None
338 text = lines[1:] # remove first line
344 assert kpts is not None
345 text = lines[1:] # remove first line
339346 values = []
340347 for line in text:
341348 if mode == 'ibz_k_points':
374381 lines = open(self.out).readlines()
375382 for line in lines:
376383 if line.rfind(' Loop number : ') > -1:
377 niter = int(line.split(':')[1].split()[0].strip()) # last iter
384 niter = int(line.split(':')[1].split()[0].strip()) # last iter
378385 return niter
379386
380387 def read_magnetic_moment(self):
382389 lines = open(self.out).readlines()
383390 for line in lines:
384391 if line.rfind('total moment :') > -1:
385 magmom = float(line.split(':')[1].strip()) # last iter
392 magmom = float(line.split(':')[1].strip()) # last iter
386393 return magmom
387394
388395 def read_electronic_temperature(self):
398405 """ Returns list of last eigenvalues, occupations
399406 for given kpt and spin. """
400407 values = []
401 assert mode in ['eigenvalues' , 'occupations'], 'mode not in [\'eigenvalues\' , \'occupations\']'
408 assert mode in ['eigenvalues', 'occupations']
402409 eigval = os.path.join(self.directory, 'EIGVAL.OUT')
403410 lines = open(eigval).readlines()
404411 nstsv = None
406413 if line.rfind(': nstsv') > -1:
407414 nstsv = int(line.split(':')[0].strip())
408415 break
409 assert not nstsv is None
416 assert nstsv is not None
410417 kpts = None
411418 for line in lines:
412419 if line.rfind(': nkpt') > -1:
413420 kpts = int(line.split(':')[0].strip())
414421 break
415 assert not kpts is None
422 assert kpts is not None
416423 text = lines[3:] # remove first 3 lines
417424 # find the requested k-point
418425 beg = 2 + (nstsv + 4) * kpt
4949 def RunSerialDacapo(ARGS):
5050 DACAPOEXE = os.environ.get('DACAPOEXE_SERIAL')
5151 if DACAPOEXE is None:
52 raise Exception, 'DACAPOEXE_SERIAL was not found in your environment'
52 raise Exception('DACAPOEXE_SERIAL was not found in your environment')
5353 cmd = string.join([DACAPOEXE,ARGS],' ')
5454 status = os.system(cmd)
5555 if status != 0:
129129 # UNDEFINED = fields[3]
130130 fields = string.split(line)
131131 if __debug__:
132 print fields
132 print(fields)
133133
134134 nodename = fields[0]
135135 nprocs = int(fields[1])
136136 if __debug__:
137 print nodename,nprocs
137 print(nodename,nprocs)
138138 for n in range(nprocs):
139139 nodeline = '%s\n' % (fields[0])
140140 nf.write(nodeline)
144144 nf.close()
145145
146146 if __debug__:
147 print 'SGE_O_WORKDIR = ',os.environ.get('SGE_O_WORKDIR')
148 print 'NHOSTS = ',os.environ.get('NHOSTS')
149 print 'NSLOTS = ',os.environ.get('NSLOTS')
147 print('SGE_O_WORKDIR = ',os.environ.get('SGE_O_WORKDIR'))
148 print('NHOSTS = ',os.environ.get('NHOSTS'))
149 print('NSLOTS = ',os.environ.get('NSLOTS'))
150150
151151
152152 if NPROCS > 1:
154154 MPICMD = 'mpirun -np %i' % NPROCS
155155 DACAPOEXE = os.environ.get('DACAPOEXE_PARALLEL')
156156 parcmd = string.join([MPICMD,DACAPOEXE,ARGS],' ')
157 if __debug__: print parcmd
158
159 print 'Running "%s"' % parcmd
157 if __debug__: print(parcmd)
158
159 print('Running "%s"' % parcmd)
160160 p = Popen(parcmd,
161161 shell=True,
162162 stdin=PIPE,
170170
171171 if status != 0:
172172 (sout,serr) = p.communicate()
173 print 'stdout = ',sout
174 print 'stderr = ',serr
173 print('stdout = ',sout)
174 print('stderr = ',serr)
175175 all_is_ok = False
176 print '**** the command failed ****'
176 print('**** the command failed ****')
177177
178178 if not all_is_ok:
179179 sys.exit('"%s" failed' % parcmd)
180180
181 print
182 print 'One iteration from parallel run complete'
183 print '*******************************************************'
184 print
181 print()
182 print('One iteration from parallel run complete')
183 print('*******************************************************')
184 print()
185185 else:
186186 RunSerialDacapo(ARGS)
187187
3131 nc = netCDF(arg,'r')
3232 energy = nc.variables.get('TotalEnergy',None)
3333 if energy is not None:
34 print energy[:][-1]
34 print(energy[:][-1])
3535 else:
36 print None
36 print(None)
3737 nc.close()
3838 else:
39 print calc
39 print(calc)
4040
4141 if options.p is not None:
4242 if options.r is not None:
00 #!/usr/bin/env python
1 from __future__ import print_function
2
13 import os,string,sys
24
35 # tell me about the architecture
4 print 'Running as user: ', os.environ['USER']
5 print 'In directory: ',os.getcwd()
6 print('Running as user: ', os.environ['USER'])
7 print('In directory: ',os.getcwd())
68
79 try:
810 import platform
9 print '------------- system information ---------------'
10 print 'Hostname = ',os.environ['HOST']
11 print 'Architecture = ',platform.architecture()
12 print 'distribution = ',platform.dist()
13 print 'libc version = ',platform.libc_ver()
14 print 'Machine type = ',platform.machine()
15 print 'Platform = ',platform.platform()
16 print 'processor type = ',platform.processor()
17 print 'system = ',platform.system()
18 print 'system version = ',platform.version()
19
20 print
21 print '------------- Python information --------'
22 print 'python was compiled with: ',platform.python_compiler()
23 print 'python version = ',platform.python_version()
24 print 'python was built: ',platform.python_build()
25
26 except:
27 print '*** you have an older version of python'
28 print '*** you missed some important system information because of that'
29 print '*** consider upgrading to version 2.3 or greater'
30 print 'python version = ',sys.version
31 print 'uname = '
11 print('------------- system information ---------------')
12 print('Hostname = ',os.environ['HOST'])
13 print('Architecture = ',platform.architecture())
14 print('distribution = ',platform.dist())
15 print('libc version = ',platform.libc_ver())
16 print('Machine type = ',platform.machine())
17 print('Platform = ',platform.platform())
18 print('processor type = ',platform.processor())
19 print('system = ',platform.system())
20 print('system version = ',platform.version())
21
22 print()
23 print('------------- Python information --------')
24 print('python was compiled with: ',platform.python_compiler())
25 print('python version = ',platform.python_version())
26 print('python was built: ',platform.python_build())
27
28 except:
29 print('*** you have an older version of python')
30 print('*** you missed some important system information because of that')
31 print('*** consider upgrading to version 2.3 or greater')
32 print('python version = ',sys.version)
33 print('uname = ')
3234 os.system('uname -a')
3335
3436
35 print '-------------- User ---------------------'
37 print('-------------- User ---------------------')
3638 shell = os.environ.get('SHELL')
37 print 'SHELL = ',shell
38
39 print
39 print('SHELL = ',shell)
40
41 print()
4042
4143 try:
4244 import Numeric
43 print 'Numeric version = ',Numeric.__version__
44 except:
45 print '*** Numeric is not installed.'
46 print '*** Get it from http://sourceforge.net/projects/numpy'
45 print('Numeric version = ',Numeric.__version__)
46 except:
47 print('*** Numeric is not installed.')
48 print('*** Get it from http://sourceforge.net/projects/numpy')
4749
4850 try:
4951 import numarray
50 print 'numarray version = ',numarray.__version__
51 except:
52 print '*** numarray is not installed.'
53 print '*** Get it from http://sourceforge.net/projects/numpy'
52 print('numarray version = ',numarray.__version__)
53 except:
54 print('*** numarray is not installed.')
55 print('*** Get it from http://sourceforge.net/projects/numpy')
5456
5557 try:
5658 import numpy
57 print 'numpy version = ', numpy.__version__
58 except:
59 print '*** numpy is not installed'
59 print('numpy version = ', numpy.__version__)
60 except:
61 print('*** numpy is not installed')
6062
6163 try:
6264 import Scientific
63 print 'Found Scientific'
65 print('Found Scientific')
6466 try:
6567 import Scientific.IO.NetCDF
66 print 'Found Scientific.IO.NetCDF'
68 print('Found Scientific.IO.NetCDF')
6769 except:
68 print 'Scientific.IO.NetCDF appears broken.'
69 print 'Is netcdf installed?'
70 print 'did you set $NETCDF_PREFIX when you installed Scientific?'
71 except:
72 print '*** Scientific not installed'
73 print '*** Get it at http://starship.python.net/~hinsen/ScientificPython/'
70 print('Scientific.IO.NetCDF appears broken.')
71 print('Is netcdf installed?')
72 print('did you set $NETCDF_PREFIX when you installed Scientific?')
73 except:
74 print('*** Scientific not installed')
75 print('*** Get it at http://starship.python.net/~hinsen/ScientificPython/')
7476
7577
7678 try:
7779 import ASE
78 print 'Found ASE at ', ASE.__file__
79 except Exception,error:
80 print error
81 print '*** No ASE found. Did you install it?'
80 print('Found ASE at ', ASE.__file__)
81 except Exception as error:
82 print(error)
83 print('*** No ASE found. Did you install it?')
8284
8385 try:
8486 import ase
85 print 'Found an ase version: "%s"' % ase.__version__
86 print 'at :',ase.__file__
87 except:
88 print '*** No ase found. Did you install it?'
87 print('Found an ase version: "%s"' % ase.__version__)
88 print('at :',ase.__file__)
89 except:
90 print('*** No ase found. Did you install it?')
8991
9092
9193 try:
9294 import Dacapo
93 print 'Found Dacapo python modules'
94 except:
95 print '*** No Dacapo modules found, did you install them?'
96 print ' Get them at dcwww.fysik.dtu.dk/campos'
95 print('Found Dacapo python modules')
96 except:
97 print('*** No Dacapo modules found, did you install them?')
98 print(' Get them at dcwww.fysik.dtu.dk/campos')
9799
98100 try:
99101 import Gnuplot
100 print 'Found Gnuplot python module'
101 except:
102 print '*** No Gnuplot module found'
102 print('Found Gnuplot python module')
103 except:
104 print('*** No Gnuplot module found')
103105
104106 try:
105107 import matplotlib
106 print 'Found matplotlib version: ',matplotlib.__version__
107 except:
108 print 'no matplotlib found'
108 print('Found matplotlib version: ',matplotlib.__version__)
109 except:
110 print('no matplotlib found')
109111
110112 libs = ['cblas',
111113 'lapack',
125127 for libpath in os.environ['LD_LIBRARY_PATH'].split(':'):
126128 libpaths.append(libpath)
127129
128 print
129 print '------------------ libraries ------------------'
130 print()
131 print('------------------ libraries ------------------')
130132 for lib in libs:
131133 found = False
132134 for path in libpaths:
133135 if os.path.exists(os.path.join(path,'lib%s.a' % lib)):
134136 found = True
135 print 'found %s in %s' % ('lib%s.a' % lib,path)
137 print('found %s in %s' % ('lib%s.a' % lib,path))
136138 if not found:
137 print '*** Could not find lib%s.a' % lib
139 print('*** Could not find lib%s.a' % lib)
138140
139141
140142
161163
162164
163165
164 print
165 print '------------------- compilers -----------------'
166 print()
167 print('------------------- compilers -----------------')
166168 c = ['pgf90','pgf77',
167169 'ifort','ifc',
168170 'g95',
172174 ]
173175 for compiler in c:
174176 if IsOnPath(compiler):
175 print '%s found' % compiler
176 else:
177 print '*** %s not found' % compiler
177 print('%s found' % compiler)
178 else:
179 print('*** %s not found' % compiler)
178180
179181
180182
181 print
182 print '-------------- Check for ASE and Dacapo tools -------------'
183 print()
184 print('-------------- Check for ASE and Dacapo tools -------------')
183185 dacapo_tools = ['dacapo.run',
184186 'stripnetcdf'
185187 ]
188190 f = IsOnPath(exe)
189191 if f:
190192 if FileIsExecutable(f):
191 print '%s found at %s' % (exe,f)
192 else:
193 print '%s found, but it is not executable' % exe
194
195 else:
196 print '%s not found' % exe
197 print 'Dacapo/Tools is not on your executable path'
193 print('%s found at %s' % (exe,f))
194 else:
195 print('%s found, but it is not executable' % exe)
196
197 else:
198 print('%s not found' % exe)
199 print('Dacapo/Tools is not on your executable path')
198200
199201
200202 ase_executables = ['plottrajectory']
203205 f = IsOnPath(exe)
204206 if f:
205207 if FileIsExecutable(f):
206 print '%s found at %s' % (exe,f)
207 else:
208 print '%s found, but it is not executable' % exe
209
210 else:
211 print '*** %s not found' % exe
212 print 'ASE/Tools is not on your executable path'
213
214
215
216 print
217 print '-------- Location of dacapo executables ------------'
208 print('%s found at %s' % (exe,f))
209 else:
210 print('%s found, but it is not executable' % exe)
211
212 else:
213 print('*** %s not found' % exe)
214 print('ASE/Tools is not on your executable path')
215
216
217
218 print()
219 print('-------- Location of dacapo executables ------------')
218220
219221 exe = os.environ.get('DACAPOEXE_SERIAL',None)
220222 f = IsOnPath(exe)
221223 if f:
222224 if FileIsExecutable(f):
223 print 'default serial executable is: %s' % (exe)
224 else:
225 print '%s found, but it is not executable' % exe
225 print('default serial executable is: %s' % (exe))
226 else:
227 print('%s found, but it is not executable' % exe)
226228
227229 else:
228 print '*** %s not found' % exe
229 print 'No default serial dacapo executable found'
230 print('*** %s not found' % exe)
231 print('No default serial dacapo executable found')
230232
231233 exe = os.environ.get('DACAPOEXE_PARALLEL',None)
232234 f = IsOnPath(exe)
233235 if f:
234236 if FileIsExecutable(f):
235 print 'default parallel executable is: %s' % (exe)
236 else:
237 print '%s found, but it is not executable' % exe
237 print('default parallel executable is: %s' % (exe))
238 else:
239 print('%s found, but it is not executable' % exe)
238240
239241 else:
240 print '*** %s not found' % exe
241 print 'No default parallel dacapo executable found'
242 print('*** %s not found' % exe)
243 print('No default parallel dacapo executable found')
242244
243245
244246 psp = os.environ.get('DACAPOPATH', '/usr/share/dacapo-psp')
245247 if os.path.isdir(psp):
246 print 'Pseudopotential database = ',psp
248 print('Pseudopotential database = ',psp)
247249 else:
248 print '*** "%s" is not a directory, please check $DACAPOPATH'
249
250
251 print
252 print '-----------miscellaneous utilities-------------'
250 print('*** "%s" is not a directory, please check $DACAPOPATH')
251
252
253 print()
254 print('-----------miscellaneous utilities-------------')
253255 for exe in ['rasmol','gnuplot','vmd','vtk',
254256 'rsync','ssh','scp']:
255257 f = IsOnPath(exe)
256258 if f:
257259 if FileIsExecutable(f):
258 print '%s found at %s' % (exe,f)
259 else:
260 print '%s found, but it is not executable' % exe
261
262 else:
263 print '*** %s not found on your path' % exe
264
265
266 print
267 print '--------------- mpi ------------------'
260 print('%s found at %s' % (exe,f))
261 else:
262 print('%s found, but it is not executable' % exe)
263
264 else:
265 print('*** %s not found on your path' % exe)
266
267
268 print()
269 print('--------------- mpi ------------------')
268270 for exe in ['recon','lamboot','mpirun','lamhalt']:
269271 f = IsOnPath(exe)
270272 if f:
271273 if FileIsExecutable(f):
272 print '%s found at %s' % (exe,f)
273 else:
274 print '%s found, but it is not executable' % exe
275
276 else:
277 print '*** %s not found' % exe
278 print 'maybe you do not have lam-mpi installed'
279
280
281
282
283 print
284 print '---------- PYTHON environment variables -------------'
285 print 'PYTHONSTARTUP = ',os.environ.get('PYTHONSTARTUP')
286 print 'PYTHONOPTIMIZE = ',os.environ.get('PYTHONOPTIMIZE')
287 print 'PYTHONPATH:'
274 print('%s found at %s' % (exe,f))
275 else:
276 print('%s found, but it is not executable' % exe)
277
278 else:
279 print('*** %s not found' % exe)
280 print('maybe you do not have lam-mpi installed')
281
282
283
284
285 print()
286 print('---------- PYTHON environment variables -------------')
287 print('PYTHONSTARTUP = ',os.environ.get('PYTHONSTARTUP'))
288 print('PYTHONOPTIMIZE = ',os.environ.get('PYTHONOPTIMIZE'))
289 print('PYTHONPATH:')
288290 for x in sys.path:
289 print '"%s"' % x
290
291
292 print
293 print '----------- system path --------------------'
291 print('"%s"' % x)
292
293
294 print()
295 print('----------- system path --------------------')
294296 path = os.environ.get('PATH')
295297 for x in string.split(path,':'):
296 print '"%s"' % x
298 print('"%s"' % x)
5555 'options':qsub_options,
5656 'script':fname}
5757
58 print cmd
58 print(cmd)
5959
6060 os.system(cmd)
6161 os.close(h)
7070 #end''' % {'ncfile':ncfile,
7171 'tags':string.join([str(t) for t in freetags],',')}
7272
73 print script
73 print(script)
7474 f = open(fname,'w')
7575 f.write(script)
7676 f.close()
9393 'options':qsub_options,
9494 'script':fname}
9595
96 print cmd
96 print(cmd)
9797
9898 os.system(cmd)
9999 os.close(h)
2121
2222 calc = Jacapo(arg)
2323 calc.strip()
24 print 'stripped %s' % arg
24 print('stripped %s' % arg)
2525
0 """ASE LAMMPS Calculator Library Version"""
1
2 from __future__ import print_function
3
4 import ctypes
5 import operator
6
7 import numpy as np
8 from numpy.linalg import norm
9
10 import ase.units
11 from ase.calculators.calculator import Calculator
12 from ase.data import chemical_symbols, atomic_masses
13 from ase.utils import basestring
14
15
16 # TODO
17 # 1. should we make a new lammps object each time ?
18 # 4. need a routine to get the model back from lammps
19 # 5. if we send a command to lmps directly then the calculator does
20 # not know about it and the energy could be wrong.
21 # 6. do we need a subroutine generator that converts a lammps string
22 # into a python function that can be called
23 # 8. make matscipy as fallback
24 # 9. keep_alive not needed with no system changes
25 #10. it may be a good idea to unify the cell handling with the one found in
26 # lammpsrun.py
27
28
29 # this one may be moved to some more generial place
30 def is_upper_triangular(arr, atol=1e-8):
31 """test for upper triangular matrix based on numpy"""
32 # must be (n x n) matrix
33 assert len(arr.shape)==2
34 assert arr.shape[0] == arr.shape[1]
35 return np.allclose(np.tril(arr, k=-1), 0., atol=atol)
36
37
38 def convert_cell(ase_cell):
39 """
40 Convert a parallel piped (forming right hand basis)
41 to lower triangular matrix LAMMPS can accept. This
42 function transposes cell matrix so the bases are column vectors
43 """
44 cell = np.matrix.transpose(ase_cell)
45
46 if not is_upper_triangular(cell):
47 # rotate bases into triangular matrix
48 tri_mat = np.zeros((3, 3))
49 A = cell[:, 0]
50 B = cell[:, 1]
51 C = cell[:, 2]
52 tri_mat[0, 0] = norm(A)
53 Ahat = A / norm(A)
54 AxBhat = np.cross(A, B) / norm(np.cross(A, B))
55 tri_mat[0, 1] = np.dot(B, Ahat)
56 tri_mat[1, 1] = norm(np.cross(Ahat, B))
57 tri_mat[0, 2] = np.dot(C, Ahat)
58 tri_mat[1, 2] = np.dot(C, np.cross(AxBhat, Ahat))
59 tri_mat[2, 2] = norm(np.dot(C, AxBhat))
60
61 # create and save the transformation for coordinates
62 volume = np.linalg.det(ase_cell)
63 trans = np.array([np.cross(B, C), np.cross(C, A), np.cross(A, B)])
64 trans /= volume
65 coord_transform = np.dot(tri_mat, trans)
66
67 return tri_mat, coord_transform
68 else:
69 return cell, None
70
71
72 lammps_real = {
73 "mass": 0.001 * ase.units.kg / ase.units.mol,
74 "distance": ase.units.Angstrom,
75 "time": ase.units.fs,
76 "energy": ase.units.kcal/ase.units.mol,
77 "velocity": ase.units.Angstrom / ase.units.fs,
78 "force": ase.units.kcal/ase.units.mol/ase.units.Angstrom,
79 "pressure": 101325 * ase.units.Pascal
80 }
81
82 lammps_metal = {
83 "mass": 0.001 * ase.units.kg / ase.units.mol,
84 "distance": ase.units.Angstrom,
85 "time": 1e-12 * ase.units.second,
86 "energy": ase.units.eV,
87 "velocity": ase.units.Angstrom / (1e-12*ase.units.second),
88 "force": ase.units.eV/ase.units.Angstrom,
89 "pressure": 1e5 * ase.units.Pascal
90 }
91
92 lammps_units = {"real": lammps_real,
93 "metal": lammps_metal}
94
95
96 def unit_convert(quantity, units='metal'):
97 try:
98 return lammps_units[units][quantity]
99 except:
100 raise NotImplementedError("Unit {} in unit system {} is not "
101 "implemented.".format(quantity, units))
102
103
104 class LAMMPSlib(Calculator):
105 r"""
106 **Introduction**
107
108 LAMMPSlib is an interface and calculator for LAMMPS_. LAMMPSlib uses
109 the python interface that comes with LAMMPS to solve an atoms model
110 for energy, atom forces and cell stress. This calculator creates a
111 '.lmp' object which is a running lammps program, so further commands
112 can be sent to this object executed until it is explicitly closed. Any
113 additional variables calculated by lammps can also be extracted. This
114 is still experimental code.
115
116 **Arguments**
117
118 ================= ==========================================================
119 Keyword Description
120 ================= ==========================================================
121 ``lmpcmds`` list of strings of LAMMPS commands. You need to supply
122 enough to define the potential to be used e.g.
123
124 ["pair_style eam/alloy",
125 "pair_coeff * * potentials/NiAlH_jea.eam.alloy Ni Al"]
126
127 ``atom_types`` dictionary of ``atomic_symbol :lammps_atom_type`` pairs,
128 e.g. ``{'Cu':1}`` to bind copper to lammps atom type 1.
129 Default method assigns lammps atom types in order that they
130 appear in the atoms model. Autocreated if <None>.
131
132 ``log_file`` string
133 path to the desired LAMMPS log file
134
135 ``lammps_header`` string to use for lammps setup. Default is to use
136 metal units and simple atom simulation.
137
138 lammps_header=['units metal',
139 'atom_style atomic',
140 'atom_modify map array sort 0 0'])
141
142 ``keep_alive`` Boolean
143 whether to keep the lammps routine alive for more commands
144
145 ================= ==========================================================
146
147
148 **Requirements**
149
150 To run this calculator you must have LAMMPS installed and compiled to
151 enable the python interface. See the LAMMPS manual.
152
153 If the following code runs then lammps is installed correctly.
154
155 >>> from lammps import lammps
156 >>> lmp = lammps()
157
158 The version of LAMMPS is also important. LAMMPSlib is suitable for
159 versions after approximately 2011. Prior to this the python interface
160 is slightly different from that used by LAMMPSlib. It is not difficult
161 to change to the earlier format.
162
163 **LAMMPS and LAMMPSlib**
164
165 The LAMMPS calculator is another calculator that uses LAMMPS (the
166 program) to calculate the energy by generating input files and running
167 a separate LAMMPS job to perform the analysis. The output data is then
168 read back into python. LAMMPSlib makes direct use of the LAMMPS (the
169 program) python interface. As well as directly running any LAMMPS
170 command line it allows the values of any of LAMMPS variables to be
171 extracted and returned to python.
172
173 **Example**
174
175 Provided that the respective potential file is in the working directory, one
176 can simply run (note that LAMMPS needs to be compiled to work with EAM
177 potentials)
178
179 ::
180
181 from ase import Atom, Atoms
182 from ase.build import bulk
183 from lammpslib import LAMMPSlib
184
185 cmds = ["pair_style eam/alloy",
186 "pair_coeff * * NiAlH_jea.eam.alloy Al H"]
187
188 Ni = bulk('Ni', cubic=True)
189 H = Atom('H', position=Ni.cell.diagonal()/2)
190 NiH = Ni + H
191
192 lammps = LAMMPSlib(lmpcmds=cmds, log_file='test.log')
193
194 NiH.set_calculator(lammps)
195 print("Energy ", NiH.get_potential_energy())
196
197
198 **Implementation**
199
200 LAMMPS provides a set of python functions to allow execution of the
201 underlying C++ LAMMPS code. The functions used by the LAMMPSlib
202 interface are::
203
204 from lammps import lammps
205
206 lmp = lammps(cmd_args) # initiate LAMMPS object with command line args
207
208 lmp.scatter_atoms('x',1,3,positions) # atom coords to LAMMPS C array
209 lmp.command(cmd) # executes a one line cmd string
210 lmp.extract_variable(...) # extracts a per atom variable
211 lmp.extract_global(...) # extracts a global variable
212 lmp.close() # close the lammps object
213
214 For a single atom model the following lammps file commands would be run
215 by invoking the get_potential_energy() method::
216
217 units metal
218 atom_style atomic
219 atom_modify map array sort 0 0
220
221 region cell prism 0 xhi 0 yhi 0 zhi xy xz yz units box
222 create_box 1 cell
223 create_atoms 1 single 0 0 0 units box
224 mass * 1.0
225
226 ## user lmpcmds get executed here
227 pair_style eam/alloy
228 pair_coeff * * NiAlH_jea.eam.alloy Al
229 ## end of user lmmpcmds
230
231 run 0
232
233
234 **Notes**
235
236 .. _LAMMPS: http://lammps.sandia.gov/
237
238 * Units: The default lammps_header sets the units to Angstrom and eV
239 and for compatibility with ASE Stress is in GPa.
240
241 * The global energy is currently extracted from LAMMPS using
242 extract_variable since lammps.lammps currently extract_global only
243 accepts the following ['dt', 'boxxlo', 'boxxhi', 'boxylo', 'boxyhi',
244 'boxzlo', 'boxzhi', 'natoms', 'nlocal'].
245
246 * If an error occurs while lammps is in control it will crash
247 Python. Check the output of the log file to find the lammps error.
248
249 * If the are commands directly sent to the LAMMPS object this may
250 change the energy value of the model. However the calculator will not
251 know of it and still return the original energy value.
252
253 """
254
255 implemented_properties = ['energy', 'forces', 'stress']
256
257 started = False
258 initialized = False
259
260 default_parameters = dict(
261 atom_types=None,
262 log_file=None,
263 lammps_name='',
264 keep_alive=False,
265 lammps_header=['units metal',
266 'atom_style atomic',
267 'atom_modify map array sort 0 0'],
268 boundary=True,
269 create_box=True,
270 create_atoms=True,
271 read_molecular_info=False,
272 comm=None)
273
274 def __init__(self, *args, **kwargs):
275 Calculator.__init__(self, *args, **kwargs)
276 self.lmp = None
277
278 def __del__(self):
279 if self.started:
280 self.lmp.close()
281
282 def set_cell(self, atoms, change=False):
283 lammps_cell, self.coord_transform = convert_cell(atoms.get_cell())
284 xhi = lammps_cell[0, 0]
285 yhi = lammps_cell[1, 1]
286 zhi = lammps_cell[2, 2]
287 xy = lammps_cell[0, 1]
288 xz = lammps_cell[0, 2]
289 yz = lammps_cell[1, 2]
290
291 if change:
292 cell_cmd = ('change_box all '
293 'x final 0 {} y final 0 {} z final 0 {} '
294 'xy final {} xz final {} yz final {}'
295 ''.format(xhi, yhi, zhi, xy, xz, yz))
296 else:
297 # just in case we'll want to run with a funny shape box,
298 # and here command will only happen once, and before
299 # any calculation
300 if self.parameters.create_box:
301 self.lmp.command('box tilt large')
302 cell_cmd = ('region cell prism '
303 '0 {} 0 {} 0 {} '
304 '{} {} {} units box'
305 ''.format(xhi, yhi, zhi, xy, xz, yz))
306
307 self.lmp.command(cell_cmd)
308
309 def set_lammps_pos(self, atoms):
310 pos = atoms.get_positions() / unit_convert("distance", self.units)
311
312 # If necessary, transform the positions to new coordinate system
313 if self.coord_transform is not None:
314 pos = np.dot(self.coord_transform, pos.transpose())
315 pos = pos.transpose()
316
317 # Convert ase position matrix to lammps-style position array
318 # contiguous in memory
319 lmp_positions = list(pos.ravel())
320
321 # Convert that lammps-style array into a C object
322 c_double_array = (ctypes.c_double * len(lmp_positions))
323 lmp_c_positions = c_double_array(*lmp_positions)
324 # self.lmp.put_coosrds(lmp_c_positions)
325 self.lmp.scatter_atoms('x', 1, 3, lmp_c_positions)
326
327 def calculate(self, atoms, properties, system_changes):
328 self.propagate(atoms, properties, system_changes, 0)
329
330 def propagate(self, atoms, properties, system_changes, n_steps, dt=None,
331 dt_not_real_time=False, velocity_field=None):
332
333 """"atoms: Atoms object
334 Contains positions, unit-cell, ...
335 properties: list of str
336 List of what needs to be calculated. Can be any combination
337 of 'energy', 'forces', 'stress', 'dipole', 'charges', 'magmom'
338 and 'magmoms'.
339 system_changes: list of str
340 List of what has changed since last calculation. Can be
341 any combination of these five: 'positions', 'numbers', 'cell',
342 'pbc', 'charges' and 'magmoms'.
343 """
344 if len(system_changes) == 0:
345 return
346
347 self.coord_transform = None
348
349 if not self.started:
350 self.start_lammps()
351 if not self.initialized:
352 self.initialise_lammps(atoms)
353 else: # still need to reset cell
354 # reset positions so that if they are crazy from last
355 # propagation, change_box (in set_cell()) won't hang
356 # could do this only after testing for crazy positions?
357 # could also use scatter_atoms() to set values (requires
358 # MPI comm), or extra_atoms() to get pointers to local
359 # data structures to zero, but then will have to be
360 # careful with parallelism
361 self.lmp.command("set atom * x 0.0 y 0.0 z 0.0")
362 self.set_cell(atoms, change=True)
363
364 if self.parameters.atom_types is None:
365 raise NameError("atom_types are mandatory.")
366
367 do_rebuild = (not np.array_equal(atoms.numbers, self.previous_atoms_numbers)
368 or ("numbers" in system_changes))
369 if not do_rebuild:
370 do_redo_atom_types = not np.array_equal(atoms.numbers, self.previous_atoms_numbers)
371 else:
372 do_redo_atom_types = False
373
374 self.lmp.command('echo none') # don't echo the atom positions
375 if do_rebuild:
376 self.rebuild(atoms)
377 elif do_redo_atom_types:
378 self.redo_atom_types(atoms)
379 self.lmp.command('echo log') # switch back log
380
381 self.set_lammps_pos(atoms)
382
383 if n_steps > 0:
384 if velocity_field is None:
385 vel = (atoms.get_velocities() /
386 unit_convert("velocity", self.units))
387 else:
388 vel = atoms.arrays[velocity_field]
389
390 # If necessary, transform the velocities to new coordinate system
391 if self.coord_transform is not None:
392 vel = np.dot(self.coord_transform, np.matrix.transpose(vel))
393 vel = np.matrix.transpose(vel)
394
395 # Convert ase velocities matrix to lammps-style velocities array
396 lmp_velocities = list(vel.ravel())
397
398 # Convert that lammps-style array into a C object
399 c_double_array = (ctypes.c_double * len(lmp_velocities))
400 lmp_c_velocities = c_double_array(*lmp_velocities)
401 self.lmp.scatter_atoms('v', 1, 3, lmp_c_velocities)
402
403 # Run for 0 time to calculate
404 if dt is not None:
405 if dt_not_real_time:
406 self.lmp.command('timestep %.30f' % dt)
407 else:
408 self.lmp.command('timestep %.30f' %
409 (dt/unit_convert("time", self.units)))
410 self.lmp.command('run %d' % n_steps)
411
412 if n_steps > 0:
413 # TODO this must be slower than native copy, but why is it broken?
414 pos = np.array(
415 [x for x in self.lmp.gather_atoms("x", 1, 3)]).reshape(-1, 3)
416 if self.coord_transform is not None:
417 pos = np.dot(pos, self.coord_transform)
418 atoms.set_positions(
419 pos * unit_convert("distance", self.units))
420
421 vel = np.array(
422 [v for v in self.lmp.gather_atoms("v", 1, 3)]).reshape(-1, 3)
423 if self.coord_transform is not None:
424 vel = np.dot(vel, self.coord_transform)
425 if velocity_field is None:
426 atoms.set_velocities(
427 vel * unit_convert("velocity", self.units))
428
429 # Extract the forces and energy
430 self.results['energy'] = (self.lmp.extract_variable('pe', None, 0) *
431 unit_convert("energy", self.units))
432
433 stress = np.empty(6)
434 stress_vars = ['pxx', 'pyy', 'pzz', 'pyz', 'pxz', 'pxy']
435
436 for i, var in enumerate(stress_vars):
437 stress[i] = self.lmp.extract_variable(var, None, 0)
438
439 stress_mat = np.zeros((3, 3))
440 stress_mat[0, 0] = stress[0]
441 stress_mat[1, 1] = stress[1]
442 stress_mat[2, 2] = stress[2]
443 stress_mat[1, 2] = stress[3]
444 stress_mat[2, 1] = stress[3]
445 stress_mat[0, 2] = stress[4]
446 stress_mat[2, 0] = stress[4]
447 stress_mat[0, 1] = stress[5]
448 stress_mat[1, 0] = stress[5]
449 if self.coord_transform is not None:
450 stress_mat = np.dot(self.coord_transform.T,
451 np.dot(stress_mat, self.coord_transform))
452 stress[0] = stress_mat[0, 0]
453 stress[1] = stress_mat[1, 1]
454 stress[2] = stress_mat[2, 2]
455 stress[3] = stress_mat[1, 2]
456 stress[4] = stress_mat[0, 2]
457 stress[5] = stress_mat[0, 1]
458
459 self.results['stress'] = (stress *
460 (-unit_convert("pressure", self.units)))
461
462 # this does not necessarily yield the forces ordered by atom-id!
463 # f = np.zeros((len(atoms), 3))
464 # force_vars = ['fx', 'fy', 'fz']
465 # for i, var in enumerate(force_vars):
466 # f[:, i] = (
467 # np.asarray(
468 # self.lmp.extract_variable(var, 'all', 1)[:len(atoms)]) *
469 # unit_convert("force", self.units))
470
471 # definitely yields atom-id ordered array
472 f = (np.array(self.lmp.gather_atoms("f", 1, 3)).reshape(-1,3) *
473 unit_convert("force", self.units))
474
475 if self.coord_transform is not None:
476 self.results['forces'] = np.dot(f, self.coord_transform)
477 else:
478 self.results['forces'] = f.copy()
479
480 # otherwise check_state will always trigger a new calculation
481 self.atoms = atoms.copy()
482
483 if not self.parameters.keep_alive:
484 self.lmp.close()
485
486 def lammpsbc(self, pbc):
487 if pbc:
488 return 'p'
489 else:
490 return 's'
491
492 def rebuild(self, atoms):
493 try:
494 n_diff = len(atoms.numbers) - len(self.previous_atoms_numbers)
495 except:
496 n_diff = len(atoms.numbers)
497
498 if n_diff > 0:
499 if any([("reax/c" in cmd) for cmd in self.parameters.lmpcmds]):
500 self.lmp.command("pair_style lj/cut 2.5")
501 self.lmp.command("pair_coeff * * 1 1")
502
503 for cmd in self.parameters.lmpcmds:
504 if ("pair_style" in cmd) or ("pair_coeff" in cmd):
505 self.lmp.command(cmd)
506
507 cmd = "create_atoms 1 random {} 1 NULL".format(n_diff)
508 self.lmp.command(cmd)
509 elif n_diff < 0:
510 cmd = "group delatoms id {}:{}".format(
511 len(atoms.numbers) + 1, len(self.previous_atoms_numbers))
512 self.lmp.command(cmd)
513 cmd = "delete_atoms group delatoms"
514 self.lmp.command(cmd)
515
516 self.redo_atom_types(atoms)
517
518 def redo_atom_types(self, atoms):
519 current_types = set(
520 (i + 1, self.parameters.atom_types[sym]) for i, sym
521 in enumerate(atoms.get_chemical_symbols()))
522
523 try:
524 previous_types = set(
525 (i + 1, self.parameters.atom_types[chemical_symbols[Z]])
526 for i, Z in enumerate(self.previous_atoms_numbers))
527 except:
528 previous_types = set()
529
530 for (i, i_type) in current_types - previous_types:
531 cmd = "set atom {} type {}".format(i, i_type)
532 self.lmp.command(cmd)
533
534 self.previous_atoms_numbers = atoms.numbers.copy()
535
536 def restart_lammps(self, atoms):
537 if self.started:
538 self.lmp.command("clear")
539 # hope there's no other state to be reset
540 self.started = False
541 self.initialized = False
542 self.previous_atoms_numbers = []
543 self.start_lammps()
544 self.initialise_lammps(atoms)
545
546 def start_lammps(self):
547 # Only import lammps when running a calculation
548 # so it is not required to use other parts of the
549 # module
550 from lammps import lammps
551 # start lammps process
552 if self.parameters.log_file is None:
553 cmd_args = ['-echo', 'log', '-log', 'none', '-screen', 'none',
554 '-nocite']
555 else:
556 cmd_args = ['-echo', 'log', '-log', self.parameters.log_file,
557 '-screen', 'none', '-nocite']
558
559 self.cmd_args = cmd_args
560
561 if self.lmp is None:
562 self.lmp = lammps(self.parameters.lammps_name, self.cmd_args,
563 comm=self.parameters.comm)
564
565 # Use metal units: Angstrom, ps, and eV
566 for cmd in self.parameters.lammps_header:
567 self.lmp.command(cmd)
568
569 for cmd in self.parameters.lammps_header:
570 if "units" in cmd:
571 self.units = cmd.split()[1]
572
573 if 'lammps_header_extra' in self.parameters:
574 if self.parameters.lammps_header_extra is not None:
575 for cmd in self.parameters.lammps_header_extra:
576 self.lmp.command(cmd)
577
578 self.started = True
579
580 def initialise_lammps(self, atoms):
581 # Initialising commands
582 if self.parameters.boundary:
583 # if the boundary command is in the supplied commands use that
584 # otherwise use atoms pbc
585 pbc = atoms.get_pbc()
586 for cmd in self.parameters.lmpcmds:
587 if 'boundary' in cmd:
588 break
589 else:
590 self.lmp.command('boundary ' +
591 ' '.join([self.lammpsbc(bc) for bc in pbc]))
592
593 # Initialize cell
594 self.set_cell(atoms, change=not self.parameters.create_box)
595
596 if self.parameters.atom_types is None:
597 # if None is given, create von atoms object in order of appearance
598 s = atoms.get_chemical_symbols()
599 _, idx = np.unique(s, return_index=True)
600 s_red = np.array(s)[np.sort(idx)].tolist()
601 self.parameters.atom_types = {j : i+1 for i, j in enumerate(s_red)}
602
603
604 # Collect chemical symbols
605 symbols = np.asarray(atoms.get_chemical_symbols())
606
607 # Initialize box
608 if self.parameters.create_box:
609 # count number of known types
610 n_types = len(self.parameters.atom_types)
611 create_box_command = 'create_box {} cell'.format(n_types)
612 self.lmp.command(create_box_command)
613
614 # Initialize the atoms with their types
615 # positions do not matter here
616 if self.parameters.create_atoms:
617 self.lmp.command('echo none') # don't echo the atom positions
618 self.rebuild(atoms)
619 self.lmp.command('echo log') # turn back on
620
621 # execute the user commands
622 for cmd in self.parameters.lmpcmds:
623 self.lmp.command(cmd)
624
625 # Set masses after user commands,
626 # to override EAM provided masses, e.g.
627 masses = atoms.get_masses()
628 for sym in self.parameters.atom_types:
629 for i in range(len(atoms)):
630 if symbols[i] == sym:
631 # convert from amu (ASE) to lammps mass unit)
632 self.lmp.command('mass %d %.30f' % (
633 self.parameters.atom_types[sym],
634 masses[i] / unit_convert("mass", self.units)))
635 break
636
637 # Define force & energy variables for extraction
638 self.lmp.command('variable pxx equal pxx')
639 self.lmp.command('variable pyy equal pyy')
640 self.lmp.command('variable pzz equal pzz')
641 self.lmp.command('variable pxy equal pxy')
642 self.lmp.command('variable pxz equal pxz')
643 self.lmp.command('variable pyz equal pyz')
644
645 # I am not sure why we need this next line but LAMMPS will
646 # raise an error if it is not there. Perhaps it is needed to
647 # ensure the cell stresses are calculated
648 self.lmp.command('thermo_style custom pe pxx')
649
650 self.lmp.command('variable fx atom fx')
651 self.lmp.command('variable fy atom fy')
652 self.lmp.command('variable fz atom fz')
653
654 # do we need this if we extract from a global ?
655 self.lmp.command('variable pe equal pe')
656
657 self.lmp.command("neigh_modify delay 0 every 1 check yes")
658
659 self.initialized = True
660
661
662
663 # keep this one for the moment being...
664 def write_lammps_data(filename, atoms, atom_types, comment=None, cutoff=None,
665 molecule_ids=None, charges=None, units='metal'):
666
667 if isinstance(filename, basestring):
668 fh = open(filename, 'w')
669 else:
670 fh = filename
671
672 if comment is None:
673 comment = 'lammpslib autogenerated data file'
674 fh.write(comment.strip() + '\n\n')
675
676 fh.write('{0} atoms\n'.format(len(atoms)))
677 fh.write('{0} atom types\n'.format(len(atom_types)))
678
679
680 fh.write('\n')
681 cell, coord_transform = convert_cell(atoms.get_cell())
682 fh.write('{0:16.8e} {1:16.8e} xlo xhi\n'.format(0.0, cell[0, 0]))
683 fh.write('{0:16.8e} {1:16.8e} ylo yhi\n'.format(0.0, cell[1, 1]))
684 fh.write('{0:16.8e} {1:16.8e} zlo zhi\n'.format(0.0, cell[2, 2]))
685 fh.write('{0:16.8e} {1:16.8e} {2:16.8e} xy xz yz\n'
686 ''.format(cell[0, 1], cell[0, 2], cell[1, 2]))
687
688 fh.write('\nMasses\n\n')
689 sym_mass = {}
690 masses = atoms.get_masses()
691 symbols = atoms.get_chemical_symbols()
692 for sym in atom_types:
693 for i in range(len(atoms)):
694 if symbols[i] == sym:
695 sym_mass[sym] = masses[i] / unit_convert("mass", units)
696 break
697 else:
698 sym_mass[sym] = (atomic_masses[chemical_symbols.index(sym)] /
699 unit_convert("mass", units))
700
701 for (sym, typ) in sorted(atom_types.items(), key=operator.itemgetter(1)):
702 fh.write('{0} {1}\n'.format(typ, sym_mass[sym]))
703
704 fh.write('\nAtoms # full\n\n')
705 if molecule_ids is None:
706 molecule_ids = np.zeros(len(atoms), dtype=int)
707 if charges is None:
708 charges = atoms.get_initial_charges()
709 for i, (sym, mol, q, pos) in enumerate(
710 zip(symbols, molecule_ids, charges, atoms.get_positions())):
711 typ = atom_types[sym]
712 fh.write('{0} {1} {2} {3:16.8e} {4:16.8e} {5:16.8e} {6:16.8e}\n'
713 .format(i + 1, mol, typ, q, pos[0], pos[1], pos[2]))
714
715 if isinstance(filename, basestring):
716 fh.close()
3333 import decimal as dec
3434 from ase import Atoms
3535 from ase.parallel import paropen
36 from ase.units import GPa
36 from ase.units import GPa, Ang, fs
3737 from ase.utils import basestring
3838
3939
8686 self.keep_alive = keep_alive
8787 self.keep_tmp_files = keep_tmp_files
8888 self.no_data_file = no_data_file
89
90 # if True writes velocities from atoms.get_velocities() to LAMMPS input
91 self.write_velocities = False
92
93 # file object, if is not None the trajectory will be saved in it
94 self.trajectory_out = None
95
96 # period of system snapshot saving (in MD steps)
97 self.dump_period = 1
8998 if tmp_dir is not None:
9099 # If tmp_dir is pointing somewhere, don't remove stuff!
91100 self.keep_tmp_files = True
182191 self._lmp_handle.stdin.close()
183192 return self._lmp_handle.wait()
184193
185 def run(self):
194 def run(self, set_atoms=False):
186195 """Method which explicitly runs LAMMPS."""
187196
188197 self.calls += 1
283292 # it could
284293 raise RuntimeError('Atoms have gone missing')
285294
286 self.read_lammps_trj(lammps_trj=lammps_trj)
295 self.read_lammps_trj(lammps_trj=lammps_trj, set_atoms=set_atoms)
287296 lammps_trj_fd.close()
288297 if not self.no_data_file:
289298 lammps_data_fd.close()
296305 lammps_data = 'data.' + self.label
297306 write_lammps_data(
298307 lammps_data, self.atoms, self.specorder,
299 force_skew=self.always_triclinic, prismobj=self.prism)
308 force_skew=self.always_triclinic, prismobj=self.prism,
309 velocities=self.write_velocities)
300310
301311 def write_lammps_in(self, lammps_in=None, lammps_trj=None,
302312 lammps_data=None):
349359 for x in self.atoms.get_cell()]
350360 ).encode('utf-8'))
351361
352 p = self.prism
353362 f.write('lattice sc 1.0\n'.encode('utf-8'))
354 xhi, yhi, zhi, xy, xz, yz = p.get_lammps_prism_str()
355 if self.always_triclinic or p.is_skewed():
363 xhi, yhi, zhi, xy, xz, yz = self.prism.get_lammps_prism_str()
364 if self.always_triclinic or self.prism.is_skewed():
356365 f.write('region asecell prism 0.0 {0} 0.0 {1} 0.0 {2} '
357366 ''.format(xhi, yhi, zhi).encode('utf-8'))
358367 f.write('{0} {1} {2} side in units box\n'
382391 f.write('create_atoms {0} single {1} {2} {3} units box\n'
383392 ''.format(
384393 *((species_i[s],) +
385 p.pos_to_lammps_fold_str(pos))).encode('utf-8'))
394 self.prism.pos_to_lammps_fold_str(pos))
395 ).encode('utf-8'))
386396
387397 # if NOT self.no_lammps_data, then simply refer to the data-file
388398 else:
406416 'pair_coeff * * 1 1 \n'
407417 'mass * 1.0 \n'.encode('utf-8'))
408418
419 if 'group' in parameters:
420 f.write(('\n'.join(['group {0}'.format(p)
421 for p in parameters['group']]) +
422 '\n').encode('utf-8'))
423
409424 f.write(
410425 '\n### run\n'
411 'fix fix_nve all nve\n'
412 'dump dump_all all custom 1 {0} id type x y z vx vy vz fx fy fz\n'
413 ''.format(lammps_trj).encode('utf-8'))
426 'fix fix_nve all nve\n'.encode('utf-8'))
427
428 if 'fix' in parameters:
429 f.write(('\n'.join(['fix {0}'.format(p)
430 for p in parameters['fix']]) +
431 '\n').encode('utf-8'))
432
433 f.write(
434 'dump dump_all all custom {1} {0} id type x y z vx vy vz '
435 'fx fy fz\n'
436 ''.format(lammps_trj, self.dump_period).encode('utf-8'))
414437 f.write('thermo_style custom {0}\n'
415438 'thermo_modify flush yes\n'
416439 'thermo 1\n'.format(
417440 ' '.join(self._custom_thermo_args)).encode('utf-8'))
441
442 if 'timestep' in parameters:
443 f.write('timestep {0}\n'.format(
444 parameters['timestep']).encode('utf-8'))
418445
419446 if 'minimize' in parameters:
420447 f.write('minimize {0}\n'.format(
484511 # TODO: extend to proper dealing with multiple steps in one
485512 # trajectory file
486513 if 'ITEM: TIMESTEP' in line:
514
487515 n_atoms = 0
488516 lo = []
489517 hi = []
536564 velocities = [velocities[x - 1] for x in id]
537565 forces = [forces[x - 1] for x in id]
538566
567 # determine cell tilt (triclinic case!)
568 if len(tilt) >= 3:
569 # for >=lammps-7Jul09 use labels behind "ITEM: BOX BOUNDS"
570 # to assign tilt (vector) elements ...
571 if len(tilt_items) >= 3:
572 xy = tilt[tilt_items.index('xy')]
573 xz = tilt[tilt_items.index('xz')]
574 yz = tilt[tilt_items.index('yz')]
575 # ... otherwise assume default order in 3rd column
576 # (if the latter was present)
577 else:
578 xy = tilt[0]
579 xz = tilt[1]
580 yz = tilt[2]
581 else:
582 xy = xz = yz = 0
583 xhilo = (hi[0] - lo[0]) - xy - xz
584 yhilo = (hi[1] - lo[1]) - yz
585 zhilo = (hi[2] - lo[2])
586
587 # The simulation box bounds are included in each snapshot and
588 # if the box is triclinic (non-orthogonal), then the tilt
589 # factors are also printed; see the region prism command for
590 # a description of tilt factors.
591 # For triclinic boxes the box bounds themselves (first 2
592 # quantities on each line) are a true "bounding box" around
593 # the simulation domain, which means they include the effect of
594 # any tilt.
595 # [ http://lammps.sandia.gov/doc/dump.html , lammps-7Jul09 ]
596 #
597 # This *should* extract the lattice vectors that LAMMPS uses
598 # from the true "bounding box" printed in the dump file.
599 # It might fail in some cases (negative tilts?!) due to the
600 # MIN / MAX construction of these box corners:
601 #
602 # void Domain::set_global_box()
603 # [...]
604 # if (triclinic) {
605 # [...]
606 # boxlo_bound[0] = MIN(boxlo[0],boxlo[0]+xy);
607 # boxlo_bound[0] = MIN(boxlo_bound[0],boxlo_bound[0]+xz);
608 # boxlo_bound[1] = MIN(boxlo[1],boxlo[1]+yz);
609 # boxlo_bound[2] = boxlo[2];
610 # # boxhi_bound[0] = MAX(boxhi[0],boxhi[0]+xy);
611 # boxhi_bound[0] = MAX(boxhi_bound[0],boxhi_bound[0]+xz);
612 # boxhi_bound[1] = MAX(boxhi[1],boxhi[1]+yz);
613 # boxhi_bound[2] = boxhi[2];
614 # }
615 # [ lammps-7Jul09/src/domain.cpp ]
616 #
617 cell = [[xhilo, 0, 0], [xy, yhilo, 0], [xz, yz, zhilo]]
618
619 # These have been put into the correct order
620 cell_atoms = np.array(cell)
621 type_atoms = np.array(type)
622
623 if self.atoms:
624 cell_atoms = self.atoms.get_cell()
625
626 # BEWARE: reconstructing the rotation from the LAMMPS
627 # output trajectory file fails in case of shrink
628 # wrapping for a non-periodic direction
629 # -> hence rather obtain rotation from prism object
630 # used to generate the LAMMPS input
631 # rotation_lammps2ase = np.dot(
632 # np.linalg.inv(np.array(cell)), cell_atoms)
633 rotation_lammps2ase = np.linalg.inv(self.prism.R)
634
635 type_atoms = self.atoms.get_atomic_numbers()
636 positions_atoms = np.dot(positions, rotation_lammps2ase)
637 velocities_atoms = np.dot(velocities, rotation_lammps2ase)
638 forces_atoms = np.dot(forces, rotation_lammps2ase)
639
640 if set_atoms:
641 # assume periodic boundary conditions here (as in
642 # write_lammps)
643 self.atoms = Atoms(type_atoms, positions=positions_atoms,
644 cell=cell_atoms)
645 self.atoms.set_velocities(velocities_atoms
646 * (Ang/(fs*1000.)))
647
648 self.forces = forces_atoms
649 if self.trajectory_out is not None:
650 tmp_atoms = Atoms(type_atoms, positions=positions_atoms,
651 cell=cell_atoms)
652 tmp_atoms.set_velocities(velocities_atoms)
653 self.trajectory_out.write(tmp_atoms)
539654 f.close()
540
541 # determine cell tilt (triclinic case!)
542 if len(tilt) >= 3:
543 # for >=lammps-7Jul09 use labels behind "ITEM: BOX BOUNDS" to
544 # assign tilt (vector) elements ...
545 if len(tilt_items) >= 3:
546 xy = tilt[tilt_items.index('xy')]
547 xz = tilt[tilt_items.index('xz')]
548 yz = tilt[tilt_items.index('yz')]
549 # ... otherwise assume default order in 3rd column
550 # (if the latter was present)
551 else:
552 xy = tilt[0]
553 xz = tilt[1]
554 yz = tilt[2]
555 else:
556 xy = xz = yz = 0
557 xhilo = (hi[0] - lo[0]) - xy - xz
558 yhilo = (hi[1] - lo[1]) - yz
559 zhilo = (hi[2] - lo[2])
560
561 # The simulation box bounds are included in each snapshot and if the
562 # box is triclinic (non-orthogonal), then the tilt factors are also
563 # printed; see the region prism command for a description of tilt
564 # factors.
565 # For triclinic boxes the box bounds themselves (first 2 quantities
566 # on each line) are a true "bounding box" around the simulation
567 # domain, which means they include the effect of any tilt.
568 # [ http://lammps.sandia.gov/doc/dump.html , lammps-7Jul09 ]
569 #
570 # This *should* extract the lattice vectors that LAMMPS uses from
571 # the true "bounding box" printed in the dump file.
572 # It might fail in some cases (negative tilts?!) due to the
573 # MIN / MAX construction of these box corners:
574 #
575 # void Domain::set_global_box()
576 # [...]
577 # if (triclinic) {
578 # [...]
579 # boxlo_bound[0] = MIN(boxlo[0],boxlo[0]+xy);
580 # boxlo_bound[0] = MIN(boxlo_bound[0],boxlo_bound[0]+xz);
581 # boxlo_bound[1] = MIN(boxlo[1],boxlo[1]+yz);
582 # boxlo_bound[2] = boxlo[2];
583 #
584 # boxhi_bound[0] = MAX(boxhi[0],boxhi[0]+xy);
585 # boxhi_bound[0] = MAX(boxhi_bound[0],boxhi_bound[0]+xz);
586 # boxhi_bound[1] = MAX(boxhi[1],boxhi[1]+yz);
587 # boxhi_bound[2] = boxhi[2];
588 # }
589 # [ lammps-7Jul09/src/domain.cpp ]
590 #
591 cell = [[xhilo, 0, 0], [xy, yhilo, 0], [xz, yz, zhilo]]
592
593 # These have been put into the correct order
594 cell_atoms = np.array(cell)
595 type_atoms = np.array(type)
596
597 if self.atoms:
598 cell_atoms = self.atoms.get_cell()
599
600 # BEWARE: reconstructing the rotation from the LAMMPS output
601 # trajectory file fails in case of shrink wrapping for
602 # a non-periodic direction
603 # -> hence rather obtain rotation from prism object used
604 # to generate the LAMMPS input
605 # rotation_lammps2ase = np.dot(np.linalg.inv(np.array(cell)),
606 # cell_atoms)
607 rotation_lammps2ase = np.linalg.inv(self.prism.R)
608
609 type_atoms = self.atoms.get_atomic_numbers()
610 positions_atoms = np.dot(positions, rotation_lammps2ase)
611 # velocities_atoms = np.dot(velocities, rotation_lammps2ase)
612 forces_atoms = np.dot(forces, rotation_lammps2ase)
613
614 if set_atoms:
615 # assume periodic boundary conditions here (as in write_lammps)
616 self.atoms = Atoms(type_atoms, positions=positions_atoms,
617 cell=cell_atoms)
618
619 self.forces = forces_atoms
620655
621656
622657 class SpecialTee(object):
837872
838873 if velocities and atoms.get_velocities() is not None:
839874 f.write('\n\nVelocities \n\n'.encode('utf-8'))
840 for i, v in enumerate(atoms.get_velocities()):
875 for i, v in enumerate(atoms.get_velocities() / (Ang/(fs*1000.))):
841876 f.write('{0:>6} {1} {2} {3}\n'.format(
842877 *(i + 1,) + tuple(v)).encode('utf-8'))
843878
3232 label='mopac', atoms=None, **kwargs):
3333 """Construct MOPAC-calculator object.
3434
35 Parameters
36 ==========
35 Parameters:
36
3737 label: str
3838 Prefix for filenames (label.mop, label.out, ...)
3939
40 Examples
41 ========
40 Examples:
41
4242 Use default values to do a single SCF calculation and print
4343 the forces (task='1SCF GRADIENTS')
4444
0 from __future__ import print_function
10 """
21 This module defines the ASE interface to SIESTA.
32
87 http://www.uam.es/departamentos/ciencias/fismateriac/siesta
98
109 2017.04 - Pedro Brandimarte: changes for python 2-3 compatible
10
1111 """
12
13 from __future__ import print_function
1214 import os
1315 from os.path import join, isfile, islink
1416 import numpy as np
7678 """ASE interface to the SIESTA code.
7779
7880 Parameters:
79 -label : The base head of all created files.
80 -mesh_cutoff : Energy in eV.
81 - label : The base head of all created files.
82 - mesh_cutoff : Energy in eV.
8183 The mesh cutoff energy for determining number of
8284 grid points.
83 -energy_shift : Energy in eVV
85 - energy_shift : Energy in eVV
8486 The confining energy of the basis sets.
85 -kpts : Tuple of 3 integers, the k-points in different
87 - kpts : Tuple of 3 integers, the k-points in different
8688 directions.
87 -xc : The exchange-correlation potential. Can be set to
89 - xc : The exchange-correlation potential. Can be set to
8890 any allowed value for either the Siesta
8991 XC.funtional or XC.authors keyword. Default "LDA"
90 -basis_set : "SZ"|"SZP"|"DZ"|"DZP", strings which specify the
92 - basis_set : "SZ"|"SZP"|"DZ"|"DZP", strings which specify the
9193 type of functions basis set.
92 -spin : "UNPOLARIZED"|"COLLINEAR"|"FULL". The level of spin
94 - spin : "UNPOLARIZED"|"COLLINEAR"|"FULL". The level of spin
9395 description to be used.
94 -species : None|list of Species objects. The species objects
96 - species : None|list of Species objects. The species objects
9597 can be used to to specify the basis set,
9698 pseudopotential and whether the species is ghost.
9799 The tag on the atoms object and the element is used
98100 together to identify the species.
99 -pseudo_path : None|path. This path is where
101 - pseudo_path : None|path. This path is where
100102 pseudopotentials are taken from.
101103 If None is given, then then the path given
102104 in $SIESTA_PP_PATH will be used.
103 -pseudo_qualifier: None|string. This string will be added to the
105 - pseudo_qualifier: None|string. This string will be added to the
104106 pseudopotential path that will be retrieved.
105107 For hydrogen with qualifier "abc" the
106108 pseudopotential "H.abc.psf" will be retrieved.
107 -atoms : The Atoms object.
108 -restart : str. Prefix for restart file.
109 - atoms : The Atoms object.
110 - restart : str. Prefix for restart file.
109111 May contain a directory.
110112 Default is None, don't restart.
111 -siesta_default: Use siesta default parameter if the parameter
113 - siesta_default: Use siesta default parameter if the parameter
112114 is not explicitly set.
113 -ignore_bad_restart_file: bool.
115 - ignore_bad_restart_file: bool.
114116 Ignore broken or missing restart file.
115117 By default, it is an error if the restart
116118 file is missing or broken.
117 -fdf_arguments: Explicitly given fdf arguments. Dictonary using
119 - fdf_arguments: Explicitly given fdf arguments. Dictonary using
118120 Siesta keywords as given in the manual. List values
119121 are written as fdf blocks with each element on a
120122 separate line, while tuples will write each element
916918 # debye to e*Ang
917919 self.results['dipole'] = dipole * 0.2081943482534
918920
919 def get_polarizability(self, mbpt_inp=None, output_name='mbpt_lcao.out',
920 format_output='hdf5', units='au'):
921 """
921 def pyscf_tddft(self, Edir=np.array([1.0, 0.0, 0.0]),
922 freq=np.arange(0.0, 10.0, 0.1),
923 units='au',
924 run_tddft=True,
925 save_kernel = True,
926 kernel_name = "tddft_kernel.npy",
927 fname="pol_tensor.npy",
928 fname_nonin = "noninpol_tensor.npy", **kw):
929 """
930 Perform TDDFT calculation using the pyscf.nao module for a molecule.
931
932 Parameters
933 ----------
934 freq: array like
935 frequency range for which the polarizability should
936 be computed, in eV
937 units : str, optional
938 unit for the returned polarizability, can be au (atomic units)
939 or nm**2
940 run_tddft: to run the tddft_calculation or not
941 fname: str
942 Name of input file name for polariazbility tensor.
943 if run_tddft is True: output file
944 if run_tddft is False: input file
945
946 kw: keywords for the tddft_iter function from pyscf
947
948 Returns
949 -------
950 Add to the self.results dict the following items:
951 freq range: array like
952 array of dimension (nff) containing the frequency range in eV.
953
954 polarizability nonin: array like (complex)
955 array of dimension (nff, 3, 3) with nff the frequency number,
956 the second and third dimension are the matrix elements of the
957 non-interactive polarizability::
958
959 P_xx, P_xy, P_xz, Pyx, .......
960
961
962 polarizability: array like (complex)
963 array of dimension (nff, 3, 3) with nff the frequency number,
964 the second and third dimension are the matrix elements of the
965 interactive polarizability::
966
967 P_xx, P_xy, P_xz, Pyx, .......
968
969 density change nonin: array like (complex)
970 contains the non interacting density change in product basis
971
972 density change inter: array like (complex)
973 contains the interacting density change in product basis
974
975 References
976 ----------
977 https://github.com/cfm-mpc/pyscf/tree/nao
978
979 Example
980 -------
981 from ase.units import Ry, eV, Ha
982 from ase.calculators.siesta import Siesta
983 from ase import Atoms
984 import numpy as np
985 import matplotlib.pyplot as plt
986
987 # Define the systems
988 Na8 = Atoms('Na8',
989 positions=[[-1.90503810, 1.56107288, 0.00000000],
990 [1.90503810, 1.56107288, 0.00000000],
991 [1.90503810, -1.56107288, 0.00000000],
992 [-1.90503810, -1.56107288, 0.00000000],
993 [0.00000000, 0.00000000, 2.08495836],
994 [0.00000000, 0.00000000, -2.08495836],
995 [0.00000000, 3.22798122, 2.08495836],
996 [0.00000000, 3.22798122, -2.08495836]],
997 cell=[20, 20, 20])
998
999 # Siesta input
1000 siesta = Siesta(
1001 mesh_cutoff=150 * Ry,
1002 basis_set='DZP',
1003 pseudo_qualifier='',
1004 energy_shift=(10 * 10**-3) * eV,
1005 fdf_arguments={
1006 'SCFMustConverge': False,
1007 'COOP.Write': True,
1008 'WriteDenchar': True,
1009 'PAO.BasisType': 'split',
1010 'DM.Tolerance': 1e-4,
1011 'DM.MixingWeight': 0.01,
1012 'MaxSCFIterations': 300,
1013 'DM.NumberPulay': 4,
1014 'XML.Write': True})
1015
1016 Na8.set_calculator(siesta)
1017 e = Na8.get_potential_energy()
1018 freq, pol = siesta.get_polarizability_pyscf_inter(label="siesta",
1019 jcutoff=7,
1020 iter_broadening=0.15/Ha,
1021 xc_code='LDA,PZ',
1022 tol_loc=1e-6,
1023 tol_biloc=1e-7,
1024 freq = np.arange(0.0, 5.0, 0.05))
1025 # plot polarizability
1026 plt.plot(freq, pol[:, 0, 0].imag)
1027 plt.show()
1028 """
1029
1030 from ase.calculators.siesta.mbpt_lcao_utils import pol2cross_sec
1031 assert units in ["nm**2", "au"]
1032
1033 if run_tddft:
1034 from pyscf.nao import tddft_iter
1035 from ase.units import Ha
1036
1037 tddft = tddft_iter(**kw)
1038 if save_kernel:
1039 np.save(kernel_name, tddft.kernel)
1040
1041 omegas = freq / Ha + 1j * tddft.eps
1042 tddft.comp_dens_nonin_along_Eext(omegas, Eext=Edir)
1043 tddft.comp_dens_inter_along_Eext(omegas, Eext=Edir)
1044
1045 # save polarizability tensor and density change to files
1046 self.results["freq range"] = freq
1047 self.results['polarizability nonin'] = np.zeros((freq.size, 3, 3),
1048 dtype=tddft.p0_mat.dtype)
1049 self.results['polarizability inter'] = np.zeros((freq.size, 3, 3),
1050 dtype=tddft.p_mat.dtype)
1051 self.results["density change nonin"] = tddft.dn0
1052 self.results["density change inter"] = tddft.dn
1053 for xyz1 in range(3):
1054 for xyz2 in range(3):
1055 if units == 'nm**2':
1056 p0 = pol2cross_sec(-tddft.p0_mat[xyz1, xyz2, :],
1057 freq)
1058 p = pol2cross_sec(-tddft.p_mat[xyz1, xyz2, :],
1059 freq)
1060 self.results['polarizability nonin'][:, xyz1, xyz2] = p0
1061 self.results['polarizability inter'][:, xyz1, xyz2] = p
1062 else:
1063 self.results['polarizability nonin'][:, xyz1, xyz2] = \
1064 -tddft.p0_mat[xyz1, xyz2, :]
1065 self.results['polarizability inter'][:, xyz1, xyz2] = \
1066 -tddft.p_mat[xyz1, xyz2, :]
1067
1068 else:
1069 # load polarizability tensor from previous calculations
1070 p0_mat = np.load(fname_nonin)
1071 p_mat = np.load(fname)
1072
1073 self.results['polarizability nonin'] = np.zeros((freq.size, 3, 3),
1074 dtype=p0_mat.dtype)
1075 self.results['polarizability inter'] = np.zeros((freq.size, 3, 3),
1076 dtype=p_mat.dtype)
1077
1078 for xyz1 in range(3):
1079 for xyz2 in range(3):
1080 if units == 'nm**2':
1081 p0 = pol2cross_sec(-p0_mat[xyz1, xyz2, :], freq)
1082 p = pol2cross_sec(-p_mat[xyz1, xyz2, :], freq)
1083
1084 self.results['polarizability nonin'][:, xyz1, xyz2] = p0
1085 self.results['polarizability inter'][:, xyz1, xyz2] = p
1086 else:
1087 self.results['polarizability nonin'][:, xyz1, xyz2] = \
1088 -p0_mat[xyz1, xyz2, :]
1089 self.results['polarizability inter'][:, xyz1, xyz2] = \
1090 -p_mat[xyz1, xyz2, :]
1091
1092 def pyscf_tddft_eels(self, velec = np.array([20.0, 0.0, 0.0]),
1093 b = np.array([0.0, 0.0, 0.0]),
1094 freq=np.arange(0.0, 10.0, 0.1),
1095 tddft = None,
1096 save_kernel = True,
1097 kernel_name = "tddft_kernel.npy",
1098 tmp_fname = None,
1099 **kw):
1100 """
1101 Perform TDDFT calculation using the pyscf.nao module for a molecule.
1102 The external pertubation is created by a electron moving at the velocity velec
1103 and with an impact parameter b
1104
1105 Parameters
1106 ----------
1107 freq: array like
1108 frequency range for which the polarizability should
1109 be computed, in eV
1110 velec: array like
1111 velocity vector of the projectile
1112 b: array like
1113 offset vector of the projectile
1114 tddft: tddft_tem class from a previous calculation
1115 save_kernel: save the kernel for future use
1116 kernel_name: name of the file for the kernel
1117 tmp_fname: temporary name to save the eels spectra while running the calculations
1118 kw: keywords for the tddft_tem function from pyscf
1119
1120 Returns
1121 -------
1122 tddft:
1123 if running pyscf_tddft_eels in a loop over the velocity or the
1124 impact parameter, there is no point to initialize again the tddft
1125 calculation (vertex and kernel will be the same)
1126
1127 Add to the self.results dict the following items:
1128 freq range: array like
1129 array of dimension (nff) containing the frequency range in eV.
1130
1131 eel spectra nonin: array like (complex)
1132 array of dimension (nff) with nff the frequency number,
1133
1134
1135 eel spectra inter: array like (complex)
1136 array of dimension (nff) with nff the frequency number,
1137
1138 density change eels nonin: array like (complex)
1139 contains the non interacting density change in product basis
1140
1141 density change eels inter: array like (complex)
1142 contains the interacting density change in product basis
1143
1144 References
1145 ----------
1146 https://github.com/cfm-mpc/pyscf/tree/nao
1147
1148 Example
1149 -------
1150 from ase.units import Ry, eV, Ha
1151 from ase.calculators.siesta import Siesta
1152 from ase import Atoms
1153 import numpy as np
1154 import matplotlib.pyplot as plt
1155
1156 # Define the systems
1157 Na8 = Atoms('Na8',
1158 positions=[[-1.90503810, 1.56107288, 0.00000000],
1159 [1.90503810, 1.56107288, 0.00000000],
1160 [1.90503810, -1.56107288, 0.00000000],
1161 [-1.90503810, -1.56107288, 0.00000000],
1162 [0.00000000, 0.00000000, 2.08495836],
1163 [0.00000000, 0.00000000, -2.08495836],
1164 [0.00000000, 3.22798122, 2.08495836],
1165 [0.00000000, 3.22798122, -2.08495836]],
1166 cell=[20, 20, 20])
1167
1168 # enter siesta input
1169 siesta = Siesta(
1170 mesh_cutoff=150 * Ry,
1171 basis_set='DZP',
1172 pseudo_qualifier='',
1173 energy_shift=(10 * 10**-3) * eV,
1174 fdf_arguments={
1175 'SCFMustConverge': False,
1176 'COOP.Write': True,
1177 'WriteDenchar': True,
1178 'PAO.BasisType': 'split',
1179 'DM.Tolerance': 1e-4,
1180 'DM.MixingWeight': 0.01,
1181 'MaxSCFIterations': 300,
1182 'DM.NumberPulay': 4,
1183 'XML.Write': True})
1184
1185
1186 Na8.set_calculator(siesta)
1187 e = Na8.get_potential_energy()
1188 tddft = siesta.pyscf_tddft_eels(label="siesta", jcutoff=7, iter_broadening=0.15/Ha,
1189 xc_code='LDA,PZ', tol_loc=1e-6, tol_biloc=1e-7, freq = np.arange(0.0, 5.0, 0.05))
1190
1191 # plot eel spectra
1192 fig = plt.figure(1)
1193 ax1 = fig.add_subplot(121)
1194 ax2 = fig.add_subplot(122)
1195 ax1.plot(siesta.results["freq range"], siesta.results["eel spectra nonin"].imag)
1196 ax2.plot(siesta.results["freq range"], siesta.results["eel spectra inter"].imag)
1197
1198 ax1.set_xlabel(r"$\omega$ (eV)")
1199 ax2.set_xlabel(r"$\omega$ (eV)")
1200
1201 ax1.set_ylabel(r"Im($P_{xx}$) (au)")
1202 ax2.set_ylabel(r"Im($P_{xx}$) (au)")
1203
1204 ax1.set_title(r"Non interacting")
1205 ax2.set_title(r"Interacting")
1206
1207 fig.tight_layout()
1208
1209 plt.show()
1210
1211 """
1212
1213
1214 from pyscf.nao import tddft_tem
1215 from ase.units import Ha
1216
1217 assert velec.size == 3
1218 assert b.size == 3
1219
1220 if tddft is None:
1221 self.results["freq range"] = freq
1222 omegas = freq / Ha
1223
1224 # for eels, omega is real array
1225 tddft = tddft_tem(freq = omegas, **kw)
1226 if save_kernel:
1227 np.save(kernel_name, tddft.kernel)
1228
1229
1230 self.results['eel spectra nonin'] = tddft.get_spectrum_nonin(velec=velec,
1231 beam_offset = b,
1232 tmp_fname=tmp_fname)
1233
1234 self.results['eel spectra inter'] = tddft.get_spectrum_inter(velec=velec,
1235 beam_offset = b,
1236 tmp_fname=tmp_fname)
1237
1238 self.results["density change eels nonin"] = tddft.dn0
1239 self.results["density change eels inter"] = tddft.dn
1240
1241 return tddft
1242
1243
1244 def get_polarizability_mbpt(self, mbpt_inp=None,
1245 output_name='mbpt_lcao.out',
1246 format_output='hdf5', units='au'):
1247 """
1248 Warning!!
1249 Out dated version, try get_polarizability_pyscf
1250
1251
9221252 Calculate the polarizability by running the mbpt_lcao program.
9231253 The mbpt_lcao program need the siesta output, therefore siesta need
9241254 to be run first.
10421372 """
10431373 from ase.calculators.siesta.mbpt_lcao import MBPT_LCAO
10441374 from ase.calculators.siesta.mbpt_lcao_io import read_mbpt_lcao_output
1375 import warnings
1376
1377 warnings.warn("Out dated version, try get_polarizability_pyscf")
10451378
10461379 if mbpt_inp is not None:
10471380 tddft = MBPT_LCAO(mbpt_inp)
906906 self.figname = 'default'
907907 self.cmap = cm.jet
908908 self.units = 'au'
909 self.interpolation = "bicubic"
909910 # for the moment only the polarizability can be modify in nm**2
910911 self.vmin = None
911912 self.vmax = None
295295 ('WriteCoorStep', False),
296296 ('WriteForces', False),
297297 ('WriteMDhistory', False),
298 ('XML.Write', False),
298299 ('GeometryConstraints', None),
299300 ('MD.FCDispl', 0.04), # Bohr
300301 ('MD.FCfirst', 1),
584585 ('WriteCoorStep', False),
585586 ('WriteForces', False),
586587 ('WriteMDhistory', False),
588 ('XML.Write', False),
587589 ('GeometryConstraints', None),
588590 ('MD.FCDispl', 0.04), # Bohr
589591 ('MD.FCfirst', 1),
99 from ase.parallel import parprint, paropen
1010 from ase.vibrations import Vibrations
1111 from ase.utils import basestring
12 import warnings
1213
1314 # XXX This class contains much repeated code. FIXME
1415
2829 density-functional theory",
2930 Phys. Rev. B 54, 7830 (1996)
3031
31 The calculator object (calc) must be Siesta, and the mbpt_lcao
32 (http://mbpt-domiprod.wikidot.com/) program must be installed.
32 The calculator object (calc) must be Siesta, and the
33 pyscf program (nao branch: https://github.com/cfm-mpc/pyscf/tree/nao)
34 must be installed.
3335
3436 >>> calc.get_dipole_moment(atoms)
3537
3638 In addition to the methods included in the ``Vibrations`` class
37 the ``Infrared`` class introduces two new methods;
39 the ``Raman`` as the ``Infrared`` class introduces two methods;
3840 *get_spectrum()* and *write_spectra()*. The *summary()*, *get_energies()*,
3941 *get_frequencies()*, *get_spectrum()* and *write_spectra()*
4042 methods all take an optional *method* keyword. Use
6971 moment in the xy-plane will be considered. Default behavior is to
7072 use the dipole moment in all directions.
7173
74 freq_pol: float or array of float
75 frequency at which the Raman intensity is computed, can be float or array
76
7277 Example:
7378
7479 See the example test/siesta/mbpt_lcao/script_raman.py
105110 9 2206.78 66.1575 12.6139 0.0000 0.6417
106111 """
107112
108 def __init__(self, atoms, siesta, mbpt_inp, indices=None, name='ram',
109 delta=0.01, nfree=2, directions=None):
110 assert nfree in [2, 4]
111 self.atoms = atoms
113 def __init__(self, atoms, siesta, indices=None, name='ram',
114 delta=0.01, nfree=2, directions=None, freq_pol=0.0, **kw):
115
116 Vibrations.__init__(self, atoms, indices=indices, name=name,
117 delta = delta, nfree=nfree)
112118 if atoms.constraints:
113 print('WARNING! \n Your Atoms object is constrained. '
119 warnings.warn('WARNING! \n Your Atoms object is constrained. ' +
114120 'Some forces may be unintended set to zero. \n')
121 self.name = name + '-d%.3f' % delta
115122 self.calc = atoms.get_calculator()
116 if indices is None:
117 indices = range(len(atoms))
118 self.indices = np.asarray(indices)
119 self.nfree = nfree
120 self.name = name + '-d%.3f' % delta
121 self.delta = delta
122 self.H = None
123
123124 if directions is None:
124125 self.directions = np.asarray([0, 1, 2])
125126 else:
127128 self.ir = True
128129 self.ram = True
129130 self.siesta = siesta
130 self.mbpt_inp = mbpt_inp
131
132 if isinstance(freq_pol, list):
133 self.freq_pol = np.array(freq_pol)
134 elif isinstance(freq_pol, float):
135 self.freq_pol = np.array([freq_pol])
136 elif isinstance(freq_pol, float) or isinstance(freq_pol, np.ndarray):
137 self.freq_pol = freq_pol
138 else:
139 raise ValueError("wrong type for freq_pol, only float, list or array")
140
141 self.pyscf_arg = kw
131142
132143 def get_polarizability(self):
133 return self.siesta.get_polarizability(self.mbpt_inp,
134 format_output='txt',
135 units='au')
136
137 def read(self, method='standard', direction='central'):
144 if "tddft_iter_tol" in list(self.pyscf_arg.keys()):
145 if self.pyscf_arg["tddft_iter_tol"] > 1e-4:
146 warnings.warn("tddft_iter_tol > 1e-4, polarizability may not have " +
147 "enough precision. The Raman intensity will not be precise.")
148 else:
149 self.pyscf_arg["tddft_iter_tol"] = 1e-4
150
151 self.siesta.pyscf_tddft(Edir=np.array([1.0, 1.0, 1.0]), **self.pyscf_arg)
152 return self.siesta.results["freq range"], \
153 self.siesta.results["polarizability nonin"], \
154 self.siesta.results["polarizability inter"]
155
156 def read(self, method='standard', direction='central', inter = True):
138157 self.method = method.lower()
139158 self.direction = direction.lower()
140159 assert self.method in ['standard', 'frederiksen']
145164 # Get "static" dipole moment polarizability and forces
146165 name = '%s.eq.pckl' % self.name
147166 [forces_zero, dipole_zero, freq_zero,
148 pol_zero] = pickle.load(open(name))
167 noninPol_zero, pol_zero] = pickle.load(open(name, "rb"))
149168 self.dipole_zero = (sum(dipole_zero**2)**0.5) / units.Debye
150169 self.force_zero = max([sum((forces_zero[j])**2)**0.5
151170 for j in self.indices])
171 self.noninPol_zero = noninPol_zero * (units.Bohr)**3 # Ang**3
152172 self.pol_zero = pol_zero * (units.Bohr)**3 # Ang**3
153173
154174 ndof = 3 * len(self.indices)
160180 for a in self.indices:
161181 for i in 'xyz':
162182 name = '%s.%d%s' % (self.name, a, i)
163 [fminus, dminus, frminus, pminus] = pickle.load(
164 open(name + '-.pckl'))
165 [fplus, dplus, frplus, pplus] = pickle.load(
166 open(name + '+.pckl'))
183 [fminus, dminus, frminus, noninpminus, pminus] = pickle.load(
184 open(name + '-.pckl', "rb"))
185 [fplus, dplus, frplus, noninpplus, pplus] = pickle.load(
186 open(name + '+.pckl', "rb"))
167187 if self.nfree == 4:
168 [fminusminus, dminusminus, frminusminus, pminusminus] =\
169 pickle.load(open(name + '--.pckl'))
170 [fplusplus, dplusplus, frplusplus, pplusplus] =\
171 pickle.load(open(name + '++.pckl'))
188 [fminusminus, dminusminus, frminusminus,
189 noninpminusminus, pminusminus] =\
190 pickle.load(open(name + '--.pckl', "rb"))
191 [fplusplus, dplusplus, frplusplus,
192 noninpplusplus, pplusplus] =\
193 pickle.load(open(name + '++.pckl', "rb"))
172194 if self.method == 'frederiksen':
173195 fminus[a] += -fminus.sum(0)
174196 fplus[a] += -fplus.sum(0)
178200 if self.nfree == 2:
179201 H[r] = (fminus - fplus)[self.indices].ravel() / 2.0
180202 dpdx[r] = (dminus - dplus)
181 dadx[r] = (pminus - pplus)
203 if inter:
204 dadx[r] = (pminus - pplus)
205 else:
206 dadx[r] = (noninpminus - noninpplus)
182207 if self.nfree == 4:
183208 H[r] = (-fminusminus + 8 * fminus - 8 * fplus +
184209 fplusplus)[self.indices].ravel() / 12.0
185210 dpdx[r] = (-dplusplus + 8 * dplus - 8 * dminus +
186211 dminusminus) / 6.0
187 dadx[r] = (-pplusplus + 8 * pplus - 8 * pminus +
188 pminusminus) / 6.0
212 if inter:
213 dadx[r] = (-pplusplus + 8 * pplus - 8 * pminus +
214 pminusminus) / 6.0
215 else:
216 dadx[r] = (-noninpplusplus + 8 * noninpplus - 8 * noninpminus +
217 noninpminusminus) / 6.0
189218 H[r] /= 2 * self.delta
190219 dpdx[r] /= 2 * self.delta
191220 dadx[r] /= 2 * self.delta # polarizability in Ang
220249
221250 # Raman
222251 dadq = np.array([(dadx[j, :, :, :] / (units.Bohr**2)) /
223 sqrt(m[self.indices[j / 3]] * units._amu / units._me)
252 sqrt(m[self.indices[j // 3]] * units._amu / units._me)
224253 for j in range(ndof)])
225254 dadQ = np.zeros((ndof, 3, 3, dadq.shape[1]), dtype=complex)
226255 for w in range(dadq.shape[1]):
232261 dadQ[:, 0, 0, :])**2 + 6 * (dadQ[:, 0, 1, :]**2 +
233262 dadQ[:, 1, 2, :]**2 + dadQ[:, 2, 0, :]**2))
234263
235 intensities = np.zeros((ndof), dtype=float)
236 intensities_ram_enh = np.zeros((ndof), dtype=float)
264 intensities = np.zeros((ndof, self.freq_pol.size), dtype=np.complex128)
265 intensities_ram_enh = np.zeros((ndof, self.freq_pol.size), dtype=np.complex128)
237266
238267 # calculate the coefficients for calculating Raman Signal
239268 for j in range(ndof):
240 aj = self.get_pol_freq(0.0, freq_zero, ak[j, :])
241 gj2 = self.get_pol_freq(0.0, freq_zero, gk2[j, :])
242
243 intensities[j] = (45 * aj**2 + 7 * gj2) / 45.0
269 aj = self.get_nearrest_value(self.freq_pol, freq_zero, ak[j, :])
270 gj2 = self.get_nearrest_value(self.freq_pol, freq_zero, gk2[j, :])
271
272 intensities[j, :] = (45 * aj**2 + 7 * gj2) / 45.0
244273
245274 self.intensities_ram = intensities # Bohr**4 .me**-1
246275 self.intensities_ram_enh = intensities_ram_enh # Bohr**4 .me**-1
247276
248 def get_pol_freq(self, freq, freq_array, quantity):
277 def get_nearrest_value(self, val, x_range, y, kind="cubic", prec = 1e-3):
249278 """
250 get the intensity at the right frequency, for non-resonnant Raman,
251 the frequency is 0.0 eV.
252 For resonnant Raman it should change (but not yet implemented)
279 return the closest value of y at val (interpolating the function)
280 val may be a number or an array
253281 """
254 from ase.calculators.siesta.mbpt_lcao_utils import interpolate
255 if freq.imag > 1E-10:
256 return 0.0
257
258 w, interpol = interpolate(
259 freq_array, quantity, 100 * quantity.shape[0])
260 i = 0
261 while w[i] < freq:
262 i = i + 1
263
264 return interpol[i]
282 import scipy.interpolate as interp
283
284
285 func = interp.interp1d(x_range, y, kind = kind)
286 new_range = np.arange(x_range[0], x_range[x_range.size-1], prec)
287 interpol = func(new_range)
288
289 if isinstance(val, np.ndarray):
290 mult = np.zeros(val.shape, dtype=interpol.dtype)
291
292 for i, va in enumerate(val):
293 idx = (np.abs(new_range-va)).argmin()
294 mult[i] = interpol[idx]
295 return mult
296 else:
297 idx = (np.abs(new_range-val)).argmin()
298 return np.array([interpol[idx]])
265299
266300 def intensity_prefactor(self, intensity_unit):
267301 if intensity_unit == '(D/A)2/amu':
278312 raise RuntimeError('Intensity unit >' + intensity_unit +
279313 '< unknown.')
280314
281 def summary(self, method='standard', direction='central',
282 intensity_unit_ir='(D/A)2/amu', intensity_unit_ram='au', log=stdout):
283 hnu = self.get_energies(method, direction)
315 def summary(self, method='standard', direction='central', freq_pol = 0.0,
316 intensity_unit_ir='(D/A)2/amu', intensity_unit_ram='au', log=stdout,
317 inter = True):
318 hnu = self.get_energies(method, direction, inter=inter)
284319 s = 0.01 * units._e / units._c / units._hplanck
285320 iu_ir, iu_string_ir = self.intensity_prefactor(intensity_unit_ir)
286321 iu_ram, iu_string_ram = self.intensity_prefactor(intensity_unit_ram)
287322 arr = []
323
324 freq_idx = (np.abs(self.freq_pol-freq_pol)).argmin()
325 print("index: ", freq_idx)
288326
289327 if intensity_unit_ir == '(D/A)2/amu':
290328 iu_format_ir = '%9.4f '
322360 c = ' '
323361 e = e.real
324362 arr.append([n, 1000 * e, s * e, iu_ir * self.intensities_ir[n],
325 iu_ram * self.intensities_ram[n].real, iu_ram *
326 self.intensities_ram[n].imag])
363 iu_ram * self.intensities_ram[n, freq_idx].real, iu_ram *
364 self.intensities_ram[n, freq_idx].imag])
327365 parprint(('%3d %6.1f%s %7.1f%s ' + iu_format_ir + iu_format_ram +
328366 iu_format_ram + iu_format_ram) %
329367 (n, 1000 * e, c, s * e, c, iu_ir * self.intensities_ir[n],
330 iu_ram * self.intensities_ram[n].real, iu_ram *
331 self.intensities_ram[n].imag, iu_ram *
332 self.intensities_ram_enh[n].real), file=log)
368 iu_ram * self.intensities_ram[n, freq_idx].real, iu_ram *
369 self.intensities_ram[n, freq_idx].imag, iu_ram *
370 self.intensities_ram_enh[n, freq_idx].real), file=log)
333371 parprint(
334372 '-----------------------------------------------------------------------------------------',
335373 file=log)
344382 def write_latex_array(self, fname='vib_latex_array.tex.table', caption='', nb_column=5,
345383 hline=False, method='standard', direction='central',
346384 intensity_unit_ir='(D/A)2/amu', intensity_unit_ram='au',
347 label='tab_vib', log=stdout):
385 label='tab_vib', log=stdout, freq_pol=0.0):
348386 """
349387 Write the summary into a latex table that can be easily incorporate into a latex file.
350388 """
353391 s = 0.01 * units._e / units._c / units._hplanck
354392 iu_ir, iu_string_ir = self.intensity_prefactor(intensity_unit_ir)
355393 iu_ram, iu_string_ram = self.intensity_prefactor(intensity_unit_ram)
394
395 freq_idx = (np.abs(self.freq_pol-freq_pol)).argmin()
396
356397
357398 if intensity_unit_ir == '(D/A)2/amu':
358399 iu_format_ir = '%9.4f '
403444 f.write(" \hline \n")
404445 for n, e in enumerate(hnu):
405446 if e.imag != 0:
406 c = 'i'
447 c = ' + i'
407448 e = e.imag
408449 else:
409450 c = ' '
410451 e = e.real
411 f.write((' %3d & %6.1f & %s & %7.1f & %s & ' + iu_format_ir +
452 f.write((' %3d & %6.1f %s & %7.1f %s & ' + iu_format_ir +
412453 ' & ' + iu_format_ram + ' \n') % (n, 1000 * e, c, s * e, c,
413454 iu_ir * self.intensities_ir[n], iu_ram *
414 self.intensities_ram[n].real))
455 self.intensities_ram[n, freq_idx].real))
415456 if hline:
416457 f.write(r" \hline \n")
417458 f.write(" \end{tabular} \n")
423464
424465 def get_spectrum(self, start=800, end=4000, npts=None, width=4,
425466 type='Gaussian', method='standard', direction='central',
426 intensity_unit='(D/A)2/amu', normalize=False):
467 intensity_unit='(D/A)2/amu', normalize=False, freq_pol=0.0):
427468 """Get raman spectrum.
428469
429470 The method returns wavenumbers in cm^-1 with corresponding
433474 normalize=True ensures the integral over the peaks to give the
434475 intensity.
435476 """
477 name = '%s.eq.pckl' % self.name
478 [forces_zero, dipole_zero, freq_zero, noninPol_zero,
479 pol_zero] = pickle.load(open(name, "rb"))
480
481 freq_idx = (np.abs(self.freq_pol-freq_pol)).argmin()
482
436483 frequencies = self.get_frequencies(method, direction).real
437484 intensities_ir = self.intensities_ir
438 intensities_ram = self.intensities_ram
439 intensities_ram_enh = self.intensities_ram_enh
485 intensities_ram = self.intensities_ram[:, freq_idx]
486 intensities_ram_enh = self.intensities_ram_enh[:, freq_idx]
440487 energies, spectrum_ir = self.fold(frequencies, intensities_ir,
441488 start, end, npts, width, type,
442489 normalize)
443 energies, spectrum_ram = self.fold(frequencies, intensities_ram,
490 energies, spectrum_ram = self.fold(frequencies, intensities_ram.real,
444491 start, end, npts, width, type,
445492 normalize)
446 energies, spectrum_ram_enh = self.fold(frequencies, intensities_ram_enh,
493 energies, spectrum_ram_enh = self.fold(frequencies, intensities_ram_enh.real,
447494 start, end, npts, width, type,
448495 normalize)
449496 return energies, spectrum_ir, spectrum_ram, spectrum_ram_enh
468515 # Second column is absorbance scaled so that data runs from 1 to 0
469516 spectrum2_ir = 1. - spectrum_ir / spectrum_ir.max()
470517 spectrum2_ram = 1. - spectrum_ram / spectrum_ram.max()
471 spectrum2_ram_enh = 1. - spectrum_ram_enh / spectrum_ram_enh.max()
518 if abs(spectrum_ram_enh.max()) > 0.0:
519 spectrum2_ram_enh = 1. - spectrum_ram_enh / spectrum_ram_enh.max()
520 else:
521 spectrum2_ram_enh = np.zeros(spectrum_ram.shape, dtype = np.float64)
522
472523 outdata = np.empty([len(energies), 7])
473524 outdata.T[0] = energies
474525 outdata.T[1] = spectrum_ir
2727
2828 from ase.calculators.calculator import kpts2ndarray
2929 from ase.utils import basestring
30
31 from ase.calculators.vasp.setups import setups_defaults
3032
3133 # Parameters that can be set in INCAR. The values which are None
3234 # are not written and default parameters of VASP are used for them.
623625 'qdo_pre', # Calculate prefactor (instanton)
624626 ]
625627
626 list_keys = [
628 list_int_keys = [
629 'iband', # bands to calculate partial charge for
630 'kpuse', # k-point to calculate partial charge for
631 'ldaul', # DFT+U parameters, overruled by dict key 'ldau_luj'
632 'random_seed', # List of ints used to seed RNG for advanced MD routines
633 # (Bucko)
634 'auger_bmin_eeh', # 4 ints | Various undocumented parameters for Auger
635 'auger_bmax_eeh', # 4 ints | calculations
636 'auger_bmin_ehh', # 4 ints |
637 'auger_bmax_ehh', # 4 ints |
638 'balist', # nbas ints | Undocumented Bond-Boost parameter (GH patches)
639 'kpoint_bse', # 4 ints | Undocumented parameter
640 'nsubsys', # <=3 ints | Last atom # for each of up to 3 thermostats
641 'vdw_refstate', # ntyp ints | Undocumented classical vdW parameter
642 'vdw_mbd_size', # 3 ints | Supercell size for TS MBD vdW correction
643 'nbands_index', # nbands_out ints | Undocumented QP parameter
644 'kpts_index', # kpts_out ints | Undocumented QP parameter
645 'isp_index', # isp_out ints | Undocumented QP parameter
646 'nomega_index', # nomega_out ints | Undocumented QP parameter
647 'ntarget_states', # nbands ints | Undocumented CRPA parameter
648 'wanproj_i', # nions ints | Undocumented Wannier parameter
649 'wanproj_l', # ? ints | Undocumented Wannier parameter
650 ]
651
652 list_bool_keys = [
653 'lattice_constraints', # 3 bools | Undocumented advanced MD parameter
654 'lrctype', # ntyp bools | Enable relaxed-core calc. for these atoms
655 'lvdw_onecell', # 3 bools | Enable periodicity in A, B, C vector for vdW
656 ]
657
658 list_float_keys = [
627659 'dipol', # center of cell for dipol
628660 'eint', # energy range to calculate partial charge for
629661 'ferwe', # Fixed band occupation (spin-paired)
630662 'ferdo', # Fixed band occupation (spin-plarized)
631 'iband', # bands to calculate partial charge for
632663 'magmom', # initial magnetic moments
633 'kpuse', # k-point to calculate partial charge for
634664 'ropt', # number of grid points for non-local proj in real space
635665 'rwigs', # Wigner-Seitz radii
636666 'ldauu', # ldau parameters, has potential to redundant w.r.t. dict
637 'ldaul', # key 'ldau_luj', but 'ldau_luj' can't be read direct from
638 'ldauj', # the INCAR (since it needs to know information about atomic
667 'ldauj', # key 'ldau_luj', but 'ldau_luj' can't be read direct from
668 # the INCAR (since it needs to know information about atomic
639669 # species. In case of conflict 'ldau_luj' gets written out
640670 # when a calculation is set up
641
642 'random_seed', # List of ints used to seed RNG for advanced MD routines
643 # (Bucko)
644671 'vdw_c6', # List of floats of C6 parameters (J nm^6 mol^-1) for each
645672 # species (DFT-D2 and DFT-TS)
646673 'vdw_c6au', # List of floats of C6 parameters (a.u.) for each species
652679 'vdw_alpha', # List of floats of free-atomic polarizabilities for each
653680 # species (DFT-TS)
654681 'langevin_gamma', # List of floats for langevin friction coefficients
655 'auger_bmin_eeh', # 4 ints | Various undocumented parameters for Auger
656 'auger_bmax_eeh', # 4 ints | calculations start here...
657 'auger_bmin_ehh', # 4 ints
658 'auger_bmax_ehh', # 4 ints
659 'auger_emin_eeh', # 4 floats
660 'auger_emax_eeh', # 4 floats
661 'auger_emin_ehh', # 4 floats
662 'auger_emax_ehh', # 4 floats | End of Auger parameters
682 'auger_emin_eeh', # 4 floats | Various undocumented parameters for Auger
683 'auger_emax_eeh', # 4 floats | calculations
684 'auger_emin_ehh', # 4 floats |
685 'auger_emax_ehh', # 4 floats |
663686 'avecconst', # 3 floats | magnitude of magnetic moment (NMR)
664687 'magdipol', # 3 floats | magnitude of magnetic dipole (NMR)
665688 'bconst', # 3 floats | magnitude of constant magnetic field (NMR)
666689 'magpos', # 3 floats | position for magnetic moment w/ 'nucind' (NMR)
667 'balist', # nbas ints | Undocumented Bond-Boost parameter (GH patches)
668690 'bext', # 3 floats | Undocumented (probably external magnetic field)
669691 'core_c', # ntyp floats | pseudo-core charge magnitude (VASPsol)
670692 'sigma_rc_k', # ntyp floats | width of pseudo-core gaussians (VASPsol)
671693 'darwinr', # ntypd (?) floats | Undocumented parameter
672694 'darwinv', # ntypd (?) floats | Undocumented parameter
673 'kpoint_bse', # 4 ints | Undocumented parameter
674695 'dummy_k', # ? floats | Force const. connecting dummy atoms to sys.
675696 'dummy_r0', # ? floats | Minimum dist., ang., etc. for dummy atom DOFs
676697 'dummy_positions', # 3 floats | Position of dummy atom(s?)
677 'nsubsys', # <=3 ints | Last atom # for each of up to 3 thermostats
678698 'psubsys', # <=3 floats | Coll. prob. for each of up to 3 thermostats
679699 'tsubsys', # <=3 floats | Temp. for each of up to 3 thermostats
680700 'increm', # ? floats | Undocumented advanced MD parameter
681701 'value_min', # ? floats | Undocumented advanced MD parameter
682702 'value_max', # ? floats | Undocumented advanced MD parameter
683 'lattice_constraints', # 3 bools | Undocumented advanced MD parameter
684703 'hills_position', # ? floats | Dummy particle(s) pos. for metadynamics
685704 'hills_velocity', # ? floats | Dummy particle(s) vel. for metadynamics
686705 'spring_k', # ? floats | Spring constant for harmonic constraints
697716 'vca', # ? floats | Atom weight for VCA calculations
698717 'stm', # 7 floats | "range for STM data"
699718 'qspiral', # 3 floats | Undocumented parameter
700 'lrctype', # ntyp bools | Enable relaxed-core calc. for these atoms
701719 'external_stress', # 6 floats | Target stress (adds w/ external_pressure)
702 'vdw_refstate', # ntyp ints | Undocumented classical vdW parameter
703 'lvdw_onecell', # 3 bools | Enable periodicity in A, B, C vector for vdW
704 'vdw_mbd_size', # 3 ints | Supercell size for TS MBD vdW correction
705720 'm_constr', # 3*nions floats | Local magmom assigned to each spin DOF
706 'nbands_index', # nbands_out ints | Undocumented QP parameter
707 'kpts_index', # kpts_out ints | Undocumented QP parameter
708 'isp_index', # isp_out ints | Undocumented QP parameter
709 'nomega_index', # nomega_out ints | Undocumented QP parameter
710 'ntarget_states', # nbands ints | Undocumented CRPA parameter
711721 'quad_efg', # ntyp floats | Nuclear quadrupole moments
712722 'ngyromag', # ntyp floats | Nuclear gyromagnetic ratios
713723 'rcrhocut', # ntyp floats | Core density cutoff rad. for HF relcore calc
714724 'ofield_k', # 3 floats | Undocumented parameter
715725 'paripot', # ? floats | Undocumented parameter
716726 'smearings', # ? floats | ismear,sigma smearing params to loop over
717 'wanproj_i', # nions ints | Undocumented Wannier parameter
718 'wanproj_l', # ? ints | Undocumented Wannier parameter
719727 'wanproj_e', # 2 floats | Undocumented Wannier parameter
720728 ]
721729
778786 'hse06': {'gga': 'PE', 'lhfcalc': True, 'hfscreen': 0.2},
779787 'hsesol': {'gga': 'PS', 'lhfcalc': True, 'hfscreen': 0.2}}
780788
781 # elements which have no-suffix files only
782 setups_defaults = {'K': '_pv',
783 'Ca': '_pv',
784 'Rb': '_pv',
785 'Sr': '_sv',
786 'Y': '_sv',
787 'Zr': '_sv',
788 'Nb': '_pv',
789 'Cs': '_sv',
790 'Ba': '_sv',
791 'Fr': '_sv',
792 'Ra': '_sv',
793 'Sc': '_sv'}
794
795
796789 def __init__(self, restart=None):
797790 self.float_params = {}
798791 self.exp_params = {}
799792 self.string_params = {}
800793 self.int_params = {}
801794 self.bool_params = {}
802 self.list_params = {}
795 self.list_bool_params = {}
796 self.list_int_params = {}
797 self.list_float_params = {}
803798 self.special_params = {}
804799 self.dict_params = {}
805800 for key in float_keys:
812807 self.int_params[key] = None
813808 for key in bool_keys:
814809 self.bool_params[key] = None
815 for key in list_keys:
816 self.list_params[key] = None
810 for key in list_bool_keys:
811 self.list_bool_params[key] = None
812 for key in list_int_keys:
813 self.list_int_params[key] = None
814 for key in list_float_keys:
815 self.list_float_params[key] = None
817816 for key in special_keys:
818817 self.special_params[key] = None
819818 for key in dict_keys:
879878 self.int_params[key] = kwargs[key]
880879 elif key in self.bool_params:
881880 self.bool_params[key] = kwargs[key]
882 elif key in self.list_params:
883 self.list_params[key] = kwargs[key]
881 elif key in self.list_bool_params:
882 self.list_bool_params[key] = kwargs[key]
883 elif key in self.list_int_params:
884 self.list_int_params[key] = kwargs[key]
885 elif key in self.list_float_params:
886 self.list_float_params[key] = kwargs[key]
884887 elif key in self.special_params:
885888 self.special_params[key] = kwargs[key]
886889 elif key in self.dict_params:
964967 symbols = []
965968 symbolcount = {}
966969
967 # make sure we find POTCARs for elements which have no-suffix files only
968 setups = self.setups_defaults.copy()
969 # override with user defined setups
970 # Default setup lists are available: 'minimal', 'recommended' and 'GW'
971 # These may be provided as a string e.g.::
972 #
973 # calc = Vasp(setups='recommended')
974 #
975 # or in a dict with other specifications e.g.::
976 #
977 # calc = Vasp(setups={'base': 'minimal', 'Ca': '_sv', 2: 'O_s'})
978 #
979 # Where other keys are either atom identities or indices, and the
980 # corresponding values are suffixes or the full name of the setup
981 # folder, respectively.
982
983 # Default to minimal basis
984 if p['setups'] is None:
985 p['setups'] = {'base': 'minimal'}
986
987 # String shortcuts are initialised to dict form
988 elif isinstance(p['setups'], str):
989 if p['setups'].lower() in ('minimal', 'recommended', 'gw'):
990 p['setups'] = {'base': p['setups']}
991
992 # Dict form is then queried to add defaults from setups.py.
993 if 'base' in p['setups']:
994 setups = setups_defaults[p['setups']['base'].lower()]
995 else:
996 setups = {}
997
998 # Override defaults with user-defined setups
970999 if p['setups'] is not None:
9711000 setups.update(p['setups'])
9721001
11371166 for key, val in self.exp_params.items():
11381167 if key == 'ediffg' and val is None:
11391168 RuntimeError('Please set EDIFFG < 0')
1140 for key, val in self.list_params.items():
1141 if val is not None:
1142 if key in ('dipol', 'eint', 'ropt', 'rwigs', 'langevin_gamma'):
1169
1170 for key, val in self.list_bool_params.items():
1171 if val is None:
1172 pass
1173 else:
1174 incar.write(' %s = ' % key.upper())
1175 [incar.write('%s ' % _to_vasp_bool(x)) for x in val]
1176 incar.write('\n')
1177
1178 for key, val in self.list_int_params.items():
1179 if val is None:
1180 pass
1181 elif key == 'ldaul' and (self.dict_params['ldau_luj'] is not None):
1182 pass
1183 else:
1184 incar.write(' %s = ' % key.upper())
1185 [incar.write('%d ' % x) for x in val]
1186 incar.write('\n')
1187
1188 for key, val in self.list_float_params.items():
1189 if val is None:
1190 pass
1191 elif ((key in ('ldauu', 'ldauj')) and
1192 (self.dict_params['ldau_luj'] is not None)):
1193 pass
1194 elif key == 'magmom':
1195 incar.write(' %s = ' % key.upper())
1196 magmom_written = True
1197 # Work out compact a*x b*y notation and write in this form
1198 list = [[1, val[0]]]
1199 for n in range(1, len(val)):
1200 if val[n] == val[n - 1]:
1201 list[-1][0] += 1
1202 else:
1203 list.append([1, val[n]])
1204 [incar.write('%i*%.4f ' % (mom[0], mom[1]))
1205 for mom in list]
1206 incar.write('\n')
1207 else:
11431208 incar.write(' %s = ' % key.upper())
11441209 [incar.write('%.4f ' % x) for x in val]
1145 # ldau_luj is a dictionary that encodes all the
1146 # data. It is not a vasp keyword. An alternative to
1147 # the dictionary is to to use 'ldauu', 'ldauj',
1148 # 'ldaul', which are vasp keywords.
1149 elif (key in ('ldauu', 'ldauj') and
1150 self.dict_params['ldau_luj'] is None):
1151 incar.write(' %s = ' % key.upper())
1152 [incar.write('%.4f ' % x) for x in val]
1153 elif (key in ('ldaul') and
1154 self.dict_params['ldau_luj'] is None):
1155 incar.write(' %s = ' % key.upper())
1156 [incar.write('%d ' % x) for x in val]
1157 elif key in ('ferwe', 'ferdo'):
1158 incar.write(' %s = ' % key.upper())
1159 [incar.write('%.1f ' % x) for x in val]
1160 elif key in ('iband', 'kpuse', 'random_seed'):
1161 incar.write(' %s = ' % key.upper())
1162 [incar.write('%i ' % x) for x in val]
1163 elif key == 'magmom':
1164 incar.write(' %s = ' % key.upper())
1165 magmom_written = True
1166 list = [[1, val[0]]]
1167 for n in range(1, len(val)):
1168 if val[n] == val[n - 1]:
1169 list[-1][0] += 1
1170 else:
1171 list.append([1, val[n]])
1172 [incar.write('%i*%.4f ' % (mom[0],
1173 mom[1]))
1174 for mom in list]
1175 incar.write('\n')
1210 incar.write('\n')
1211
11761212 for key, val in self.bool_params.items():
11771213 if val is not None:
11781214 incar.write(' %s = ' % key.upper())
12351271 raise ValueError("KSPACING value {0} is not allowable. "
12361272 "Please use None or a positive number."
12371273 "".format(self.float_params['kspacing']))
1238
12391274
12401275 p = self.input_params
12411276 kpoints = open(join(directory, 'KPOINTS'), 'w')
13471382 self.bool_params[key] = True
13481383 elif 'false' in data[2].lower():
13491384 self.bool_params[key] = False
1350 elif key in list_keys:
1351 list = []
1352 if key in ('dipol', 'eint', 'ferwe', 'ferdo',
1353 'ropt', 'rwigs',
1354 'ldauu', 'ldaul', 'ldauj', 'langevin_gamma'):
1355 for a in data[2:]:
1356 if a in ["!", "#"]:
1357 break
1358 list.append(float(a))
1359 elif key in ('iband', 'kpuse', 'random_seed'):
1360 for a in data[2:]:
1361 if a in ["!", "#"]:
1362 break
1363 list.append(int(a))
1364 self.list_params[key] = list
1385
1386 elif key in list_bool_keys:
1387 self.list_bool_keys[key] = [_from_vasp_bool(x) for x in
1388 _args_without_comment(data)]
1389
1390 elif key in list_int_keys:
1391 self.list_int_params[key] = [int(x) for x in
1392 _args_without_comment(data)]
1393
1394 elif key in list_float_keys:
13651395 if key == 'magmom':
13661396 list = []
13671397 i = 2
13811411 if self.atoms is not None:
13821412 self.atoms.set_initial_magnetic_moments(
13831413 list[self.resort])
1414 else:
1415 data = _args_without_comment(data)
1416 self.list_float_params[key] = [float(x) for x in data]
1417 # elif key in list_keys:
1418 # list = []
1419 # if key in ('dipol', 'eint', 'ferwe', 'ferdo',
1420 # 'ropt', 'rwigs',
1421 # 'ldauu', 'ldaul', 'ldauj', 'langevin_gamma'):
1422 # for a in data[2:]:
1423 # if a in ["!", "#"]:
1424 # break
1425 # list.append(float(a))
1426 # elif key in ('iband', 'kpuse', 'random_seed'):
1427 # for a in data[2:]:
1428 # if a in ["!", "#"]:
1429 # break
1430 # list.append(int(a))
1431 # self.list_params[key] = list
1432 # if key == 'magmom':
1433 # list = []
1434 # i = 2
1435 # while i < len(data):
1436 # if data[i] in ["#", "!"]:
1437 # break
1438 # if data[i] == "*":
1439 # b = list.pop()
1440 # i += 1
1441 # for j in range(int(b)):
1442 # list.append(float(data[i]))
1443 # else:
1444 # list.append(float(data[i]))
1445 # i += 1
1446 # self.list_params['magmom'] = list
1447 # list = np.array(list)
1448 # if self.atoms is not None:
1449 # self.atoms.set_initial_magnetic_moments(
1450 # list[self.resort])
13841451 elif key in special_keys:
13851452 if key == 'lreal':
13861453 if 'true' in data[2].lower():
14531520 'string_params',
14541521 'int_params',
14551522 'bool_params',
1456 'list_params',
1523 'list_bool_params',
1524 'list_int_params',
1525 'list_float_params',
14571526 'special_params',
14581527 'dict_params',
14591528 'input_params'
14651534 if val is None:
14661535 del(dct[key])
14671536 return dct
1537
1538
1539 def _args_without_comment(data, marks=['!', '#']):
1540 """Check split arguments list for a comment, return data up to marker
1541
1542 INCAR reader splits list arguments on spaces and leaves comment markers as
1543 individual items. This function returns only the data portion of the list.
1544
1545 """
1546 comment_locs = [data.index(mark) for mark in marks
1547 if mark in data]
1548 if comment_locs == []:
1549 return data
1550 else:
1551 return data[:min(comment_locs)]
1552
1553
1554 def _from_vasp_bool(x):
1555 """Cast vasp boolean to Python bool
1556
1557 VASP files sometimes use T or F as shorthand for the preferred Boolean
1558 notation .TRUE. or .FALSE. As capitalisation is pretty inconsistent in
1559 practice, we allow all cases to be cast to a Python bool.
1560
1561 """
1562 assert isinstance(x, str)
1563 if x.lower() == '.true.' or x.lower() == 't':
1564 return True
1565 elif x.lower() == '.false.' or x.lower() == 'f':
1566 return False
1567 else:
1568 raise ValueError('Value "%s" not recognized as bool' % x)
1569
1570
1571 def _to_vasp_bool(x):
1572 """Convert Python boolean to string for VASP input
1573
1574 In case the value was modified to a string already, appropriate strings
1575 will also be accepted and cast to a standard .TRUE. / .FALSE. format.
1576
1577 """
1578 if isinstance(x, str):
1579 if x.lower() in ('.true.', 't'):
1580 x = True
1581 elif x.lower() in ('.false.', 'f'):
1582 x = False
1583 else:
1584 raise ValueError('"%s" not recognised as VASP Boolean')
1585 assert isinstance(x, bool)
1586 if x:
1587 return '.TRUE.'
1588 else:
1589 return '.FALSE.'
88
99 import time
1010 import os
11 import sys
1112
1213
1314 class VaspInteractive(GenerateVaspInput, Calculator):
7172 if self.print_log:
7273 print(text, end=ending)
7374 self.process.stdin.write(text + ending)
75 if sys.version_info[0] >= 3:
76 self.process.stdin.flush()
7477
7578 def _stdout(self, text):
7679 if self.txt is not None:
8790 self.initialize(atoms)
8891 self.write_input(atoms, directory=self.path)
8992 self._stdout("Starting VASP for initial step...\n")
90 self.process = Popen(self.command, stdout=PIPE,
91 stdin=PIPE, stderr=PIPE, cwd=self.path)
93 if sys.version_info[0] >= 3:
94 self.process = Popen(self.command, stdout=PIPE,
95 stdin=PIPE, stderr=PIPE, cwd=self.path,
96 universal_newlines=True)
97 else:
98 self.process = Popen(self.command, stdout=PIPE,
99 stdin=PIPE, stderr=PIPE, cwd=self.path)
92100 else:
93101 self._stdout("Inputting positions...\n")
94102 for atom in atoms.get_scaled_positions():
0 setups_defaults = {'minimal':
1 {'K': '_pv',
2 'Ca': '_pv',
3 'Rb': '_pv',
4 'Sr': '_sv',
5 'Y': '_sv',
6 'Zr': '_sv',
7 'Nb': '_pv',
8 'Cs': '_sv',
9 'Ba': '_sv',
10 'Fr': '_sv',
11 'Ra': '_sv',
12 'Sc': '_sv'},
13 #
14 'recommended':
15 {'Li': '_sv',
16 'Na': '_pv',
17 'K': '_sv',
18 'Ca': '_sv',
19 'Sc': '_sv',
20 'Ti': '_sv',
21 'V': '_sv',
22 'Cr': '_pv',
23 'Mn': '_pv',
24 'Ga': '_d',
25 'Ge': '_d',
26 'Rb': '_sv',
27 'Sr': '_sv',
28 'Y': '_sv',
29 'Zr': '_sv',
30 'Nb': '_sv',
31 'Mo': '_sv',
32 'Tc': '_pv',
33 'Ru': '_pv',
34 'Rh': '_pv',
35 'In': '_d',
36 'Sn': '_d',
37 'Cs': '_sv',
38 'Ba': '_sv',
39 'Pr': '_3',
40 'Nd': '_3',
41 'Pm': '_3',
42 'Sm': '_3',
43 'Eu': '_2',
44 'Gd': '_3',
45 'Tb': '_3',
46 'Dy': '_3',
47 'Ho': '_3',
48 'Er':'_3',
49 'Tm':'_3',
50 'Yb':'_2',
51 'Lu':'_3',
52 'Hf': '_pv',
53 'Ta': '_pv',
54 'W': '_pv',
55 'Tl': '_d',
56 'Pb': '_d',
57 'Bi':'_d',
58 'Po': '_d',
59 'At': '_d',
60 'Fr':'_sv',
61 'Ra':'_sv'},
62 #
63 'gw':
64 {'H': '_GW',
65 'He': '_GW',
66 'Li': '_sv_GW',
67 'Be': '_sv_GW',
68 'B': '_GW',
69 'C': '_GW',
70 'N': '_GW',
71 'O': '_GW',
72 'F': '_GW',
73 'Ne': '_GW',
74 'Na': '_sv_GW',
75 'Mg': '_sv_GW',
76 'Al': '_GW',
77 'Si': '_GW',
78 'P': '_GW',
79 'S': '_GW',
80 'Cl': '_GW',
81 'Ar': '_GW',
82 'K': '_sv_GW',
83 'Ca': '_sv_GW',
84 'Sc': '_sv_GW',
85 'Ti': '_sv_GW',
86 'V': '_sv_GW',
87 'Cr': '_sv_GW',
88 'Mn': '_sv_GW',
89 'Fe': '_sv_GW',
90 'Co': '_sv_GW',
91 'Ni': '_sv_GW',
92 'Cu': '_sv_GW',
93 'Zn': '_sv_GW',
94 'Ga': '_d_GW',
95 'Ge': '_d_GW',
96 'As': '_GW',
97 'Se': '_GW',
98 'Br': '_GW',
99 'Kr': '_GW',
100 'Rb': '_sv_GW',
101 'Sr': '_sv_GW',
102 'Y': '_sv_GW',
103 'Zr': '_sv_GW',
104 'Nb': '_sv_GW',
105 'Mo': '_sv_GW',
106 'Tc': '_sv_GW',
107 'Ru': '_sv_GW',
108 'Rh': '_sv_GW',
109 'Pd': '_sv_GW',
110 'Ag': '_sv_GW',
111 'Cd': '_sv_GW',
112 'In': '_d_GW',
113 'Sn': '_d_GW',
114 'Sb': '_d_GW',
115 'Te': '_GW',
116 'I': '_GW',
117 'Xe': '_GW',
118 'Cs': '_sv_GW',
119 'Ba': '_sv_GW',
120 'La': '_GW',
121 'Ce': '_GW',
122 'Hf': '_sv_GW',
123 'Ta': '_sv_GW',
124 'W': '_sv_GW',
125 'Re': '_sv_GW',
126 'Os': '_sv_GW',
127 'Ir': '_sv_GW',
128 'Pt': '_sv_GW',
129 'Au': '_sv_GW',
130 'Hg': '_sv_GW',
131 'Tl': '_d_GW',
132 'Pb': '_d_GW',
133 'Bi': '_d_GW',
134 'Po': '_d_GW',
135 'At': '_d_GW',
136 'Rn': '_d_GW'}
137 }
123123 self.magnetic_moment = self.read_magnetic_moment()
124124 if (self.int_params['lorbit'] is not None and
125125 (self.int_params['lorbit'] >= 10 or
126 self.list_params['rwigs'])):
126 self.list_float_params['rwigs'])):
127127 self.magnetic_moments = self.read_magnetic_moments(atoms)
128128 else:
129129 self.magnetic_moments = None
133133 self.old_int_params = self.int_params.copy()
134134 self.old_input_params = self.input_params.copy()
135135 self.old_bool_params = self.bool_params.copy()
136 self.old_list_params = self.list_params.copy()
136 self.old_list_bool_params = self.list_bool_params.copy()
137 self.old_list_int_params = self.list_int_params.copy()
138 self.old_list_float_params = self.list_float_params.copy()
137139 self.old_dict_params = self.dict_params.copy()
138140 self.atoms = atoms.copy()
139141 self.name = 'vasp'
336338 (self.string_params != self.old_string_params) or
337339 (self.int_params != self.old_int_params) or
338340 (self.bool_params != self.old_bool_params) or
339 (self.list_params != self.old_list_params) or
341 (self.list_bool_params != self.old_list_bool_params) or
342 (self.list_int_params != self.old_list_int_params) or
343 (self.list_float_params != self.old_list_float_params) or
340344 (self.input_params != self.old_input_params) or
341345 (self.dict_params != self.old_dict_params) or
342346 not self.converged)):
400404 def get_magnetic_moments(self, atoms):
401405 if ((self.int_params['lorbit'] is not None and
402406 self.int_params['lorbit'] >= 10) or
403 self.list_params['rwigs']):
407 self.list_float_params['rwigs']):
404408 self.update(atoms)
405409 return self.magnetic_moments
406410 else:
662666 self.nbands = self.read_nbands()
663667 self.read_ldau()
664668 p = self.int_params
665 q = self.list_params
669 q = self.list_float_params
666670 if self.spinpol:
667671 self.magnetic_moment = self.read_magnetic_moment()
668 if p['lorbit'] >= 10 or (p['lorbit'] is None and q['rwigs']):
672 if ((p['lorbit'] is not None and p['lorbit'] >= 10)
673 or (p['lorbit'] is None and q['rwigs'])):
669674 self.magnetic_moments = self.read_magnetic_moments(self.atoms)
670675 else:
671676 self.magnetic_moments = None
1818 @staticmethod
1919 def add_arguments(parser):
2020 parser.add_argument('calculation',
21 help='Path to output file(s) from calculation')
21 help='Path to output file(s) from calculation.')
2222 parser.add_argument('-q', '--quiet', action='store_true')
2323 parser.add_argument('-k', '--path', help='Example "GXL".')
2424 parser.add_argument('-n', '--points', type=int, default=100,
6161 try:
6262 cs = crystal_structure_from_cell(cell)
6363 except ValueError:
64 err += ('\nGPAW cannot autimatically '
64 err += ('\nASE cannot automatically '
6565 'recognize this crystal structure')
6666 else:
6767 from ase.dft.kpoints import special_paths
3232 '--crystal-structure', '-a', '--lattice-constant',
3333 '--orthorhombic', '--cubic', '-r', '--repeat', '-g',
3434 '--gui', '--periodic'],
35 'completion':
36 ['-0', '--dry-run'],
35 'convert':
36 ['-v', '--verbose', '-i', '--input-format', '-o',
37 '--output-format', '-f', '--force', '-n',
38 '--image-number'],
3739 'db':
3840 ['-v', '--verbose', '-q', '--quiet', '-n', '--count', '-l',
3941 '--long', '-i', '--insert-into', '-a',
4446 '--csv', '-w', '--open-web-browser', '--no-lock-file',
4547 '--analyse', '-j', '--json', '-m', '--show-metadata',
4648 '--set-metadata', '-M', '--metadata-from-python-script',
47 '--unique'],
49 '--unique', '--strip-data'],
4850 'eos':
4951 ['-p', '--plot', '-t', '--type'],
5052 'find':
5153 ['-v', '--verbose', '-l', '--long', '-i', '--include', '-x',
5254 '--exclude'],
5355 'gui':
54 ['-n', '--image-number', '-u', '--show-unit-cell', '-r',
55 '--repeat', '-R', '--rotations', '-o', '--output', '-g',
56 '--graph', '-t', '--terminal', '--interpolate', '-b',
57 '--bonds', '-s', '--scale'],
56 ['-n', '--image-number', '-r', '--repeat', '-R', '--rotations',
57 '-o', '--output', '-g', '--graph', '-t', '--terminal',
58 '--interpolate', '-b', '--bonds', '-s', '--scale'],
5859 'info':
5960 ['-v', '--verbose'],
6061 'nomad-upload':
6162 ['-t', '--token', '-n', '--do-not-save-token', '-0', '--dry-run'],
63 'reciprocal':
64 ['-v', '--verbose', '-p', '--path', '-d', '--dimension',
65 '--no-vectors', '-k', '--k-points', '-i',
66 '--ibz-k-points'],
6267 'run':
6368 ['-t', '--tag', '-p', '--parameters', '-d', '--database', '-S',
6469 '--skip', '--properties', '-f', '--maximum-force',
00 from __future__ import print_function
11 import os
2 import sys
23
34 # Path of the complete.py script:
45 my_dir, _ = os.path.split(os.path.realpath(__file__))
78
89 class CLICommand:
910 short_description = 'Add tab-completion for Bash'
10 cmd = 'complete -o default -C {} ase'.format(filename)
11 description = ('Will show the command that needs to be added to your '
12 '~/.bashrc file.')
13 cmd = ('complete -o default -C "{py} {filename}" ase'
14 .format(py=sys.executable, filename=filename))
1115
1216 @staticmethod
1317 def add_arguments(parser):
14 parser.add_argument('filename', nargs='?')
15 parser.add_argument('-0', '--dry-run', action='store_true')
18 pass
1619
1720 @staticmethod
1821 def run(args):
19 filename = args.filename or os.path.expanduser('~/.bashrc')
2022 cmd = CLICommand.cmd
2123 print(cmd)
22 if args.dry_run:
23 return
24 with open(filename) as fd:
25 if cmd + '\n' in fd.readlines():
26 print('Completion script already installed!')
27 return
28 with open(filename, 'a') as fd:
29 print(cmd, file=fd)
3024
3125
3226 def update(filename, commands):
5145 def add_argument(self, *args, **kwargs):
5246 dct[command].extend(arg for arg in args
5347 if arg.startswith('-'))
48
49 def add_mutually_exclusive_group(self, required=False):
50 return self
5451
5552 for command, module_name in commands:
5653 module = import_module(module_name)
0 import os
1
2 from ase.io import read, write
3
4
5 class CLICommand:
6 short_description = 'Convert between file formats'
7 description = ('Convert between file formats. Use "-" for stdin/stdout. '
8 'See ase info --formats for known formats.')
9
10 @staticmethod
11 def add_arguments(parser):
12 add = parser.add_argument
13 add('-v', '--verbose', action='store_true')
14 add('input', nargs='+', metavar='input-file')
15 add('-i', '--input-format')
16 add('output', metavar='output-file')
17 add('-o', '--output-format')
18 add('-f', '--force', action='store_true',
19 help='Overwrite an existing file.')
20 add('-n', '--image-number',
21 default=':', metavar='NUMBER',
22 help='Pick image(s) from trajectory. NUMBER can be a '
23 'single number (use a negative number to count from '
24 'the back) or a range: start:stop:step, where the '
25 '":step" part can be left out - default values are '
26 '0:nimages:1.')
27
28 @staticmethod
29 def run(args, parser):
30 if args.verbose:
31 print(', '.join(args.input), '->', args.output)
32
33 configs = []
34 for filename in args.input:
35 atoms = read(filename, args.image_number, format=args.input_format)
36 if isinstance(atoms, list):
37 configs.extend(atoms)
38 else:
39 configs.append(atoms)
40
41 if not args.force and os.path.isfile(args.output):
42 parser.error('File already exists: {}'.format(args.output))
43
44 write(args.output, configs, format=args.output_format)
33 import sys
44
55 from ase.io import read
6 from ase.io.formats import filetype
6 from ase.io.formats import filetype, UnknownFileTypeError
77 from ase.db import connect
88 from ase.db.core import parse_selection
99 from ase.db.jsondb import JSONDatabase
4141 query = parse_selection(args.query)
4242 include = args.include.split(',') if args.include else []
4343 exclude = args.exclude.split(',') if args.exclude else []
44
45 if args.long:
46 print('pbc {:10} {:15} path'.format('formula', 'filetype'))
4447
4548 for path in allpaths(args.folder, include, exclude):
4649 format, row = check(path, query, args.verbose)
8386
8487 try:
8588 format = filetype(path, guess=False)
86 except OSError:
87 return '', None
88 if format is None:
89 except (OSError, UnknownFileTypeError):
8990 return '', None
9091
9192 if format in ['db', 'json']:
0 from __future__ import print_function
01 import platform
12 import sys
23
34 from ase.utils import import_module, FileNotFoundError
4 from ase.io.formats import filetype, all_formats
5 from ase.utils import search_current_git_hash
6 from ase.io.formats import filetype, all_formats, UnknownFileTypeError
57 from ase.io.ulm import print_ulm_info
68 from ase.io.bundletrajectory import print_bundletrajectory_info
9 from ase.io.formats import all_formats as fmts
710
811
912 class CLICommand:
1316 def add_arguments(parser):
1417 parser.add_argument('filenames', nargs='*')
1518 parser.add_argument('-v', '--verbose', action='store_true')
19 parser.add_argument('--formats', action='store_true',
20 help='list file formats known to ase')
1621
1722 @staticmethod
1823 def run(args):
1924 if not args.filenames:
2025 print_info()
26 if args.formats:
27 print()
28 print_formats()
2129 return
2230
2331 n = max(len(filename) for filename in args.filenames) + 2
2735 except FileNotFoundError:
2836 format = '?'
2937 description = 'No such file'
38 except UnknownFileTypeError:
39 format = '?'
40 description = '?'
3041 else:
31 if format and format in all_formats:
32 description, code = all_formats[format]
33 else:
34 format = '?'
35 description = '?'
42 description, code = all_formats.get(format, ('?', '?'))
3643
3744 print('{:{}}{} ({})'.format(filename + ':', n,
3845 description, format))
5259 except ImportError:
5360 versions.append((name, 'no'))
5461 else:
55 versions.append((name + '-' + module.__version__,
62 # Search for git hash
63 githash = search_current_git_hash(module)
64 if githash is None:
65 githash = ''
66 else:
67 githash = '-{:.10}'.format(githash)
68 versions.append((name + '-' + module.__version__ + githash,
5669 module.__file__.rsplit('/', 1)[0] + '/'))
5770
5871 for a, b in versions:
59 print('{:16}{}'.format(a, b))
72 print('{:25}{}'.format(a, b))
73
74 def print_formats():
75 print('Supported formats:')
76 for f in list(sorted(fmts)):
77 print(' {}: {}'.format(f, fmts[f][0]))
1818 ('ulm', 'ase.io.ulm'),
1919 ('find', 'ase.cli.find'),
2020 ('nomad-upload', 'ase.cli.nomad'),
21 ('convert', 'ase.cli.convert'),
22 ('reciprocal', 'ase.cli.reciprocal'),
2123 ('completion', 'ase.cli.completion')]
2224
2325
4850 parsers[command] = subparser
4951
5052 if hook:
51 args = hook(parser)
53 args = hook(parser, args)
5254 else:
5355 args = parser.parse_args(args)
5456
0 from __future__ import print_function
1 import numpy as np
2
3 from ase.io import read
4 from ase.geometry import crystal_structure_from_cell
5 from ase.dft.kpoints import (get_special_points, special_paths,
6 parse_path_string, labels_from_kpts,
7 get_monkhorst_pack_size_and_offset)
8 from ase.dft.bz import bz1d_plot, bz2d_plot, bz3d_plot
9
10
11 class CLICommand:
12 short_description = 'Show the reciprocal space'
13
14 @staticmethod
15 def add_arguments(parser):
16 add = parser.add_argument
17 add('name', metavar='input-file')
18 add('output', nargs='?')
19 add('-v', '--verbose', action='store_true')
20 add('-p', '--path', nargs='?', type=str, const='default',
21 help='Add a band path. Example: "GXL".')
22 add('-d', '--dimension', type=int, default=3,
23 help='Dimension of the cell.')
24 add('--no-vectors', action='store_true',
25 help="Don't show reciprocal vectors.")
26 kp = parser.add_mutually_exclusive_group(required=False)
27 kp.add_argument('-k', '--k-points', action='store_true',
28 help='Add k-points of the calculator.')
29 kp.add_argument('-i', '--ibz-k-points', action='store_true',
30 help='Add irreducible k-points of the calculator.')
31
32 @staticmethod
33 def run(args, parser):
34 atoms = read(args.name)
35
36 cell = atoms.get_cell()
37 icell = atoms.get_reciprocal_cell()
38
39 try:
40 cs = crystal_structure_from_cell(cell)
41 except ValueError:
42 cs = None
43
44 if args.verbose:
45 if cs:
46 print('Crystal:', cs)
47 print('Special points:', special_paths[cs])
48 print('Lattice vectors:')
49 for i, v in enumerate(cell):
50 print('{}: ({:16.9f},{:16.9f},{:16.9f})'.format(i + 1, *v))
51 print('Reciprocal vectors:')
52 for i, v in enumerate(icell):
53 print('{}: ({:16.9f},{:16.9f},{:16.9f})'.format(i + 1, *v))
54
55 # band path
56 if args.path:
57 if args.path == 'default':
58 args.path = special_paths[cs]
59 paths = []
60 special_points = get_special_points(cell)
61 for names in parse_path_string(args.path):
62 points = []
63 for name in names:
64 points.append(np.dot(icell.T, special_points[name]))
65 paths.append((names, points))
66 else:
67 paths = None
68
69 # k points
70 points = None
71 if atoms.calc is not None and hasattr(atoms.calc, 'get_bz_k_points'):
72 bzk = atoms.calc.get_bz_k_points()
73 if args.path is None:
74 try:
75 size, offset = get_monkhorst_pack_size_and_offset(bzk)
76 except ValueError:
77 # This was not a MP-grid. Must be a path in the BZ:
78 args.path = ''.join(labels_from_kpts(bzk, cell)[2])
79
80 if args.k_points:
81 points = bzk
82 elif args.ibz_k_points:
83 points = atoms.calc.get_ibz_k_points()
84 if points is not None:
85 for i in range(len(points)):
86 points[i] = np.dot(icell.T, points[i])
87
88 # get the correct backend
89 if not args.output:
90 import matplotlib
91 matplotlib.use('Qt4Agg')
92 import matplotlib.pyplot as plt
93
94 kwargs = {'cell': cell,
95 'vectors': not args.no_vectors,
96 'paths': paths,
97 'points': points}
98 if args.dimension == 1:
99 bz1d_plot(**kwargs)
100 elif args.dimension == 2:
101 bz2d_plot(**kwargs)
102 else:
103 bz3d_plot(interactive=True, **kwargs)
104
105 if args.output:
106 plt.savefig(args.output)
107 else:
108 plt.show()
77 """Collection of atomic configurations and associated data.
88
99 Example of use:
10
10
1111 >>> from ase.collections import s22
1212 >>> len(s22)
1313 22
2323 """
2424 def __init__(self, name):
2525 """Create a collection lazily.
26
26
2727 Will read data from json file when needed.
28
28
2929 A collection can be iterated over to get the Atoms objects and indexed
3030 with names to get individual members.
3131
3232 Attributes:
33
33
3434 name: str
3535 Name of collection.
3636 data: dict
4040 names: list
4141 Names of configurations in the collection.
4242 """
43
43
4444 self.name = name
4545 self._names = []
4646 self._systems = {}
4747 self._data = {}
4848 self.filename = op.join(op.dirname(__file__), name + '.json')
49
49
5050 def __getitem__(self, name):
5151 self._read()
5252 return self._systems[name].copy()
5353
54 def has(self, name):
55 # Not __contains__() because __iter__ yields the systems.
56 self._read()
57 return name in self._systems
58
5459 def __iter__(self):
5560 for name in self.names:
5661 yield self[name]
57
62
5863 def __len__(self):
5964 return len(self.names)
60
65
6166 def __str__(self):
6267 return '<{0}-collection, {1} systems: {2}, {3}, ...>'.format(
6368 self.name, len(self), *self.names[:2])
64
69
6570 def __repr__(self):
6671 return 'Collection({0!r})'.format(self.name)
67
72
6873 @property
6974 def names(self):
7075 self._read()
7176 return list(self._names)
72
77
7378 @property
7479 def data(self):
7580 self._read()
7681 return self._data
77
82
7883 def _read(self):
7984 if self._names:
8085 return
66
77 __all__ = ['FixCartesian', 'FixBondLength', 'FixedMode', 'FixConstraintSingle',
88 'FixAtoms', 'UnitCellFilter', 'FixScaled', 'StrainFilter',
9 'FixedPlane', 'Filter', 'FixConstraint', 'FixedLine',
9 'FixedPlane', 'Filter', 'FixConstraint', 'FixedLine',
1010 'FixBondLengths', 'FixInternals', 'Hookean', 'ExternalForce']
1111
1212
217217 Ignored"""
218218 self.pairs = np.asarray(pairs)
219219 self.tolerance = tolerance
220 self.bondlengths = bondlengths
220 self.bondlengths = bondlengths
221221
222222 self.removed_dof = len(pairs)
223223
282282
283283 def initialize_bond_lengths(self, atoms):
284284 bondlengths = np.zeros(len(self.pairs))
285
285
286286 for i, ab in enumerate(self.pairs):
287287 bondlengths[i] = atoms.get_distance(ab[0], ab[1], mic=True)
288288
918918 elif self._type == 'point':
919919 p1 = positions[self.index]
920920 p2 = self.origin
921 displace = p2 - p1
921 displace = find_mic([p2 -p1], atoms.cell, atoms._pbc)[0][0]
922922 bondlength = np.linalg.norm(displace)
923923 if bondlength > self.threshold:
924924 magnitude = self.spring * (bondlength - self.threshold)
948948 elif self._type == 'point':
949949 p1 = positions[self.index]
950950 p2 = self.origin
951 displace = p2 - p1
951 displace = find_mic([p2 -p1], atoms.cell, atoms._pbc)[0][0]
952952 bondlength = np.linalg.norm(displace)
953953 if bondlength > self.threshold:
954954 return 0.5 * self.spring * (bondlength - self.threshold)**2
10621062
10631063 If a Trajectory tries to save this object, it will instead
10641064 save the underlying Atoms object. To prevent this, override
1065 the _images_ method.
1065 the iterimages method.
10661066 """
10671067
10681068 self.atoms = atoms
10821082 self.index = np.asarray(indices, int)
10831083 self.n = len(self.index)
10841084
1085 def _images_(self):
1085 def iterimages(self):
10861086 # Present the real atoms object to Trajectory and friends
1087 return self.atoms._images_()
1087 return self.atoms.iterimages()
10881088
10891089 def get_cell(self):
10901090 """Returns the computational cell.
14521452
14531453 def get_forces(self, apply_constraint=False):
14541454 '''
1455 returns an array with shape (natoms+2,3) of the atomic forces
1455 returns an array with shape (natoms+3,3) of the atomic forces
14561456 and unit cell stresses.
14571457
14581458 the first natoms rows are the forces on the atoms, the last
14621462
14631463 atoms_forces = self.atoms.get_forces()
14641464 stress = self.atoms.get_stress()
1465 self.stress = voigt_6_to_full_3x3_stress(stress) * self.mask
14661465
14671466 volume = self.atoms.get_volume()
14681467 virial = -volume * voigt_6_to_full_3x3_stress(stress)
14861485 forces = np.zeros((natoms + 3, 3))
14871486 forces[:natoms] = atoms_forces
14881487 forces[natoms:] = virial / self.cell_factor
1488
1489 self.stress = -full_3x3_to_voigt_6_stress(virial)/volume
14891490 return forces
14901491
14911492 def get_stress(self):
4242 from ase.visualize import view
4343 from ase import Atoms
4444 from ase.calculators.calculator import kptdensity2monkhorstpack
45 from ase.utils import FileNotFoundError
4645
4746
4847 # Every client-connetions gets one of these tuples:
6362 databases = {}
6463 home = '' # link to homepage
6564 open_ase_gui = True # click image to open ASE's GUI
65 download_button = True
6666
6767 # List of (project-name, title) tuples (will be filled in at run-time):
6868 projects = []
9191 next_con_id = 1
9292 connections = {}
9393
94 tmpdir = tempfile.mkdtemp() # used to cache png-files
95
9694 if 'ASE_DB_APP_CONFIG' in os.environ:
9795 app.config.from_envvar('ASE_DB_APP_CONFIG')
9896 connect_databases(app.config['ASE_DB_NAMES'])
9997 home = app.config['ASE_DB_HOMEPAGE']
98 tmpdir = app.config['ASE_DB_TMPDIR']
99 download_button = app.config['ASE_DB_DOWNLOAD']
100100 open_ase_gui = False
101 try:
102 os.unlink('tmpdir')
103 except FileNotFoundError:
104 pass
105 os.symlink(tmpdir, 'tmpdir')
101 else:
102 tmpdir = tempfile.mkdtemp() # used to cache png-files
106103
107104 # Find numbers in formulas so that we can convert H2O to H<sub>2</sub>O:
108105 SUBSCRIPT = re.compile(r'(\d+)')
131128 except ValueError:
132129 cid = 0
133130 con = connections.get(cid)
134 with open(op.join(tmpdir, '{:02}.error'.format(errors % 100)), 'w') as fd:
131 with open(op.join(tmpdir, '{:02}.err'.format(errors % 100)), 'w') as fd:
135132 print(repr((errors, con, e, request)), file=fd)
136133 if hasattr(e, '__traceback__'):
137134 traceback.print_tb(e.__traceback__, file=fd)
277274 nrows=nrows,
278275 addcolumns=addcolumns,
279276 row1=page * limit + 1,
280 row2=min((page + 1) * limit, nrows))
277 row2=min((page + 1) * limit, nrows),
278 download_button=download_button)
281279
282280
283281 @app.route('/image/<name>')
382380 return data, '{0}.xyz'.format(id)
383381
384382
385 @app.route('/json')
386 @download
387 def jsonall():
388 con_id = int(request.args['x'])
389 con = connections[con_id]
390 data = tofile(con.project, con.query[2], 'json', con.limit)
391 return data, 'selection.json'
383 if download_button:
384 @app.route('/json')
385 @download
386 def jsonall():
387 con_id = int(request.args['x'])
388 con = connections[con_id]
389 data = tofile(con.project, con.query[2], 'json', con.limit)
390 return data, 'selection.json'
392391
393392
394393 @app.route('/json/<int:id>')
399398 return data, '{0}.json'.format(id)
400399
401400
402 @app.route('/sqlite')
403 @download
404 def sqliteall():
405 con_id = int(request.args['x'])
406 con = connections[con_id]
407 data = tofile(con.project, con.query[2], 'db', con.limit)
408 return data, 'selection.db'
401 if download_button:
402 @app.route('/sqlite')
403 @download
404 def sqliteall():
405 con_id = int(request.args['x'])
406 con = connections[con_id]
407 data = tofile(con.project, con.query[2], 'db', con.limit)
408 return data, 'selection.db'
409409
410410
411411 @app.route('/sqlite/<int:id>')
2222 class CLICommand:
2323 short_description = 'Manipulate and query ASE database'
2424
25 description = """Selection is a comma-separated list of
25 description = """Query is a comma-separated list of
2626 selections where each selection is of the type "ID", "key" or
2727 "key=value". Instead of "=", one can also use "<", "<=", ">=", ">"
2828 and "!=" (these must be protected from the shell by using quotes).
9797 help='Use metadata from a Python file.')
9898 add('--unique', action='store_true',
9999 help='Give rows a new unique id when using --insert-into.')
100 add('--strip-data', action='store_true',
101 help='Strip data when using --insert-into.')
100102
101103 @staticmethod
102104 def run(args):
179181 nkvp += len(kvp)
180182 if args.unique:
181183 row['unique_id'] = '%x' % randint(16**31, 16**32 - 1)
182 db2.write(row, data=row.get('data'), **kvp)
184 if args.strip_data:
185 db2.write(row.toatoms(), **kvp)
186 else:
187 db2.write(row, data=row.get('data'), **kvp)
183188 nrows += 1
184189
185190 out('Added %s (%s updated)' %
2929 if value == '-':
3030 kvp[key] = np.nan
3131
32 con2.write(row, data=row.get('data'), **kvp)
32 atoms = row.toatoms()
33 if opts.remove_constrints:
34 atoms.constraints = []
35 con2.write(atoms, data=row.get('data'), **kvp)
3336
3437 assert row is not None, 'Your database is empty!'
3538
4851 action='store_true')
4952 parser.add_option('-N', '--convert-minus-to-not-a-number',
5053 action='store_true')
54 parser.add_option('-C', '--remove-constraints',
55 action='store_true')
5156 opts, args = parser.parse_args()
5257 for name in args:
5358 convert(name, opts)
1212 from ase.calculators.calculator import all_properties, all_changes
1313 from ase.data import atomic_numbers
1414 from ase.parallel import world, DummyMPI, parallel_function, parallel_generator
15 from ase.utils import Lock, basestring
15 from ase.utils import Lock, basestring, PurePath
1616
1717
1818 T2000 = 946681200.0 # January 1. 2000
2727 'calculator': ('Calculator', 'ASE-calculator name', ''),
2828 'energy': ('Energy', 'Total energy', 'eV'),
2929 'fmax': ('Maximum force', '', 'eV/Ang'),
30 'smax': ('Maximum stress', '', '`\\text{eV/Ang}^3`'),
31 'pbc': ('PBC', 'Periodic boundary conditions', ''),
3032 'charge': ('Charge', '', '|e|'),
3133 'mass': ('Mass', '', 'au'),
3234 'magmom': ('Magnetic moment', '', 'au'),
148150
149151 if not append and world.rank == 0 and os.path.isfile(name):
150152 os.remove(name)
153
154 if isinstance(name, PurePath):
155 name = str(name)
156
157 if type != 'postgresql' and isinstance(name, basestring):
158 name = os.path.abspath(name)
151159
152160 if type == 'json':
153161 from ase.db.jsondb import JSONDatabase
229229 results[prop] = self[prop]
230230 if results:
231231 atoms.calc = SinglePointCalculator(atoms, **results)
232 atoms.calc.name = self.calculator
232 atoms.calc.name = self.get('calculator', 'unknown')
233233
234234 if add_additional_information:
235235 atoms.info = {}
1414
1515 from __future__ import absolute_import, print_function
1616 import json
17 import numbers
1718 import os
1819 import sqlite3
1920 import sys
288289 text_key_values = []
289290 number_key_values = []
290291 for key, value in key_value_pairs.items():
291 if isinstance(value, (float, int, np.bool_)):
292 if isinstance(value, (numbers.Real, np.bool_)):
292293 number_key_values.append([key, float(value), id])
293294 else:
294295 assert isinstance(value, basestring)
3232 }
3333
3434 #rowentry {background-color: #FFFFFF;}
35 #rowentry:hover {background-color: #DDDDDD;
36 cursor: pointer}
35 #rowentry:hover {background-color: #DDDDDD;}
36 tr.rowentry > td > a {
37 color: #000000;
38 text-decoration: none;
39 display: block;
40 width: 100%;
41 height: 100%;
42 }
100100 block = (title, rows)
101101 else:
102102 continue
103 elif block.endswith('.png'):
103 elif any(block.endswith(ext) for ext in ['.png', '.csv']):
104104 name = op.join(tmpdir, prefix + block)
105105 if not op.isfile(name):
106106 self.create_figures(row, prefix, tmpdir,
108108 if op.getsize(name) == 0:
109109 # Skip empty files:
110110 block = None
111 elif block.endswith('.csv'):
112 block = read_csv_table(name)
113 else:
114 assert block in ['ATOMS', 'CELL', 'FORCES'], block
111115
112116 newcolumn.append(block)
113117 if block is not None:
183187 if op.isfile(block) and op.getsize(block) > 0:
184188 print(block)
185189 print()
190 elif block.endswith('.csv'):
191 if op.isfile(block) and op.getsize(block) > 0:
192 with open(block) as f:
193 print(f.read())
194 print()
186195 elif block == 'CELL':
187196 print('Unit cell in Ang:')
188197 print('axis|periodic| x| y| z')
213222
214223 if self.data:
215224 print('Data:', self.data, '\n')
225
226
227 def read_csv_table(name):
228 with open(name) as f:
229 title = f.readline()[1:].strip()
230 return (title, [line.rsplit(',', 2) for line in f])
2424 def cutlist(lst, length):
2525 if len(lst) <= length or length == 0:
2626 return lst
27 return lst[:9] + ['... ({0} more)'.format(len(lst) - 9)]
27 return lst[:9] + ['... ({} more)'.format(len(lst) - 9)]
2828
2929
3030 class Table:
8282 L.append([len(c) for c in self.columns])
8383 N = np.max(L, axis=0)
8484
85 fmt = '{0:{align}{width}}'
85 fmt = '{:{align}{width}}'
8686 print('|'.join(fmt.format(c, align='<>'[a], width=w)
8787 for c, a, w in zip(self.columns, self.right, N)))
8888 for row in self.rows:
9797
9898 if self.limit and nrows == self.limit:
9999 n = self.connection.count(query)
100 print('Rows:', n, '(showing first {0})'.format(self.limit))
100 print('Rows:', n, '(showing first {})'.format(self.limit))
101101 else:
102102 print('Rows:', nrows)
103103
143143 numbers.add(column)
144144 elif isinstance(value, float):
145145 numbers.add(column)
146 value = '{0:.3f}'.format(value)
146 value = '{:.3f}'.format(value)
147147 elif value is None:
148148 value = ''
149149 self.strings.append(value)
3333 </li>
3434
3535 <li>
36 <a href="{{ home }}{{ project }}/{{ project }}.html">About</a>
36 <a href="{{ home }}{{ project }}/{{ project }}.html">More information</a>
3737 </li>
3838 {% endif %}
3939
116116 <tbody>
117117 {% for key, value, unit in rows %}
118118 <tr>
119 <td> {{ key }} </td>
119 <td> {{ key|safe }} </td>
120120 <td class="text-center"> {{ value|safe }} </td>
121121 <td class="text-center"> {{ unit|safe }} </td>
122122 </tr>
6161 {% endif %}
6262 {% endwith %}
6363 <small lcass="form-text text-muted">
64 <a data-toggle="collapse" href="#collapse1">Show all keys ...</a>
64 <a data-toggle="collapse" href="#collapse1">Toggle list of keys ...</a>
6565 </small><br/>
6666 <div id="collapse1" class="collapse">
6767 <table class="table table-striped">
8686 </div>
8787
8888 <div class="col-xs-6">
89
89 {% if download_button %}
9090 <div class="btn-group pull-right">
9191 <button type="button" class="btn btn-default dropdown-toggle btn-sm" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
9292 Download <span class="caret"></span>
9696 <li><a href="/json?x={{ x }}">JSON file</a></li>
9797 </ul>
9898 </div>
99
99 {% endif %}
100100 <div class="btn-group pull-right">
101101 <button type="button" class="btn btn-default dropdown-toggle btn-sm" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
102102 Add Column <span class="caret"></span>
165165
166166 {% for row in t.rows -%}
167167
168 <tr id="rowentry" onclick="document.location.href = '/id/{{ row.dct.id }}?project={{ project }}';">
168 <tr id="rowentry" class="rowentry">
169169 {%- autoescape false -%}
170170 {%- for s in row.strings -%}
171171 {% if s != "" %}
172 <td class="text-center">{{ s }}</td>
172 <td class="text-center"><a href='/id/{{ row.dct.id }}?project={{ project }}'>{{ s }}</a></td>
173173 {% else %}
174 <td class="text-center"> - </td>
174 <td class="text-center"><a href='/id/{{ row.dct.id }}?project={{ project }}'> - </a></td>
175175 {% endif %}
176176 {% endfor %}
177177 {% endautoescape %}
241241 {% set key, text = control[1:] %}
242242 {% set choise = con.query[1][key] %}
243243 {{ text }}:<select name="bool_{{ key }}">
244 <option value="" {% if '' == choise %} selected {% endif %}>NA</option>
244 <option value="" {% if '' == choise %} selected {% endif %}>-</option>
245245 <option value="1" {% if '1' == choise %} selected {% endif %}>Yes</option>
246246 <option value="0" {% if '0' == choise %} selected {% endif %}>No</option>
247247 </select>
4141 kd = default_key_descriptions.copy()
4242 kd.update(meta['key_descriptions'])
4343 meta['key_descriptions'] = kd
44 for key, value in kd.items():
45 if not value[1]:
46 kd[key] = (value[0], value[0], value[2])
44
45 # Long description may be missing:
46 for key, (short, long, unit) in kd.items():
47 if not long:
48 kd[key] = (short, short, unit)
4749
4850 sk = []
4951 for special in meta['special_keys']:
116116 def plot_with_colors(self, ax=None, emin=-10, emax=5, filename=None,
117117 show=None, energies=None, colors=None,
118118 ylabel=None, clabel='$s_z$', cmin=-1.0, cmax=1.0,
119 sortcolors=False, loc=None):
119 sortcolors=False, loc=None, s=2):
120120 """Plot band-structure with colors."""
121121
122122 import matplotlib.pyplot as plt
133133 xcoords = xcoords.ravel()[perm].reshape(shape)
134134
135135 for e_k, c_k, x_k in zip(energies, colors, xcoords):
136 things = ax.scatter(x_k, e_k, c=c_k, s=2,
136 things = ax.scatter(x_k, e_k, c=c_k, s=s,
137137 vmin=cmin, vmax=cmax)
138138
139139 cbar = plt.colorbar(things)
150150
151151 def pretty(kpt):
152152 if kpt == 'G':
153 kpt = r'\Gamma'
153 kpt = r'$\Gamma$'
154154 elif len(kpt) == 2:
155 kpt = kpt[0] + '_' + kpt[1]
156 return '$' + kpt + '$'
155 kpt = kpt[0] + '$_' + kpt[1] + '$'
156 return kpt
157157
158158 emin += self.reference
159159 emax += self.reference
177177 ax.set_xticklabels(labels)
178178 ax.axis(xmin=0, xmax=self.xcoords[-1], ymin=emin, ymax=emax)
179179 ax.set_ylabel(ylabel)
180 ax.axhline(self.reference, color='k')
180 ax.axhline(self.reference, color='k', ls=':')
181181 self.ax = ax
182182 return ax
183183
8787 elif spin is None:
8888 gap, k1, n1, k2, n2 = find_gap(N_sk, ev_sk.ravel(), ec_sk.ravel(),
8989 direct)
90 if direct:
91 # Check also spin flips:
92 for s in [0, 1]:
93 g, k, n, _, _ = find_gap(N_sk, ev_sk[s], ec_sk[1 - s], direct)
94 if g < gap:
95 gap = g
96 k1 = k
97 n1 = n
98 k2 = k + nk
99 n2 = n + 1
100
90101 if gap > 0.0:
91102 s1, k1 = divmod(k1, nk)
92103 s2, k2 = divmod(k2, nk)
93104 else:
94105 s1 = None
95106 s2 = None
107
96108 else:
97109 gap, k1, n1, k2, n2 = find_gap(N_sk[spin:spin + 1], ev_sk[spin],
98110 ec_sk[spin], direct)
114126 p('No gap!')
115127 elif direct:
116128 p('Direct gap: {:.3f} eV'.format(gap))
117 p('Transition at:', skn(s1, k1, n1))
129 if s1 == s2:
130 p('Transition at:', skn(s1, k1, n1))
131 else:
132 p('Transition at:', skn('{}->{}'.format(s1, s2), k1, n1))
118133 else:
119134 p('Gap: {:.3f} eV'.format(gap))
120135 p('Transition (v -> c):')
0 from math import pi, sin, cos
1 import numpy as np
2
3
4 def bz_vertices(icell):
5 from scipy.spatial import Voronoi
6 I = (np.indices((3, 3, 3)) - 1).reshape((3, 27))
7 G = np.dot(icell.T, I).T
8 vor = Voronoi(G)
9 bz1 = []
10 for vertices, points in zip(vor.ridge_vertices, vor.ridge_points):
11 if -1 not in vertices and 13 in points:
12 normal = G[points].sum(0)
13 normal /= (normal**2).sum()**0.5
14 bz1.append((vor.vertices[vertices], normal))
15 return bz1
16
17
18 def bz3d_plot(cell, vectors=False, paths=None, points=None,
19 elev=None, scale=1, interactive=False):
20 import matplotlib.pyplot as plt
21 from mpl_toolkits.mplot3d import Axes3D
22 from mpl_toolkits.mplot3d import proj3d
23 from matplotlib.patches import FancyArrowPatch
24 Axes3D # silence pyflakes
25
26 class Arrow3D(FancyArrowPatch):
27 def __init__(self, xs, ys, zs, *args, **kwargs):
28 FancyArrowPatch.__init__(self, (0, 0), (0, 0), *args, **kwargs)
29 self._verts3d = xs, ys, zs
30
31 def draw(self, renderer):
32 xs3d, ys3d, zs3d = self._verts3d
33 xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
34 self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))
35 FancyArrowPatch.draw(self, renderer)
36
37 icell = np.linalg.inv(cell).T
38 kpoints = points
39 fig = plt.figure(figsize=(5, 5))
40 ax = fig.gca(projection='3d')
41
42 azim = pi / 5
43 elev = elev or pi / 6
44 x = sin(azim)
45 y = cos(azim)
46 view = [x * cos(elev), y * cos(elev), sin(elev)]
47
48 bz1 = bz_vertices(icell)
49
50 maxp = 0.0
51 for points, normal in bz1:
52 if np.dot(normal, view) < 0 and not interactive:
53 ls = ':'
54 else:
55 ls = '-'
56 x, y, z = np.concatenate([points, points[:1]]).T
57 ax.plot(x, y, z, c='k', ls=ls)
58 maxp = max(maxp, points.max())
59
60 if vectors:
61 ax.add_artist(Arrow3D([0, icell[0, 0]],
62 [0, icell[0, 1]],
63 [0, icell[0, 2]],
64 mutation_scale=20, lw=1,
65 arrowstyle='-|>', color='k'))
66 ax.add_artist(Arrow3D([0, icell[1, 0]],
67 [0, icell[1, 1]],
68 [0, icell[1, 2]],
69 mutation_scale=20, lw=1,
70 arrowstyle='-|>', color='k'))
71 ax.add_artist(Arrow3D([0, icell[2, 0]],
72 [0, icell[2, 1]],
73 [0, icell[2, 2]],
74 mutation_scale=20, lw=1,
75 arrowstyle='-|>', color='k'))
76 maxp = max(maxp, 0.6 * icell.max())
77
78 if paths is not None:
79 for names, points in paths:
80 x, y, z = np.array(points).T
81 ax.plot(x, y, z, c='r', ls='-')
82
83 for name, point in zip(names, points):
84 x, y, z = point
85 if name == 'G':
86 name = '\\Gamma'
87 elif len(name) > 1:
88 name = name[0] + '_' + name[1]
89 ax.text(x, y, z, '$' + name + '$',
90 ha='center', va='bottom', color='r')
91
92 if kpoints is not None:
93 for p in kpoints:
94 ax.scatter(p[0], p[1], p[2], c='b')
95
96 ax.set_axis_off()
97 ax.autoscale_view(tight=True)
98 s = maxp / 0.5 * 0.45 * scale
99 ax.set_xlim(-s, s)
100 ax.set_ylim(-s, s)
101 ax.set_zlim(-s, s)
102 ax.set_aspect('equal')
103
104 ax.view_init(azim=azim / pi * 180, elev=elev / pi * 180)
105
106
107 def bz2d_plot(cell, vectors=False, paths=None, points=None):
108 import matplotlib.pyplot as plt
109 # 2d in x-y plane
110 assert all(abs(cell[2][0:2]) < 1e-6) and all(abs(cell.T[2][0:2]) < 1e-6)
111
112 icell = np.linalg.inv(cell).T
113 kpoints = points
114 ax = plt.axes()
115
116 bz1 = bz_vertices(icell)
117
118 maxp = 0.0
119 for points, normal in bz1:
120 x, y, z = np.concatenate([points, points[:1]]).T
121 ax.plot(x, y, c='k', ls='-')
122 maxp = max(maxp, points.max())
123
124 if vectors:
125 ax.arrow(0, 0, icell[0, 0], icell[0, 1],
126 lw=1, color='k',
127 length_includes_head=True,
128 head_width=0.03, head_length=0.05)
129 ax.arrow(0, 0, icell[1, 0], icell[1, 1],
130 lw=1, color='k',
131 length_includes_head=True,
132 head_width=0.03, head_length=0.05)
133 maxp = max(maxp, icell.max())
134
135 if paths is not None:
136 for names, points in paths:
137 x, y, z = np.array(points).T
138 ax.plot(x, y, c='r', ls='-')
139
140 for name, point in zip(names, points):
141 x, y, z = point
142 if name == 'G':
143 name = '\\Gamma'
144 elif len(name) > 1:
145 name = name[0] + '_' + name[1]
146 if abs(z) < 1e-6:
147 ax.text(x, y, '$' + name + '$',
148 ha='center', va='bottom', color='r')
149
150 if kpoints is not None:
151 for p in kpoints:
152 ax.scatter(p[0], p[1], c='b')
153
154 ax.set_axis_off()
155 ax.autoscale_view(tight=True)
156 s = maxp * 1.05
157 ax.set_xlim(-s, s)
158 ax.set_ylim(-s, s)
159 ax.set_aspect('equal')
160
161
162 def bz1d_plot(cell, vectors=False, paths=None, points=None):
163 import matplotlib.pyplot as plt
164 # 1d in x
165 assert (all(abs(cell[2][0:2]) < 1e-6) and
166 all(abs(cell.T[2][0:2]) < 1e-6) and
167 abs(cell[0][1]) < 1e-6 and abs(cell[1][0]) < 1e-6)
168
169 icell = np.linalg.inv(cell).T
170 kpoints = points
171 ax = plt.axes()
172
173 maxp = 0.0
174 x = np.array([-0.5 * icell[0, 0], 0.5 * icell[0, 0], -0.5 * icell[0, 0]])
175 y = np.array([0, 0, 0])
176 ax.plot(x, y, c='k', ls='-')
177 maxp = icell[0, 0]
178
179 if vectors:
180 ax.arrow(0, 0, icell[0, 0], 0,
181 lw=1, color='k',
182 length_includes_head=True,
183 head_width=0.03, head_length=0.05)
184 maxp = max(maxp, icell.max())
185
186 if paths is not None:
187 for names, points in paths:
188 x, y, z = np.array(points).T
189 ax.plot(x, y, c='r', ls='-')
190
191 for name, point in zip(names, points):
192 x, y, z = point
193 if name == 'G':
194 name = '\\Gamma'
195 elif len(name) > 1:
196 name = name[0] + '_' + name[1]
197 if abs(y) < 1e-6 and abs(z) < 1e-6:
198 ax.text(x, y, '$' + name + '$',
199 ha='center', va='bottom', color='r')
200
201 if kpoints is not None:
202 for p in kpoints:
203 ax.scatter(p[0], 0, c='b')
204
205 ax.set_axis_off()
206 ax.autoscale_view(tight=True)
207 s = maxp * 1.05
208 ax.set_xlim(-s, s)
209 ax.set_ylim(-s, s)
210 ax.set_aspect('equal')
33 import numpy as np
44
55 from ase.dft.kpoints import get_monkhorst_pack_size_and_offset
6 from ase.parallel import world
67
78
89 class DOS:
119120 M = np.linalg.inv(kpts[1:, :] - kpts[0, :])
120121 except np.linalg.linalg.LinAlgError:
121122 continue
123 n = -1
122124 for i in range(I):
123125 for j in range(J):
124126 for k in range(K):
127 n += 1
128 if n % world.size != world.rank:
129 continue
125130 E = np.array([eigs[(i + a) % I, (j + b) % J, (k + c) % K]
126131 for a, b, c in indices[s]])
127132 if weights is None:
131136 (k + c) % K]
132137 for a, b, c in indices[s]])
133138 integrate(kpts, M, E, w)
139
140 world.sum(dos)
134141
135142 return dos * abs(np.linalg.det(cell))
136143
289289
290290 if latt == 'monoclinic':
291291 # Transform From Niggli to Setyawana-Curtarolo cell:
292 T = np.array([[0, 1, 0], [-1, 0, 0], [0, 0, 1]])
293 scell = np.dot(T, rcell)
294
292 a, b, c, alpha, beta, gamma = cell_to_cellpar(rcell, radians=True)
293 if abs(beta - np.pi / 2) > eps:
294 T = np.array([[0, 1, 0],
295 [-1, 0, 0],
296 [0, 0, 1]])
297 scell = np.dot(T, rcell)
298 elif abs(gamma - np.pi / 2) > eps:
299 T = np.array([[0, 0, 1],
300 [1, 0, 0],
301 [0, -1, 0]])
302 else:
303 raise ValueError('You are using a badly oriented ' +
304 'monoclinic unit cell. Please choose one with ' +
305 'either beta or gamma != pi/2')
306
307 scell = np.dot(np.dot(T, rcell), T.T)
295308 a, b, c, alpha, beta, gamma = cell_to_cellpar(scell, radians=True)
309
310 assert alpha < np.pi / 2, 'Your monoclinic angle has to be < pi / 2'
311
296312 M = np.dot(M, T.T)
297313 eta = (1 - b * cos(alpha) / c) / (2 * sin(alpha)**2)
298314 nu = 1 / 2 - eta * c * cos(alpha) / b
3535 assert not self.cell[2, :2].any() and not self.cell[:2, 2].any()
3636
3737 self.symmetries = symmetries or []
38
38
39
3940 def calculate_ldos(self, bias):
4041 """Calculate local density of states for given bias."""
4142 if self.ldos is not None and bias == self.bias:
4849 if self.use_density:
4950 self.ldos = calc.get_pseudo_density()
5051 return
51
52
5253 if bias < 0:
5354 emin = bias
5455 emax = 0.0
6465 for k in range(nkpts)]
6566 for s in range(nspins)])
6667 eigs -= calc.get_fermi_level()
67 ldos = 0.0
68 ldos = np.zeros(calc.get_pseudo_wave_function(0,0,0).shape)
69
6870 for s in range(nspins):
6971 for k in range(nkpts):
7072 for n in range(nbands):
8284 # (x,y) -> (x,-y)
8385 ldos[:, 1:] += ldos[:, :0:-1].copy()
8486 ldos[:, 1:] *= 0.5
85
87
8688 if 2 in self.symmetries:
8789 # (x,y) -> (y,x)
8890 ldos += ldos.transpose((1, 0, 2)).copy()
8991 ldos *= 0.5
90
92
9193 self.ldos = ldos
94
9295
9396 def write(self, filename='stm.pckl'):
9497 """Write local density of states to pickle file."""
9598 with open(filename, 'wb') as f:
9699 pickle.dump((self.ldos, self.bias, self.cell), f,
97100 protocol=pickle.HIGHEST_PROTOCOL)
98
101
102
99103 def get_averaged_current(self, bias, z):
100 """Calculate avarage current at height z.
104 """Calculate avarage current at height z (in Angstrom).
101105
102106 Use this to get an idea of what current to use when scanning."""
103107
112116 # Average and do linear interpolation:
113117 return ((1 - dn) * self.ldos[:, :, n].mean() +
114118 dn * self.ldos[:, :, (n + 1) % nz].mean())
115
119
120
116121 def scan(self, bias, current, z0=None, repeat=(1, 1)):
117122 """Constant current 2-d scan.
118
123
119124 Returns three 2-d arrays (x, y, z) containing x-coordinates,
120125 y-coordinates and heights. These three arrays can be passed to
121126 matplotlibs contourf() function like this:
122
127
123128 >>> import matplotlib.pyplot as plt
124129 >>> plt.gca(aspect='equal')
125130 >>> plt.contourf(x, y, z)
126131 >>> plt.show()
127
132
128133 """
129
134
130135 self.calculate_ldos(bias)
131136
132137 L = self.cell[2, 2]
147152 x, y = np.dot(ij / s0, self.cell[:2, :2]).T.reshape((2,) + s)
148153
149154 return x, y, heights
150
155
156
157 def scan2(self, bias, z, repeat=(1, 1)):
158 """Constant height 2-d scan.
159
160 Returns three 2-d arrays (x, y, I) containing x-coordinates,
161 y-coordinates and currents. These three arrays can be passed to
162 matplotlibs contourf() function like this:
163
164 >>> import matplotlib.pyplot as plt
165 >>> plt.gca(aspect='equal')
166 >>> plt.contourf(x, y, I)
167 >>> plt.show()
168
169 """
170
171 self.calculate_ldos(bias)
172
173 nz = self.ldos.shape[2]
174 ldos = self.ldos.reshape((-1, nz))
175
176 I = np.empty(ldos.shape[0])
177
178 zp = z / self.cell[2, 2] * nz
179 zp = int(zp) % nz
180
181 for i, a in enumerate(ldos):
182 I[i] = self.find_current(a, zp)
183
184 s0 = I.shape = self.ldos.shape[:2]
185 I = np.tile(I, repeat)
186 s = I.shape
187
188 ij = np.indices(s, dtype=float).reshape((2, -1)).T
189 x, y = np.dot(ij / s0, self.cell[:2, :2]).T.reshape((2,) + s)
190
191 # Returing scan with axes in Angstrom.
192 return x, y, I
193
194
151195 def linescan(self, bias, current, p1, p2, npoints=50, z0=None):
152196 """Constant current line scan.
153197
175219 q = np.dot(p, M) * shape
176220 line[i] = interpolate(q, heights)
177221 return np.linspace(0, s, npoints), line
178
179
222
223
224 def pointcurrent(self, bias, x, y, z):
225 """Current for a single x, y, z position for a given bias."""
226
227 self.calculate_ldos(bias)
228
229 nx = self.ldos.shape[0]
230 ny = self.ldos.shape[1]
231 nz = self.ldos.shape[2]
232
233 # Find grid point:
234 xp = x / np.linalg.norm(self.cell[0]) * nx
235 dx = xp - np.floor(xp)
236 xp = int(xp) % nx
237
238 yp = y / np.linalg.norm(self.cell[1]) * ny
239 dy = yp - np.floor(yp)
240 yp = int(yp) % ny
241
242 zp = z / np.linalg.norm(self.cell[2]) * nz
243 dz = zp - np.floor(zp)
244 zp = int(zp) % nz
245
246 # 3D interpolation of the LDOS at point (x,y,z) at given bias.
247 xyzldos = (((1 - dx) + (1 - dy) + (1 - dz)) * self.ldos[xp, yp, zp] +
248 dx * self.ldos[(xp + 1) % nx, yp, zp] +
249 dy * self.ldos[xp, (yp + 1) % ny, zp] +
250 dz * self.ldos[xp, yp, (zp + 1) % nz])
251
252 return dos2current(bias, xyzldos)
253
254
255 def sts(self, x, y, z, bias0, bias1, biasstep):
256 """Returns the dI/dV curve for position x, y at height z (in Angstrom),
257 for bias from bias0 to bias1 with step biasstep."""
258
259 biases = np.arange(bias0, bias1+biasstep, biasstep)
260 I = np.zeros(biases.shape)
261
262 for b in np.arange(len(biases)):
263 print(b, biases[b])
264 I[b] = self.pointcurrent(biases[b], x, y, z)
265
266 dIdV = np.gradient(I,biasstep)
267
268 return biases, I, dIdV
269
270
271 def find_current(self, ldos, z):
272 """ Finds current for given LDOS at height z."""
273 nz = self.ldos.shape[2]
274
275 zp = z / self.cell[2, 2] * nz
276 dz = zp - np.floor(zp)
277 zp = int(zp) % nz
278
279 ldosz = (1 - dz) * ldos[zp] + dz * ldos[(zp + 1) % nz]
280
281 return dos2current(self.bias, ldosz)
282
283
284 def dos2current(bias, dos):
285 # Borrowed from gpaw/analyse/simple_stm.py:
286 # The connection between density n and current I
287 # n [e/Angstrom^3] = 0.0002 sqrt(I [nA])
288 # as given in Hofer et al., RevModPhys 75 (2003) 1287
289 return 5000. * dos**2 * (1 if bias > 0 else -1)
290
291
180292 def interpolate(q, heights):
181293 qi = q.astype(int)
182294 f = q - qi
189301 g[0] * f[1] * heights[n0, m1] +
190302 f[0] * f[1] * heights[n1, m1])
191303 return z
192
193
304
305
194306 def find_height(ldos, current, h, z0=None):
195307 if z0 is None:
196308 n = len(ldos) - 2
205317
206318 c2, c1 = ldos[n:n + 2]
207319 return (n + 1 - (current - c1) / (c2 - c1)) * h
320
321
322 def delta(biases, bias, width):
323 """Return a delta-function centered at 'bias'"""
324 x = -((biases - bias) / width)**2
325 return np.exp(x) / (np.sqrt(np.pi) * width)
214214 return last_id + 1
215215
216216 def get_largest_in_db(self, var):
217 return self.c.select(sort='-{0}'.format(var)).next().get(var)
217 return next(self.c.select(sort='-{0}'.format(var))).get(var)
218218
219219 def add_unrelaxed_candidate(self, candidate, description):
220220 """ Adds a new candidate which needs to be relaxed. """
11 The class has been tested on linux and Mac OS X.
22 """
33 from subprocess import Popen, PIPE
4 import os
45 import time
56 from ase.io import write, read
67
2021 n_simul: The number of simultaneous relaxations.
2122 calc_script: Reference to the relaxation script.
2223 """
24
2325 def __init__(self, data_connection, tmp_folder,
2426 n_simul, calc_script):
2527 self.dc = data_connection
4951
5052 # Mark the structure as queued and run the external py script.
5153 self.dc.mark_as_queued(a)
54 if not os.path.isdir(self.tmp_folder):
55 os.mkdir(self.tmp_folder)
5256 fname = '{0}/cand{1}.traj'.format(self.tmp_folder,
5357 a.info['confid'])
5458 write(fname, a)
5963 """ Checks if any relaxations are done and load in the structure
6064 from the traj file. """
6165 p = Popen(['ps -x -U `whoami`'], shell=True,
62 stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
66 stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True,
67 universal_newlines=True)
6368 (_, fout) = (p.stdin, p.stdout)
6469 lines = fout.readlines()
6570 lines = [l for l in lines if l.find('defunct') == -1]
6363 unique_syms, comp = np.unique(sorted(atoms.get_chemical_symbols()),
6464 return_counts=True)
6565 l = get_layer_comps(atoms)
66 sym_dict = dict((s, np.array(c) / len(l))
66 sym_dict = dict((s, int(np.array(c) / len(l)))
6767 for s, c in zip(unique_syms, comp))
6868 for la in l:
6969 correct_by = sym_dict.copy()
5757 a2top = a2[-self.n_top:]
5858 cum_diff, max_diff = self.__compare_structure__(a1top, a2top)
5959
60 if cum_diff < self.pair_cor_cum_diff and max_diff < self.pair_cor_max:
61 return True
60 return (cum_diff < self.pair_cor_cum_diff
61 and max_diff < self.pair_cor_max)
6262
6363 def __compare_structure__(self, a1, a2):
6464 """ Private method for calculating the structural difference. """
8282 total_cum_diff += cum_diff / t_size * ntype / float(len(numbers))
8383 return (total_cum_diff, max_diff)
8484
85
85
8686 class SequentialComparator(object):
8787 """Use more than one comparison class and test them all in sequence.
88
88
8989 Supply a list of integers if for example two comparison tests both
9090 need to be positive if two atoms objects are truly equal.
9191 Ex:
102102 if not isinstance(logics, list):
103103 logics = [logics]
104104 assert len(logics) == len(methods)
105
105
106106 self.methods = []
107107 self.logics = []
108108 for m, l in zip(methods, logics):
109109 if hasattr(m, 'looks_like'):
110110 self.methods.append(m)
111111 self.logics.append(l)
112
112
113113 def looks_like(self, a1, a2):
114114 mdct = dict((l, []) for l in self.logics)
115115 for m, l in zip(self.methods, self.logics):
116116 mdct[l].append(m)
117
117
118118 for methods in mdct.values():
119119 for m in methods:
120120 if not m.looks_like(a1, a2):
122122 else:
123123 return True
124124 return False
125
126
125
126
127127 class StringComparator(object):
128128 """Compares the calculated hash strings. These strings should be stored
129129 in atoms.info['key_value_pairs'][key1] and
133133 """
134134 def __init__(self, *keys):
135135 self.keys = keys
136
136
137137 def looks_like(self, a1, a2):
138138 for k in self.keys:
139139 if a1.info['key_value_pairs'][k] == a2.info['key_value_pairs'][k]:
140140 return True
141141 return False
142
143
142
143
144144 class EnergyComparator(object):
145145 """Compares the energy of the supplied atoms objects using
146146 get_potential_energy().
147
147
148148 Parameters:
149
149
150150 dE: the difference in energy below which two energies are
151151 deemed equal.
152152 """
153153 def __init__(self, dE=0.02):
154154 self.dE = dE
155
155
156156 def looks_like(self, a1, a2):
157157 dE = abs(a1.get_potential_energy() - a2.get_potential_energy())
158158 if dE >= self.dE:
159159 return False
160160 else:
161161 return True
162
163
162
163
164164 class RawScoreComparator(object):
165165 """Compares the raw_score of the supplied individuals
166166 objects using a1.info['key_value_pairs']['raw_score'].
167
167
168168 Parameters:
169
169
170170 dist: the difference in raw_score below which two
171171 scores are deemed equal.
172172 """
173173 def __init__(self, dist=0.02):
174174 self.dist = dist
175
175
176176 def looks_like(self, a1, a2):
177177 d = abs(get_raw_score(a1) - get_raw_score(a2))
178178 if d >= self.dist:
180180 else:
181181 return True
182182
183
183
184184 class NoComparator(object):
185185 """Returns False always. If you don't want any comparator."""
186186 def looks_like(self, *args):
187187 return False
188
189
188
189
190190 class AtomsComparator(object):
191191 """Compares the Atoms objects directly."""
192192 def looks_like(self, a1, a2):
22 case the relaxation went wrong. """
33 from ase.ga.data import DataConnection
44 from optparse import OptionParser
5
6 try:
7 input = raw_input # Python 2+3 compatibility
8 except NameError:
9 pass
510
611 parser = OptionParser(
712 description='Show which structures are queued, but not done')
2833 for ni in l:
2934 s += '%d ' % ni
3035 else:
31 s = raw_input('Choose which you want to requeue or type Q to quit: ')
36 s = input('Choose which you want to requeue or type Q to quit: ')
3237 if s.find('Q') != -1:
3338 exit()
3439 iline = s.split()
22 is_orthorhombic, orthorhombic)
33 from ase.geometry.geometry import (wrap_positions,
44 get_layers, find_mic,
5 get_duplicate_atoms)
5 get_duplicate_atoms,
6 get_angles, get_distances)
67 from ase.geometry.distance import distance
78
89
1011 'is_orthorhombic', 'orthorhombic',
1112 'get_layers', 'find_mic', 'get_duplicate_atoms',
1213 'cell_to_cellpar', 'cellpar_to_cell',
13 'crystal_structure_from_cell', 'distance']
14 'crystal_structure_from_cell', 'distance',
15 'get_angles', 'get_distances']
170170 elif abs(angles - pi / 2).max() < eps:
171171 return 'orthorhombic'
172172 elif (abs(a - b) < eps and
173 abs(gamma - pi / 3 * 2) < eps and
173 (abs(gamma - pi / 3 * 2) < eps or abs(gamma - pi / 3) < eps) and
174174 abs(angles[:2] - pi / 2).max() < eps):
175175 return 'hexagonal'
176 elif (c >= a and c >= b and beta > pi / 2 and
177 abs(angles[::2] - pi / 2).max() < eps):
176 elif (abs(angles - pi / 2) > eps).sum() == 1:
178177 return 'monoclinic'
179178 elif (abc.ptp() < eps and angles.ptp() < eps and
180179 np.abs(angles).max() < pi / 2):
66 different orientations.
77 - detection of duplicate atoms / atoms within cutoff radius
88 """
9
10 from math import pi
911
1012 import numpy as np
1113
190192 return D_min, D_min_len
191193
192194
195 def get_angles(v1, v2, cell=None, pbc=None):
196 """Get angles formed by two lists of vectors.
197
198 calculate angle in degrees between vectors v1 and v2
199
200 Set a cell and pbc to enable minimum image
201 convention, otherwise angles are taken as-is.
202 """
203
204 f = 180 / pi
205
206 # Check if using mic
207 if cell is not None or pbc is not None:
208 if cell is None or pbc is None:
209 raise ValueError("cell or pbc must be both set or both be None")
210
211 v1 = find_mic(v1, cell, pbc)[0]
212 v2= find_mic(v2, cell, pbc)[0]
213
214
215 v1 /= np.linalg.norm(v1, axis=1)[:, np.newaxis]
216 v2 /= np.linalg.norm(v2, axis=1)[:, np.newaxis]
217
218 angles = np.arccos(np.einsum('ij,ij->i', v1, v2))
219
220 return angles * f
221
222
223 def get_distances(p1, p2=None, cell=None, pbc=None):
224 """Return distance matrix of every position in p1 with every position in p2
225
226 if p2 is not set, it is assumed that distances between all positions in p1
227 are desired. p2 will be set to p1 in this case.
228
229 Use set cell and pbc to use the minimum image convention.
230 """
231 if p2 is None:
232 p2 = p1
233
234 p1, p2 = np.array(p1), np.array(p2)
235
236 # Allocate matrix for vectors as [p1, p2, 3]
237 D = np.zeros((len(p1), len(p2), 3))
238
239 for offset, pos1 in enumerate(p1):
240 D[offset, :, :] = p2 - pos1
241
242 # Collapse to linear indexing
243 D.shape = (-1, 3)
244
245 # Check if using mic
246 if cell is not None or pbc is not None:
247 if cell is None or pbc is None:
248 raise ValueError("cell or pbc must be both set or both be None")
249
250 D, D_len = find_mic(D, cell, pbc)
251 else:
252 D_len = np.sqrt((D**2).sum(1))
253
254 # Expand back to matrix indexing
255 D.shape = (-1, len(p2), 3)
256 D_len.shape = (-1, len(p2))
257
258 return D, D_len
259
260
193261 def get_duplicate_atoms(atoms, cutoff=0.1, delete=False):
194262 """Get list of duplicate atoms and delete them if requested.
195263
0 # encoding: utf-8
01 from __future__ import unicode_literals
2
3 import os
4 import numpy as np
5
16 from ase.gui.i18n import _
2
7 from ase import Atoms
38 import ase.gui.ui as ui
4 from ase.gui.widgets import Element
5
6
7 def txt2pos(txt):
8 try:
9 x, y, z = (float(x) for x in txt.split(','))
10 except ValueError as ex:
11 ui.error(_('Bad position'), ex)
12 else:
13 return x, y, z
9 from ase.data import atomic_numbers, chemical_symbols
1410
1511
1612 class AddAtoms:
1713 def __init__(self, gui):
18 # XXXXXXXXXXX still array based, not Atoms-based. Will crash
19 win = ui.Window(_('Add atoms'))
20 self.element = Element()
21 win.add(self.element)
22 self.absolute_position = ui.Entry('0,0,0')
23 self.relative_position = ui.Entry('1.5,0,0')
24 win.add([_('Absolute position:'),
25 self.absolute_position,
26 ui.Button(_('Add'), self.add_absolute)])
27 win.add([_('Relative to average position (of selection):'),
28 self.relative_position,
29 ui.Button(_('Add'), self.add_relative)])
3014 self.gui = gui
15 win = self.win = ui.Window(_('Add atoms'))
16 win.add(_('Specify chemical symbol, formula, or filename.'))
3117
32 def add_absolute(self):
33 pos = txt2pos(self.absolute_position.value)
34 self.add(pos)
18 def set_molecule(value):
19 self.entry.value = value
20 self.focus()
3521
36 def add_relative(self):
37 rpos = txt2pos(self.relative_position.value)
22 def choose_file():
23 chooser = ui.ASEFileChooser(self.win.win)
24 filename = chooser.go()
25 if filename is None: # No file selected
26 return
27
28 self.entry.value = filename
29
30 # Load the file immediately, so we can warn now in case of error
31 self.readfile(filename, format=chooser.format)
32
33 self.entry = ui.Entry('', callback=self.add)
34 win.add([_('Add:'), self.entry,
35 ui.Button(_('File ...'), callback=choose_file)])
36
37 self._filename = None
38 self._atoms_from_file = None
39
40 from ase.collections import g2
41 labels = list(sorted(g2.names))
42 values = labels
43
44 box = ui.ComboBox(labels, values, callback=set_molecule)
45 win.add([_('Get molecule:'), box])
46 box.value = 'H2'
47
48 spinners = [ui.SpinBox(0.0, -1e3, 1e3, 0.1, rounding=2, width=3)
49 for __ in range(3)]
50
51 win.add([_('Coordinates:')] + spinners)
52 self.spinners = spinners
53 win.add(_('Coordinates are relative to the center of the selection, '
54 'if any, else absolute.'))
55 self.picky = ui.CheckButton(_('Check positions'), True)
56 win.add([ui.Button(_('Add'), self.add),
57 self.picky])
58 self.focus()
59
60 def readfile(self, filename, format=None):
61 if filename == self._filename:
62 # We have this file already
63 return self._atoms_from_file
64
65 from ase.io import read
66 try:
67 atoms = read(filename)
68 except Exception as err:
69 ui.show_io_error(filename, err)
70 atoms = None
71 filename = None
72
73 # Cache selected Atoms/filename (or None) for future calls
74 self._atoms_from_file = atoms
75 self._filename = filename
76 return atoms
77
78 def get_atoms(self):
79 val = self.entry.value
80
81 if val in atomic_numbers: # Note: This means val is a symbol!
82 return Atoms(val)
83
84 if val.isdigit() and int(val) < len(chemical_symbols):
85 return Atoms(numbers=[int(val)])
86
87 from ase.collections import g2
88 if val in g2.names:
89 return g2[val]
90
91 if os.path.exists(val):
92 return self.readfile(val) # May show UI error
93
94 ui.showerror(_('Cannot add atoms'),
95 _('{} is neither atom, molecule, nor file')
96 .format(val))
97
98 return None
99
100 def getcoords(self):
101 addcoords = np.array([spinner.value for spinner in self.spinners])
102
38103 pos = self.gui.atoms.positions
39 if self.gui.images.selected.any():
104 if self.gui.images.selected[:len(pos)].any():
40105 pos = pos[self.gui.images.selected[:len(pos)]]
41 if len(pos) == 0:
42 ui.error('No atoms present')
43 else:
44106 center = pos.mean(0)
45 self.add(center + rpos)
107 addcoords += center
46108
47 def add(self, pos):
48 if pos is None or self.element.symbol is None:
109 return addcoords
110
111 def focus(self):
112 self.entry.entry.focus_set()
113
114 def add(self):
115 newatoms = self.get_atoms()
116 if newatoms is None: # Error dialog was shown
49117 return
118
119 newcenter = self.getcoords()
120
121 # Not newatoms.center() because we want the same centering method
122 # used for adding atoms relative to selections (mean).
123 previous_center = newatoms.positions.mean(0)
124 newatoms.positions += newcenter - previous_center
125
50126 atoms = self.gui.atoms
51 atoms.append(self.element.symbol)
52 atoms.positions[-1] = pos
127
128 if len(atoms) and self.picky.value:
129 from ase.geometry import get_distances
130 disps, dists = get_distances(atoms.positions,
131 newatoms.positions)
132 mindist = dists.min()
133 if mindist < 0.5:
134 ui.showerror(_('Bad positions'),
135 _('Atom would be less than 0.5 Å from '
136 'an existing atom. To override, '
137 'uncheck the check positions option.'))
138 return
139
140 atoms += newatoms
141
53142 if len(atoms) > self.gui.images.maxnatoms:
54143 self.gui.images.initialize(list(self.gui.images),
55144 self.gui.images.filenames)
145
56146 self.gui.images.selected[:] = False
147
57148 # 'selected' array may be longer than current atoms
58 self.gui.images.selected[len(atoms) - 1] = True
149 self.gui.images.selected[len(atoms) - len(newatoms):len(atoms)] = True
59150 self.gui.set_frame()
60151 self.gui.draw()
00 # Copyright 2008, 2009
11 # CAMd (see accompanying license files for details).
22 from __future__ import print_function, unicode_literals
3 import warnings
34
45
56 class CLICommand:
1112 @staticmethod
1213 def add_arguments(parser):
1314 add = parser.add_argument
14 add('filenames', nargs='*')
15 add('-n', '--image-number',
16 default=':', metavar='NUMBER',
17 help='Pick image(s) from trajectory. NUMBER can be a '
18 'single number (use a negative number to count from '
19 'the back) or a range: start:stop:step, where the '
20 '":step" part can be left out - default values are '
21 '0:nimages:1.')
22 add('-u', '--show-unit-cell', type=int,
23 default=1, metavar='I',
24 help="0: Don't show unit cell. 1: Show unit cell. "
25 '2: Show all of unit cell.')
15 add('filenames', nargs='*',
16 help='Files to open. Append @SLICE to a filename to pick '
17 'a subset of images from that file. See --image-number '
18 'for SLICE syntax.')
19 add('-n', '--image-number', metavar='SLICE', default=':',
20 help='Pick individual image or slice from each of the files. '
21 'SLICE can be a number or a Python slice-like expression '
22 'such as :STOP, START:STOP, or START:STOP:STEP, '
23 'where START, STOP, and STEP are integers. '
24 'Indexing counts from 0. '
25 'Negative numbers count backwards from last image. '
26 'Using @SLICE syntax for a filename overrides this option '
27 'for that file.')
2628 add('-r', '--repeat',
2729 default='1',
2830 help='Repeat unit cell. Use "-r 2" or "-r 2,3,1".')
6163 images = Images()
6264
6365 if args.filenames:
64 from ase.io import string2index
65 images.read(args.filenames, string2index(args.image_number))
66 images.read(args.filenames, args.image_number)
6667 else:
6768 images.initialize([Atoms()])
6869
7677 images.repeat_images([int(c) for c in r])
7778
7879 if args.radii_scale:
79 images.set_radii(args.radii_scale)
80 images.scale_radii(args.radii_scale)
8081
8182 if args.output is not None:
82 images.write(args.output, rotations=args.rotations,
83 show_unit_cell=args.show_unit_cell)
83 warnings.warn('You should be using "ase convert ..." instead!')
84 images.write(args.output, rotations=args.rotations)
8485 args.terminal = True
8586
8687 if args.terminal:
9293 print()
9394 else:
9495 from ase.gui.gui import GUI
95 gui = GUI(images, args.rotations, args.show_unit_cell, args.bonds)
96 gui.run(args.graph)
96 gui = GUI(images, args.rotations, args.bonds, args.graph)
97 gui.run()
0 # encoding: utf-8
1 '''celleditor.py - Window for editing the cell of an atoms object
2 '''
3 from __future__ import division, unicode_literals
4 from ase.gui.i18n import _
5
6 import ase.gui.ui as ui
7 import numpy as np
8
9
10 class CellEditor:
11 '''Window for editing the cell of an atoms object.'''
12 def __init__(self, gui):
13 self.gui = gui
14 self.gui.register_vulnerable(self)
15
16 # Create grid control for cells
17 # xx xy xz ||x|| pbc
18 # yx yy yz ||y|| pbc
19 # zx zy zz ||z|| pbc
20 self.cell_grid = []
21 self.pbc = []
22 self.angles = []
23
24 atoms = self.gui.atoms
25
26 cell = atoms.cell
27 mags = atoms.get_cell_lengths_and_angles()[0:3]
28 angles = atoms.get_cell_lengths_and_angles()[3:6]
29 pbc = atoms.pbc
30
31 for i in [0, 1, 2]: # x_ y_ z_
32 row = []
33 for j in [0, 1, 2]: # _x _y _z
34 row.append(ui.SpinBox(cell[i][j], -30, 30, 0.1,
35 self.apply_vectors, rounding=7, width=9))
36 row.append(ui.SpinBox(mags[i], -30, 30, 0.1, self.apply_magnitudes,
37 rounding=7, width=9))
38 self.cell_grid.append(row)
39 self.pbc.append(ui.CheckButton('', bool(pbc[i]), self.apply_pbc))
40 self.angles.append(ui.SpinBox(angles[i], -360, 360, 15, self.apply_angles,
41 rounding=7, width=9))
42
43 self.scale_atoms = ui.CheckButton('', False)
44 self.vacuum = ui.SpinBox(5, 0, 15, 0.1, self.apply_vacuum)
45
46 # TRANSLATORS: This is a title of a window.
47 win = self.win = ui.Window(_('Cell Editor'))
48
49 x, y, z = self.cell_grid
50
51 win.add([_('A: '), x[0], x[1], x[2], _('||A||: '), x[3],
52 _('perodic: '), self.pbc[0]])
53 win.add([_('B: '), y[0], y[1], y[2], _('||B||: '), y[3],
54 _('perodic: '), self.pbc[1]])
55 win.add([_('C: '), z[0], z[1], z[2], _('||C||: '), z[3],
56 _('perodic: '), self.pbc[2]])
57 win.add([_('∠BC: '), self.angles[0], _('∠AC: '), self.angles[1],
58 _('∠AB: '), self.angles[2]])
59 win.add([_("Scale atoms with cell: "), self.scale_atoms])
60 win.add([ui.Button(_('Apply Vectors'), self.apply_vectors),
61 ui.Button(_('Apply Magnitudes'), self.apply_magnitudes),
62 ui.Button(_('Apply Angles'), self.apply_angles)])
63 win.add([_('Pressing <Enter> as you enter values will ' +
64 'automatically apply correctly')])
65 win.add([ui.Button(_('Center'), self.apply_center),
66 ui.Button(_('Wrap'), self.apply_wrap),
67 _('Vacuum: '), self.vacuum,
68 ui.Button(_('Apply Vacuum'), self.apply_vacuum)])
69
70 #win.add([_('\tx: '), self.x, _(' unit cells'), self.x_warn])
71 #win.add([_('\ty: '), self.y, _(' unit cells'), self.y_warn])
72 #win.add([_('\tz: '), self.z, _(' unit cells')])
73 #win.add([_('Vacuum: '), self.vacuum_check, self.vacuum, (u'Å')])
74
75 def apply_center(self, *args):
76 atoms = self.gui.atoms.copy()
77 atoms.center()
78 self.gui.new_atoms(atoms)
79
80 def apply_wrap(self, *args):
81 atoms = self.gui.atoms.copy()
82 atoms.wrap()
83 self.gui.new_atoms(atoms)
84
85 def apply_vacuum(self, *args):
86 atoms = self.gui.atoms.copy()
87
88 axis = []
89 for index, pbc in enumerate(atoms.pbc):
90 if not pbc:
91 axis.append(index)
92
93 atoms.center(vacuum=self.vacuum.value, axis=axis)
94 self.gui.new_atoms(atoms)
95
96
97 def apply_vectors(self, *args):
98 atoms = self.gui.atoms.copy()
99 x, y, z = self.cell_grid
100
101 new_cell = np.array([[x[0].value, x[1].value, x[2].value],
102 [y[0].value, y[1].value, y[2].value],
103 [z[0].value, z[1].value, z[2].value]])
104
105 atoms.set_cell(new_cell, scale_atoms=self.scale_atoms.var.get())
106 self.gui.new_atoms(atoms)
107
108 def apply_magnitudes(self, *args):
109 atoms = self.gui.atoms.copy()
110 x, y, z = self.cell_grid
111
112 old_cell = atoms.cell
113
114 old_mags = atoms.get_cell_lengths_and_angles()[0:3]
115 new_mags = np.array([x[3].value, y[3].value, z[3].value])
116
117 atoms.set_cell(old_cell / old_mags * new_mags,
118 scale_atoms=self.scale_atoms.var.get())
119
120 self.gui.new_atoms(atoms)
121
122
123 def apply_angles(self, *args):
124 atoms = self.gui.atoms.copy()
125
126 cell_data = atoms.get_cell_lengths_and_angles()
127 cell_data[3:7] = [self.angles[0].value, self.angles[1].value,
128 self.angles[2].value]
129
130 atoms.set_cell(cell_data, scale_atoms=self.scale_atoms.var.get())
131
132 self.gui.new_atoms(atoms)
133
134
135 def apply_pbc(self, *args):
136 atoms = self.gui.atoms.copy()
137
138 pbc = [pbc.var.get() for pbc in self.pbc]
139 atoms.set_pbc(pbc)
140
141 self.gui.new_atoms(atoms)
142
143
144 def notify_atoms_changed(self):
145 atoms = self.gui.atoms
146
147 cell = atoms.cell
148 mags = atoms.get_cell_lengths_and_angles()[0:3]
149 angles = atoms.get_cell_lengths_and_angles()[3:6]
150 pbc = atoms.pbc
151
152 for i in [0, 1, 2]:
153 for j in [0, 1, 2]:
154 if np.isnan(cell[i][j]):
155 cell[i][j] = 0
156 self.cell_grid[i][j].value = cell[i][j]
157
158 if np.isnan(mags[i]):
159 mags[i] = 0
160 self.cell_grid[i][3].value = mags[i]
161
162 if np.isnan(angles[i]):
163 angles[i] = 0
164 self.angles[i].value = angles[i]
165
166 self.pbc[i].var.set(bool(pbc[i]))
167
1515 self.gui = gui
1616 self.win.add(ui.Label(_('Choose how the atoms are colored:')))
1717 values = ['jmol', 'tag', 'force', 'velocity',
18 'initial charge', 'magmom']
18 'initial charge', 'magmom', 'neighbors']
1919 labels = [_('By atomic number, default "jmol" colors'),
2020 _('By tag'),
2121 _('By force'),
2222 _('By velocity'),
2323 _('By initial charge'),
24 _('By magnetic moment')]
24 _('By magnetic moment'),
25 _('By number of neighbors'),]
2526
2627 self.radio = ui.RadioButtons(labels, values, self.toggle,
2728 vertical=True)
4445 radio['velocity'].active = atoms.has('momenta')
4546 radio['initial charge'].active = atoms.has('initial_charges')
4647 radio['magmom'].active = get_magmoms(atoms).any()
48 radio['neighbors'].active = True
4749
4850 def toggle(self, value):
4951 self.gui.colormode = value
50 if value == 'jmol':
52 if value == 'jmol' or value == 'neighbors':
5153 text = ''
5254 else:
5355 scalars = np.array([self.gui.get_color_scalars(i)
0 from __future__ import unicode_literals
0 from __future__ import unicode_literals, division
11
22 import os
33 import pickle
77 import weakref
88 from functools import partial
99 from ase.gui.i18n import _
10 from time import time
1011
1112 import numpy as np
1213
13 from ase import __version__, Atoms
14 from ase import __version__
1415 import ase.gui.ui as ui
1516 from ase.gui.calculator import SetCalculator
1617 from ase.gui.crystal import SetupBulkCrystal
3536
3637 def __init__(self, images=None,
3738 rotations='',
38 show_unit_cell=True,
39 show_bonds=False):
40
41 # Try to change into directory of file you are viewing
42 try:
43 os.chdir(os.path.split(sys.argv[1])[0])
44 # This will fail sometimes (e.g. for starting a new session)
45 except:
46 pass
47
48 if not images:
49 images = Images()
50 images.initialize([Atoms()])
39 show_bonds=False, expr=None):
40
41 if not isinstance(images, Images):
42 images = Images(images)
5143
5244 self.images = images
5345
5446 self.config = read_defaults()
5547
56 menu = self.get_menu_data(show_unit_cell, show_bonds)
48 menu = self.get_menu_data(show_bonds)
5749
5850 self.window = ui.ASEGUIWindow(close=self.exit, menu=menu,
5951 config=self.config, scroll=self.scroll,
7163 self.vulnerable_windows = []
7264 self.simulation = {} # Used by modules on Calculate menu.
7365 self.module_state = {} # Used by modules to store their state.
66
7467 self.arrowkey_mode = self.ARROWKEY_SCAN
7568 self.move_atoms_mask = None
69
70 self.set_frame(len(self.images) - 1, focus=True)
71
72 # Used to move the structure with the mouse
73 self.prev_pos = None
74 self.last_scroll_time = time()
75 self.orig_scale = self.scale
76
77 if len(self.images) > 1:
78 self.movie()
79
80 if expr is None:
81 expr = self.config['gui_graphs_string']
82
83 if expr is not None and expr != '' and len(self.images) > 1:
84 self.plot_graphs(expr=expr)
7685
7786 @property
7887 def moving(self):
7988 return self.arrowkey_mode != self.ARROWKEY_SCAN
8089
81 def run(self, expr=None, test=None):
82 self.set_frame(len(self.images) - 1, focus=True)
83
84 if len(self.images) > 1:
85 self.movie()
86
87 if expr is None:
88 expr = self.config['gui_graphs_string']
89
90 if expr is not None and expr != '' and len(self.images) > 1:
91 self.plot_graphs(expr=expr)
92
90 def run(self, test=None):
9391 if test:
9492 self.window.test(test)
9593 else:
114112 self.move_atoms_mask = self.images.selected.copy()
115113
116114 self.draw()
117
118115
119116 def step(self, key):
120117 d = {'Home': -10000000,
153150 CTRL = event.modifier == 'ctrl'
154151
155152 # Bug: Simultaneous CTRL + shift is the same as just CTRL.
156 # Therefore binding Page Up / Page Dn (keycodes next/prior)
157 # to movement in Z direction.
153 # Therefore movement in Z direction does not support the
154 # shift modifier.
158155 dxdydz = {'up': (0, 1 - CTRL, CTRL),
159156 'down': (0, -1 + CTRL, -CTRL),
160157 'right': (1, 0, 0),
161 'left': (-1, 0, 0),
162 'next': (0, 0, 1),
163 'prior': (0, 0, -1)}.get(event.key, None)
158 'left': (-1, 0, 0)}.get(event.key, None)
159
160 # Get scroll direction using shift + right mouse button
161 # event.type == '6' is mouse motion, see:
162 # http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/event-types.html
163 if event.type == '6':
164 cur_pos = np.array([event.x, -event.y])
165 # Continue scroll if button has not been released
166 if self.prev_pos is None or time() - self.last_scroll_time > .5:
167 self.prev_pos = cur_pos
168 self.last_scroll_time = time()
169 else:
170 dxdy = cur_pos - self.prev_pos
171 dxdydz = np.append(dxdy, [0])
172 self.prev_pos = cur_pos
173 self.last_scroll_time = time()
164174
165175 if dxdydz is None:
166176 return
183193 self.atoms.positions[mask] = tmp_atoms.positions + center
184194 self.set_frame()
185195 else:
186 self.center -= vec
196 # The displacement vector is scaled
197 # so that the cursor follows the structure
198 # Scale by a third works for some reason
199 scale = self.orig_scale / (3 * self.scale)
200 self.center -= vec * scale
201
187202 # dx * 0.1 * self.axes[:, 0] - dy * 0.1 * self.axes[:, 1])
188203
189204 self.draw()
279294 process.stdin.close()
280295 self.graphs.append(process)
281296
297 def reciprocal(self):
298 fd, filename = tempfile.mkstemp('.xyz', 'ase.gui-')
299 os.close(fd)
300 self.images.write(filename)
301 os.system('(sleep 60; rm %s) &' % filename)
302 process = subprocess.Popen([sys.executable, '-m', 'ase', 'reciprocal',
303 filename],
304 stdin=subprocess.PIPE)
305 process.stdin.close()
306
282307 def open(self, button=None, filename=None):
283 from ase.io.formats import all_formats, get_ioformat
284
285 labels = [_('Automatic')]
286 values = ['']
287
288 def key(item):
289 return item[1][0]
290
291 for format, (description, code) in sorted(all_formats.items(),
292 key=key):
293 io = get_ioformat(format)
294 if io.read and description != '?':
295 labels.append(_(description))
296 values.append(format)
297
298 format = [None]
299
300 def callback(value):
301 format[0] = value
302
303 chooser = ui.LoadFileDialog(self.window.win, _('Open ...'))
304 ui.Label(_('Choose parser:')).pack(chooser.top)
305 formats = ui.ComboBox(labels, values, callback)
306 formats.pack(chooser.top)
308 chooser = ui.ASEFileChooser(self.window.win)
307309
308310 filename = filename or chooser.go()
311 format = chooser.format
309312 if filename:
310 self.images.read([filename], slice(None), format[0])
313 try:
314 self.images.read([filename], slice(None), format)
315 except Exception as err:
316 ui.show_io_error(filename, err)
317 return # Hmm. Is self.images in a consistent state?
311318 self.set_frame(len(self.images) - 1, focus=True)
312319
313320 def modify_atoms(self, key=None):
318325 from ase.gui.add import AddAtoms
319326 AddAtoms(self)
320327
321 def quick_info_window(self):
328 def cell_editor(self, key=None):
329 from ase.gui.celleditor import CellEditor
330 CellEditor(self)
331
332 def quick_info_window(self, key=None):
322333 from ase.gui.quickinfo import info
323 ui.Window('Quick Info').add(info(self))
334 ui.Window(_('Quick Info')).add(info(self))
324335
325336 def bulk_window(self):
326337 SetupBulkCrystal(self)
409420 os.system('(%s %s &); (sleep 60; rm %s) &' %
410421 (command, filename, filename))
411422
412 def get_menu_data(self, show_unit_cell, show_bonds):
423 def get_menu_data(self, show_bonds):
413424 M = ui.MenuItem
414425 return [
415426 (_('_File'),
423434 [M(_('Select _all'), self.select_all),
424435 M(_('_Invert selection'), self.invert_selection),
425436 M(_('Select _constrained atoms'), self.select_constrained_atoms),
426 M(_('Select _immobile atoms'), self.select_immobile_atoms,
427 key='Ctrl+I'),
428 #M('---'),
437 M(_('Select _immobile atoms'), self.select_immobile_atoms),
438 # M('---'),
429439 # M(_('_Copy'), self.copy_atoms, 'Ctrl+C'),
430440 # M(_('_Paste'), self.paste_atoms, 'Ctrl+V'),
431441 M('---'),
436446 M(_('_Add atoms'), self.add_atoms, 'Ctrl+A'),
437447 M(_('_Delete selected atoms'), self.delete_selected_atoms,
438448 'Backspace'),
449 M(_('Edit _cell'), self.cell_editor, 'Ctrl+E'),
439450 M('---'),
440451 M(_('_First image'), self.step, 'Home'),
441452 M(_('_Previous image'), self.step, 'Page-Up'),
444455
445456 (_('_View'),
446457 [M(_('Show _unit cell'), self.toggle_show_unit_cell, 'Ctrl+U',
447 value=show_unit_cell > 0),
458 value=True),
448459 M(_('Show _axes'), self.toggle_show_axes, value=True),
449460 M(_('Show _bonds'), self.toggle_show_bonds, 'Ctrl+B',
450461 value=show_bonds),
458469 _('_Magnetic Moments'), # XXX check if exist
459470 _('_Element Symbol'),
460471 _('_Initial Charges'), # XXX check if exist
461 ]),
472 ]),
462473 M('---'),
463 M(_('Quick Info ...'), self.quick_info_window),
474 M(_('Quick Info ...'), self.quick_info_window, 'Ctrl+I'),
464475 M(_('Repeat ...'), self.repeat_window, 'R'),
465476 M(_('Rotate ...'), self.rotate_window),
466477 M(_('Colors ...'), self.colors_window, 'C'),
493504 (_('_Tools'),
494505 [M(_('Graphs ...'), self.plot_graphs),
495506 M(_('Movie ...'), self.movie),
496 M(_('Expert mode ...'), self.execute, 'Ctrl+E', disabled=True),
507 M(_('Expert mode ...'), self.execute, disabled=True),
497508 M(_('Constraints ...'), self.constraints_window),
498509 M(_('Render scene ...'), self.render_window),
499510 M(_('_Move atoms'), self.toggle_move_mode, 'Ctrl+M'),
500511 M(_('_Rotate atoms'), self.toggle_rotate_mode, 'Ctrl+R'),
501512 M(_('NE_B'), self.neb),
502 M(_('B_ulk Modulus'), self.bulk_modulus)]),
513 M(_('B_ulk Modulus'), self.bulk_modulus),
514 M(_('Reciprocal space ...'), self.reciprocal)]),
503515
504516 # TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
505517 (_('_Setup'),
22
33 import numpy as np
44
5 from ase import Atoms
56 from ase.calculators.singlepoint import SinglePointCalculator
67 from ase.constraints import FixAtoms
78 from ase.data import covalent_radii
910 from ase.io import read, write, string2index
1011 from ase.gui.i18n import _
1112
13 import warnings
14
1215
1316 class Images:
1417 def __init__(self, images=None):
1518 self.covalent_radii = covalent_radii.copy()
1619 self.config = read_defaults()
1720 self.atom_scale = self.config['radii_scale']
18 if images is not None:
19 self.initialize(images)
21 if images is None:
22 images = [Atoms()]
23 self.initialize(images)
2024
2125 def __len__(self):
2226 return len(self._images)
4751 if not isinstance(c, FixAtoms)]
4852 atoms.constraints.append(FixAtoms(mask=~dynamic))
4953
54 def scale_radii(self, scaling_factor):
55 self.covalent_radii *= scaling_factor
56
5057 def get_energy(self, atoms):
5158 try:
5259 e = atoms.get_potential_energy() * self.repeat.prod()
6067 except RuntimeError:
6168 return None
6269 else:
63 return np.tile(F.T, self.repeat.prod()).T
70 return F
6471
6572 def initialize(self, images, filenames=None, init_magmom=False):
6673 nimages = len(images)
137144 self.initialize(self.images, filenames=self.filenames)
138145 return
139146
140 def read(self, filenames, index=-1, filetype=None):
147 def read(self, filenames, default_index=':', filetype=None):
148 from ase.utils import basestring
149 if isinstance(default_index, basestring):
150 default_index = string2index(default_index)
141151 images = []
142152 names = []
143153 for filename in filenames:
144 i = read(filename, index, filetype)
145
146 if not isinstance(i, list):
147 i = [i]
148 images.extend(i)
149 names.extend([filename] * len(i))
154 from ase.io.formats import parse_filename
155
156 if '.json@' in filename or '.db@' in filename:
157 # Ugh! How would one deal with this?
158 # The parse_filename and string2index somehow conspire
159 # to cause an error. See parse_filename
160 # in ase.io.formats for this particular
161 # special case. -askhl
162 #
163 # TODO Someone figure out how to see what header
164 # a JSON file should have.
165 imgs = read(filename, default_index, filetype)
166 if hasattr(imgs, 'iterimages'):
167 imgs = list(imgs.iterimages())
168 names += [filename] * len(imgs)
169 images += imgs
170 continue # Argh!
171
172 if '@' in filename:
173 actual_filename, index = parse_filename(filename, None)
174 else:
175 actual_filename, index = parse_filename(filename,
176 default_index)
177
178 imgs = read(filename, default_index, filetype)
179 if hasattr(imgs, 'iterimages'):
180 imgs = list(imgs.iterimages())
181
182 images.extend(imgs)
183
184 # Name each file as filename@index:
185 if isinstance(index, slice):
186 start = index.start or 0
187 step = index.step or 1
188 else:
189 start = index # index is just an integer
190 assert len(imgs) == 1
191 step = 1
192 for i, img in enumerate(imgs):
193 names.append('{}@{}'.format(actual_filename, start + i * step))
150194
151195 self.initialize(images, names)
196
197 def repeat_results(self, atoms, repeat=None, oldprod=None):
198 """Return a dictionary which updates the magmoms, energy and forces
199 to the repeated amount of atoms.
200 """
201 def getresult(name, get_quantity):
202 # ase/io/trajectory.py line 170 does this by using
203 # the get_property(prop, atoms, allow_calculation=False)
204 # so that is an alternative option.
205 try:
206 if (not atoms.calc or
207 atoms.calc.calculation_required(atoms, [name])):
208 quantity = None
209 else:
210 quantity = get_quantity()
211 except Exception as err:
212 quantity = None
213 errmsg = ('An error occured while retrieving {} '
214 'from the calculator: {}'.format(name, err))
215 warnings.warn(errmsg)
216 return quantity
217
218 if repeat is None:
219 repeat = self.repeat.prod()
220 if oldprod is None:
221 oldprod = self.repeat.prod()
222
223 results = {}
224
225 original_length = len(atoms) // oldprod
226 newprod = repeat.prod()
227
228 # Read the old properties
229 magmoms = getresult('magmoms', atoms.get_magnetic_moments)
230 magmom = getresult('magmom', atoms.get_magnetic_moment)
231 energy = getresult('energy', atoms.get_potential_energy)
232 forces = getresult('forces', atoms.get_forces)
233
234 # Update old properties to the repeated image
235 if magmoms is not None:
236 magmoms = np.tile(magmoms[:original_length], newprod)
237 results['magmoms'] = magmoms
238
239 if magmom is not None:
240 magmom = magmom * newprod / oldprod
241 results['magmom'] = magmom
242
243 if forces is not None:
244 forces = np.tile(forces[:original_length].T, newprod).T
245 results['forces'] = forces
246
247 if energy is not None:
248 energy = energy * newprod / oldprod
249 results['energy'] = energy
250
251 return results
152252
153253 def repeat_unit_cell(self):
154254 for atoms in self:
155 # Get quantities taking into account current repeat():
156 ref_energy = self.get_energy(atoms)
157 ref_forces = self.get_forces(atoms)
158 atoms.calc = SinglePointCalculator(atoms,
159 energy=ref_energy,
160 forces=ref_forces)
255 # Get quantities taking into account current repeat():'
256 results = self.repeat_results(atoms, self.repeat.prod(),
257 oldprod=self.repeat.prod())
258
161259 atoms.cell *= self.repeat.reshape((3, 1))
260 atoms.calc = SinglePointCalculator(atoms, **results)
162261 self.repeat = np.ones(3, int)
163262
164263 def repeat_images(self, repeat):
167266 oldprod = self.repeat.prod()
168267 images = []
169268 constraints_removed = False
269
170270 for i, atoms in enumerate(self):
171271 refcell = atoms.get_cell()
172272 fa = []
176276 else:
177277 constraints_removed = True
178278 atoms.set_constraint(fa)
179 del atoms[len(atoms) // oldprod:]
279
280 # Update results dictionary to repeated atoms
281 results = self.repeat_results(atoms, repeat, oldprod)
282
283 del atoms[len(atoms) // oldprod:] # Original atoms
284
180285 atoms *= repeat
181286 atoms.cell = refcell
287
288 atoms.calc = SinglePointCalculator(atoms, **results)
289
182290 images.append(atoms)
183291
184292 if constraints_removed:
129129 win = self.win = ui.Window(_('Nanoparticle'))
130130 win.add(ui.Text(introtext))
131131
132 self.element = Element('', self.update)
132 self.element = Element('', self.apply)
133133 lattice_button = ui.Button(_('Get structure'),
134134 self.set_structure_data)
135135 self.elementinfo = ui.Label(' ')
200200 self.smaller_button = None
201201 self.largeer_button = None
202202
203 self.element[1].entry.focus_set()
203 self.element.grab_focus()
204204
205205 def default_direction_table(self):
206206 'Set default directions and values for the current crystal structure.'
390390 def update(self, *args):
391391 if self.no_update:
392392 return
393 self.element.check()
393 self.element.Z # Check
394394 if self.auto.value:
395395 self.makeatoms()
396396 if self.atoms is not None:
401401
402402 def set_structure_data(self, *args):
403403 'Called when the user presses [Get structure].'
404 if not self.element.check():
404 z = self.element.Z
405 if z is None:
405406 return
406 z = self.element.Z
407407 ref = ase.data.reference_states[z]
408408 if ref is None:
409409 structure = None
431431
432432 def makeatoms(self, *args):
433433 'Make the atoms according to the current specification.'
434 if not self.element.check():
434 symbol = self.element.symbol
435 if symbol is None:
435436 self.clearatoms()
436437 self.makeinfo()
437438 return False
451452 for x in self.direction_table_rows.rows]
452453 self.update_size_diameter(update=False)
453454 rounding = self.round_radio.value
454 self.atoms = wulff_construction(self.element.symbol,
455 self.atoms = wulff_construction(symbol,
455456 surfaces,
456457 surfaceenergies,
457458 self.size_natoms.value,
458459 self.factory[struct],
459460 rounding, lc)
460 python = py_template_wulff % {'element': self.element.symbol,
461 python = py_template_wulff % {'element': symbol,
461462 'surfaces': str(surfaces),
462463 'energies': str(surfaceenergies),
463464 'latconst': lc_str,
468469 # Layer-by-layer specification
469470 surfaces = [x[0] for x in self.direction_table]
470471 layers = [x[1].value for x in self.direction_table_rows.rows]
471 self.atoms = self.factory[struct](self.element.symbol,
472 self.atoms = self.factory[struct](symbol,
472473 copy(surfaces),
473474 layers, latticeconstant=lc)
474475 imp = self.import_names[struct]
475476 python = py_template_layers % {'import': imp,
476 'element': self.element.symbol,
477 'element': symbol,
477478 'surfaces': str(surfaces),
478479 'layers': str(layers),
479480 'latconst': lc_str,
520521 self.smaller_button.active = self.atoms is not None
521522 self.larger_button.active = self.atoms is not None
522523
523 def apply(self):
524 def apply(self, callbackarg=None):
524525 self.makeatoms()
525526 if self.atoms is not None:
526527 self.gui.new_atoms(self.atoms)
5555 done
5656
5757 gitrevert:
58 git checkout -- ag.pot '*/LC_MESSAGES/ag.po'
58 git checkout -- '*/LC_MESSAGES/ag.po'
5959
6060 clean:
6161 rm -f ./*/LC_MESSAGES/ag.mo
+0
-1571
ase/gui/po/ag.pot less more
0 # SOME DESCRIPTIVE TITLE.
1 # Copyright (C) YEAR ASE developers
2 # This file is distributed under the same license as the PACKAGE package.
3 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
4 #
5 #, fuzzy
6 msgid ""
7 msgstr ""
8 "Project-Id-Version: ase\n"
9 "Report-Msgid-Bugs-To: ase-users@listserv.fysik.dtu.dk\n"
10 "POT-Creation-Date: 2017-04-11 20:41+0200\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
14 "Language: \n"
15 "MIME-Version: 1.0\n"
16 "Content-Type: text/plain; charset=UTF-8\n"
17 "Content-Transfer-Encoding: 8bit\n"
18 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
19
20 #: ../add.py:12
21 msgid "Bad position"
22 msgstr ""
23
24 #. XXXXXXXXXXX still array based, not Atoms-based. Will crash
25 #: ../add.py:20
26 msgid "Add atoms"
27 msgstr ""
28
29 #: ../add.py:25
30 msgid "Absolute position:"
31 msgstr ""
32
33 #: ../add.py:27 ../add.py:30 ../nanoparticle.py:262
34 msgid "Add"
35 msgstr ""
36
37 #: ../add.py:28
38 msgid "Relative to average position (of selection):"
39 msgstr ""
40
41 #: ../colors.py:14
42 msgid "Colors"
43 msgstr ""
44
45 #: ../colors.py:16
46 msgid "Choose how the atoms are colored:"
47 msgstr ""
48
49 #: ../colors.py:18
50 msgid "By atomic number, default \"jmol\" colors"
51 msgstr ""
52
53 #: ../colors.py:19
54 msgid "By tag"
55 msgstr ""
56
57 #: ../colors.py:20
58 msgid "By force"
59 msgstr ""
60
61 #: ../colors.py:21
62 msgid "By velocity"
63 msgstr ""
64
65 #: ../colors.py:22
66 msgid "By charge"
67 msgstr ""
68
69 #: ../colors.py:23
70 msgid "By magnetic moment"
71 msgstr ""
72
73 #: ../colors.py:65
74 msgid "Green"
75 msgstr ""
76
77 #: ../colors.py:65
78 msgid "Yellow"
79 msgstr ""
80
81 #: ../constraints.py:8
82 msgid "Constraints"
83 msgstr ""
84
85 #: ../constraints.py:9 ../constraints.py:11 ../settings.py:14
86 msgid "Constrain"
87 msgstr ""
88
89 #: ../constraints.py:10 ../constraints.py:14
90 msgid "selected atoms"
91 msgstr ""
92
93 #: ../constraints.py:12
94 msgid "immobile atoms"
95 msgstr ""
96
97 #: ../constraints.py:13
98 msgid "Unconstrain"
99 msgstr ""
100
101 #: ../constraints.py:15
102 msgid "Clear constraints"
103 msgstr ""
104
105 #: ../crystal.py:16
106 msgid ""
107 " Use this dialog to create crystal lattices. First select the structure,\n"
108 " either from a set of common crystal structures, or by space group "
109 "description.\n"
110 " Then add all other lattice parameters.\n"
111 "\n"
112 " If an experimental crystal structure is available for an atom, you can\n"
113 " look up the crystal type and lattice constant, otherwise you have to "
114 "specify it\n"
115 " yourself. "
116 msgstr ""
117
118 #: ../crystal.py:34 ../graphene.py:30
119 #, python-format
120 msgid " %(natoms)i atoms: %(symbols)s, Volume: %(volume).3f A<sup>3</sup>"
121 msgstr ""
122
123 #: ../crystal.py:71
124 msgid "Create Bulk Crystal by Spacegroup"
125 msgstr ""
126
127 #: ../crystal.py:85
128 msgid "Number: 1"
129 msgstr ""
130
131 #: ../crystal.py:87
132 msgid "Lattice: "
133 msgstr ""
134
135 #: ../crystal.py:88
136 msgid "\tSpace group: "
137 msgstr ""
138
139 #: ../crystal.py:95
140 msgid "Size: x: "
141 msgstr ""
142
143 #: ../crystal.py:95 ../crystal.py:177
144 msgid " y: "
145 msgstr ""
146
147 #: ../crystal.py:96 ../crystal.py:178
148 msgid " z: "
149 msgstr ""
150
151 #: ../crystal.py:97 ../surfaceslab.py:77 ../surfaceslab.py:78
152 #: ../surfaceslab.py:79
153 msgid " unit cells"
154 msgstr ""
155
156 #: ../crystal.py:118 ../crystal.py:122 ../crystal.py:126 ../crystal.py:130
157 #: ../crystal.py:134 ../crystal.py:138
158 msgid "free"
159 msgstr ""
160
161 #: ../crystal.py:119 ../crystal.py:128
162 msgid "equals b"
163 msgstr ""
164
165 #: ../crystal.py:120 ../crystal.py:124
166 msgid "equals c"
167 msgstr ""
168
169 #: ../crystal.py:121 ../crystal.py:125 ../crystal.py:129 ../crystal.py:133
170 #: ../crystal.py:137 ../crystal.py:141
171 msgid "fixed"
172 msgstr ""
173
174 #: ../crystal.py:123 ../crystal.py:127
175 msgid "equals a"
176 msgstr ""
177
178 #: ../crystal.py:131 ../crystal.py:140
179 msgid "equals beta"
180 msgstr ""
181
182 #: ../crystal.py:132 ../crystal.py:136
183 msgid "equals gamma"
184 msgstr ""
185
186 #: ../crystal.py:135 ../crystal.py:139
187 msgid "equals alpha"
188 msgstr ""
189
190 #: ../crystal.py:145
191 msgid "Lattice parameters"
192 msgstr ""
193
194 #: ../crystal.py:147
195 msgid "\t\ta:\t"
196 msgstr ""
197
198 #: ../crystal.py:148
199 msgid "\talpha:\t"
200 msgstr ""
201
202 #: ../crystal.py:152
203 msgid "\t\tb:\t"
204 msgstr ""
205
206 #: ../crystal.py:153
207 msgid "\tbeta:\t"
208 msgstr ""
209
210 #: ../crystal.py:157
211 msgid "\t\tc:\t"
212 msgstr ""
213
214 #: ../crystal.py:158
215 msgid "\tgamma:\t"
216 msgstr ""
217
218 #: ../crystal.py:161 ../surfaceslab.py:57
219 msgid "Get from database"
220 msgstr ""
221
222 #: ../crystal.py:166
223 msgid "Basis: "
224 msgstr ""
225
226 #: ../crystal.py:176
227 msgid " Element:\t"
228 msgstr ""
229
230 #: ../crystal.py:177
231 msgid "\tx: "
232 msgstr ""
233
234 #: ../crystal.py:198
235 msgid "Creating a crystal."
236 msgstr ""
237
238 #: ../crystal.py:242
239 #, python-format
240 msgid "Symbol: %s"
241 msgstr ""
242
243 #: ../crystal.py:247
244 #, python-format
245 msgid "Number: %s"
246 msgstr ""
247
248 #: ../crystal.py:250
249 msgid "Invalid Spacegroup!"
250 msgstr ""
251
252 #: ../crystal.py:393 ../crystal.py:397
253 msgid "Please specify a consistent set of atoms."
254 msgstr ""
255
256 #: ../crystal.py:407 ../graphene.py:264 ../nanoparticle.py:528
257 #: ../nanotube.py:84 ../surfaceslab.py:221
258 msgid "No valid atoms."
259 msgstr ""
260
261 #: ../crystal.py:408 ../graphene.py:265 ../nanoparticle.py:529
262 #: ../nanotube.py:85 ../surfaceslab.py:222 ../widgets.py:76
263 msgid "You have not (yet) specified a consistent set of parameters."
264 msgstr ""
265
266 #: ../crystal.py:529
267 msgid "Can't find lattice definition!"
268 msgstr ""
269
270 #: ../energyforces.py:15
271 msgid "Output:"
272 msgstr ""
273
274 #: ../energyforces.py:44
275 msgid "Save output"
276 msgstr ""
277
278 #: ../energyforces.py:61
279 msgid "Potential energy and forces"
280 msgstr ""
281
282 #: ../energyforces.py:65
283 msgid "Calculate potential energy and the force on all atoms"
284 msgstr ""
285
286 #: ../energyforces.py:69
287 msgid "Write forces on the atoms"
288 msgstr ""
289
290 #: ../energyforces.py:86
291 msgid "Potential Energy:\n"
292 msgstr ""
293
294 #: ../energyforces.py:87
295 #, python-format
296 msgid " %8.2f eV\n"
297 msgstr ""
298
299 #: ../energyforces.py:88
300 #, python-format
301 msgid ""
302 " %8.4f eV/atom\n"
303 "\n"
304 msgstr ""
305
306 #: ../energyforces.py:90
307 msgid "Forces:\n"
308 msgstr ""
309
310 #: ../graphene.py:17
311 msgid ""
312 "Set up a graphene sheet or a graphene nanoribbon. A nanoribbon may\n"
313 "optionally be saturated with hydrogen (or another element)."
314 msgstr ""
315
316 #: ../graphene.py:38 ../gui.py:466
317 msgid "Graphene"
318 msgstr ""
319
320 #. Choose structure
321 #: ../graphene.py:45
322 msgid "Structure: "
323 msgstr ""
324
325 #: ../graphene.py:47
326 msgid "Infinite sheet"
327 msgstr ""
328
329 #: ../graphene.py:47
330 msgid "Unsaturated ribbon"
331 msgstr ""
332
333 #: ../graphene.py:48
334 msgid "Saturated ribbon"
335 msgstr ""
336
337 #. Orientation
338 #: ../graphene.py:55
339 msgid "Orientation: "
340 msgstr ""
341
342 #: ../graphene.py:58
343 msgid "zigzag"
344 msgstr ""
345
346 #: ../graphene.py:58
347 msgid "armchair"
348 msgstr ""
349
350 #: ../graphene.py:71 ../graphene.py:82
351 msgid " Bond length: "
352 msgstr ""
353
354 #: ../graphene.py:72 ../graphene.py:83 ../graphene.py:107 ../nanotube.py:45
355 msgid "Å"
356 msgstr ""
357
358 #. Choose the saturation element and bond length
359 #: ../graphene.py:77
360 msgid "Saturation: "
361 msgstr ""
362
363 #: ../graphene.py:80
364 msgid "H"
365 msgstr ""
366
367 #. Size
368 #: ../graphene.py:96
369 msgid "Width: "
370 msgstr ""
371
372 #: ../graphene.py:97
373 msgid " Length: "
374 msgstr ""
375
376 #. Vacuum
377 #: ../graphene.py:105 ../surfaceslab.py:80
378 msgid "Vacuum: "
379 msgstr ""
380
381 #: ../graphene.py:153
382 msgid " No element specified!"
383 msgstr ""
384
385 #: ../graphene.py:200
386 msgid "Please specify a consistent set of atoms. "
387 msgstr ""
388
389 #: ../graphs.py:11
390 msgid ""
391 "Symbols:\n"
392 "<c>e</c>: total energy\n"
393 "<c>epot</c>: potential energy\n"
394 "<c>ekin</c>: kinetic energy\n"
395 "<c>fmax</c>: maximum force\n"
396 "<c>fave</c>: average force\n"
397 "<c>R[n,0-2]</c>: position of atom number <c>n</c>\n"
398 "<c>d(n<sub>1</sub>,n<sub>2</sub>)</c>: distance between two atoms "
399 "<c>n<sub>1</sub></c> and <c>n<sub>2</sub></c>\n"
400 "<c>i</c>: current image number\n"
401 "<c>E[i]</c>: energy of image number <c>i</c>\n"
402 "<c>F[n,0-2]</c>: force on atom number <c>n</c>\n"
403 "<c>V[n,0-2]</c>: velocity of atom number <c>n</c>\n"
404 "<c>M[n]</c>: magnetic moment of atom number <c>n</c>\n"
405 "<c>A[0-2,0-2]</c>: unit-cell basis vectors\n"
406 "<c>s</c>: path length\n"
407 "<c>a(n1,n2,n3)</c>: angle between atoms <c>n<sub>1</sub></c>, <c>n<sub>2</"
408 "sub></c> and <c>n<sub>3</sub></c>, centered on <c>n<sub>2</sub></c>\n"
409 "<c>dih(n1,n2,n3,n4)</c>: dihedral angle between <c>n<sub>1</sub></c>, "
410 "<c>n<sub>2</sub></c>, <c>n<sub>3</sub></c> and <c>n<sub>4</sub></c>\n"
411 "<c>T</c>: temperature (K)"
412 msgstr ""
413
414 #: ../graphs.py:42 ../graphs.py:44
415 msgid "Plot"
416 msgstr ""
417
418 #: ../graphs.py:46
419 msgid "Save"
420 msgstr ""
421
422 #: ../graphs.py:47
423 msgid "Clear"
424 msgstr ""
425
426 #: ../graphs.py:72
427 msgid "Save data to file ... "
428 msgstr ""
429
430 #: ../gui.py:243
431 msgid "Automatic"
432 msgstr ""
433
434 #: ../gui.py:261
435 msgid "Open ..."
436 msgstr ""
437
438 #: ../gui.py:262
439 msgid "Choose parser:"
440 msgstr ""
441
442 #: ../gui.py:373
443 msgid "_File"
444 msgstr ""
445
446 #: ../gui.py:374
447 msgid "_Open"
448 msgstr ""
449
450 #: ../gui.py:375
451 msgid "_New"
452 msgstr ""
453
454 #: ../gui.py:376
455 msgid "_Save"
456 msgstr ""
457
458 #: ../gui.py:378
459 msgid "_Quit"
460 msgstr ""
461
462 #: ../gui.py:380
463 msgid "_Edit"
464 msgstr ""
465
466 #: ../gui.py:381
467 msgid "Select _all"
468 msgstr ""
469
470 #: ../gui.py:382
471 msgid "_Invert selection"
472 msgstr ""
473
474 #: ../gui.py:383
475 msgid "Select _constrained atoms"
476 msgstr ""
477
478 #: ../gui.py:384
479 msgid "Select _immobile atoms"
480 msgstr ""
481
482 #: ../gui.py:390
483 msgid "Hide selected atoms"
484 msgstr ""
485
486 #: ../gui.py:391
487 msgid "Show selected atoms"
488 msgstr ""
489
490 #: ../gui.py:393
491 msgid "_Modify"
492 msgstr ""
493
494 #: ../gui.py:394
495 msgid "_Add atoms"
496 msgstr ""
497
498 #: ../gui.py:395
499 msgid "_Delete selected atoms"
500 msgstr ""
501
502 #: ../gui.py:398
503 msgid "_First image"
504 msgstr ""
505
506 #: ../gui.py:399
507 msgid "_Previous image"
508 msgstr ""
509
510 #: ../gui.py:400
511 msgid "_Next image"
512 msgstr ""
513
514 #: ../gui.py:401
515 msgid "_Last image"
516 msgstr ""
517
518 #: ../gui.py:403
519 msgid "_View"
520 msgstr ""
521
522 #: ../gui.py:404
523 msgid "Show _unit cell"
524 msgstr ""
525
526 #: ../gui.py:406
527 msgid "Show _axes"
528 msgstr ""
529
530 #: ../gui.py:407
531 msgid "Show _bonds"
532 msgstr ""
533
534 #: ../gui.py:409
535 msgid "Show _velocities"
536 msgstr ""
537
538 #: ../gui.py:411
539 msgid "Show _forces"
540 msgstr ""
541
542 #: ../gui.py:413
543 msgid "Show _Labels"
544 msgstr ""
545
546 #: ../gui.py:414
547 msgid "_None"
548 msgstr ""
549
550 #: ../gui.py:415
551 msgid "Atom _Index"
552 msgstr ""
553
554 #: ../gui.py:416
555 msgid "_Magnetic Moments"
556 msgstr ""
557
558 #: ../gui.py:417
559 msgid "_Element Symbol"
560 msgstr ""
561
562 #: ../gui.py:419
563 msgid "Quick Info ..."
564 msgstr ""
565
566 #: ../gui.py:420
567 msgid "Repeat ..."
568 msgstr ""
569
570 #: ../gui.py:421
571 msgid "Rotate ..."
572 msgstr ""
573
574 #: ../gui.py:422
575 msgid "Colors ..."
576 msgstr ""
577
578 #. TRANSLATORS: verb
579 #: ../gui.py:424
580 msgid "Focus"
581 msgstr ""
582
583 #: ../gui.py:425
584 msgid "Zoom in"
585 msgstr ""
586
587 #: ../gui.py:426
588 msgid "Zoom out"
589 msgstr ""
590
591 #: ../gui.py:427
592 msgid "Change View"
593 msgstr ""
594
595 #: ../gui.py:429
596 msgid "Reset View"
597 msgstr ""
598
599 #: ../gui.py:430
600 msgid "xy-plane"
601 msgstr ""
602
603 #: ../gui.py:431
604 msgid "yz-plane"
605 msgstr ""
606
607 #: ../gui.py:432
608 msgid "zx-plane"
609 msgstr ""
610
611 #: ../gui.py:433
612 msgid "yx-plane"
613 msgstr ""
614
615 #: ../gui.py:434
616 msgid "zy-plane"
617 msgstr ""
618
619 #: ../gui.py:435
620 msgid "xz-plane"
621 msgstr ""
622
623 #: ../gui.py:436
624 msgid "a2,a3-plane"
625 msgstr ""
626
627 #: ../gui.py:437
628 msgid "a3,a1-plane"
629 msgstr ""
630
631 #: ../gui.py:438
632 msgid "a1,a2-plane"
633 msgstr ""
634
635 #: ../gui.py:439
636 msgid "a3,a2-plane"
637 msgstr ""
638
639 #: ../gui.py:440
640 msgid "a1,a3-plane"
641 msgstr ""
642
643 #: ../gui.py:441
644 msgid "a2,a1-plane"
645 msgstr ""
646
647 #: ../gui.py:442
648 msgid "Settings ..."
649 msgstr ""
650
651 #: ../gui.py:444
652 msgid "VMD"
653 msgstr ""
654
655 #: ../gui.py:445
656 msgid "RasMol"
657 msgstr ""
658
659 #: ../gui.py:446
660 msgid "xmakemol"
661 msgstr ""
662
663 #: ../gui.py:447
664 msgid "avogadro"
665 msgstr ""
666
667 #: ../gui.py:449
668 msgid "_Tools"
669 msgstr ""
670
671 #: ../gui.py:450
672 msgid "Graphs ..."
673 msgstr ""
674
675 #: ../gui.py:451
676 msgid "Movie ..."
677 msgstr ""
678
679 #: ../gui.py:452
680 msgid "Expert mode ..."
681 msgstr ""
682
683 #: ../gui.py:453
684 msgid "Constraints ..."
685 msgstr ""
686
687 #: ../gui.py:454
688 msgid "Render scene ..."
689 msgstr ""
690
691 #: ../gui.py:455
692 msgid "_Move atoms"
693 msgstr ""
694
695 #: ../gui.py:456
696 msgid "NE_B"
697 msgstr ""
698
699 #: ../gui.py:457
700 msgid "B_ulk Modulus"
701 msgstr ""
702
703 #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
704 #: ../gui.py:460
705 msgid "_Setup"
706 msgstr ""
707
708 #: ../gui.py:461
709 msgid "_Bulk Crystal"
710 msgstr ""
711
712 #: ../gui.py:462
713 msgid "_Surface slab"
714 msgstr ""
715
716 #: ../gui.py:463
717 msgid "_Nanoparticle"
718 msgstr ""
719
720 #: ../gui.py:465
721 msgid "Nano_tube"
722 msgstr ""
723
724 #: ../gui.py:468
725 msgid "_Calculate"
726 msgstr ""
727
728 #: ../gui.py:469
729 msgid "Set _Calculator"
730 msgstr ""
731
732 #: ../gui.py:470
733 msgid "_Energy and Forces"
734 msgstr ""
735
736 #: ../gui.py:471
737 msgid "Energy Minimization"
738 msgstr ""
739
740 #: ../gui.py:474
741 msgid "_Help"
742 msgstr ""
743
744 #: ../gui.py:475
745 msgid "_About"
746 msgstr ""
747
748 #: ../gui.py:479
749 msgid "Webpage ..."
750 msgstr ""
751
752 #: ../modify.py:18
753 msgid "No atoms selected!"
754 msgstr ""
755
756 #: ../modify.py:21
757 msgid "Modify"
758 msgstr ""
759
760 #: ../modify.py:24
761 msgid "Change element"
762 msgstr ""
763
764 #: ../modify.py:27
765 msgid "Tag"
766 msgstr ""
767
768 #: ../modify.py:29
769 msgid "Moment"
770 msgstr ""
771
772 #: ../movie.py:11
773 msgid "Movie"
774 msgstr ""
775
776 #: ../movie.py:12
777 msgid "Image number:"
778 msgstr ""
779
780 #: ../movie.py:18
781 msgid "First"
782 msgstr ""
783
784 #: ../movie.py:19
785 msgid "Back"
786 msgstr ""
787
788 #: ../movie.py:20
789 msgid "Forward"
790 msgstr ""
791
792 #: ../movie.py:21
793 msgid "Last"
794 msgstr ""
795
796 #: ../movie.py:23
797 msgid "Play"
798 msgstr ""
799
800 #: ../movie.py:24
801 msgid "Stop"
802 msgstr ""
803
804 #. TRANSLATORS: This function plays an animation forwards and backwards
805 #. alternatingly, e.g. for displaying vibrational movement
806 #: ../movie.py:28
807 msgid "Rock"
808 msgstr ""
809
810 #: ../movie.py:41
811 msgid " Frame rate: "
812 msgstr ""
813
814 #: ../movie.py:41
815 msgid " Skip frames: "
816 msgstr ""
817
818 #: ../nanoparticle.py:23
819 msgid ""
820 "Create a nanoparticle either by specifying the number of layers, or using "
821 "the\n"
822 "Wulff construction. Please press the [Help] button for instructions on how "
823 "to\n"
824 "specify the directions.\n"
825 "WARNING: The Wulff construction currently only works with cubic crystals!\n"
826 msgstr ""
827
828 #: ../nanoparticle.py:30
829 #, python-brace-format
830 msgid ""
831 "\n"
832 "The nanoparticle module sets up a nano-particle or a cluster with a given\n"
833 "crystal structure.\n"
834 "\n"
835 "1) Select the element, the crystal structure and the lattice constant(s).\n"
836 " The [Get structure] button will find the data for a given element.\n"
837 "\n"
838 "2) Choose if you want to specify the number of layers in each direction, or "
839 "if\n"
840 " you want to use the Wulff construction. In the latter case, you must\n"
841 " specify surface energies in each direction, and the size of the cluster.\n"
842 "\n"
843 "How to specify the directions:\n"
844 "------------------------------\n"
845 "\n"
846 "First time a direction appears, it is interpreted as the entire family of\n"
847 "directions, i.e. (0,0,1) also covers (1,0,0), (-1,0,0) etc. If one of "
848 "these\n"
849 "directions is specified again, the second specification overrules that "
850 "specific\n"
851 "direction. For this reason, the order matters and you can rearrange the\n"
852 "directions with the [Up] and [Down] keys. You can also add a new "
853 "direction,\n"
854 "remember to press [Add] or it will not be included.\n"
855 "\n"
856 "Example: (1,0,0) (1,1,1), (0,0,1) would specify the {100} family of "
857 "directions,\n"
858 "the {111} family and then the (001) direction, overruling the value given "
859 "for\n"
860 "the whole family of directions.\n"
861 msgstr ""
862
863 #. Structures: Abbreviation, name,
864 #. 4-index (boolean), two lattice const (bool), factory
865 #: ../nanoparticle.py:90
866 msgid "Face centered cubic (fcc)"
867 msgstr ""
868
869 #: ../nanoparticle.py:92
870 msgid "Body centered cubic (bcc)"
871 msgstr ""
872
873 #: ../nanoparticle.py:94
874 msgid "Simple cubic (sc)"
875 msgstr ""
876
877 #: ../nanoparticle.py:96
878 msgid "Hexagonal closed-packed (hcp)"
879 msgstr ""
880
881 #: ../nanoparticle.py:98
882 msgid "Graphite"
883 msgstr ""
884
885 #: ../nanoparticle.py:130
886 msgid "Nanoparticle"
887 msgstr ""
888
889 #: ../nanoparticle.py:134
890 msgid "Get structure"
891 msgstr ""
892
893 #: ../nanoparticle.py:154 ../surfaceslab.py:72
894 msgid "Structure:"
895 msgstr ""
896
897 #: ../nanoparticle.py:159
898 msgid "Lattice constant: a ="
899 msgstr ""
900
901 #: ../nanoparticle.py:163
902 msgid "Layer specification"
903 msgstr ""
904
905 #: ../nanoparticle.py:163
906 msgid "Wulff construction"
907 msgstr ""
908
909 #: ../nanoparticle.py:166
910 msgid "Method: "
911 msgstr ""
912
913 #: ../nanoparticle.py:174
914 msgid "Add new direction:"
915 msgstr ""
916
917 #. Information
918 #: ../nanoparticle.py:180
919 msgid "Information about the created cluster:"
920 msgstr ""
921
922 #: ../nanoparticle.py:181
923 msgid "Number of atoms: "
924 msgstr ""
925
926 #: ../nanoparticle.py:183
927 msgid " Approx. diameter: "
928 msgstr ""
929
930 #: ../nanoparticle.py:192
931 msgid "Automatic Apply"
932 msgstr ""
933
934 #: ../nanoparticle.py:195 ../nanotube.py:51
935 msgid "Creating a nanoparticle."
936 msgstr ""
937
938 #: ../nanoparticle.py:197 ../nanotube.py:52 ../surfaceslab.py:84
939 msgid "Apply"
940 msgstr ""
941
942 #: ../nanoparticle.py:198 ../nanotube.py:53 ../surfaceslab.py:85
943 msgid "OK"
944 msgstr ""
945
946 #: ../nanoparticle.py:225
947 msgid "Up"
948 msgstr ""
949
950 #: ../nanoparticle.py:226
951 msgid "Down"
952 msgstr ""
953
954 #: ../nanoparticle.py:227
955 msgid "Delete"
956 msgstr ""
957
958 #: ../nanoparticle.py:269
959 msgid "Number of atoms"
960 msgstr ""
961
962 #: ../nanoparticle.py:269
963 msgid "Diameter"
964 msgstr ""
965
966 #: ../nanoparticle.py:277
967 msgid "above "
968 msgstr ""
969
970 #: ../nanoparticle.py:277
971 msgid "below "
972 msgstr ""
973
974 #: ../nanoparticle.py:277
975 msgid "closest "
976 msgstr ""
977
978 #: ../nanoparticle.py:280
979 msgid "Smaller"
980 msgstr ""
981
982 #: ../nanoparticle.py:281
983 msgid "Larger"
984 msgstr ""
985
986 #: ../nanoparticle.py:282
987 msgid "Choose size using:"
988 msgstr ""
989
990 #: ../nanoparticle.py:284
991 msgid "atoms"
992 msgstr ""
993
994 #: ../nanoparticle.py:285
995 msgid "ų"
996 msgstr ""
997
998 #: ../nanoparticle.py:287
999 msgid "Rounding: If exact size is not possible, choose the size:"
1000 msgstr ""
1001
1002 #: ../nanoparticle.py:315
1003 msgid "Surface energies (as energy/area, NOT per atom):"
1004 msgstr ""
1005
1006 #: ../nanoparticle.py:317
1007 msgid "Number of layers:"
1008 msgstr ""
1009
1010 #: ../nanoparticle.py:345
1011 msgid "At least one index must be non-zero"
1012 msgstr ""
1013
1014 #: ../nanoparticle.py:348
1015 msgid "Invalid hexagonal indices"
1016 msgstr ""
1017
1018 #: ../nanoparticle.py:414
1019 msgid "Unsupported or unknown structure"
1020 msgstr ""
1021
1022 #: ../nanoparticle.py:415
1023 #, python-brace-format
1024 msgid "Element = {0}, structure = {1}"
1025 msgstr ""
1026
1027 #: ../nanotube.py:13
1028 msgid ""
1029 "Set up a Carbon nanotube by specifying the (n,m) roll-up vector.\n"
1030 "Please note that m <= n.\n"
1031 "\n"
1032 "Nanotubes of other elements can be made by specifying the element\n"
1033 "and bond length."
1034 msgstr ""
1035
1036 #: ../nanotube.py:26
1037 #, python-brace-format
1038 msgid ""
1039 "{natoms} atoms, diameter: {diameter:.3f} Å, total length: {total_length:.3f} "
1040 "Å"
1041 msgstr ""
1042
1043 #: ../nanotube.py:40
1044 msgid "Nanotube"
1045 msgstr ""
1046
1047 #: ../nanotube.py:43
1048 msgid "Bond length: "
1049 msgstr ""
1050
1051 #: ../nanotube.py:46
1052 msgid "Select roll-up vector (n,m) and tube length:"
1053 msgstr ""
1054
1055 #: ../nanotube.py:49
1056 msgid "Length:"
1057 msgstr ""
1058
1059 #: ../quickinfo.py:6
1060 msgid "Single image loaded."
1061 msgstr ""
1062
1063 #: ../quickinfo.py:7
1064 #, python-format
1065 msgid "Image %d loaded (0 - %d)."
1066 msgstr ""
1067
1068 #: ../quickinfo.py:8
1069 msgid "Unit cell is fixed."
1070 msgstr ""
1071
1072 #: ../quickinfo.py:9
1073 msgid "Unit cell varies."
1074 msgstr ""
1075
1076 #: ../quickinfo.py:11
1077 #, python-format
1078 msgid ""
1079 "%s\n"
1080 "\n"
1081 "Number of atoms: %d.\n"
1082 "\n"
1083 "Unit cell:\n"
1084 " %8.3f %8.3f %8.3f\n"
1085 " %8.3f %8.3f %8.3f\n"
1086 " %8.3f %8.3f %8.3f\n"
1087 "\n"
1088 "%s\n"
1089 "%s\n"
1090 msgstr ""
1091
1092 #: ../quickinfo.py:33
1093 msgid "This frame has no atoms."
1094 msgstr ""
1095
1096 #: ../quickinfo.py:53
1097 msgid "no"
1098 msgstr ""
1099
1100 #: ../quickinfo.py:53
1101 msgid "yes"
1102 msgstr ""
1103
1104 #. TRANSLATORS: This has the form Periodic: no, no, yes
1105 #: ../quickinfo.py:57
1106 #, python-format
1107 msgid "Periodic: %s, %s, %s"
1108 msgstr ""
1109
1110 #: ../render.py:19
1111 msgid ""
1112 " Textures can be used to highlight different parts of\n"
1113 " an atomic structure. This window applies the default\n"
1114 " texture to the entire structure and optionally\n"
1115 " applies a different texture to subsets of atoms that\n"
1116 " can be selected using the mouse.\n"
1117 " An alternative selection method is based on a boolean\n"
1118 " expression in the entry box provided, using the\n"
1119 " variables x, y, z, or Z. For example, the expression\n"
1120 " Z == 11 and x > 10 and y > 10\n"
1121 " will mark all sodium atoms with x or coordinates\n"
1122 " larger than 10. In either case, the button labeled\n"
1123 " `Create new texture from selection` will enable\n"
1124 " to change the attributes of the current selection.\n"
1125 " "
1126 msgstr ""
1127
1128 #: ../render.py:38
1129 msgid "Render current view in povray ... "
1130 msgstr ""
1131
1132 #: ../render.py:42
1133 #, python-format
1134 msgid "Rendering %d atoms."
1135 msgstr ""
1136
1137 #: ../render.py:49
1138 msgid "Render constraints"
1139 msgstr ""
1140
1141 #: ../render.py:54
1142 msgid "Width"
1143 msgstr ""
1144
1145 #: ../render.py:54
1146 msgid " Height"
1147 msgstr ""
1148
1149 #: ../render.py:63
1150 msgid "Render unit cell"
1151 msgstr ""
1152
1153 #: ../render.py:75
1154 msgid "Line width"
1155 msgstr ""
1156
1157 #: ../render.py:76
1158 msgid "Angstrom "
1159 msgstr ""
1160
1161 #: ../render.py:86
1162 msgid "Set"
1163 msgstr ""
1164
1165 #: ../render.py:88
1166 msgid "Output basename: "
1167 msgstr ""
1168
1169 #: ../render.py:90
1170 msgid " Filename: "
1171 msgstr ""
1172
1173 #: ../render.py:102
1174 msgid " Default texture for atoms: "
1175 msgstr ""
1176
1177 #: ../render.py:103
1178 msgid " transparency: "
1179 msgstr ""
1180
1181 #: ../render.py:106
1182 msgid "Define atom selection for new texture:"
1183 msgstr ""
1184
1185 #: ../render.py:108
1186 msgid "Select"
1187 msgstr ""
1188
1189 #: ../render.py:112
1190 msgid "Create new texture from selection"
1191 msgstr ""
1192
1193 #: ../render.py:115
1194 msgid "Help on textures"
1195 msgstr ""
1196
1197 #: ../render.py:131
1198 msgid "Camera type: "
1199 msgstr ""
1200
1201 #: ../render.py:132
1202 msgid " Camera distance"
1203 msgstr ""
1204
1205 #: ../render.py:134
1206 msgid "Render current frame"
1207 msgstr ""
1208
1209 #: ../render.py:138
1210 #, python-format
1211 msgid "Render all %d frames"
1212 msgstr ""
1213
1214 #: ../render.py:143
1215 msgid "Transparent background"
1216 msgstr ""
1217
1218 #: ../render.py:146
1219 msgid "Run povray "
1220 msgstr ""
1221
1222 #: ../render.py:149
1223 msgid "Keep povray files "
1224 msgstr ""
1225
1226 #: ../render.py:152
1227 msgid "Show output window"
1228 msgstr ""
1229
1230 #: ../render.py:237
1231 msgid " transparency: "
1232 msgstr ""
1233
1234 #: ../render.py:247
1235 msgid ""
1236 "Can not create new texture! Must have some atoms selected to create a new "
1237 "material!"
1238 msgstr ""
1239
1240 #: ../repeat.py:10
1241 msgid "Repeat"
1242 msgstr ""
1243
1244 #: ../repeat.py:11
1245 msgid "Repeat atoms:"
1246 msgstr ""
1247
1248 #: ../repeat.py:15
1249 msgid "Set unit cell"
1250 msgstr ""
1251
1252 #: ../rotate.py:13
1253 msgid "Rotate"
1254 msgstr ""
1255
1256 #: ../rotate.py:14
1257 msgid "Rotation angles:"
1258 msgstr ""
1259
1260 #: ../rotate.py:18
1261 msgid "Update"
1262 msgstr ""
1263
1264 #: ../rotate.py:19
1265 msgid ""
1266 "Note:\n"
1267 "You can rotate freely\n"
1268 "with the mouse, by holding\n"
1269 "down mouse button 2."
1270 msgstr ""
1271
1272 #: ../save.py:14
1273 msgid ""
1274 "Append name with \"@n\" in order to write image\n"
1275 "number \"n\" instead of the current image. Append\n"
1276 "\"@start:stop\" or \"@start:stop:step\" if you want\n"
1277 "to write a range of images. You can leave out\n"
1278 "\"start\" and \"stop\" so that \"name@:\" will give\n"
1279 "you all images. Negative numbers count from the\n"
1280 "last image. Examples: \"name@-1\": last image,\n"
1281 "\"name@-2:\": last two."
1282 msgstr ""
1283
1284 #: ../save.py:26
1285 msgid "Save ..."
1286 msgstr ""
1287
1288 #: ../settings.py:10
1289 msgid "Settings"
1290 msgstr ""
1291
1292 #. Constraints
1293 #: ../settings.py:13
1294 msgid "Constraints:"
1295 msgstr ""
1296
1297 #: ../settings.py:16
1298 msgid "release"
1299 msgstr ""
1300
1301 #: ../settings.py:17 ../settings.py:26
1302 msgid " selected atoms"
1303 msgstr ""
1304
1305 #: ../settings.py:18
1306 msgid "Constrain immobile atoms"
1307 msgstr ""
1308
1309 #: ../settings.py:19
1310 msgid "Clear all constraints"
1311 msgstr ""
1312
1313 #. Visibility
1314 #: ../settings.py:22
1315 msgid "Visibility:"
1316 msgstr ""
1317
1318 #: ../settings.py:23
1319 msgid "Hide"
1320 msgstr ""
1321
1322 #: ../settings.py:25
1323 msgid "show"
1324 msgstr ""
1325
1326 #: ../settings.py:27
1327 msgid "View all atoms"
1328 msgstr ""
1329
1330 #. Miscellaneous
1331 #: ../settings.py:30
1332 msgid "Miscellaneous:"
1333 msgstr ""
1334
1335 #: ../settings.py:33
1336 msgid "Scale atomic radii:"
1337 msgstr ""
1338
1339 #: ../simulation.py:30
1340 msgid " (rerun simulation)"
1341 msgstr ""
1342
1343 #: ../simulation.py:31
1344 msgid " (continue simulation)"
1345 msgstr ""
1346
1347 #: ../simulation.py:33
1348 msgid "Select starting configuration:"
1349 msgstr ""
1350
1351 #: ../simulation.py:38
1352 #, python-format
1353 msgid "There are currently %i configurations loaded."
1354 msgstr ""
1355
1356 #: ../simulation.py:43
1357 msgid "Choose which one to use as the initial configuration"
1358 msgstr ""
1359
1360 #: ../simulation.py:47
1361 #, python-format
1362 msgid "The first configuration %s."
1363 msgstr ""
1364
1365 #: ../simulation.py:50
1366 msgid "Configuration number "
1367 msgstr ""
1368
1369 #: ../simulation.py:56
1370 #, python-format
1371 msgid "The last configuration %s."
1372 msgstr ""
1373
1374 #: ../simulation.py:92
1375 msgid "Run"
1376 msgstr ""
1377
1378 #: ../simulation.py:112
1379 msgid "No calculator: Use Calculate/Set Calculator on the menu."
1380 msgstr ""
1381
1382 #: ../simulation.py:123
1383 msgid "No atoms present"
1384 msgstr ""
1385
1386 #: ../status.py:57
1387 #, python-format
1388 msgid " tag=%(tag)s"
1389 msgstr ""
1390
1391 #. TRANSLATORS: mom refers to magnetic moment
1392 #: ../status.py:61
1393 #, python-brace-format
1394 msgid " mom={0:1.2f}"
1395 msgstr ""
1396
1397 #: ../status.py:65
1398 #, python-brace-format
1399 msgid " q={0:1.2f}"
1400 msgstr ""
1401
1402 #: ../status.py:110
1403 msgid "dihedral"
1404 msgstr ""
1405
1406 #: ../surfaceslab.py:14
1407 msgid ""
1408 " Use this dialog to create surface slabs. Select the element by\n"
1409 "writing the chemical symbol or the atomic number in the box. Then\n"
1410 "select the desired surface structure. Note that some structures can\n"
1411 "be created with an othogonal or a non-orthogonal unit cell, in these\n"
1412 "cases the non-orthogonal unit cell will contain fewer atoms.\n"
1413 "\n"
1414 " If the structure matches the experimental crystal structure, you can\n"
1415 "look up the lattice constant, otherwise you have to specify it\n"
1416 "yourself."
1417 msgstr ""
1418
1419 #. Name, structure, orthogonal, function
1420 #: ../surfaceslab.py:26
1421 msgid "FCC(100)"
1422 msgstr ""
1423
1424 #: ../surfaceslab.py:26 ../surfaceslab.py:27 ../surfaceslab.py:28
1425 #: ../surfaceslab.py:29
1426 msgid "fcc"
1427 msgstr ""
1428
1429 #: ../surfaceslab.py:27
1430 msgid "FCC(110)"
1431 msgstr ""
1432
1433 #: ../surfaceslab.py:28 ../surfaceslab.py:172
1434 msgid "FCC(111)"
1435 msgstr ""
1436
1437 #: ../surfaceslab.py:29 ../surfaceslab.py:175
1438 msgid "FCC(211)"
1439 msgstr ""
1440
1441 #: ../surfaceslab.py:30
1442 msgid "BCC(100)"
1443 msgstr ""
1444
1445 #: ../surfaceslab.py:30 ../surfaceslab.py:31 ../surfaceslab.py:32
1446 msgid "bcc"
1447 msgstr ""
1448
1449 #: ../surfaceslab.py:31 ../surfaceslab.py:169
1450 msgid "BCC(110)"
1451 msgstr ""
1452
1453 #: ../surfaceslab.py:32 ../surfaceslab.py:166
1454 msgid "BCC(111)"
1455 msgstr ""
1456
1457 #: ../surfaceslab.py:33 ../surfaceslab.py:179
1458 msgid "HCP(0001)"
1459 msgstr ""
1460
1461 #: ../surfaceslab.py:33 ../surfaceslab.py:34 ../surfaceslab.py:133
1462 #: ../surfaceslab.py:189
1463 msgid "hcp"
1464 msgstr ""
1465
1466 #: ../surfaceslab.py:34 ../surfaceslab.py:182
1467 msgid "HCP(10-10)"
1468 msgstr ""
1469
1470 #: ../surfaceslab.py:35
1471 msgid "DIAMOND(100)"
1472 msgstr ""
1473
1474 #: ../surfaceslab.py:35 ../surfaceslab.py:36
1475 msgid "diamond"
1476 msgstr ""
1477
1478 #: ../surfaceslab.py:36
1479 msgid "DIAMOND(111)"
1480 msgstr ""
1481
1482 #: ../surfaceslab.py:69
1483 msgid "Surface"
1484 msgstr ""
1485
1486 #: ../surfaceslab.py:73
1487 msgid "Orthogonal cell:"
1488 msgstr ""
1489
1490 #: ../surfaceslab.py:74
1491 msgid "Lattice constant:\ta"
1492 msgstr ""
1493
1494 #: ../surfaceslab.py:76
1495 msgid "\t\tc"
1496 msgstr ""
1497
1498 #: ../surfaceslab.py:77
1499 msgid "Size: \tx: "
1500 msgstr ""
1501
1502 #: ../surfaceslab.py:78
1503 msgid "\ty: "
1504 msgstr ""
1505
1506 #: ../surfaceslab.py:79
1507 msgid "\tz: "
1508 msgstr ""
1509
1510 #. TRANSLATORS: This is a title of a window.
1511 #: ../surfaceslab.py:83
1512 msgid "Creating a surface."
1513 msgstr ""
1514
1515 #: ../surfaceslab.py:163
1516 msgid "Please enter an even value for orthogonal cell"
1517 msgstr ""
1518
1519 #: ../surfaceslab.py:176
1520 msgid "Please enter a value divisible by 3 for orthogonal cell"
1521 msgstr ""
1522
1523 #: ../surfaceslab.py:196
1524 msgid "Vacuum: {} Å."
1525 msgstr ""
1526
1527 #. TRANSLATORS: e.g. "Au fcc100 surface with 2 atoms."
1528 #. or "Au fcc100 surface with 2 atoms. Vacuum: 5 Å."
1529 #: ../surfaceslab.py:203
1530 #, python-brace-format
1531 msgid "{symbol} {surf} surface with one atom.{vacuum}"
1532 msgid_plural "{symbol} {surf} surface with {natoms} atoms.{vacuum}"
1533 msgstr[0] ""
1534 msgstr[1] ""
1535
1536 #: ../ui.py:45
1537 msgid "Error"
1538 msgstr ""
1539
1540 #: ../ui.py:52
1541 msgid "Version"
1542 msgstr ""
1543
1544 #: ../ui.py:53
1545 msgid "Web-page"
1546 msgstr ""
1547
1548 #: ../ui.py:54
1549 msgid "About"
1550 msgstr ""
1551
1552 #: ../ui.py:59 ../ui.py:63
1553 msgid "Help"
1554 msgstr ""
1555
1556 #: ../widgets.py:11
1557 msgid "Element:"
1558 msgstr ""
1559
1560 #: ../widgets.py:39
1561 msgid "No element specified!"
1562 msgstr ""
1563
1564 #: ../widgets.py:56
1565 msgid "ERROR: Invalid element!"
1566 msgstr ""
1567
1568 #: ../widgets.py:75
1569 msgid "No Python code"
1570 msgstr ""
88 msgstr ""
99 "Project-Id-Version: ase-3.5.2\n"
1010 "Report-Msgid-Bugs-To: ase-users@listserv.fysik.dtu.dk\n"
11 "POT-Creation-Date: 2017-09-20 19:21+0200\n"
12 "PO-Revision-Date: 2017-09-20 19:23+0200\n"
11 "POT-Creation-Date: 2017-12-15 17:25+0100\n"
12 "PO-Revision-Date: 2017-12-15 17:31+0100\n"
1313 "Last-Translator: Ask Hjorth Larsen <asklarsen@gmail.com>\n"
1414 "Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
1515 "Language: da\n"
2727 msgid "Add atoms"
2828 msgstr "Tilføj atomer"
2929
30 #: ../add.py:25
30 #: ../add.py:26
3131 msgid "Absolute position:"
3232 msgstr "Absolut position:"
3333
34 #: ../add.py:27 ../add.py:30 ../nanoparticle.py:264
34 #: ../add.py:28 ../add.py:31 ../nanoparticle.py:264
3535 msgid "Add"
3636 msgstr "Tilføj"
3737
38 #: ../add.py:28
38 #: ../add.py:29
3939 msgid "Relative to average position (of selection):"
4040 msgstr "Relativ til middelposition (af markering):"
4141
7171 msgid "By magnetic moment"
7272 msgstr "Efter magnetisk moment"
7373
74 #: ../colors.py:69
74 #: ../colors.py:26
75 msgid "By number of neighbors"
76 msgstr "Efter antal naboer"
77
78 #: ../colors.py:71
7579 msgid "Green"
7680 msgstr "Grøn"
7781
78 #: ../colors.py:69
82 #: ../colors.py:71
7983 msgid "Yellow"
8084 msgstr "Gul"
8185
158162 msgid " z: "
159163 msgstr " z: "
160164
161 #: ../crystal.py:97 ../surfaceslab.py:75 ../surfaceslab.py:76
162 #: ../surfaceslab.py:77
165 #: ../crystal.py:97 ../surfaceslab.py:76 ../surfaceslab.py:77
166 #: ../surfaceslab.py:78
163167 msgid " unit cells"
164168 msgstr " enhedsceller"
165169
237241 msgid " Element:\t"
238242 msgstr " Grundstof:\t"
239243
240 #: ../crystal.py:177
244 #: ../crystal.py:177 ../surfaceslab.py:76
241245 msgid "\tx: "
242246 msgstr "\tx: "
243247
263267 msgid "Please specify a consistent set of atoms."
264268 msgstr "Angiv venligst en konsistent samling atomer."
265269
266 #: ../crystal.py:407 ../graphene.py:264 ../nanoparticle.py:530
267 #: ../nanotube.py:84 ../surfaceslab.py:220
270 #: ../crystal.py:407 ../graphene.py:264 ../nanoparticle.py:531
271 #: ../nanotube.py:84 ../surfaceslab.py:223
268272 msgid "No valid atoms."
269273 msgstr "Ingen gyldige atomer."
270274
271 #: ../crystal.py:408 ../graphene.py:265 ../nanoparticle.py:531
272 #: ../nanotube.py:85 ../surfaceslab.py:221 ../widgets.py:76
275 #: ../crystal.py:408 ../graphene.py:265 ../nanoparticle.py:532
276 #: ../nanotube.py:85 ../surfaceslab.py:224 ../widgets.py:108
273277 msgid "You have not (yet) specified a consistent set of parameters."
274278 msgstr "Du har (endnu) ikke angivet konsistente parametre."
275279
327331 "Konstruér et grafénlag eller et grafénnanobånd. Et nanobånd kan eventuelt\n"
328332 "mættes med hydrogen (eller et andet grundstof)."
329333
330 #: ../graphene.py:38 ../gui.py:512
334 #: ../graphene.py:38 ../gui.py:514
331335 msgid "Graphene"
332336 msgstr "Grafén"
333337
388392 msgstr " Længde: "
389393
390394 #. Vacuum
391 #: ../graphene.py:105 ../surfaceslab.py:78
395 #: ../graphene.py:105 ../surfaceslab.py:79
392396 msgid "Vacuum: "
393397 msgstr "Vakuum: "
394398
462466 msgid "Save data to file ... "
463467 msgstr "Gem data til fil …"
464468
465 #: ../gui.py:286
469 #: ../gui.py:284
466470 msgid "Automatic"
467471 msgstr "Automatisk"
468472
469 #: ../gui.py:304
473 #: ../gui.py:302
470474 msgid "Open ..."
471475 msgstr "Åbn …"
472476
473 #: ../gui.py:305
477 #: ../gui.py:303
474478 msgid "Choose parser:"
475479 msgstr "Vælg fortolker:"
476480
477 #: ../gui.py:416
481 #: ../gui.py:418
478482 msgid "_File"
479483 msgstr "_Fil"
480484
481 #: ../gui.py:417
485 #: ../gui.py:419
482486 msgid "_Open"
483487 msgstr "_Åbn"
484488
485 #: ../gui.py:418
489 #: ../gui.py:420
486490 msgid "_New"
487491 msgstr "_Ny"
488492
489 #: ../gui.py:419
493 #: ../gui.py:421
490494 msgid "_Save"
491495 msgstr "_Gem"
492496
493 #: ../gui.py:421
497 #: ../gui.py:423
494498 msgid "_Quit"
495499 msgstr "_Afslut"
496500
497 #: ../gui.py:423
501 #: ../gui.py:425
498502 msgid "_Edit"
499503 msgstr "_Redigér"
500504
501 #: ../gui.py:424
505 #: ../gui.py:426
502506 msgid "Select _all"
503507 msgstr "Vælg _alle"
504508
505 #: ../gui.py:425
509 #: ../gui.py:427
506510 msgid "_Invert selection"
507511 msgstr "_Omvend markering"
508512
509 #: ../gui.py:426
513 #: ../gui.py:428
510514 msgid "Select _constrained atoms"
511515 msgstr "Vælg _fastgjorte atomer"
512516
513 #: ../gui.py:427
517 #: ../gui.py:429
514518 msgid "Select _immobile atoms"
515519 msgstr "Vælg _immobile atomer"
516520
517 #: ../gui.py:433
521 #: ../gui.py:434
518522 msgid "Hide selected atoms"
519523 msgstr "Skjul markerede atomer"
520524
521 #: ../gui.py:434
525 #: ../gui.py:435
522526 msgid "Show selected atoms"
523527 msgstr "Vis markerede atomer"
524528
525 #: ../gui.py:436
529 #: ../gui.py:437
526530 msgid "_Modify"
527531 msgstr "_Ændr"
528532
529 #: ../gui.py:437
533 #: ../gui.py:438
530534 msgid "_Add atoms"
531535 msgstr "_Tilføj atomer"
532536
533 #: ../gui.py:438
537 #: ../gui.py:439
534538 msgid "_Delete selected atoms"
535539 msgstr "_Slet markerede atomer"
536540
537541 #: ../gui.py:441
542 msgid "Edit _cell"
543 msgstr "Redigér _celle"
544
545 #: ../gui.py:443
538546 msgid "_First image"
539 msgstr "_Første billede"
540
541 #: ../gui.py:442
547 msgstr "Første _billede"
548
549 #: ../gui.py:444
542550 msgid "_Previous image"
543551 msgstr "_Forrige billede"
544552
545 #: ../gui.py:443
553 #: ../gui.py:445
546554 msgid "_Next image"
547555 msgstr "_Næste billede"
548556
549 #: ../gui.py:444
557 #: ../gui.py:446
550558 msgid "_Last image"
551559 msgstr "_Sidste billede"
552560
553 #: ../gui.py:446
561 #: ../gui.py:448
554562 msgid "_View"
555563 msgstr "_Vis"
556564
557 #: ../gui.py:447
565 #: ../gui.py:449
558566 msgid "Show _unit cell"
559567 msgstr "Vis _enhedscelle"
560568
561 #: ../gui.py:449
569 #: ../gui.py:451
562570 msgid "Show _axes"
563571 msgstr "Vis _akser"
564572
565 #: ../gui.py:450
573 #: ../gui.py:452
566574 msgid "Show _bonds"
567575 msgstr "Vis _bindinger"
568576
569 #: ../gui.py:452
577 #: ../gui.py:454
570578 msgid "Show _velocities"
571579 msgstr "Vis _hastigheder"
572580
573 #: ../gui.py:454
581 #: ../gui.py:456
574582 msgid "Show _forces"
575583 msgstr "Vis _kræfter"
576584
577 #: ../gui.py:456
585 #: ../gui.py:458
578586 msgid "Show _Labels"
579587 msgstr "Vis _etiketter"
580588
581 #: ../gui.py:457
589 #: ../gui.py:459
582590 msgid "_None"
583591 msgstr "_Ingen"
584592
585 #: ../gui.py:458
593 #: ../gui.py:460
586594 msgid "Atom _Index"
587595 msgstr "Atom_indeks"
588596
589 #: ../gui.py:459
597 #: ../gui.py:461
590598 msgid "_Magnetic Moments"
591599 msgstr "_Magnetiske momenter"
592600
593601 #. XXX check if exist
594 #: ../gui.py:460
602 #: ../gui.py:462
595603 msgid "_Element Symbol"
596604 msgstr "_Kemisk symbol"
597605
598 #: ../gui.py:461
606 #: ../gui.py:463
599607 msgid "_Initial Charges"
600608 msgstr "_Startladninger"
601609
602 #: ../gui.py:464
610 #: ../gui.py:466
603611 msgid "Quick Info ..."
604612 msgstr "Hurtig info …"
605613
606 #: ../gui.py:465
614 #: ../gui.py:467
607615 msgid "Repeat ..."
608616 msgstr "Gentag …"
609617
610 #: ../gui.py:466
618 #: ../gui.py:468
611619 msgid "Rotate ..."
612620 msgstr "Rotér …"
613621
614 #: ../gui.py:467
622 #: ../gui.py:469
615623 msgid "Colors ..."
616624 msgstr "Farver …"
617625
618626 #. TRANSLATORS: verb
619 #: ../gui.py:469
627 #: ../gui.py:471
620628 msgid "Focus"
621629 msgstr "Fokusér"
622630
623 #: ../gui.py:470
631 #: ../gui.py:472
624632 msgid "Zoom in"
625633 msgstr "Zoom ind"
626634
627 #: ../gui.py:471
635 #: ../gui.py:473
628636 msgid "Zoom out"
629637 msgstr "Zoom ud"
630638
631 #: ../gui.py:472
639 #: ../gui.py:474
632640 msgid "Change View"
633641 msgstr "Skift perspektiv"
634642
635 #: ../gui.py:474
643 #: ../gui.py:476
636644 msgid "Reset View"
637645 msgstr "Nulstil perspektiv"
638646
639 #: ../gui.py:475
647 #: ../gui.py:477
640648 msgid "xy-plane"
641649 msgstr "xy-plan"
642650
643 #: ../gui.py:476
651 #: ../gui.py:478
644652 msgid "yz-plane"
645653 msgstr "yz-plan"
646654
647 #: ../gui.py:477
655 #: ../gui.py:479
648656 msgid "zx-plane"
649657 msgstr "zx-plan"
650658
651 #: ../gui.py:478
659 #: ../gui.py:480
652660 msgid "yx-plane"
653661 msgstr "yx-plan"
654662
655 #: ../gui.py:479
663 #: ../gui.py:481
656664 msgid "zy-plane"
657665 msgstr "zy-plan"
658666
659 #: ../gui.py:480
667 #: ../gui.py:482
660668 msgid "xz-plane"
661669 msgstr "xz-plan"
662670
663 #: ../gui.py:481
671 #: ../gui.py:483
664672 msgid "a2,a3-plane"
665673 msgstr "a2,a3-plan"
666674
667 #: ../gui.py:482
675 #: ../gui.py:484
668676 msgid "a3,a1-plane"
669677 msgstr "a3,a1-plan"
670678
671 #: ../gui.py:483
679 #: ../gui.py:485
672680 msgid "a1,a2-plane"
673681 msgstr "a1,a2-plan"
674682
675 #: ../gui.py:484
683 #: ../gui.py:486
676684 msgid "a3,a2-plane"
677685 msgstr "a3,a2-plan"
678686
679 #: ../gui.py:485
687 #: ../gui.py:487
680688 msgid "a1,a3-plane"
681689 msgstr "a1,a3-plan"
682690
683 #: ../gui.py:486
691 #: ../gui.py:488
684692 msgid "a2,a1-plane"
685693 msgstr "a2,a1-plan"
686694
687 #: ../gui.py:487
695 #: ../gui.py:489
688696 msgid "Settings ..."
689697 msgstr "Indstillinger …"
690698
691 #: ../gui.py:489
699 #: ../gui.py:491
692700 msgid "VMD"
693701 msgstr "VMD"
694702
695 #: ../gui.py:490
703 #: ../gui.py:492
696704 msgid "RasMol"
697705 msgstr "RasMol"
698706
699 #: ../gui.py:491
707 #: ../gui.py:493
700708 msgid "xmakemol"
701709 msgstr "xmakemol"
702710
703 #: ../gui.py:492
711 #: ../gui.py:494
704712 msgid "avogadro"
705713 msgstr "avogadro"
706714
707 #: ../gui.py:494
715 #: ../gui.py:496
708716 msgid "_Tools"
709717 msgstr "_Værktøjer"
710718
711 #: ../gui.py:495
719 #: ../gui.py:497
712720 msgid "Graphs ..."
713721 msgstr "Grafer …"
714722
715 #: ../gui.py:496
723 #: ../gui.py:498
716724 msgid "Movie ..."
717725 msgstr "Film …"
718726
719 #: ../gui.py:497
727 #: ../gui.py:499
720728 msgid "Expert mode ..."
721729 msgstr "Eksperttilstand …"
722730
723 #: ../gui.py:498
731 #: ../gui.py:500
724732 msgid "Constraints ..."
725733 msgstr "Begrænsninger …"
726734
727735 # gemmer et billede af atomerne
728 #: ../gui.py:499
736 #: ../gui.py:501
729737 msgid "Render scene ..."
730738 msgstr "Tegn struktur …"
731739
732 #: ../gui.py:500
740 #: ../gui.py:502
733741 msgid "_Move atoms"
734742 msgstr "_Flyt atomer"
735743
736 #: ../gui.py:501
744 #: ../gui.py:503
737745 msgid "_Rotate atoms"
738746 msgstr "_Rotér atomer"
739747
740 #: ../gui.py:502
748 #: ../gui.py:504
741749 msgid "NE_B"
742750 msgstr "NE_B"
743751
744 #: ../gui.py:503
752 #: ../gui.py:505
745753 msgid "B_ulk Modulus"
746754 msgstr "K_ompressibilitetsmodul"
747755
748756 #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
749 #: ../gui.py:506
757 #: ../gui.py:508
750758 msgid "_Setup"
751759 msgstr "_Byg"
752760
753 #: ../gui.py:507
761 #: ../gui.py:509
754762 msgid "_Bulk Crystal"
755763 msgstr "_Krystal"
756764
757 #: ../gui.py:508
765 #: ../gui.py:510
758766 msgid "_Surface slab"
759767 msgstr "_Overflade"
760768
761 #: ../gui.py:509
769 #: ../gui.py:511
762770 msgid "_Nanoparticle"
763771 msgstr "_Nanopartikel"
764772
765 #: ../gui.py:511
773 #: ../gui.py:513
766774 msgid "Nano_tube"
767775 msgstr "Nano_rør"
768776
769 #: ../gui.py:514
777 #: ../gui.py:516
770778 msgid "_Calculate"
771779 msgstr "_Beregn"
772780
773 #: ../gui.py:515
781 #: ../gui.py:517
774782 msgid "Set _Calculator"
775783 msgstr "Angiv _beregner"
776784
777 #: ../gui.py:516
785 #: ../gui.py:518
778786 msgid "_Energy and Forces"
779787 msgstr "_Energi og kræfter"
780788
781 #: ../gui.py:517
789 #: ../gui.py:519
782790 msgid "Energy Minimization"
783791 msgstr "Energiminimering"
784792
785 #: ../gui.py:520
793 #: ../gui.py:522
786794 msgid "_Help"
787795 msgstr "_Hjælp"
788796
789 #: ../gui.py:521
797 #: ../gui.py:523
790798 msgid "_About"
791799 msgstr "_Om"
792800
793 #: ../gui.py:525
801 #: ../gui.py:527
794802 msgid "Webpage ..."
795803 msgstr "Webside …"
796804
10201028 msgid "Creating a nanoparticle."
10211029 msgstr "Konstruktion af nanopartikel."
10221030
1023 #: ../nanoparticle.py:197 ../nanotube.py:52 ../surfaceslab.py:82
1031 #: ../nanoparticle.py:197 ../nanotube.py:52 ../surfaceslab.py:83
10241032 msgid "Apply"
10251033 msgstr "Anvend"
10261034
1027 #: ../nanoparticle.py:198 ../nanotube.py:53 ../surfaceslab.py:83
1035 #: ../nanoparticle.py:198 ../nanotube.py:53 ../surfaceslab.py:84
10281036 msgid "OK"
10291037 msgstr "OK"
10301038
11481156 msgid "Length:"
11491157 msgstr "Længde:"
11501158
1151 #: ../quickinfo.py:6
1159 #: ../quickinfo.py:28
1160 msgid "This frame has no atoms."
1161 msgstr "Dette billede har ingen atomer."
1162
1163 #: ../quickinfo.py:33
11521164 msgid "Single image loaded."
11531165 msgstr "Enkelt billede indlæst."
11541166
1155 #: ../quickinfo.py:7
1156 #, python-format
1157 msgid "Image %d loaded (0 - %d)."
1158 msgstr "Billede %d indlæst (0 – %d)."
1159
1160 #: ../quickinfo.py:8
1167 #: ../quickinfo.py:35
1168 msgid "Image {} loaded (0–{})."
1169 msgstr "Billede {} indlæst (0–{})."
1170
1171 #: ../quickinfo.py:37
1172 msgid "Number of atoms: {}"
1173 msgstr "Antal atomer: {}"
1174
1175 #: ../quickinfo.py:47
1176 msgid "Unit cell [Å]:"
1177 msgstr "Enhedscelle [Å]:"
1178
1179 #: ../quickinfo.py:49
1180 msgid "no"
1181 msgstr "nej"
1182
1183 #: ../quickinfo.py:49
1184 msgid "yes"
1185 msgstr "ja"
1186
1187 #. TRANSLATORS: This has the form Periodic: no, no, yes
1188 #: ../quickinfo.py:51
1189 msgid "Periodic: {}, {}, {}"
1190 msgstr "Periodisk: {}, {}, {}"
1191
1192 #: ../quickinfo.py:55
11611193 msgid "Unit cell is fixed."
11621194 msgstr "Enhedscelle fastholdes."
11631195
1164 #: ../quickinfo.py:9
1196 #: ../quickinfo.py:57
11651197 msgid "Unit cell varies."
11661198 msgstr "Enhedscelle varierer."
11671199
1168 #: ../quickinfo.py:11
1169 #, python-format
1170 msgid ""
1171 "%s\n"
1172 "\n"
1173 "Number of atoms: %d.\n"
1174 "\n"
1175 "Unit cell:\n"
1176 " %8.3f %8.3f %8.3f\n"
1177 " %8.3f %8.3f %8.3f\n"
1178 " %8.3f %8.3f %8.3f\n"
1179 "\n"
1180 "%s\n"
1181 "%s\n"
1182 msgstr ""
1183 "%s\n"
1184 "\n"
1185 "Antal atomer: %d.\n"
1186 "\n"
1187 "Enhedscelle:\n"
1188 " %8.3f %8.3f %8.3f\n"
1189 " %8.3f %8.3f %8.3f\n"
1190 " %8.3f %8.3f %8.3f\n"
1191 "\n"
1192 "%s\n"
1193 "%s\n"
1194
1195 #: ../quickinfo.py:33
1196 msgid "This frame has no atoms."
1197 msgstr "Dette billede har ingen atomer."
1198
1199 #: ../quickinfo.py:53
1200 msgid "no"
1201 msgstr "nej"
1202
1203 #: ../quickinfo.py:53
1204 msgid "yes"
1205 msgstr "ja"
1206
1207 #. TRANSLATORS: This has the form Periodic: no, no, yes
1208 #: ../quickinfo.py:57
1209 #, python-format
1210 msgid "Periodic: %s, %s, %s"
1211 msgstr "Periodisk: %s, %s, %s"
1212
1213 #: ../quickinfo.py:61
1214 msgid "Volume: "
1215 msgstr "Volumen: "
1200 #: ../quickinfo.py:60
1201 msgid "Volume: {:.3f} ų"
1202 msgstr "Volumen: {:.3f} ų"
1203
1204 #: ../quickinfo.py:88
1205 msgid "Calculator: {} (cached)"
1206 msgstr "Beregner: {} (gemt)"
1207
1208 #: ../quickinfo.py:90
1209 msgid "Calculator: {} (attached)"
1210 msgstr "Beregner: {} (tilknyttet)"
1211
1212 #: ../quickinfo.py:97
1213 msgid "Energy: {:.3f} eV"
1214 msgstr "Energi: {:.3f} eV"
1215
1216 #: ../quickinfo.py:102
1217 msgid "Max force: {:.3f} eV/Å"
1218 msgstr "Maks. kraft: {:.3f} eV/Å"
1219
1220 #: ../quickinfo.py:107
1221 msgid "Magmom: {:.3f} µ"
1222 msgstr "Magmom: {:.3f} µ"
12161223
12171224 # gemmer et billede af atomerne
12181225 #: ../render.py:20 ../render.py:190
16091616 msgid "FCC(110)"
16101617 msgstr "FCC(110)"
16111618
1612 #: ../surfaceslab.py:26 ../surfaceslab.py:170
1619 #: ../surfaceslab.py:26 ../surfaceslab.py:173
16131620 msgid "FCC(111)"
16141621 msgstr "FCC(111)"
16151622
1616 #: ../surfaceslab.py:27 ../surfaceslab.py:173
1623 #: ../surfaceslab.py:27 ../surfaceslab.py:176
16171624 msgid "FCC(211)"
16181625 msgstr "FCC(211)"
16191626
16251632 msgid "bcc"
16261633 msgstr "bcc"
16271634
1628 #: ../surfaceslab.py:29 ../surfaceslab.py:167
1635 #: ../surfaceslab.py:29 ../surfaceslab.py:170
16291636 msgid "BCC(110)"
16301637 msgstr "BCC(110)"
16311638
1632 #: ../surfaceslab.py:30 ../surfaceslab.py:164
1639 #: ../surfaceslab.py:30 ../surfaceslab.py:167
16331640 msgid "BCC(111)"
16341641 msgstr "BCC(111)"
16351642
1636 #: ../surfaceslab.py:31 ../surfaceslab.py:177
1643 #: ../surfaceslab.py:31 ../surfaceslab.py:180
16371644 msgid "HCP(0001)"
16381645 msgstr "HCP(0001)"
16391646
1640 #: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:131
1641 #: ../surfaceslab.py:187
1647 #: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:134
1648 #: ../surfaceslab.py:190
16421649 msgid "hcp"
16431650 msgstr "hcp"
16441651
1645 #: ../surfaceslab.py:32 ../surfaceslab.py:180
1652 #: ../surfaceslab.py:32 ../surfaceslab.py:183
16461653 msgid "HCP(10-10)"
16471654 msgstr "HCP(10–10)"
16481655
16671674 msgstr "Ortogonal celle:"
16681675
16691676 #: ../surfaceslab.py:72
1670 msgid "Lattice constant:\ta"
1671 msgstr "Gitterkonstant:\ta"
1677 msgid "Lattice constant:"
1678 msgstr "Gitterkonstant:"
1679
1680 #: ../surfaceslab.py:73
1681 msgid "\ta"
1682 msgstr "\ta"
16721683
16731684 #: ../surfaceslab.py:74
1674 msgid "\t\tc"
1675 msgstr "\t\tc"
1685 msgid "\tc"
1686 msgstr "\tc"
16761687
16771688 #: ../surfaceslab.py:75
1678 msgid "Size: \tx: "
1679 msgstr "Størr.:\tx: "
1680
1681 #: ../surfaceslab.py:76
1689 msgid "Size:"
1690 msgstr "Størrelse:"
1691
1692 #: ../surfaceslab.py:77
16821693 msgid "\ty: "
16831694 msgstr "\ty: "
16841695
1685 #: ../surfaceslab.py:77
1696 #: ../surfaceslab.py:78
16861697 msgid "\tz: "
16871698 msgstr "\tz: "
16881699
16891700 #. TRANSLATORS: This is a title of a window.
1690 #: ../surfaceslab.py:81
1701 #: ../surfaceslab.py:82
16911702 msgid "Creating a surface."
16921703 msgstr "Oprettelse af overflade."
16931704
1694 #: ../surfaceslab.py:161
1705 #. TRANSLATORS: E.g. "... assume fcc crystal structure for Au"
1706 #: ../surfaceslab.py:110
1707 msgid "Error: Reference values assume {} crystal structure for {}!"
1708 msgstr "Fejl: Referenceværdierne antager {}-krystralstruktur for {}!"
1709
1710 #: ../surfaceslab.py:164
16951711 msgid "Please enter an even value for orthogonal cell"
16961712 msgstr "Indtast venligst en lige værdi for ortogonal celle"
16971713
1698 #: ../surfaceslab.py:174
1714 #: ../surfaceslab.py:177
16991715 msgid "Please enter a value divisible by 3 for orthogonal cell"
17001716 msgstr "Indtast venligst en værdi delelig med 3 for ortogonal celle"
17011717
1702 #: ../surfaceslab.py:194
1718 #: ../surfaceslab.py:197
17031719 msgid " Vacuum: {} Å."
17041720 msgstr " Vakuum: {} Å."
17051721
17061722 #. TRANSLATORS: e.g. "Au fcc100 surface with 2 atoms."
17071723 #. or "Au fcc100 surface with 2 atoms. Vacuum: 5 Å."
1708 #: ../surfaceslab.py:202
1724 #: ../surfaceslab.py:205
17091725 #, python-brace-format
17101726 msgid "{symbol} {surf} surface with one atom.{vacuum}"
17111727 msgid_plural "{symbol} {surf} surface with {natoms} atoms.{vacuum}"
17281744 msgid "About"
17291745 msgstr "Om"
17301746
1731 #: ../ui.py:60 ../ui.py:64
1747 #: ../ui.py:60 ../ui.py:64 ../widgets.py:17
17321748 msgid "Help"
17331749 msgstr "Hjælp"
17341750
1735 #: ../widgets.py:11
1751 #: ../widgets.py:14
17361752 msgid "Element:"
17371753 msgstr "Grundstof:"
17381754
1739 #: ../widgets.py:39
1755 #. This infobox is indescribably ugly because of the
1756 #. ridiculously large font size used by Tkinter. Ouch!
1757 #: ../widgets.py:34
1758 msgid ""
1759 "Enter a chemical symbol or the name of a molecule from the G2 testset:\n"
1760 "{}"
1761 msgstr ""
1762 "Indtast et kemisk symbol eller navnet på et molekyle fra G2-testsættet:\n"
1763 "{}"
1764
1765 #: ../widgets.py:68
17401766 msgid "No element specified!"
17411767 msgstr "Intet grundstof angivet!"
17421768
1743 #: ../widgets.py:56
1769 #: ../widgets.py:90
17441770 msgid "ERROR: Invalid element!"
17451771 msgstr "FEJL: ugyldigt grundstof!"
17461772
1747 #: ../widgets.py:75
1773 #: ../widgets.py:107
17481774 msgid "No Python code"
17491775 msgstr "Ingen Pythonkode"
1776
1777 #~ msgid ""
1778 #~ "%s\n"
1779 #~ "\n"
1780 #~ "Number of atoms: %d.\n"
1781 #~ "\n"
1782 #~ "Unit cell:\n"
1783 #~ " %8.3f %8.3f %8.3f\n"
1784 #~ " %8.3f %8.3f %8.3f\n"
1785 #~ " %8.3f %8.3f %8.3f\n"
1786 #~ "\n"
1787 #~ "%s\n"
1788 #~ "%s\n"
1789 #~ msgstr ""
1790 #~ "%s\n"
1791 #~ "\n"
1792 #~ "Antal atomer: %d.\n"
1793 #~ "\n"
1794 #~ "Enhedscelle:\n"
1795 #~ " %8.3f %8.3f %8.3f\n"
1796 #~ " %8.3f %8.3f %8.3f\n"
1797 #~ " %8.3f %8.3f %8.3f\n"
1798 #~ "\n"
1799 #~ "%s\n"
1800 #~ "%s\n"
1801
1802 #~ msgid "Volume: "
1803 #~ msgstr "Volumen: "
1804
1805 #~ msgid "Size: \tx: "
1806 #~ msgstr "Størr.:\tx: "
17501807
17511808 #~ msgid ""
17521809 #~ "To make most calculations on the atoms, a Calculator object must first\n"
20232080
20242081 #~ msgid "Select calculator"
20252082 #~ msgstr "Vælg beregner"
2026
2027 #~ msgid "Calculator:"
2028 #~ msgstr "Beregner:"
20292083
20302084 #~ msgid "None"
20312085 #~ msgstr "Ingen"
25292583 #~ msgid "Density: "
25302584 #~ msgstr "Tæthed: "
25312585
2532 #~ msgid "Energy: "
2533 #~ msgstr "Energi: "
2534
25352586 #~ msgid "GPAW version: "
25362587 #~ msgstr "GPAW-version: "
25372588
31103161
31113162 #~ msgid "Max force: %.2f (this frame), %.2f (all frames)"
31123163 #~ msgstr "Maks. kraft: %.2f (dette billede), %.2f (alle billeder)"
3113
3114 #~ msgid "Max force: %.2f."
3115 #~ msgstr "Maks. kraft: %.2f."
31163164
31173165 #~ msgid "Max velocity: %.2f (this frame), %.2f (all frames)"
31183166 #~ msgstr "Maks. hastighed: %.2f (dette billede), %.2f (alle billeder)"
99 msgstr ""
1010 "Project-Id-Version: ase\n"
1111 "Report-Msgid-Bugs-To: ase-users@listserv.fysik.dtu.dk\n"
12 "POT-Creation-Date: 2017-09-28 19:11+0200\n"
13 "PO-Revision-Date: 2017-09-28 19:13+0200\n"
12 "POT-Creation-Date: 2017-12-15 17:25+0100\n"
13 "PO-Revision-Date: 2017-12-15 17:38+0100\n"
1414 "Last-Translator: Robert Warmbier <Robert.Warmbier@wits.ac.za>\n"
1515 "Language-Team: German\n"
1616 "Language: de\n"
2828 msgid "Add atoms"
2929 msgstr "Füge Atome hinzu"
3030
31 #: ../add.py:25
31 #: ../add.py:26
3232 msgid "Absolute position:"
3333 msgstr "Absolute Position:"
3434
35 #: ../add.py:27 ../add.py:30 ../nanoparticle.py:264
35 #: ../add.py:28 ../add.py:31 ../nanoparticle.py:264
3636 msgid "Add"
3737 msgstr "Hinzufügen"
3838
39 #: ../add.py:28
39 #: ../add.py:29
4040 msgid "Relative to average position (of selection):"
4141 msgstr "Relativ zur gemittelten Position (von Auswahl):"
4242
7474 msgid "By magnetic moment"
7575 msgstr "Gemäß Magnetischem Moment"
7676
77 #: ../colors.py:69
77 #: ../colors.py:26
78 #, fuzzy
79 #| msgid "Number of layers:"
80 msgid "By number of neighbors"
81 msgstr "Lagenzahl:"
82
83 #: ../colors.py:71
7884 msgid "Green"
7985 msgstr "Grün"
8086
81 #: ../colors.py:69
87 #: ../colors.py:71
8288 msgid "Yellow"
8389 msgstr "Gelb"
8490
152158 msgid " z: "
153159 msgstr " z: "
154160
155 #: ../crystal.py:97 ../surfaceslab.py:75 ../surfaceslab.py:76
156 #: ../surfaceslab.py:77
161 #: ../crystal.py:97 ../surfaceslab.py:76 ../surfaceslab.py:77
162 #: ../surfaceslab.py:78
157163 msgid " unit cells"
158164 msgstr " Einheitszelle"
159165
231237 msgid " Element:\t"
232238 msgstr " Element:\t"
233239
234 #: ../crystal.py:177
240 #: ../crystal.py:177 ../surfaceslab.py:76
235241 msgid "\tx: "
236242 msgstr "\tx: "
237243
257263 msgid "Please specify a consistent set of atoms."
258264 msgstr "Bitte konsistente Atommenge spezifizieren."
259265
260 #: ../crystal.py:407 ../graphene.py:264 ../nanoparticle.py:530
261 #: ../nanotube.py:84 ../surfaceslab.py:220
266 #: ../crystal.py:407 ../graphene.py:264 ../nanoparticle.py:531
267 #: ../nanotube.py:84 ../surfaceslab.py:223
262268 msgid "No valid atoms."
263269 msgstr "Keine gültigen Atome."
264270
265 #: ../crystal.py:408 ../graphene.py:265 ../nanoparticle.py:531
266 #: ../nanotube.py:85 ../surfaceslab.py:221 ../widgets.py:76
271 #: ../crystal.py:408 ../graphene.py:265 ../nanoparticle.py:532
272 #: ../nanotube.py:85 ../surfaceslab.py:224 ../widgets.py:108
267273 msgid "You have not (yet) specified a consistent set of parameters."
268274 msgstr "(Noch) kein konsistenter Parametersatz spezifiziert."
269275
321327 "Bereite Graphenlage oder Graphen Nanoribbon vor. Ein Nanoribbon kann\n"
322328 "optional mit Wasserstoff (oder einem anderen Element) saturiert werden"
323329
324 #: ../graphene.py:38 ../gui.py:512
330 #: ../graphene.py:38 ../gui.py:514
325331 msgid "Graphene"
326332 msgstr "Graphen"
327333
382388 msgstr " Länge: "
383389
384390 #. Vacuum
385 #: ../graphene.py:105 ../surfaceslab.py:78
391 #: ../graphene.py:105 ../surfaceslab.py:79
386392 msgid "Vacuum: "
387393 msgstr "Vakuum: "
388394
435441 msgid "Save data to file ... "
436442 msgstr "Speichere Daten in Datei …"
437443
438 #: ../gui.py:286
444 #: ../gui.py:284
439445 msgid "Automatic"
440446 msgstr "Automatisch"
441447
442 #: ../gui.py:304
448 #: ../gui.py:302
443449 msgid "Open ..."
444450 msgstr "Öffne …"
445451
446 #: ../gui.py:305
452 #: ../gui.py:303
447453 msgid "Choose parser:"
448454 msgstr "Wähle Interpreter:"
449455
450 #: ../gui.py:416
456 #: ../gui.py:418
451457 msgid "_File"
452458 msgstr "_Datei"
453459
454 #: ../gui.py:417
460 #: ../gui.py:419
455461 msgid "_Open"
456462 msgstr "_Öffnen"
457463
458 #: ../gui.py:418
464 #: ../gui.py:420
459465 msgid "_New"
460466 msgstr "_Neu"
461467
462 #: ../gui.py:419
468 #: ../gui.py:421
463469 msgid "_Save"
464470 msgstr "_Speichern"
465471
466 #: ../gui.py:421
472 #: ../gui.py:423
467473 msgid "_Quit"
468474 msgstr "_Beenden"
469475
470 #: ../gui.py:423
476 #: ../gui.py:425
471477 msgid "_Edit"
472478 msgstr "_Bearbeiten"
473479
474 #: ../gui.py:424
480 #: ../gui.py:426
475481 msgid "Select _all"
476482 msgstr "Wähle _alle aus"
477483
478 #: ../gui.py:425
484 #: ../gui.py:427
479485 msgid "_Invert selection"
480486 msgstr "_Invertiere Auswahl"
481487
482 #: ../gui.py:426
488 #: ../gui.py:428
483489 msgid "Select _constrained atoms"
484490 msgstr "Wähle _constraint Atome"
485491
486 #: ../gui.py:427
492 #: ../gui.py:429
487493 msgid "Select _immobile atoms"
488494 msgstr "Wähle unbewegl_iche Atome aus"
489495
490 #: ../gui.py:433
496 #: ../gui.py:434
491497 msgid "Hide selected atoms"
492498 msgstr "Verstecke ausgewählte Atome"
493499
494 #: ../gui.py:434
500 #: ../gui.py:435
495501 msgid "Show selected atoms"
496502 msgstr "Zeige ausgewählte Atome"
497503
498 #: ../gui.py:436
504 #: ../gui.py:437
499505 msgid "_Modify"
500506 msgstr "_Modifizieren"
501507
502 #: ../gui.py:437
508 #: ../gui.py:438
503509 msgid "_Add atoms"
504510 msgstr "Füge _Atome hinzu"
505511
506 #: ../gui.py:438
512 #: ../gui.py:439
507513 msgid "_Delete selected atoms"
508514 msgstr "_Lösche ausgewählte Atome"
509515
510516 #: ../gui.py:441
517 msgid "Edit _cell"
518 msgstr "Einheits_zelle bearbeiten"
519
520 #: ../gui.py:443
511521 msgid "_First image"
512522 msgstr "_Erstes Bild"
513523
514 #: ../gui.py:442
524 #: ../gui.py:444
515525 msgid "_Previous image"
516526 msgstr "_Vorheriges Bild"
517527
518 #: ../gui.py:443
528 #: ../gui.py:445
519529 msgid "_Next image"
520530 msgstr "_Nächstes Bild"
521531
522 #: ../gui.py:444
532 #: ../gui.py:446
523533 msgid "_Last image"
524534 msgstr "_Letztes Bild"
525535
526 #: ../gui.py:446
536 #: ../gui.py:448
527537 msgid "_View"
528538 msgstr "_Ansehen"
529539
530 #: ../gui.py:447
540 #: ../gui.py:449
531541 msgid "Show _unit cell"
532542 msgstr "Zeige _Einheitszelle"
533543
534 #: ../gui.py:449
544 #: ../gui.py:451
535545 msgid "Show _axes"
536546 msgstr "Zeige _Achsen"
537547
538 #: ../gui.py:450
548 #: ../gui.py:452
539549 msgid "Show _bonds"
540550 msgstr "Zeige _Bindungen"
541551
542 #: ../gui.py:452
552 #: ../gui.py:454
543553 msgid "Show _velocities"
544554 msgstr "Zeige _Geschwindigkeiten"
545555
546 #: ../gui.py:454
556 #: ../gui.py:456
547557 msgid "Show _forces"
548558 msgstr "Zeige Krä_fte"
549559
550 #: ../gui.py:456
560 #: ../gui.py:458
551561 msgid "Show _Labels"
552562 msgstr "Zeige _Label"
553563
554 #: ../gui.py:457
564 #: ../gui.py:459
555565 msgid "_None"
556566 msgstr "_Keine"
557567
558 #: ../gui.py:458
568 #: ../gui.py:460
559569 msgid "Atom _Index"
560570 msgstr "Atom_index"
561571
562 #: ../gui.py:459
572 #: ../gui.py:461
563573 msgid "_Magnetic Moments"
564574 msgstr "_Magnetische Momente"
565575
566576 #. XXX check if exist
567 #: ../gui.py:460
577 #: ../gui.py:462
568578 msgid "_Element Symbol"
569579 msgstr "_Elementsymbol"
570580
571 #: ../gui.py:461
581 #: ../gui.py:463
572582 msgid "_Initial Charges"
573583 msgstr ""
574584
575 #: ../gui.py:464
585 #: ../gui.py:466
576586 msgid "Quick Info ..."
577587 msgstr "Kurzinfo …"
578588
579 #: ../gui.py:465
589 #: ../gui.py:467
580590 msgid "Repeat ..."
581591 msgstr "Wiederhole …"
582592
583 #: ../gui.py:466
593 #: ../gui.py:468
584594 msgid "Rotate ..."
585595 msgstr "Rotieren …"
586596
587 #: ../gui.py:467
597 #: ../gui.py:469
588598 msgid "Colors ..."
589599 msgstr "Farben …"
590600
591601 #. TRANSLATORS: verb
592 #: ../gui.py:469
602 #: ../gui.py:471
593603 msgid "Focus"
594604 msgstr "Fokus"
595605
596 #: ../gui.py:470
606 #: ../gui.py:472
597607 msgid "Zoom in"
598608 msgstr "Reinzoomen"
599609
600 #: ../gui.py:471
610 #: ../gui.py:473
601611 msgid "Zoom out"
602612 msgstr "Rauszoomen"
603613
604 #: ../gui.py:472
614 #: ../gui.py:474
605615 msgid "Change View"
606616 msgstr "Ändere Perspektive"
607617
608 #: ../gui.py:474
618 #: ../gui.py:476
609619 msgid "Reset View"
610620 msgstr "Setze Perspektive Zurück"
611621
612 #: ../gui.py:475
622 #: ../gui.py:477
613623 msgid "xy-plane"
614624 msgstr "xy-Ebene"
615625
616 #: ../gui.py:476
626 #: ../gui.py:478
617627 msgid "yz-plane"
618628 msgstr "yz-Ebene"
619629
620 #: ../gui.py:477
630 #: ../gui.py:479
621631 msgid "zx-plane"
622632 msgstr "zx-Ebene"
623633
624 #: ../gui.py:478
634 #: ../gui.py:480
625635 msgid "yx-plane"
626636 msgstr "yx-Ebene"
627637
628 #: ../gui.py:479
638 #: ../gui.py:481
629639 msgid "zy-plane"
630640 msgstr "zy-Ebene"
631641
632 #: ../gui.py:480
642 #: ../gui.py:482
633643 msgid "xz-plane"
634644 msgstr "xz-Ebene"
635645
636 #: ../gui.py:481
646 #: ../gui.py:483
637647 msgid "a2,a3-plane"
638648 msgstr "a2,a3-Ebene"
639649
640 #: ../gui.py:482
650 #: ../gui.py:484
641651 msgid "a3,a1-plane"
642652 msgstr "a3,a1-Ebene"
643653
644 #: ../gui.py:483
654 #: ../gui.py:485
645655 msgid "a1,a2-plane"
646656 msgstr "a1,a2-Ebene"
647657
648 #: ../gui.py:484
658 #: ../gui.py:486
649659 msgid "a3,a2-plane"
650660 msgstr "a3,a2-Ebene"
651661
652 #: ../gui.py:485
662 #: ../gui.py:487
653663 msgid "a1,a3-plane"
654664 msgstr "a1,a3-Ebene"
655665
656 #: ../gui.py:486
666 #: ../gui.py:488
657667 msgid "a2,a1-plane"
658668 msgstr "a2,a1-Ebene"
659669
660 #: ../gui.py:487
670 #: ../gui.py:489
661671 msgid "Settings ..."
662672 msgstr "Einstellungen …"
663673
664 #: ../gui.py:489
674 #: ../gui.py:491
665675 msgid "VMD"
666676 msgstr "VMD"
667677
668 #: ../gui.py:490
678 #: ../gui.py:492
669679 msgid "RasMol"
670680 msgstr "RasMol"
671681
672 #: ../gui.py:491
682 #: ../gui.py:493
673683 msgid "xmakemol"
674684 msgstr "xmakemol"
675685
676 #: ../gui.py:492
686 #: ../gui.py:494
677687 msgid "avogadro"
678688 msgstr "avogadro"
679689
680 #: ../gui.py:494
690 #: ../gui.py:496
681691 msgid "_Tools"
682692 msgstr "_Werkzeuge"
683693
684 #: ../gui.py:495
694 #: ../gui.py:497
685695 msgid "Graphs ..."
686696 msgstr "Graphen …"
687697
688 #: ../gui.py:496
698 #: ../gui.py:498
689699 msgid "Movie ..."
690700 msgstr "Film …"
691701
692 #: ../gui.py:497
702 #: ../gui.py:499
693703 msgid "Expert mode ..."
694704 msgstr "Expertenmodus …"
695705
696 #: ../gui.py:498
706 #: ../gui.py:500
697707 msgid "Constraints ..."
698708 msgstr "Beschränkungen …"
699709
700 #: ../gui.py:499
710 #: ../gui.py:501
701711 msgid "Render scene ..."
702712 msgstr "Zeichne Szene …"
703713
704 #: ../gui.py:500
714 #: ../gui.py:502
705715 msgid "_Move atoms"
706716 msgstr "_Bewege Atome"
707717
708 #: ../gui.py:501
718 #: ../gui.py:503
709719 msgid "_Rotate atoms"
710720 msgstr "_Rotiere Atome"
711721
712 #: ../gui.py:502
722 #: ../gui.py:504
713723 msgid "NE_B"
714724 msgstr "NE_B"
715725
716 #: ../gui.py:503
726 #: ../gui.py:505
717727 msgid "B_ulk Modulus"
718728 msgstr "_Kompressionsmodul"
719729
720730 #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
721 #: ../gui.py:506
731 #: ../gui.py:508
722732 msgid "_Setup"
723733 msgstr "_Erstellen"
724734
725 #: ../gui.py:507
735 #: ../gui.py:509
726736 msgid "_Bulk Crystal"
727737 msgstr "_Kristallstruktur"
728738
729 #: ../gui.py:508
739 #: ../gui.py:510
730740 msgid "_Surface slab"
731741 msgstr "_Oberfläche"
732742
733 #: ../gui.py:509
743 #: ../gui.py:511
734744 msgid "_Nanoparticle"
735745 msgstr "_Nanoparikel"
736746
737 #: ../gui.py:511
747 #: ../gui.py:513
738748 msgid "Nano_tube"
739749 msgstr "Nano_röhre"
740750
741 #: ../gui.py:514
751 #: ../gui.py:516
742752 msgid "_Calculate"
743753 msgstr "_Berechne"
744754
745 #: ../gui.py:515
755 #: ../gui.py:517
746756 msgid "Set _Calculator"
747757 msgstr "Setze _Berechner"
748758
749 #: ../gui.py:516
759 #: ../gui.py:518
750760 msgid "_Energy and Forces"
751761 msgstr "_Energie und Kräfte"
752762
753 #: ../gui.py:517
763 #: ../gui.py:519
754764 msgid "Energy Minimization"
755765 msgstr "Energieminimierung"
756766
757 #: ../gui.py:520
767 #: ../gui.py:522
758768 msgid "_Help"
759769 msgstr "_Hilfe"
760770
761 #: ../gui.py:521
771 #: ../gui.py:523
762772 msgid "_About"
763773 msgstr "_Info"
764774
765 #: ../gui.py:525
775 #: ../gui.py:527
766776 msgid "Webpage ..."
767777 msgstr "Webseite …"
768778
963973 msgid "Creating a nanoparticle."
964974 msgstr "Erzeuge Nanopartikel."
965975
966 #: ../nanoparticle.py:197 ../nanotube.py:52 ../surfaceslab.py:82
976 #: ../nanoparticle.py:197 ../nanotube.py:52 ../surfaceslab.py:83
967977 msgid "Apply"
968978 msgstr "Anwenden"
969979
970 #: ../nanoparticle.py:198 ../nanotube.py:53 ../surfaceslab.py:83
980 #: ../nanoparticle.py:198 ../nanotube.py:53 ../surfaceslab.py:84
971981 msgid "OK"
972982 msgstr "Ok"
973983
10911101 msgid "Length:"
10921102 msgstr "Länge:"
10931103
1094 #: ../quickinfo.py:6
1104 #: ../quickinfo.py:28
1105 msgid "This frame has no atoms."
1106 msgstr "Dieses Bild hat keine Atome."
1107
1108 #: ../quickinfo.py:33
10951109 msgid "Single image loaded."
10961110 msgstr "Einzelnes Bild geladen."
10971111
1098 #: ../quickinfo.py:7
1099 #, python-format
1100 msgid "Image %d loaded (0 - %d)."
1101 msgstr "Bild %d geladen (0 - %d)."
1102
1103 #: ../quickinfo.py:8
1112 #: ../quickinfo.py:35
1113 msgid "Image {} loaded (0–{})."
1114 msgstr "Bild {} geladen (0–{})."
1115
1116 #: ../quickinfo.py:37
1117 msgid "Number of atoms: {}"
1118 msgstr "Anzahl der Atome: {}"
1119
1120 #: ../quickinfo.py:47
1121 msgid "Unit cell [Å]:"
1122 msgstr "Einheitszelle [Å]:"
1123
1124 #: ../quickinfo.py:49
1125 msgid "no"
1126 msgstr "Nein"
1127
1128 #: ../quickinfo.py:49
1129 msgid "yes"
1130 msgstr "Ja"
1131
1132 #. TRANSLATORS: This has the form Periodic: no, no, yes
1133 #: ../quickinfo.py:51
1134 msgid "Periodic: {}, {}, {}"
1135 msgstr "Periodisch: {}, {}, {}"
1136
1137 #: ../quickinfo.py:55
11041138 msgid "Unit cell is fixed."
11051139 msgstr "Einheitszelle ist fest."
11061140
1107 #: ../quickinfo.py:9
1141 #: ../quickinfo.py:57
11081142 msgid "Unit cell varies."
11091143 msgstr "Einheitszelle variiert."
11101144
1111 #: ../quickinfo.py:11
1112 #, python-format
1113 msgid ""
1114 "%s\n"
1115 "\n"
1116 "Number of atoms: %d.\n"
1117 "\n"
1118 "Unit cell:\n"
1119 " %8.3f %8.3f %8.3f\n"
1120 " %8.3f %8.3f %8.3f\n"
1121 " %8.3f %8.3f %8.3f\n"
1122 "\n"
1123 "%s\n"
1124 "%s\n"
1145 #: ../quickinfo.py:60
1146 msgid "Volume: {:.3f} ų"
1147 msgstr "Volumen: {:.3f} ų"
1148
1149 #: ../quickinfo.py:88
1150 msgid "Calculator: {} (cached)"
1151 msgstr "Berechner: {} (gespeichert)"
1152
1153 #: ../quickinfo.py:90
1154 msgid "Calculator: {} (attached)"
1155 msgstr "Berechner: {} (beigefügt)"
1156
1157 #: ../quickinfo.py:97
1158 msgid "Energy: {:.3f} eV"
1159 msgstr "Energie: {:.3f} eV"
1160
1161 #: ../quickinfo.py:102
1162 msgid "Max force: {:.3f} eV/Å"
11251163 msgstr ""
1126 "%s\n"
1127 "\n"
1128 "Anzahl Atome: %d.\n"
1129 "\n"
1130 "Einheitszelle:\n"
1131 " %8.3f %8.3f %8.3f\n"
1132 " %8.3f %8.3f %8.3f\n"
1133 " %8.3f %8.3f %8.3f\n"
1134 "\n"
1135 "%s\n"
1136 "%s\n"
1137
1138 #: ../quickinfo.py:33
1139 msgid "This frame has no atoms."
1140 msgstr "Dieses Bild hat keine Atome."
1141
1142 #: ../quickinfo.py:53
1143 msgid "no"
1144 msgstr "Nein"
1145
1146 #: ../quickinfo.py:53
1147 msgid "yes"
1148 msgstr "Ja"
1149
1150 #. TRANSLATORS: This has the form Periodic: no, no, yes
1151 #: ../quickinfo.py:57
1152 #, python-format
1153 msgid "Periodic: %s, %s, %s"
1154 msgstr "Periodisch: %s, %s, %s"
1155
1156 #: ../quickinfo.py:61
1157 msgid "Volume: "
1158 msgstr "Volumen: "
1164
1165 #: ../quickinfo.py:107
1166 msgid "Magmom: {:.3f} µ"
1167 msgstr "Magmom: {:.3f} µ"
11591168
11601169 #: ../render.py:20 ../render.py:190
11611170 msgid "Render current view in povray ... "
15371546 msgid "FCC(110)"
15381547 msgstr "FCC(110)"
15391548
1540 #: ../surfaceslab.py:26 ../surfaceslab.py:170
1549 #: ../surfaceslab.py:26 ../surfaceslab.py:173
15411550 msgid "FCC(111)"
15421551 msgstr "FCC(111)"
15431552
1544 #: ../surfaceslab.py:27 ../surfaceslab.py:173
1553 #: ../surfaceslab.py:27 ../surfaceslab.py:176
15451554 msgid "FCC(211)"
15461555 msgstr "FCC(211)"
15471556
15531562 msgid "bcc"
15541563 msgstr "bcc"
15551564
1556 #: ../surfaceslab.py:29 ../surfaceslab.py:167
1565 #: ../surfaceslab.py:29 ../surfaceslab.py:170
15571566 msgid "BCC(110)"
15581567 msgstr "BCC(110)"
15591568
1560 #: ../surfaceslab.py:30 ../surfaceslab.py:164
1569 #: ../surfaceslab.py:30 ../surfaceslab.py:167
15611570 msgid "BCC(111)"
15621571 msgstr "BCC(111)"
15631572
1564 #: ../surfaceslab.py:31 ../surfaceslab.py:177
1573 #: ../surfaceslab.py:31 ../surfaceslab.py:180
15651574 msgid "HCP(0001)"
15661575 msgstr "HCP(0001)"
15671576
1568 #: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:131
1569 #: ../surfaceslab.py:187
1577 #: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:134
1578 #: ../surfaceslab.py:190
15701579 msgid "hcp"
15711580 msgstr "hcp"
15721581
1573 #: ../surfaceslab.py:32 ../surfaceslab.py:180
1582 #: ../surfaceslab.py:32 ../surfaceslab.py:183
15741583 msgid "HCP(10-10)"
15751584 msgstr "HCP(10-10)"
15761585
15951604 msgstr "Orthogonale Einheitszelle:"
15961605
15971606 #: ../surfaceslab.py:72
1598 msgid "Lattice constant:\ta"
1599 msgstr "Gitterkonstante:\ta"
1607 msgid "Lattice constant:"
1608 msgstr "Gitterkonstante:"
1609
1610 #: ../surfaceslab.py:73
1611 msgid "\ta"
1612 msgstr "\ta"
16001613
16011614 #: ../surfaceslab.py:74
1602 msgid "\t\tc"
1603 msgstr "\t\tc"
1615 msgid "\tc"
1616 msgstr "\tc"
16041617
16051618 #: ../surfaceslab.py:75
1606 msgid "Size: \tx: "
1607 msgstr "Größe: \tx: "
1608
1609 #: ../surfaceslab.py:76
1619 msgid "Size:"
1620 msgstr "Größe:"
1621
1622 #: ../surfaceslab.py:77
16101623 msgid "\ty: "
16111624 msgstr "\ty: "
16121625
1613 #: ../surfaceslab.py:77
1626 #: ../surfaceslab.py:78
16141627 msgid "\tz: "
16151628 msgstr "\tz: "
16161629
16171630 #. TRANSLATORS: This is a title of a window.
1618 #: ../surfaceslab.py:81
1631 #: ../surfaceslab.py:82
16191632 msgid "Creating a surface."
16201633 msgstr "Erzeuge Oberfläche."
16211634
1622 #: ../surfaceslab.py:161
1635 #. TRANSLATORS: E.g. "... assume fcc crystal structure for Au"
1636 #: ../surfaceslab.py:110
1637 msgid "Error: Reference values assume {} crystal structure for {}!"
1638 msgstr ""
1639
1640 #: ../surfaceslab.py:164
16231641 msgid "Please enter an even value for orthogonal cell"
16241642 msgstr "Bitte einen geraden Wert für orthogonale Zelle angeben"
16251643
1626 #: ../surfaceslab.py:174
1644 #: ../surfaceslab.py:177
16271645 msgid "Please enter a value divisible by 3 for orthogonal cell"
16281646 msgstr "Bitte einen durch 3 teilbaren Wert für orthogonale Zelle angeben"
16291647
1630 #: ../surfaceslab.py:194
1648 #: ../surfaceslab.py:197
16311649 msgid " Vacuum: {} Å."
16321650 msgstr " Vakuum: {} Å."
16331651
16341652 #. TRANSLATORS: e.g. "Au fcc100 surface with 2 atoms."
16351653 #. or "Au fcc100 surface with 2 atoms. Vacuum: 5 Å."
1636 #: ../surfaceslab.py:202
1654 #: ../surfaceslab.py:205
16371655 #, python-brace-format
16381656 msgid "{symbol} {surf} surface with one atom.{vacuum}"
16391657 msgid_plural "{symbol} {surf} surface with {natoms} atoms.{vacuum}"
16561674 msgid "About"
16571675 msgstr "Info"
16581676
1659 #: ../ui.py:60 ../ui.py:64
1677 #: ../ui.py:60 ../ui.py:64 ../widgets.py:17
16601678 msgid "Help"
16611679 msgstr "Hilfe"
16621680
1663 #: ../widgets.py:11
1681 #: ../widgets.py:14
16641682 msgid "Element:"
16651683 msgstr "Element:"
16661684
1667 #: ../widgets.py:39
1685 #. This infobox is indescribably ugly because of the
1686 #. ridiculously large font size used by Tkinter. Ouch!
1687 #: ../widgets.py:34
1688 msgid ""
1689 "Enter a chemical symbol or the name of a molecule from the G2 testset:\n"
1690 "{}"
1691 msgstr ""
1692
1693 #: ../widgets.py:68
16681694 msgid "No element specified!"
16691695 msgstr "Kein Element spezifiziert!"
16701696
1671 #: ../widgets.py:56
1697 #: ../widgets.py:90
16721698 msgid "ERROR: Invalid element!"
16731699 msgstr "FEHLER: Ungültiges Element!"
16741700
1675 #: ../widgets.py:75
1701 #: ../widgets.py:107
16761702 msgid "No Python code"
16771703 msgstr "Kein Python-Code"
1704
1705 #~ msgid ""
1706 #~ "%s\n"
1707 #~ "\n"
1708 #~ "Number of atoms: %d.\n"
1709 #~ "\n"
1710 #~ "Unit cell:\n"
1711 #~ " %8.3f %8.3f %8.3f\n"
1712 #~ " %8.3f %8.3f %8.3f\n"
1713 #~ " %8.3f %8.3f %8.3f\n"
1714 #~ "\n"
1715 #~ "%s\n"
1716 #~ "%s\n"
1717 #~ msgstr ""
1718 #~ "%s\n"
1719 #~ "\n"
1720 #~ "Anzahl Atome: %d.\n"
1721 #~ "\n"
1722 #~ "Einheitszelle:\n"
1723 #~ " %8.3f %8.3f %8.3f\n"
1724 #~ " %8.3f %8.3f %8.3f\n"
1725 #~ " %8.3f %8.3f %8.3f\n"
1726 #~ "\n"
1727 #~ "%s\n"
1728 #~ "%s\n"
1729
1730 #~ msgid "Volume: "
1731 #~ msgstr "Volumen: "
1732
1733 #~ msgid "Size: \tx: "
1734 #~ msgstr "Größe: \tx: "
16781735
16791736 #~ msgid "Magnetic moment"
16801737 #~ msgstr "Magnetisches Moment"
18281885 #~ msgid "Select calculator"
18291886 #~ msgstr "Wähle Berechner"
18301887
1831 #~ msgid "Calculator:"
1832 #~ msgstr "Berechner:"
1833
18341888 #~ msgid "None"
18351889 #~ msgstr "Keiner"
18361890
22012255 #~ msgid "Density: "
22022256 #~ msgstr "Dichte: "
22032257
2204 #~ msgid "Energy: "
2205 #~ msgstr "Energie: "
2206
22072258 #~ msgid "GPAW version: "
22082259 #~ msgstr "GPAW Version: "
22092260
77 msgstr ""
88 "Project-Id-Version: ase-3.5.2\n"
99 "Report-Msgid-Bugs-To: ase-users@listserv.fysik.dtu.dk\n"
10 "POT-Creation-Date: 2017-09-20 19:21+0200\n"
11 "PO-Revision-Date: 2017-09-20 19:24+0200\n"
10 "POT-Creation-Date: 2017-12-15 17:25+0100\n"
11 "PO-Revision-Date: 2017-12-15 17:40+0100\n"
1212 "Last-Translator: Ask Hjorth Larsen <asklarsen@gmail.com>\n"
1313 "Language-Team: English (British) <ase-users@listserv.fysik.dtu.dk>\n"
1414 "Language: en_GB\n"
2626 msgid "Add atoms"
2727 msgstr "Add atoms"
2828
29 #: ../add.py:25
29 #: ../add.py:26
3030 msgid "Absolute position:"
3131 msgstr "Absolute position:"
3232
33 #: ../add.py:27 ../add.py:30 ../nanoparticle.py:264
33 #: ../add.py:28 ../add.py:31 ../nanoparticle.py:264
3434 msgid "Add"
3535 msgstr "Add"
3636
37 #: ../add.py:28
37 #: ../add.py:29
3838 msgid "Relative to average position (of selection):"
3939 msgstr "Relative to average position (of selection):"
4040
7070 msgid "By magnetic moment"
7171 msgstr "By magnetic moment"
7272
73 #: ../colors.py:69
73 #: ../colors.py:26
74 msgid "By number of neighbors"
75 msgstr "By number of neighbors"
76
77 #: ../colors.py:71
7478 msgid "Green"
7579 msgstr "Green"
7680
77 #: ../colors.py:69
81 #: ../colors.py:71
7882 msgid "Yellow"
7983 msgstr "Yellow"
8084
157161 msgid " z: "
158162 msgstr " z: "
159163
160 #: ../crystal.py:97 ../surfaceslab.py:75 ../surfaceslab.py:76
161 #: ../surfaceslab.py:77
164 #: ../crystal.py:97 ../surfaceslab.py:76 ../surfaceslab.py:77
165 #: ../surfaceslab.py:78
162166 msgid " unit cells"
163167 msgstr " unit cells"
164168
236240 msgid " Element:\t"
237241 msgstr " Element:\t"
238242
239 #: ../crystal.py:177
243 #: ../crystal.py:177 ../surfaceslab.py:76
240244 msgid "\tx: "
241245 msgstr "\tx: "
242246
262266 msgid "Please specify a consistent set of atoms."
263267 msgstr "Please specify a consistent set of atoms."
264268
265 #: ../crystal.py:407 ../graphene.py:264 ../nanoparticle.py:530
266 #: ../nanotube.py:84 ../surfaceslab.py:220
269 #: ../crystal.py:407 ../graphene.py:264 ../nanoparticle.py:531
270 #: ../nanotube.py:84 ../surfaceslab.py:223
267271 msgid "No valid atoms."
268272 msgstr "No valid atoms."
269273
270 #: ../crystal.py:408 ../graphene.py:265 ../nanoparticle.py:531
271 #: ../nanotube.py:85 ../surfaceslab.py:221 ../widgets.py:76
274 #: ../crystal.py:408 ../graphene.py:265 ../nanoparticle.py:532
275 #: ../nanotube.py:85 ../surfaceslab.py:224 ../widgets.py:108
272276 msgid "You have not (yet) specified a consistent set of parameters."
273277 msgstr "You have not (yet) specified a consistent set of parameters."
274278
326330 "Set up a graphene sheet or a graphene nanoribbon. A nanoribbon may\n"
327331 "optionally be saturated with hydrogen (or another element)."
328332
329 #: ../graphene.py:38 ../gui.py:512
333 #: ../graphene.py:38 ../gui.py:514
330334 msgid "Graphene"
331335 msgstr "Graphene"
332336
387391 msgstr " Length: "
388392
389393 #. Vacuum
390 #: ../graphene.py:105 ../surfaceslab.py:78
394 #: ../graphene.py:105 ../surfaceslab.py:79
391395 msgid "Vacuum: "
392396 msgstr "Vacuum: "
393397
461465 msgid "Save data to file ... "
462466 msgstr "Save data to file ... "
463467
464 #: ../gui.py:286
468 #: ../gui.py:284
465469 msgid "Automatic"
466470 msgstr "Automatic"
467471
468 #: ../gui.py:304
472 #: ../gui.py:302
469473 msgid "Open ..."
470474 msgstr "Open ..."
471475
472 #: ../gui.py:305
476 #: ../gui.py:303
473477 msgid "Choose parser:"
474478 msgstr "Choose parser:"
475479
476 #: ../gui.py:416
480 #: ../gui.py:418
477481 msgid "_File"
478482 msgstr "_File"
479483
480 #: ../gui.py:417
484 #: ../gui.py:419
481485 msgid "_Open"
482486 msgstr "_Open"
483487
484 #: ../gui.py:418
488 #: ../gui.py:420
485489 msgid "_New"
486490 msgstr "_New"
487491
488 #: ../gui.py:419
492 #: ../gui.py:421
489493 msgid "_Save"
490494 msgstr "_Save"
491495
492 #: ../gui.py:421
496 #: ../gui.py:423
493497 msgid "_Quit"
494498 msgstr "_Quit"
495499
496 #: ../gui.py:423
500 #: ../gui.py:425
497501 msgid "_Edit"
498502 msgstr "_Edit"
499503
500 #: ../gui.py:424
504 #: ../gui.py:426
501505 msgid "Select _all"
502506 msgstr "Select _all"
503507
504 #: ../gui.py:425
508 #: ../gui.py:427
505509 msgid "_Invert selection"
506510 msgstr "_Invert selection"
507511
508 #: ../gui.py:426
512 #: ../gui.py:428
509513 msgid "Select _constrained atoms"
510514 msgstr "Select _constrained atoms"
511515
512 #: ../gui.py:427
516 #: ../gui.py:429
513517 msgid "Select _immobile atoms"
514518 msgstr "Select _immobile atoms"
515519
516 #: ../gui.py:433
520 #: ../gui.py:434
517521 msgid "Hide selected atoms"
518522 msgstr "Hide selected atoms"
519523
520 #: ../gui.py:434
524 #: ../gui.py:435
521525 msgid "Show selected atoms"
522526 msgstr "Show selected atoms"
523527
524 #: ../gui.py:436
528 #: ../gui.py:437
525529 msgid "_Modify"
526530 msgstr "_Modify"
527531
528 #: ../gui.py:437
532 #: ../gui.py:438
529533 msgid "_Add atoms"
530534 msgstr "_Add atoms"
531535
532 #: ../gui.py:438
536 #: ../gui.py:439
533537 msgid "_Delete selected atoms"
534538 msgstr "_Delete selected atoms"
535539
536540 #: ../gui.py:441
541 msgid "Edit _cell"
542 msgstr "Edit _cell"
543
544 #: ../gui.py:443
537545 msgid "_First image"
538546 msgstr "_First image"
539547
540 #: ../gui.py:442
548 #: ../gui.py:444
541549 msgid "_Previous image"
542550 msgstr "_Previous image"
543551
544 #: ../gui.py:443
552 #: ../gui.py:445
545553 msgid "_Next image"
546554 msgstr "_Next image"
547555
548 #: ../gui.py:444
556 #: ../gui.py:446
549557 msgid "_Last image"
550558 msgstr "_Last image"
551559
552 #: ../gui.py:446
560 #: ../gui.py:448
553561 msgid "_View"
554562 msgstr "_View"
555563
556 #: ../gui.py:447
564 #: ../gui.py:449
557565 msgid "Show _unit cell"
558566 msgstr "Show _unit cell"
559567
560 #: ../gui.py:449
568 #: ../gui.py:451
561569 msgid "Show _axes"
562570 msgstr "Show _axes"
563571
564 #: ../gui.py:450
572 #: ../gui.py:452
565573 msgid "Show _bonds"
566574 msgstr "Show _bonds"
567575
568 #: ../gui.py:452
576 #: ../gui.py:454
569577 msgid "Show _velocities"
570578 msgstr "Show _velocities"
571579
572 #: ../gui.py:454
580 #: ../gui.py:456
573581 msgid "Show _forces"
574582 msgstr "Show _forces"
575583
576 #: ../gui.py:456
584 #: ../gui.py:458
577585 msgid "Show _Labels"
578586 msgstr "Show _Labels"
579587
580 #: ../gui.py:457
588 #: ../gui.py:459
581589 msgid "_None"
582590 msgstr "_None"
583591
584 #: ../gui.py:458
592 #: ../gui.py:460
585593 msgid "Atom _Index"
586594 msgstr "Atom _Index"
587595
588 #: ../gui.py:459
596 #: ../gui.py:461
589597 msgid "_Magnetic Moments"
590598 msgstr "_Magnetic Moments"
591599
592600 #. XXX check if exist
593 #: ../gui.py:460
601 #: ../gui.py:462
594602 msgid "_Element Symbol"
595603 msgstr "_Element Symbol"
596604
597 #: ../gui.py:461
605 #: ../gui.py:463
598606 msgid "_Initial Charges"
599607 msgstr "_Initial Charges"
600608
601 #: ../gui.py:464
609 #: ../gui.py:466
602610 msgid "Quick Info ..."
603611 msgstr "Quick Info ..."
604612
605 #: ../gui.py:465
613 #: ../gui.py:467
606614 msgid "Repeat ..."
607615 msgstr "Repeat ..."
608616
609 #: ../gui.py:466
617 #: ../gui.py:468
610618 msgid "Rotate ..."
611619 msgstr "Rotate ..."
612620
613 #: ../gui.py:467
621 #: ../gui.py:469
614622 msgid "Colors ..."
615623 msgstr "Colours ..."
616624
617625 #. TRANSLATORS: verb
618 #: ../gui.py:469
626 #: ../gui.py:471
619627 msgid "Focus"
620628 msgstr "Focus"
621629
622 #: ../gui.py:470
630 #: ../gui.py:472
623631 msgid "Zoom in"
624632 msgstr "Zoom in"
625633
626 #: ../gui.py:471
634 #: ../gui.py:473
627635 msgid "Zoom out"
628636 msgstr "Zoom out"
629637
630 #: ../gui.py:472
638 #: ../gui.py:474
631639 msgid "Change View"
632640 msgstr "Change View"
633641
634 #: ../gui.py:474
642 #: ../gui.py:476
635643 msgid "Reset View"
636644 msgstr "Reset View"
637645
638 #: ../gui.py:475
646 #: ../gui.py:477
639647 msgid "xy-plane"
640648 msgstr "xy-plane"
641649
642 #: ../gui.py:476
650 #: ../gui.py:478
643651 msgid "yz-plane"
644652 msgstr "yz-plane"
645653
646 #: ../gui.py:477
654 #: ../gui.py:479
647655 msgid "zx-plane"
648656 msgstr "zx-plane"
649657
650 #: ../gui.py:478
658 #: ../gui.py:480
651659 msgid "yx-plane"
652660 msgstr "yx-plane"
653661
654 #: ../gui.py:479
662 #: ../gui.py:481
655663 msgid "zy-plane"
656664 msgstr "zy-plane"
657665
658 #: ../gui.py:480
666 #: ../gui.py:482
659667 msgid "xz-plane"
660668 msgstr "xz-plane"
661669
662 #: ../gui.py:481
670 #: ../gui.py:483
663671 msgid "a2,a3-plane"
664672 msgstr "a2,a3-plane"
665673
666 #: ../gui.py:482
674 #: ../gui.py:484
667675 msgid "a3,a1-plane"
668676 msgstr "a3,a1-plane"
669677
670 #: ../gui.py:483
678 #: ../gui.py:485
671679 msgid "a1,a2-plane"
672680 msgstr "a1,a2-plane"
673681
674 #: ../gui.py:484
682 #: ../gui.py:486
675683 msgid "a3,a2-plane"
676684 msgstr "a3,a2-plane"
677685
678 #: ../gui.py:485
686 #: ../gui.py:487
679687 msgid "a1,a3-plane"
680688 msgstr "a1,a3-plane"
681689
682 #: ../gui.py:486
690 #: ../gui.py:488
683691 msgid "a2,a1-plane"
684692 msgstr "a2,a1-plane"
685693
686 #: ../gui.py:487
694 #: ../gui.py:489
687695 msgid "Settings ..."
688696 msgstr "Settings ..."
689697
690 #: ../gui.py:489
698 #: ../gui.py:491
691699 msgid "VMD"
692700 msgstr "VMD"
693701
694 #: ../gui.py:490
702 #: ../gui.py:492
695703 msgid "RasMol"
696704 msgstr "RasMol"
697705
698 #: ../gui.py:491
706 #: ../gui.py:493
699707 msgid "xmakemol"
700708 msgstr "xmakemol"
701709
702 #: ../gui.py:492
710 #: ../gui.py:494
703711 msgid "avogadro"
704712 msgstr "avogadro"
705713
706 #: ../gui.py:494
714 #: ../gui.py:496
707715 msgid "_Tools"
708716 msgstr "_Tools"
709717
710 #: ../gui.py:495
718 #: ../gui.py:497
711719 msgid "Graphs ..."
712720 msgstr "Graphs ..."
713721
714 #: ../gui.py:496
722 #: ../gui.py:498
715723 msgid "Movie ..."
716724 msgstr "Film ..."
717725
718 #: ../gui.py:497
726 #: ../gui.py:499
719727 msgid "Expert mode ..."
720728 msgstr "Expert mode ..."
721729
722 #: ../gui.py:498
730 #: ../gui.py:500
723731 msgid "Constraints ..."
724732 msgstr "Constraints ..."
725733
726 #: ../gui.py:499
734 #: ../gui.py:501
727735 msgid "Render scene ..."
728736 msgstr "Render scene ..."
729737
730 #: ../gui.py:500
738 #: ../gui.py:502
731739 msgid "_Move atoms"
732740 msgstr "_Move atoms"
733741
734 #: ../gui.py:501
742 #: ../gui.py:503
735743 msgid "_Rotate atoms"
736744 msgstr "_Rotate atoms"
737745
738 #: ../gui.py:502
746 #: ../gui.py:504
739747 msgid "NE_B"
740748 msgstr "NE_B"
741749
742 #: ../gui.py:503
750 #: ../gui.py:505
743751 msgid "B_ulk Modulus"
744752 msgstr "B_ulk Modulus"
745753
746754 #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
747 #: ../gui.py:506
755 #: ../gui.py:508
748756 msgid "_Setup"
749757 msgstr "_Setup"
750758
751 #: ../gui.py:507
759 #: ../gui.py:509
752760 msgid "_Bulk Crystal"
753761 msgstr "_Bulk Crystal"
754762
755 #: ../gui.py:508
763 #: ../gui.py:510
756764 msgid "_Surface slab"
757765 msgstr "_Surface slab"
758766
759 #: ../gui.py:509
767 #: ../gui.py:511
760768 msgid "_Nanoparticle"
761769 msgstr "_Nanoparticle"
762770
763 #: ../gui.py:511
771 #: ../gui.py:513
764772 msgid "Nano_tube"
765773 msgstr "Nano_tube"
766774
767 #: ../gui.py:514
775 #: ../gui.py:516
768776 msgid "_Calculate"
769777 msgstr "_Calculate"
770778
771 #: ../gui.py:515
779 #: ../gui.py:517
772780 msgid "Set _Calculator"
773781 msgstr "Set _Calculator"
774782
775 #: ../gui.py:516
783 #: ../gui.py:518
776784 msgid "_Energy and Forces"
777785 msgstr "_Energy and Forces"
778786
779 #: ../gui.py:517
787 #: ../gui.py:519
780788 msgid "Energy Minimization"
781789 msgstr "Energy Minimization"
782790
783 #: ../gui.py:520
791 #: ../gui.py:522
784792 msgid "_Help"
785793 msgstr "_Help"
786794
787 #: ../gui.py:521
795 #: ../gui.py:523
788796 msgid "_About"
789797 msgstr "_About"
790798
791 #: ../gui.py:525
799 #: ../gui.py:527
792800 msgid "Webpage ..."
793801 msgstr "Webpage ..."
794802
10231031 msgid "Creating a nanoparticle."
10241032 msgstr "Creating a nanoparticle."
10251033
1026 #: ../nanoparticle.py:197 ../nanotube.py:52 ../surfaceslab.py:82
1034 #: ../nanoparticle.py:197 ../nanotube.py:52 ../surfaceslab.py:83
10271035 msgid "Apply"
10281036 msgstr "Apply"
10291037
1030 #: ../nanoparticle.py:198 ../nanotube.py:53 ../surfaceslab.py:83
1038 #: ../nanoparticle.py:198 ../nanotube.py:53 ../surfaceslab.py:84
10311039 msgid "OK"
10321040 msgstr "OK"
10331041
11511159 msgid "Length:"
11521160 msgstr "Length:"
11531161
1154 #: ../quickinfo.py:6
1162 #: ../quickinfo.py:28
1163 msgid "This frame has no atoms."
1164 msgstr "This frame has no atoms."
1165
1166 #: ../quickinfo.py:33
11551167 msgid "Single image loaded."
11561168 msgstr "Single image loaded."
11571169
1158 #: ../quickinfo.py:7
1159 #, python-format
1160 msgid "Image %d loaded (0 - %d)."
1161 msgstr "Image %d loaded (0 - %d)."
1162
1163 #: ../quickinfo.py:8
1170 #: ../quickinfo.py:35
1171 msgid "Image {} loaded (0–{})."
1172 msgstr "Image {} loaded (0–{})."
1173
1174 #: ../quickinfo.py:37
1175 msgid "Number of atoms: {}"
1176 msgstr "Number of atoms: {}"
1177
1178 #: ../quickinfo.py:47
1179 msgid "Unit cell [Å]:"
1180 msgstr "Unit cell [Å]:"
1181
1182 #: ../quickinfo.py:49
1183 msgid "no"
1184 msgstr "no"
1185
1186 #: ../quickinfo.py:49
1187 msgid "yes"
1188 msgstr "yes"
1189
1190 #. TRANSLATORS: This has the form Periodic: no, no, yes
1191 #: ../quickinfo.py:51
1192 msgid "Periodic: {}, {}, {}"
1193 msgstr "Periodic: {}, {}, {}"
1194
1195 #: ../quickinfo.py:55
11641196 msgid "Unit cell is fixed."
11651197 msgstr "Unit cell is fixed."
11661198
1167 #: ../quickinfo.py:9
1199 #: ../quickinfo.py:57
11681200 msgid "Unit cell varies."
11691201 msgstr "Unit cell varies."
11701202
1171 #: ../quickinfo.py:11
1172 #, python-format
1173 msgid ""
1174 "%s\n"
1175 "\n"
1176 "Number of atoms: %d.\n"
1177 "\n"
1178 "Unit cell:\n"
1179 " %8.3f %8.3f %8.3f\n"
1180 " %8.3f %8.3f %8.3f\n"
1181 " %8.3f %8.3f %8.3f\n"
1182 "\n"
1183 "%s\n"
1184 "%s\n"
1185 msgstr ""
1186 "%s\n"
1187 "\n"
1188 "Number of atoms: %d.\n"
1189 "\n"
1190 "Unit cell:\n"
1191 " %8.3f %8.3f %8.3f\n"
1192 " %8.3f %8.3f %8.3f\n"
1193 " %8.3f %8.3f %8.3f\n"
1194 "\n"
1195 "%s\n"
1196 "%s\n"
1197
1198 #: ../quickinfo.py:33
1199 msgid "This frame has no atoms."
1200 msgstr "This frame has no atoms."
1201
1202 #: ../quickinfo.py:53
1203 msgid "no"
1204 msgstr "no"
1205
1206 #: ../quickinfo.py:53
1207 msgid "yes"
1208 msgstr "yes"
1209
1210 #. TRANSLATORS: This has the form Periodic: no, no, yes
1211 #: ../quickinfo.py:57
1212 #, python-format
1213 msgid "Periodic: %s, %s, %s"
1214 msgstr "Periodic: %s, %s, %s"
1215
1216 #: ../quickinfo.py:61
1217 msgid "Volume: "
1218 msgstr "Volume: "
1203 #: ../quickinfo.py:60
1204 msgid "Volume: {:.3f} ų"
1205 msgstr "Volume: {:.3f} ų"
1206
1207 #: ../quickinfo.py:88
1208 msgid "Calculator: {} (cached)"
1209 msgstr "Calculator: {} (cached)"
1210
1211 #: ../quickinfo.py:90
1212 msgid "Calculator: {} (attached)"
1213 msgstr "Calculator: {} (attached)"
1214
1215 #: ../quickinfo.py:97
1216 msgid "Energy: {:.3f} eV"
1217 msgstr "Energy: {:.3f} eV"
1218
1219 #: ../quickinfo.py:102
1220 msgid "Max force: {:.3f} eV/Å"
1221 msgstr "Max force: {:.3f} eV/Å"
1222
1223 #: ../quickinfo.py:107
1224 msgid "Magmom: {:.3f} µ"
1225 msgstr "Magmom: {:.3f} µ"
12191226
12201227 #: ../render.py:20 ../render.py:190
12211228 msgid "Render current view in povray ... "
16141621 msgid "FCC(110)"
16151622 msgstr "FCC(110)"
16161623
1617 #: ../surfaceslab.py:26 ../surfaceslab.py:170
1624 #: ../surfaceslab.py:26 ../surfaceslab.py:173
16181625 msgid "FCC(111)"
16191626 msgstr "FCC(111)"
16201627
1621 #: ../surfaceslab.py:27 ../surfaceslab.py:173
1628 #: ../surfaceslab.py:27 ../surfaceslab.py:176
16221629 msgid "FCC(211)"
16231630 msgstr "FCC(211)"
16241631
16301637 msgid "bcc"
16311638 msgstr "bcc"
16321639
1633 #: ../surfaceslab.py:29 ../surfaceslab.py:167
1640 #: ../surfaceslab.py:29 ../surfaceslab.py:170
16341641 msgid "BCC(110)"
16351642 msgstr "BCC(110)"
16361643
1637 #: ../surfaceslab.py:30 ../surfaceslab.py:164
1644 #: ../surfaceslab.py:30 ../surfaceslab.py:167
16381645 msgid "BCC(111)"
16391646 msgstr "BCC(111)"
16401647
1641 #: ../surfaceslab.py:31 ../surfaceslab.py:177
1648 #: ../surfaceslab.py:31 ../surfaceslab.py:180
16421649 msgid "HCP(0001)"
16431650 msgstr "HCP(0001)"
16441651
1645 #: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:131
1646 #: ../surfaceslab.py:187
1652 #: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:134
1653 #: ../surfaceslab.py:190
16471654 msgid "hcp"
16481655 msgstr "hcp"
16491656
1650 #: ../surfaceslab.py:32 ../surfaceslab.py:180
1657 #: ../surfaceslab.py:32 ../surfaceslab.py:183
16511658 msgid "HCP(10-10)"
16521659 msgstr "HCP(10-10)"
16531660
16721679 msgstr "Orthogonal cell:"
16731680
16741681 #: ../surfaceslab.py:72
1675 msgid "Lattice constant:\ta"
1676 msgstr "Lattice constant:\ta"
1682 msgid "Lattice constant:"
1683 msgstr "Lattice constant:"
1684
1685 #: ../surfaceslab.py:73
1686 msgid "\ta"
1687 msgstr "\ta"
16771688
16781689 #: ../surfaceslab.py:74
1679 msgid "\t\tc"
1680 msgstr "\t\tc"
1690 msgid "\tc"
1691 msgstr "\tc"
16811692
16821693 #: ../surfaceslab.py:75
1683 msgid "Size: \tx: "
1684 msgstr "Size: \tx: "
1685
1686 #: ../surfaceslab.py:76
1694 msgid "Size:"
1695 msgstr "Size:"
1696
1697 #: ../surfaceslab.py:77
16871698 msgid "\ty: "
16881699 msgstr "\ty: "
16891700
1690 #: ../surfaceslab.py:77
1701 #: ../surfaceslab.py:78
16911702 msgid "\tz: "
16921703 msgstr "\tz: "
16931704
16941705 #. TRANSLATORS: This is a title of a window.
1695 #: ../surfaceslab.py:81
1706 #: ../surfaceslab.py:82
16961707 msgid "Creating a surface."
16971708 msgstr "Creating a surface."
16981709
1699 #: ../surfaceslab.py:161
1710 #. TRANSLATORS: E.g. "... assume fcc crystal structure for Au"
1711 #: ../surfaceslab.py:110
1712 msgid "Error: Reference values assume {} crystal structure for {}!"
1713 msgstr "Error: Reference values assume {} crystal structure for {}!"
1714
1715 #: ../surfaceslab.py:164
17001716 msgid "Please enter an even value for orthogonal cell"
17011717 msgstr "Please enter an even value for orthogonal cell"
17021718
1703 #: ../surfaceslab.py:174
1719 #: ../surfaceslab.py:177
17041720 msgid "Please enter a value divisible by 3 for orthogonal cell"
17051721 msgstr "Please enter a value divisible by 3 for orthogonal cell"
17061722
1707 #: ../surfaceslab.py:194
1723 #: ../surfaceslab.py:197
17081724 msgid " Vacuum: {} Å."
17091725 msgstr " Vacuum: {} Å."
17101726
17111727 #. TRANSLATORS: e.g. "Au fcc100 surface with 2 atoms."
17121728 #. or "Au fcc100 surface with 2 atoms. Vacuum: 5 Å."
1713 #: ../surfaceslab.py:202
1729 #: ../surfaceslab.py:205
17141730 #, python-brace-format
17151731 msgid "{symbol} {surf} surface with one atom.{vacuum}"
17161732 msgid_plural "{symbol} {surf} surface with {natoms} atoms.{vacuum}"
17331749 msgid "About"
17341750 msgstr "About"
17351751
1736 #: ../ui.py:60 ../ui.py:64
1752 #: ../ui.py:60 ../ui.py:64 ../widgets.py:17
17371753 msgid "Help"
17381754 msgstr "Help"
17391755
1740 #: ../widgets.py:11
1756 #: ../widgets.py:14
17411757 msgid "Element:"
17421758 msgstr "Element:"
17431759
1744 #: ../widgets.py:39
1760 #. This infobox is indescribably ugly because of the
1761 #. ridiculously large font size used by Tkinter. Ouch!
1762 #: ../widgets.py:34
1763 msgid ""
1764 "Enter a chemical symbol or the name of a molecule from the G2 testset:\n"
1765 "{}"
1766 msgstr ""
1767 "Enter a chemical symbol or the name of a molecule from the G2 testset:\n"
1768 "{}"
1769
1770 #: ../widgets.py:68
17451771 msgid "No element specified!"
17461772 msgstr "No element specified!"
17471773
1748 #: ../widgets.py:56
1774 #: ../widgets.py:90
17491775 msgid "ERROR: Invalid element!"
17501776 msgstr "ERROR: Invalid element!"
17511777
1752 #: ../widgets.py:75
1778 #: ../widgets.py:107
17531779 msgid "No Python code"
17541780 msgstr "No Python code"
1781
1782 #~ msgid ""
1783 #~ "%s\n"
1784 #~ "\n"
1785 #~ "Number of atoms: %d.\n"
1786 #~ "\n"
1787 #~ "Unit cell:\n"
1788 #~ " %8.3f %8.3f %8.3f\n"
1789 #~ " %8.3f %8.3f %8.3f\n"
1790 #~ " %8.3f %8.3f %8.3f\n"
1791 #~ "\n"
1792 #~ "%s\n"
1793 #~ "%s\n"
1794 #~ msgstr ""
1795 #~ "%s\n"
1796 #~ "\n"
1797 #~ "Number of atoms: %d.\n"
1798 #~ "\n"
1799 #~ "Unit cell:\n"
1800 #~ " %8.3f %8.3f %8.3f\n"
1801 #~ " %8.3f %8.3f %8.3f\n"
1802 #~ " %8.3f %8.3f %8.3f\n"
1803 #~ "\n"
1804 #~ "%s\n"
1805 #~ "%s\n"
1806
1807 #~ msgid "Volume: "
1808 #~ msgstr "Volume: "
1809
1810 #~ msgid "Size: \tx: "
1811 #~ msgstr "Size: \tx: "
17551812
17561813 #~ msgid ""
17571814 #~ "To make most calculations on the atoms, a Calculator object must first\n"
20342091 #~ msgid "Select calculator"
20352092 #~ msgstr "Select calculator"
20362093
2037 #~ msgid "Calculator:"
2038 #~ msgstr "Calculator:"
2039
20402094 #~ msgid "None"
20412095 #~ msgstr "None"
20422096
25312585 #~ msgid "Density: "
25322586 #~ msgstr "Density: "
25332587
2534 #~ msgid "Energy: "
2535 #~ msgstr "Energy: "
2536
25372588 #~ msgid "GPAW version: "
25382589 #~ msgstr "GPAW version: "
25392590
31183169
31193170 #~ msgid "Max force: %.2f (this frame), %.2f (all frames)"
31203171 #~ msgstr "Max force: %.2f (this frame), %.2f (all frames)"
3121
3122 #~ msgid "Max force: %.2f."
3123 #~ msgstr "Max force: %.2f."
31243172
31253173 #~ msgid "Max velocity: %.2f (this frame), %.2f (all frames)"
31263174 #~ msgstr "Max velocity: %.2f (this frame), %.2f (all frames)"
77 msgstr ""
88 "Project-Id-Version: ase-3.5.2\n"
99 "Report-Msgid-Bugs-To: ase-users@listserv.fysik.dtu.dk\n"
10 "POT-Creation-Date: 2017-09-20 19:21+0200\n"
11 "PO-Revision-Date: 2017-09-20 19:27+0200\n"
10 "POT-Creation-Date: 2017-12-15 17:25+0100\n"
11 "PO-Revision-Date: 2017-12-15 17:48+0100\n"
1212 "Last-Translator: Max Ramirez <m.ramirez@mx.uni-saarland.de>\n"
1313 "Language-Team: Spanish\n"
1414 "Language: es\n"
2626 msgid "Add atoms"
2727 msgstr "Agregar átomos"
2828
29 #: ../add.py:25
29 #: ../add.py:26
3030 msgid "Absolute position:"
3131 msgstr "Posición absoluta:"
3232
33 #: ../add.py:27 ../add.py:30 ../nanoparticle.py:264
33 #: ../add.py:28 ../add.py:31 ../nanoparticle.py:264
3434 msgid "Add"
3535 msgstr "Agregar"
3636
37 #: ../add.py:28
37 #: ../add.py:29
3838 msgid "Relative to average position (of selection):"
3939 msgstr "Relativo a posición media (de la selección):"
4040
7070 msgid "By magnetic moment"
7171 msgstr "Por momento magnético"
7272
73 #: ../colors.py:69
73 #: ../colors.py:26
74 msgid "By number of neighbors"
75 msgstr "Por número de vecinos"
76
77 #: ../colors.py:71
7478 msgid "Green"
7579 msgstr "Verde"
7680
77 #: ../colors.py:69
81 #: ../colors.py:71
7882 msgid "Yellow"
7983 msgstr "Amarillo"
8084
159163 msgid " z: "
160164 msgstr " z: "
161165
162 #: ../crystal.py:97 ../surfaceslab.py:75 ../surfaceslab.py:76
163 #: ../surfaceslab.py:77
166 #: ../crystal.py:97 ../surfaceslab.py:76 ../surfaceslab.py:77
167 #: ../surfaceslab.py:78
164168 msgid " unit cells"
165169 msgstr " celdas unitarias"
166170
238242 msgid " Element:\t"
239243 msgstr " Elemento:%t"
240244
241 #: ../crystal.py:177
245 #: ../crystal.py:177 ../surfaceslab.py:76
242246 msgid "\tx: "
243247 msgstr "\tx: "
244248
264268 msgid "Please specify a consistent set of atoms."
265269 msgstr "Por favor, especifique un conjunto consistente de átomos."
266270
267 #: ../crystal.py:407 ../graphene.py:264 ../nanoparticle.py:530
268 #: ../nanotube.py:84 ../surfaceslab.py:220
271 #: ../crystal.py:407 ../graphene.py:264 ../nanoparticle.py:531
272 #: ../nanotube.py:84 ../surfaceslab.py:223
269273 msgid "No valid atoms."
270274 msgstr "Los átomos no son válidos."
271275
272 #: ../crystal.py:408 ../graphene.py:265 ../nanoparticle.py:531
273 #: ../nanotube.py:85 ../surfaceslab.py:221 ../widgets.py:76
276 #: ../crystal.py:408 ../graphene.py:265 ../nanoparticle.py:532
277 #: ../nanotube.py:85 ../surfaceslab.py:224 ../widgets.py:108
274278 msgid "You have not (yet) specified a consistent set of parameters."
275279 msgstr "No ha especificado aún un conjunto consistente de parámetros."
276280
328332 "Configure una sábana de grafeno o una nanocinta. Opcionalmente,\n"
329333 "la nanocinta puede ser saturada con hidrógeno u otro elemento."
330334
331 #: ../graphene.py:38 ../gui.py:512
335 #: ../graphene.py:38 ../gui.py:514
332336 msgid "Graphene"
333337 msgstr "Grafeno"
334338
389393 msgstr " Largo: "
390394
391395 #. Vacuum
392 #: ../graphene.py:105 ../surfaceslab.py:78
396 #: ../graphene.py:105 ../surfaceslab.py:79
393397 msgid "Vacuum: "
394398 msgstr "Vacío: "
395399
465469 msgid "Save data to file ... "
466470 msgstr "Salve los datos a un archivo ..."
467471
468 #: ../gui.py:286
472 #: ../gui.py:284
469473 msgid "Automatic"
470474 msgstr "Automático"
471475
472 #: ../gui.py:304
476 #: ../gui.py:302
473477 msgid "Open ..."
474478 msgstr "Abrir ..."
475479
476 #: ../gui.py:305
480 #: ../gui.py:303
477481 msgid "Choose parser:"
478482 msgstr "Elegir parser:"
479483
480 #: ../gui.py:416
484 #: ../gui.py:418
481485 msgid "_File"
482486 msgstr "_Archivo"
483487
484 #: ../gui.py:417
488 #: ../gui.py:419
485489 msgid "_Open"
486490 msgstr "_Abrir"
487491
488 #: ../gui.py:418
492 #: ../gui.py:420
489493 msgid "_New"
490494 msgstr "_Nuevo"
491495
492 #: ../gui.py:419
496 #: ../gui.py:421
493497 msgid "_Save"
494498 msgstr "_Guardar"
495499
496 #: ../gui.py:421
500 #: ../gui.py:423
497501 msgid "_Quit"
498502 msgstr "_Salir"
499503
500 #: ../gui.py:423
504 #: ../gui.py:425
501505 msgid "_Edit"
502506 msgstr "_Editar"
503507
504 #: ../gui.py:424
508 #: ../gui.py:426
505509 msgid "Select _all"
506510 msgstr "Seleccionar _todo"
507511
508 #: ../gui.py:425
512 #: ../gui.py:427
509513 msgid "_Invert selection"
510514 msgstr "_Invertir selección"
511515
512 #: ../gui.py:426
516 #: ../gui.py:428
513517 msgid "Select _constrained atoms"
514518 msgstr "Seleccionar los átomos _restringidos"
515519
516 #: ../gui.py:427
520 #: ../gui.py:429
517521 msgid "Select _immobile atoms"
518522 msgstr "Seleccionar los átomos _inmóbiles"
519523
520 #: ../gui.py:433
524 #: ../gui.py:434
521525 msgid "Hide selected atoms"
522526 msgstr "Ocultar átomos seleccionados"
523527
524 #: ../gui.py:434
528 #: ../gui.py:435
525529 msgid "Show selected atoms"
526530 msgstr "Mostrar átomos seleccionados"
527531
528 #: ../gui.py:436
532 #: ../gui.py:437
529533 msgid "_Modify"
530534 msgstr "_Modificar"
531535
532 #: ../gui.py:437
536 #: ../gui.py:438
533537 msgid "_Add atoms"
534538 msgstr "_Añadir átomos"
535539
536 #: ../gui.py:438
540 #: ../gui.py:439
537541 msgid "_Delete selected atoms"
538542 msgstr "_Borrar átomos seleccionados"
539543
540544 #: ../gui.py:441
545 msgid "Edit _cell"
546 msgstr "Editar _celda"
547
548 #: ../gui.py:443
541549 msgid "_First image"
542550 msgstr "_Primera imagen"
543551
544 #: ../gui.py:442
552 #: ../gui.py:444
545553 msgid "_Previous image"
546554 msgstr "_Imagen previa"
547555
548 #: ../gui.py:443
556 #: ../gui.py:445
549557 msgid "_Next image"
550558 msgstr "_Próxima imagen"
551559
552 #: ../gui.py:444
560 #: ../gui.py:446
553561 msgid "_Last image"
554562 msgstr "Ú_ltima imagen"
555563
556 #: ../gui.py:446
564 #: ../gui.py:448
557565 msgid "_View"
558566 msgstr "_Ver"
559567
560 #: ../gui.py:447
568 #: ../gui.py:449
561569 msgid "Show _unit cell"
562570 msgstr "Mostrar la celda _unitaria"
563571
564 #: ../gui.py:449
572 #: ../gui.py:451
565573 msgid "Show _axes"
566574 msgstr "Mostrar los _ejes"
567575
568 #: ../gui.py:450
576 #: ../gui.py:452
569577 msgid "Show _bonds"
570578 msgstr "Mostrar los _enlaces"
571579
572 #: ../gui.py:452
580 #: ../gui.py:454
573581 msgid "Show _velocities"
574582 msgstr "Mostrar las _velocidades"
575583
576 #: ../gui.py:454
584 #: ../gui.py:456
577585 msgid "Show _forces"
578586 msgstr "Mostrar las _fuerzas"
579587
580 #: ../gui.py:456
588 #: ../gui.py:458
581589 msgid "Show _Labels"
582590 msgstr "Mostrar los _etiquetas"
583591
584 #: ../gui.py:457
592 #: ../gui.py:459
585593 msgid "_None"
586594 msgstr "_Ninguno"
587595
588 #: ../gui.py:458
596 #: ../gui.py:460
589597 msgid "Atom _Index"
590598 msgstr "_Índice de Atom"
591599
592 #: ../gui.py:459
600 #: ../gui.py:461
593601 msgid "_Magnetic Moments"
594602 msgstr "Momentos _Magnético"
595603
596604 #. XXX check if exist
597 #: ../gui.py:460
605 #: ../gui.py:462
598606 msgid "_Element Symbol"
599607 msgstr "Símbolo _Químico"
600608
601 #: ../gui.py:461
609 #: ../gui.py:463
602610 msgid "_Initial Charges"
603611 msgstr "Cargas _iniciales"
604612
605 #: ../gui.py:464
613 #: ../gui.py:466
606614 msgid "Quick Info ..."
607615 msgstr "Información rápida ..."
608616
609 #: ../gui.py:465
617 #: ../gui.py:467
610618 msgid "Repeat ..."
611619 msgstr "Repetir ..."
612620
613 #: ../gui.py:466
621 #: ../gui.py:468
614622 msgid "Rotate ..."
615623 msgstr "Rotar ..."
616624
617 #: ../gui.py:467
625 #: ../gui.py:469
618626 msgid "Colors ..."
619627 msgstr "Colores ..."
620628
621629 #. TRANSLATORS: verb
622 #: ../gui.py:469
630 #: ../gui.py:471
623631 msgid "Focus"
624632 msgstr "Enfocar"
625633
626 #: ../gui.py:470
634 #: ../gui.py:472
627635 msgid "Zoom in"
628636 msgstr "Ampliar"
629637
630 #: ../gui.py:471
638 #: ../gui.py:473
631639 msgid "Zoom out"
632640 msgstr "Alejar"
633641
634 #: ../gui.py:472
642 #: ../gui.py:474
635643 msgid "Change View"
636644 msgstr "Cambiar de vista"
637645
638 #: ../gui.py:474
646 #: ../gui.py:476
639647 msgid "Reset View"
640648 msgstr "Reiniciar la vista"
641649
642 #: ../gui.py:475
650 #: ../gui.py:477
643651 msgid "xy-plane"
644652 msgstr "plano xy"
645653
646 #: ../gui.py:476
654 #: ../gui.py:478
647655 msgid "yz-plane"
648656 msgstr "plano yz"
649657
650 #: ../gui.py:477
658 #: ../gui.py:479
651659 msgid "zx-plane"
652660 msgstr "plano xz"
653661
654 #: ../gui.py:478
662 #: ../gui.py:480
655663 msgid "yx-plane"
656664 msgstr "plano yx"
657665
658 #: ../gui.py:479
666 #: ../gui.py:481
659667 msgid "zy-plane"
660668 msgstr "plano zy"
661669
662 #: ../gui.py:480
670 #: ../gui.py:482
663671 msgid "xz-plane"
664672 msgstr "plano xz"
665673
666 #: ../gui.py:481
674 #: ../gui.py:483
667675 msgid "a2,a3-plane"
668676 msgstr "plano a2,a3"
669677
670 #: ../gui.py:482
678 #: ../gui.py:484
671679 msgid "a3,a1-plane"
672680 msgstr "plano a3,a1"
673681
674 #: ../gui.py:483
682 #: ../gui.py:485
675683 msgid "a1,a2-plane"
676684 msgstr "plano a1,a2"
677685
678 #: ../gui.py:484
686 #: ../gui.py:486
679687 msgid "a3,a2-plane"
680688 msgstr "plano a3,a2"
681689
682 #: ../gui.py:485
690 #: ../gui.py:487
683691 msgid "a1,a3-plane"
684692 msgstr "plano a1,a3"
685693
686 #: ../gui.py:486
694 #: ../gui.py:488
687695 msgid "a2,a1-plane"
688696 msgstr "plano a2,a1"
689697
690 #: ../gui.py:487
698 #: ../gui.py:489
691699 msgid "Settings ..."
692700 msgstr "Ajustes ..."
693701
694 #: ../gui.py:489
702 #: ../gui.py:491
695703 msgid "VMD"
696704 msgstr "VMD"
697705
698 #: ../gui.py:490
706 #: ../gui.py:492
699707 msgid "RasMol"
700708 msgstr "RasMol"
701709
702 #: ../gui.py:491
710 #: ../gui.py:493
703711 msgid "xmakemol"
704712 msgstr "xmakemol"
705713
706 #: ../gui.py:492
714 #: ../gui.py:494
707715 msgid "avogadro"
708716 msgstr "avogadro"
709717
710 #: ../gui.py:494
718 #: ../gui.py:496
711719 msgid "_Tools"
712720 msgstr "_Herramientas"
713721
714 #: ../gui.py:495
722 #: ../gui.py:497
715723 msgid "Graphs ..."
716724 msgstr "Gráficos ..."
717725
718 #: ../gui.py:496
726 #: ../gui.py:498
719727 msgid "Movie ..."
720728 msgstr "Película ..."
721729
722 #: ../gui.py:497
730 #: ../gui.py:499
723731 msgid "Expert mode ..."
724732 msgstr "Modo experto ..."
725733
726 #: ../gui.py:498
734 #: ../gui.py:500
727735 msgid "Constraints ..."
728736 msgstr "Restricciones ..."
729737
730 #: ../gui.py:499
738 #: ../gui.py:501
731739 msgid "Render scene ..."
732740 msgstr "Dibujar escena ..."
733741
734 #: ../gui.py:500
742 #: ../gui.py:502
735743 msgid "_Move atoms"
736744 msgstr "_Mover los átomos"
737745
738 #: ../gui.py:501
746 #: ../gui.py:503
739747 msgid "_Rotate atoms"
740748 msgstr "_Rotar los átomos"
741749
742 #: ../gui.py:502
750 #: ../gui.py:504
743751 msgid "NE_B"
744752 msgstr "NE_B"
745753
746 #: ../gui.py:503
754 #: ../gui.py:505
747755 msgid "B_ulk Modulus"
748756 msgstr "Módulo de b_ulto"
749757
750758 #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
751 #: ../gui.py:506
759 #: ../gui.py:508
752760 msgid "_Setup"
753761 msgstr "_Configurar"
754762
755 #: ../gui.py:507
763 #: ../gui.py:509
756764 msgid "_Bulk Crystal"
757765 msgstr "Cristal en _bulto"
758766
759 #: ../gui.py:508
767 #: ../gui.py:510
760768 msgid "_Surface slab"
761769 msgstr "Trozo de _superficie"
762770
763 #: ../gui.py:509
771 #: ../gui.py:511
764772 msgid "_Nanoparticle"
765773 msgstr "_Nanopartícula"
766774
767 #: ../gui.py:511
775 #: ../gui.py:513
768776 msgid "Nano_tube"
769777 msgstr "Nano_tubo"
770778
771 #: ../gui.py:514
779 #: ../gui.py:516
772780 msgid "_Calculate"
773781 msgstr "_Calcular"
774782
775 #: ../gui.py:515
783 #: ../gui.py:517
776784 msgid "Set _Calculator"
777785 msgstr "Fijar el _calculador"
778786
779 #: ../gui.py:516
787 #: ../gui.py:518
780788 msgid "_Energy and Forces"
781789 msgstr "_Energía y Fuerzas"
782790
783 #: ../gui.py:517
791 #: ../gui.py:519
784792 msgid "Energy Minimization"
785793 msgstr "Minimización de energía"
786794
787 #: ../gui.py:520
795 #: ../gui.py:522
788796 msgid "_Help"
789797 msgstr "_Ayuda"
790798
791 #: ../gui.py:521
799 #: ../gui.py:523
792800 msgid "_About"
793801 msgstr "_Acerca de ag"
794802
795 #: ../gui.py:525
803 #: ../gui.py:527
796804 msgid "Webpage ..."
797805 msgstr "Página web ..."
798806
10251033 msgid "Creating a nanoparticle."
10261034 msgstr "Creando una nanopartícula."
10271035
1028 #: ../nanoparticle.py:197 ../nanotube.py:52 ../surfaceslab.py:82
1036 #: ../nanoparticle.py:197 ../nanotube.py:52 ../surfaceslab.py:83
10291037 msgid "Apply"
10301038 msgstr "Aplicar"
10311039
1032 #: ../nanoparticle.py:198 ../nanotube.py:53 ../surfaceslab.py:83
1040 #: ../nanoparticle.py:198 ../nanotube.py:53 ../surfaceslab.py:84
10331041 msgid "OK"
10341042 msgstr "Aceptar"
10351043
11531161 msgid "Length:"
11541162 msgstr "Largo:"
11551163
1156 #: ../quickinfo.py:6
1164 #: ../quickinfo.py:28
1165 msgid "This frame has no atoms."
1166 msgstr "Este cuadro no tiene átomos."
1167
1168 #: ../quickinfo.py:33
11571169 msgid "Single image loaded."
11581170 msgstr "Una imagen cargada."
11591171
1160 #: ../quickinfo.py:7
1161 #, python-format
1162 msgid "Image %d loaded (0 - %d)."
1163 msgstr "Imagen %d cargada (0 - %d)."
1164
1165 #: ../quickinfo.py:8
1172 #: ../quickinfo.py:35
1173 msgid "Image {} loaded (0–{})."
1174 msgstr "Imagen {} cargada (0–{})."
1175
1176 #: ../quickinfo.py:37
1177 msgid "Number of atoms: {}"
1178 msgstr "Número de átomos: {}"
1179
1180 #: ../quickinfo.py:47
1181 msgid "Unit cell [Å]:"
1182 msgstr "Celda unitaria [Å]:"
1183
1184 #: ../quickinfo.py:49
1185 msgid "no"
1186 msgstr "no"
1187
1188 #: ../quickinfo.py:49
1189 msgid "yes"
1190 msgstr "sí"
1191
1192 #. TRANSLATORS: This has the form Periodic: no, no, yes
1193 #: ../quickinfo.py:51
1194 msgid "Periodic: {}, {}, {}"
1195 msgstr "Periódico: {}, {}, {}"
1196
1197 #: ../quickinfo.py:55
11661198 msgid "Unit cell is fixed."
11671199 msgstr "La celda unitaria está fija."
11681200
1169 #: ../quickinfo.py:9
1201 #: ../quickinfo.py:57
11701202 msgid "Unit cell varies."
11711203 msgstr "La celda unitaria varía."
11721204
1173 #: ../quickinfo.py:11
1174 #, python-format
1175 msgid ""
1176 "%s\n"
1177 "\n"
1178 "Number of atoms: %d.\n"
1179 "\n"
1180 "Unit cell:\n"
1181 " %8.3f %8.3f %8.3f\n"
1182 " %8.3f %8.3f %8.3f\n"
1183 " %8.3f %8.3f %8.3f\n"
1184 "\n"
1185 "%s\n"
1186 "%s\n"
1187 msgstr ""
1188 "%s\n"
1189 "\n"
1190 "Número de átomos: %d.\n"
1191 "\n"
1192 "Celda unitaria:\n"
1193 " %8.3f %8.3f %8.3f\n"
1194 " %8.3f %8.3f %8.3f\n"
1195 " %8.3f %8.3f %8.3f\n"
1196 "\n"
1197 "%s\n"
1198 "%s\n"
1199
1200 #: ../quickinfo.py:33
1201 msgid "This frame has no atoms."
1202 msgstr "Este cuadro no tiene átomos."
1203
1204 #: ../quickinfo.py:53
1205 msgid "no"
1206 msgstr "no"
1207
1208 #: ../quickinfo.py:53
1209 msgid "yes"
1210 msgstr "sí"
1211
1212 #. TRANSLATORS: This has the form Periodic: no, no, yes
1213 #: ../quickinfo.py:57
1214 #, python-format
1215 msgid "Periodic: %s, %s, %s"
1216 msgstr "Periódico: %s, %s, %s"
1217
1218 #: ../quickinfo.py:61
1219 msgid "Volume: "
1220 msgstr "Volumen: "
1205 #: ../quickinfo.py:60
1206 msgid "Volume: {:.3f} ų"
1207 msgstr "Volumen: {:.3f} ų"
1208
1209 #: ../quickinfo.py:88
1210 msgid "Calculator: {} (cached)"
1211 msgstr "Calculador: {} (almacenado)"
1212
1213 #: ../quickinfo.py:90
1214 msgid "Calculator: {} (attached)"
1215 msgstr "Calculador: {} (adjunto)"
1216
1217 #: ../quickinfo.py:97
1218 msgid "Energy: {:.3f} eV"
1219 msgstr "Energía: {:.3f} eV"
1220
1221 #: ../quickinfo.py:102
1222 msgid "Max force: {:.3f} eV/Å"
1223 msgstr "Fuerza máxima: {:.3f} eV/Å"
1224
1225 #: ../quickinfo.py:107
1226 msgid "Magmom: {:.3f} µ"
1227 msgstr "Momento magnético: {:.3f} µ"
12211228
12221229 #: ../render.py:20 ../render.py:190
12231230 msgid "Render current view in povray ... "
16181625 msgid "FCC(110)"
16191626 msgstr "FCC(110)"
16201627
1621 #: ../surfaceslab.py:26 ../surfaceslab.py:170
1628 #: ../surfaceslab.py:26 ../surfaceslab.py:173
16221629 msgid "FCC(111)"
16231630 msgstr "FCC(111)"
16241631
1625 #: ../surfaceslab.py:27 ../surfaceslab.py:173
1632 #: ../surfaceslab.py:27 ../surfaceslab.py:176
16261633 msgid "FCC(211)"
16271634 msgstr "FCC(211)"
16281635
16341641 msgid "bcc"
16351642 msgstr "bcc"
16361643
1637 #: ../surfaceslab.py:29 ../surfaceslab.py:167
1644 #: ../surfaceslab.py:29 ../surfaceslab.py:170
16381645 msgid "BCC(110)"
16391646 msgstr "BCC(110)"
16401647
1641 #: ../surfaceslab.py:30 ../surfaceslab.py:164
1648 #: ../surfaceslab.py:30 ../surfaceslab.py:167
16421649 msgid "BCC(111)"
16431650 msgstr "BCC(111)"
16441651
1645 #: ../surfaceslab.py:31 ../surfaceslab.py:177
1652 #: ../surfaceslab.py:31 ../surfaceslab.py:180
16461653 msgid "HCP(0001)"
16471654 msgstr "HCP(0001)"
16481655
1649 #: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:131
1650 #: ../surfaceslab.py:187
1656 #: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:134
1657 #: ../surfaceslab.py:190
16511658 msgid "hcp"
16521659 msgstr "hcp"
16531660
1654 #: ../surfaceslab.py:32 ../surfaceslab.py:180
1661 #: ../surfaceslab.py:32 ../surfaceslab.py:183
16551662 msgid "HCP(10-10)"
16561663 msgstr "HCP(10-10)"
16571664
16761683 msgstr "Celda unitaria ortogonal:"
16771684
16781685 #: ../surfaceslab.py:72
1679 msgid "Lattice constant:\ta"
1680 msgstr "Constante de red:\ta"
1686 msgid "Lattice constant:"
1687 msgstr "Constante de red:"
1688
1689 #: ../surfaceslab.py:73
1690 msgid "\ta"
1691 msgstr "\ta"
16811692
16821693 #: ../surfaceslab.py:74
1683 msgid "\t\tc"
1684 msgstr "\t\tc"
1694 msgid "\tc"
1695 msgstr "\tc"
16851696
16861697 #: ../surfaceslab.py:75
1687 msgid "Size: \tx: "
1688 msgstr "Tamaño en\tx: "
1689
1690 #: ../surfaceslab.py:76
1698 msgid "Size:"
1699 msgstr "Tamaño:"
1700
1701 #: ../surfaceslab.py:77
16911702 msgid "\ty: "
16921703 msgstr "\ty: "
16931704
1694 #: ../surfaceslab.py:77
1705 #: ../surfaceslab.py:78
16951706 msgid "\tz: "
16961707 msgstr "\tz: "
16971708
16981709 #. TRANSLATORS: This is a title of a window.
1699 #: ../surfaceslab.py:81
1710 #: ../surfaceslab.py:82
17001711 msgid "Creating a surface."
17011712 msgstr "Crear un trozo de superficie."
17021713
1703 #: ../surfaceslab.py:161
1714 #. TRANSLATORS: E.g. "... assume fcc crystal structure for Au"
1715 #: ../surfaceslab.py:110
1716 msgid "Error: Reference values assume {} crystal structure for {}!"
1717 msgstr "Error: Valores de referencia para {0} pertenecen a la estructura {1}"
1718
1719 #: ../surfaceslab.py:164
17041720 msgid "Please enter an even value for orthogonal cell"
17051721 msgstr "Por favor entre un valor par para celda ortogonal"
17061722
1707 #: ../surfaceslab.py:174
1723 #: ../surfaceslab.py:177
17081724 msgid "Please enter a value divisible by 3 for orthogonal cell"
17091725 msgstr "Por favor entre un valor divisible por 3 para celda ortogonal"
17101726
1711 #: ../surfaceslab.py:194
1727 #: ../surfaceslab.py:197
17121728 msgid " Vacuum: {} Å."
17131729 msgstr " Vacío: {} Å."
17141730
17151731 #. TRANSLATORS: e.g. "Au fcc100 surface with 2 atoms."
17161732 #. or "Au fcc100 surface with 2 atoms. Vacuum: 5 Å."
1717 #: ../surfaceslab.py:202
1733 #: ../surfaceslab.py:205
17181734 #, python-brace-format
17191735 msgid "{symbol} {surf} surface with one atom.{vacuum}"
17201736 msgid_plural "{symbol} {surf} surface with {natoms} atoms.{vacuum}"
17371753 msgid "About"
17381754 msgstr "Acerca de ag"
17391755
1740 #: ../ui.py:60 ../ui.py:64
1756 #: ../ui.py:60 ../ui.py:64 ../widgets.py:17
17411757 msgid "Help"
17421758 msgstr "Ayuda"
17431759
1744 #: ../widgets.py:11
1760 #: ../widgets.py:14
17451761 msgid "Element:"
17461762 msgstr "Elemento:"
17471763
1748 #: ../widgets.py:39
1764 #. This infobox is indescribably ugly because of the
1765 #. ridiculously large font size used by Tkinter. Ouch!
1766 #: ../widgets.py:34
1767 msgid ""
1768 "Enter a chemical symbol or the name of a molecule from the G2 testset:\n"
1769 "{}"
1770 msgstr ""
1771 "Entre un símbolo químico o el nombre de una molécula del conjunto G2:\n"
1772 "{}"
1773
1774 #: ../widgets.py:68
17491775 msgid "No element specified!"
17501776 msgstr "¡No se especifica el elemento!"
17511777
1752 #: ../widgets.py:56
1778 #: ../widgets.py:90
17531779 msgid "ERROR: Invalid element!"
17541780 msgstr "ERROR: ¡elemento inválido!"
17551781
1756 #: ../widgets.py:75
1782 #: ../widgets.py:107
17571783 msgid "No Python code"
17581784 msgstr "No es código de Python"
1785
1786 #~ msgid ""
1787 #~ "%s\n"
1788 #~ "\n"
1789 #~ "Number of atoms: %d.\n"
1790 #~ "\n"
1791 #~ "Unit cell:\n"
1792 #~ " %8.3f %8.3f %8.3f\n"
1793 #~ " %8.3f %8.3f %8.3f\n"
1794 #~ " %8.3f %8.3f %8.3f\n"
1795 #~ "\n"
1796 #~ "%s\n"
1797 #~ "%s\n"
1798 #~ msgstr ""
1799 #~ "%s\n"
1800 #~ "\n"
1801 #~ "Número de átomos: %d.\n"
1802 #~ "\n"
1803 #~ "Celda unitaria:\n"
1804 #~ " %8.3f %8.3f %8.3f\n"
1805 #~ " %8.3f %8.3f %8.3f\n"
1806 #~ " %8.3f %8.3f %8.3f\n"
1807 #~ "\n"
1808 #~ "%s\n"
1809 #~ "%s\n"
1810
1811 #~ msgid "Volume: "
1812 #~ msgstr "Volumen: "
1813
1814 #~ msgid "Size: \tx: "
1815 #~ msgstr "Tamaño en\tx: "
17591816
17601817 #~ msgid ""
17611818 #~ "To make most calculations on the atoms, a Calculator object must first\n"
20592116 #~ msgid "Select calculator"
20602117 #~ msgstr "Seleccione Calculador (Calculator)"
20612118
2062 #~ msgid "Calculator:"
2063 #~ msgstr "Calculador:"
2064
20652119 #~ msgid "None"
20662120 #~ msgstr "Ninguno"
20672121
25712625 #~ msgid "Density: "
25722626 #~ msgstr "Densidad: "
25732627
2574 #~ msgid "Energy: "
2575 #~ msgstr "Energía: "
2576
25772628 #~ msgid "GPAW version: "
25782629 #~ msgstr "Versión de GPAW: "
25792630
31643215 #~ msgid "Max force: %.2f (this frame), %.2f (all frames)"
31653216 #~ msgstr "Fuerza máx: %.2f (este cuadro), %.2f (todos los cuadros)"
31663217
3167 #~ msgid "Max force: %.2f."
3168 #~ msgstr "Fuerza máx: %.2f."
3169
31703218 #~ msgid "Max velocity: %.2f (this frame), %.2f (all frames)"
31713219 #~ msgstr "Velocidad máxima: %.2f (este cuadro), %.2f (todos los cuadros)"
31723220
77 msgstr ""
88 "Project-Id-Version: ase\n"
99 "Report-Msgid-Bugs-To: ase-users@listserv.fysik.dtu.dk\n"
10 "POT-Creation-Date: 2017-09-28 19:11+0200\n"
11 "PO-Revision-Date: 2017-09-28 19:12+0200\n"
10 "POT-Creation-Date: 2017-12-15 17:18+0100\n"
11 "PO-Revision-Date: 2017-12-15 17:21+0100\n"
1212 "Last-Translator: Alejandro Pérez Paz <alejandroperezpaz@yahoo.com>\n"
1313 "Language-Team: Galician\n"
1414 "Language: gl\n"
2626 msgid "Add atoms"
2727 msgstr "Engadir átomos"
2828
29 #: ../add.py:25
29 #: ../add.py:26
3030 msgid "Absolute position:"
3131 msgstr "Posición absoluta:"
3232
33 #: ../add.py:27 ../add.py:30 ../nanoparticle.py:264
33 #: ../add.py:28 ../add.py:31 ../nanoparticle.py:264
3434 msgid "Add"
3535 msgstr "Engadir"
3636
37 #: ../add.py:28
37 #: ../add.py:29
3838 msgid "Relative to average position (of selection):"
3939 msgstr "Relativo a unha posición promedio (de selección):"
4040
7272 msgid "By magnetic moment"
7373 msgstr "Por momento magnético"
7474
75 #: ../colors.py:69
75 #: ../colors.py:26
76 #, fuzzy
77 #| msgid "Number of layers:"
78 msgid "By number of neighbors"
79 msgstr "Número de capas:"
80
81 #: ../colors.py:71
7682 msgid "Green"
7783 msgstr "Verde"
7884
79 #: ../colors.py:69
85 #: ../colors.py:71
8086 msgid "Yellow"
8187 msgstr "Amarelo"
8288
161167 msgid " z: "
162168 msgstr " z: "
163169
164 #: ../crystal.py:97 ../surfaceslab.py:75 ../surfaceslab.py:76
165 #: ../surfaceslab.py:77
170 #: ../crystal.py:97 ../surfaceslab.py:76 ../surfaceslab.py:77
171 #: ../surfaceslab.py:78
166172 msgid " unit cells"
167173 msgstr " celdas unidades"
168174
240246 msgid " Element:\t"
241247 msgstr " Elemento:%t"
242248
243 #: ../crystal.py:177
249 #: ../crystal.py:177 ../surfaceslab.py:76
244250 msgid "\tx: "
245251 msgstr "\tx: "
246252
266272 msgid "Please specify a consistent set of atoms."
267273 msgstr "Por favor, especifique un conxunto consistente de átomos."
268274
269 #: ../crystal.py:407 ../graphene.py:264 ../nanoparticle.py:530
270 #: ../nanotube.py:84 ../surfaceslab.py:220
275 #: ../crystal.py:407 ../graphene.py:264 ../nanoparticle.py:531
276 #: ../nanotube.py:84 ../surfaceslab.py:223
271277 msgid "No valid atoms."
272278 msgstr "Os átomos no son válidos."
273279
274 #: ../crystal.py:408 ../graphene.py:265 ../nanoparticle.py:531
275 #: ../nanotube.py:85 ../surfaceslab.py:221 ../widgets.py:76
280 #: ../crystal.py:408 ../graphene.py:265 ../nanoparticle.py:532
281 #: ../nanotube.py:85 ../surfaceslab.py:224 ../widgets.py:108
276282 msgid "You have not (yet) specified a consistent set of parameters."
277283 msgstr "Aínda non especificou un conxunto consistente de parámetros."
278284
330336 "Faga unha folla de grafeno ou unha nanocinta. Opcionalmente,\n"
331337 "a nanocinta pode estar saturada con hidróxeno u outro elemento."
332338
333 #: ../graphene.py:38 ../gui.py:512
339 #: ../graphene.py:38 ../gui.py:514
334340 msgid "Graphene"
335341 msgstr "Grafeno"
336342
391397 msgstr " Lonxitude: "
392398
393399 #. Vacuum
394 #: ../graphene.py:105 ../surfaceslab.py:78
400 #: ../graphene.py:105 ../surfaceslab.py:79
395401 msgid "Vacuum: "
396402 msgstr "Vacío: "
397403
465471 msgid "Save data to file ... "
466472 msgstr "Garde os datos nun arquivo ..."
467473
468 #: ../gui.py:286
474 #: ../gui.py:284
469475 msgid "Automatic"
470476 msgstr "Automático"
471477
472 #: ../gui.py:304
478 #: ../gui.py:302
473479 msgid "Open ..."
474480 msgstr "Abrir ..."
475481
476 #: ../gui.py:305
482 #: ../gui.py:303
477483 msgid "Choose parser:"
478484 msgstr "Escolla un párser:"
479485
480 #: ../gui.py:416
486 #: ../gui.py:418
481487 msgid "_File"
482488 msgstr "_Arquivo"
483489
484 #: ../gui.py:417
490 #: ../gui.py:419
485491 msgid "_Open"
486492 msgstr "_Abrir"
487493
488 #: ../gui.py:418
494 #: ../gui.py:420
489495 msgid "_New"
490496 msgstr "_Novo"
491497
492 #: ../gui.py:419
498 #: ../gui.py:421
493499 msgid "_Save"
494500 msgstr "_Gardar"
495501
496 #: ../gui.py:421
502 #: ../gui.py:423
497503 msgid "_Quit"
498504 msgstr "_Saír"
499505
500 #: ../gui.py:423
506 #: ../gui.py:425
501507 msgid "_Edit"
502508 msgstr "_Editar"
503509
504 #: ../gui.py:424
510 #: ../gui.py:426
505511 msgid "Select _all"
506512 msgstr "Seleccionar _todo"
507513
508 #: ../gui.py:425
514 #: ../gui.py:427
509515 msgid "_Invert selection"
510516 msgstr "_Invertir selección"
511517
512 #: ../gui.py:426
518 #: ../gui.py:428
513519 msgid "Select _constrained atoms"
514520 msgstr "Seleccionar átomos _restrinxidos"
515521
516 #: ../gui.py:427
522 #: ../gui.py:429
517523 msgid "Select _immobile atoms"
518524 msgstr "Seleccionar átomos _inamovibles"
519525
520 #: ../gui.py:433
526 #: ../gui.py:434
521527 msgid "Hide selected atoms"
522528 msgstr "Ocultar átomos seleccionados"
523529
524 #: ../gui.py:434
530 #: ../gui.py:435
525531 msgid "Show selected atoms"
526532 msgstr "Mostrar átomos seleccionados"
527533
528 #: ../gui.py:436
534 #: ../gui.py:437
529535 msgid "_Modify"
530536 msgstr "_Modificar"
531537
532 #: ../gui.py:437
538 #: ../gui.py:438
533539 msgid "_Add atoms"
534540 msgstr "_Engadir átomos"
535541
536 #: ../gui.py:438
542 #: ../gui.py:439
537543 msgid "_Delete selected atoms"
538544 msgstr "_Borrar átomos seleccionados"
539545
540546 #: ../gui.py:441
547 #, fuzzy
548 #| msgid " unit cells"
549 msgid "Edit _cell"
550 msgstr " celdas unidades"
551
552 #: ../gui.py:443
541553 msgid "_First image"
542554 msgstr "_Primeira imaxe"
543555
544 #: ../gui.py:442
556 #: ../gui.py:444
545557 msgid "_Previous image"
546558 msgstr "_Imaxe previa"
547559
548 #: ../gui.py:443
560 #: ../gui.py:445
549561 msgid "_Next image"
550562 msgstr "_Próxima imaxe"
551563
552 #: ../gui.py:444
564 #: ../gui.py:446
553565 msgid "_Last image"
554566 msgstr "Última imaxe"
555567
556 #: ../gui.py:446
568 #: ../gui.py:448
557569 msgid "_View"
558570 msgstr "_Ver"
559571
560 #: ../gui.py:447
572 #: ../gui.py:449
561573 msgid "Show _unit cell"
562574 msgstr "Mostrar celda _unidade"
563575
564 #: ../gui.py:449
576 #: ../gui.py:451
565577 msgid "Show _axes"
566578 msgstr "Mostrar _eixes"
567579
568 #: ../gui.py:450
580 #: ../gui.py:452
569581 msgid "Show _bonds"
570582 msgstr "Mostrar _enlaces"
571583
572 #: ../gui.py:452
584 #: ../gui.py:454
573585 msgid "Show _velocities"
574586 msgstr "Mostrar _velocidades"
575587
576 #: ../gui.py:454
588 #: ../gui.py:456
577589 msgid "Show _forces"
578590 msgstr "Mostrar _forzas"
579591
580 #: ../gui.py:456
592 #: ../gui.py:458
581593 msgid "Show _Labels"
582594 msgstr "Mostrar _etiquetas"
583595
584 #: ../gui.py:457
596 #: ../gui.py:459
585597 msgid "_None"
586598 msgstr "_Ningún"
587599
588 #: ../gui.py:458
600 #: ../gui.py:460
589601 msgid "Atom _Index"
590602 msgstr "_Índice do Átomo"
591603
592 #: ../gui.py:459
604 #: ../gui.py:461
593605 msgid "_Magnetic Moments"
594606 msgstr "Momentos _Magnéticos"
595607
596608 #. XXX check if exist
597 #: ../gui.py:460
609 #: ../gui.py:462
598610 msgid "_Element Symbol"
599611 msgstr "Símbolo _Químico"
600612
601 #: ../gui.py:461
613 #: ../gui.py:463
602614 msgid "_Initial Charges"
603615 msgstr ""
604616
605 #: ../gui.py:464
617 #: ../gui.py:466
606618 msgid "Quick Info ..."
607619 msgstr "Información rápida ..."
608620
609 #: ../gui.py:465
621 #: ../gui.py:467
610622 msgid "Repeat ..."
611623 msgstr "Repetir ..."
612624
613 #: ../gui.py:466
625 #: ../gui.py:468
614626 msgid "Rotate ..."
615627 msgstr "Xirar ..."
616628
617 #: ../gui.py:467
629 #: ../gui.py:469
618630 msgid "Colors ..."
619631 msgstr "Cores ..."
620632
621633 #. TRANSLATORS: verb
622 #: ../gui.py:469
634 #: ../gui.py:471
623635 msgid "Focus"
624636 msgstr "Enfocar"
625637
626 #: ../gui.py:470
638 #: ../gui.py:472
627639 msgid "Zoom in"
628640 msgstr "Ampliar"
629641
630 #: ../gui.py:471
642 #: ../gui.py:473
631643 msgid "Zoom out"
632644 msgstr "Afastar"
633645
634 #: ../gui.py:472
646 #: ../gui.py:474
635647 msgid "Change View"
636648 msgstr "Cambiar de vista"
637649
638 #: ../gui.py:474
650 #: ../gui.py:476
639651 msgid "Reset View"
640652 msgstr "Reiniciar Vista"
641653
642 #: ../gui.py:475
654 #: ../gui.py:477
643655 msgid "xy-plane"
644656 msgstr "plano xy"
645657
646 #: ../gui.py:476
658 #: ../gui.py:478
647659 msgid "yz-plane"
648660 msgstr "plano yz"
649661
650 #: ../gui.py:477
662 #: ../gui.py:479
651663 msgid "zx-plane"
652664 msgstr "plano zx"
653665
654 #: ../gui.py:478
666 #: ../gui.py:480
655667 msgid "yx-plane"
656668 msgstr "plano yx"
657669
658 #: ../gui.py:479
670 #: ../gui.py:481
659671 msgid "zy-plane"
660672 msgstr "plano zy"
661673
662 #: ../gui.py:480
674 #: ../gui.py:482
663675 msgid "xz-plane"
664676 msgstr "plano xz"
665677
666 #: ../gui.py:481
678 #: ../gui.py:483
667679 msgid "a2,a3-plane"
668680 msgstr "Plano a2,a3"
669681
670 #: ../gui.py:482
682 #: ../gui.py:484
671683 msgid "a3,a1-plane"
672684 msgstr "Plano a3,a1"
673685
674 #: ../gui.py:483
686 #: ../gui.py:485
675687 msgid "a1,a2-plane"
676688 msgstr "Plano a1,a2"
677689
678 #: ../gui.py:484
690 #: ../gui.py:486
679691 msgid "a3,a2-plane"
680692 msgstr "Plano a3,a2"
681693
682 #: ../gui.py:485
694 #: ../gui.py:487
683695 msgid "a1,a3-plane"
684696 msgstr "Plano a1,a3"
685697
686 #: ../gui.py:486
698 #: ../gui.py:488
687699 msgid "a2,a1-plane"
688700 msgstr "Plano a2,a1"
689701
690 #: ../gui.py:487
702 #: ../gui.py:489
691703 msgid "Settings ..."
692704 msgstr "Axustes ..."
693705
694 #: ../gui.py:489
706 #: ../gui.py:491
695707 msgid "VMD"
696708 msgstr "VMD"
697709
698 #: ../gui.py:490
710 #: ../gui.py:492
699711 msgid "RasMol"
700712 msgstr "RasMol"
701713
702 #: ../gui.py:491
714 #: ../gui.py:493
703715 msgid "xmakemol"
704716 msgstr "xmakemol"
705717
706 #: ../gui.py:492
718 #: ../gui.py:494
707719 msgid "avogadro"
708720 msgstr "avogadro"
709721
710 #: ../gui.py:494
722 #: ../gui.py:496
711723 msgid "_Tools"
712724 msgstr "_Ferramentas"
713725
714 #: ../gui.py:495
726 #: ../gui.py:497
715727 msgid "Graphs ..."
716728 msgstr "Gráficos ..."
717729
718 #: ../gui.py:496
730 #: ../gui.py:498
719731 msgid "Movie ..."
720732 msgstr "Película ..."
721733
722 #: ../gui.py:497
734 #: ../gui.py:499
723735 msgid "Expert mode ..."
724736 msgstr "Modo experto ..."
725737
726 #: ../gui.py:498
738 #: ../gui.py:500
727739 msgid "Constraints ..."
728740 msgstr "Restriccións ..."
729741
730 #: ../gui.py:499
742 #: ../gui.py:501
731743 msgid "Render scene ..."
732744 msgstr "Debuxar escena ..."
733745
734 #: ../gui.py:500
746 #: ../gui.py:502
735747 msgid "_Move atoms"
736748 msgstr "_Mover átomos"
737749
738 #: ../gui.py:501
750 #: ../gui.py:503
739751 msgid "_Rotate atoms"
740752 msgstr "_Xirar átomos"
741753
742 #: ../gui.py:502
754 #: ../gui.py:504
743755 msgid "NE_B"
744756 msgstr "NE_B"
745757
746 #: ../gui.py:503
758 #: ../gui.py:505
747759 msgid "B_ulk Modulus"
748760 msgstr "Módulo E_nteiro"
749761
750762 #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
751 #: ../gui.py:506
763 #: ../gui.py:508
752764 msgid "_Setup"
753765 msgstr "_Configurar"
754766
755 #: ../gui.py:507
767 #: ../gui.py:509
756768 msgid "_Bulk Crystal"
757769 msgstr "Cristal _Enteiro"
758770
759 #: ../gui.py:508
771 #: ../gui.py:510
760772 msgid "_Surface slab"
761773 msgstr "Peza de _superficie"
762774
763 #: ../gui.py:509
775 #: ../gui.py:511
764776 msgid "_Nanoparticle"
765777 msgstr "_Nanopartícula"
766778
767 #: ../gui.py:511
779 #: ../gui.py:513
768780 msgid "Nano_tube"
769781 msgstr "Nano_tubo"
770782
771 #: ../gui.py:514
783 #: ../gui.py:516
772784 msgid "_Calculate"
773785 msgstr "_Calcular"
774786
775 #: ../gui.py:515
787 #: ../gui.py:517
776788 msgid "Set _Calculator"
777789 msgstr "Fixar _calculador"
778790
779 #: ../gui.py:516
791 #: ../gui.py:518
780792 msgid "_Energy and Forces"
781793 msgstr "_Enerxía e Forzas"
782794
783 #: ../gui.py:517
795 #: ../gui.py:519
784796 msgid "Energy Minimization"
785797 msgstr "Minimización enerxética"
786798
787 #: ../gui.py:520
799 #: ../gui.py:522
788800 msgid "_Help"
789801 msgstr "_Axuda"
790802
791 #: ../gui.py:521
803 #: ../gui.py:523
792804 msgid "_About"
793805 msgstr "_Acerca de ag"
794806
795 #: ../gui.py:525
807 #: ../gui.py:527
796808 msgid "Webpage ..."
797809 msgstr "Páxina web ..."
798810
10271039 msgid "Creating a nanoparticle."
10281040 msgstr "Creando unha nanopartícula."
10291041
1030 #: ../nanoparticle.py:197 ../nanotube.py:52 ../surfaceslab.py:82
1042 #: ../nanoparticle.py:197 ../nanotube.py:52 ../surfaceslab.py:83
10311043 msgid "Apply"
10321044 msgstr "Aplicar"
10331045
1034 #: ../nanoparticle.py:198 ../nanotube.py:53 ../surfaceslab.py:83
1046 #: ../nanoparticle.py:198 ../nanotube.py:53 ../surfaceslab.py:84
10351047 msgid "OK"
10361048 msgstr "OK"
10371049
11551167 msgid "Length:"
11561168 msgstr "Lonxitude:"
11571169
1158 #: ../quickinfo.py:6
1170 #: ../quickinfo.py:28
1171 msgid "This frame has no atoms."
1172 msgstr "Este cadro non ten átomos."
1173
1174 #: ../quickinfo.py:33
11591175 msgid "Single image loaded."
11601176 msgstr "Unha imaxe cargada."
11611177
1162 #: ../quickinfo.py:7
1163 #, python-format
1164 msgid "Image %d loaded (0 - %d)."
1165 msgstr "Imaxe %d cargada (0 - %d)."
1166
1167 #: ../quickinfo.py:8
1178 #: ../quickinfo.py:35
1179 msgid "Image {} loaded (0–{})."
1180 msgstr "Imaxe {} cargada (0–{})."
1181
1182 #: ../quickinfo.py:37
1183 msgid "Number of atoms: {}"
1184 msgstr "Número de átomos: {}"
1185
1186 #: ../quickinfo.py:47
1187 msgid "Unit cell [Å]:"
1188 msgstr "Celda unidade [Å]:"
1189
1190 #: ../quickinfo.py:49
1191 msgid "no"
1192 msgstr "no"
1193
1194 #: ../quickinfo.py:49
1195 msgid "yes"
1196 msgstr "sí"
1197
1198 #. TRANSLATORS: This has the form Periodic: no, no, yes
1199 #: ../quickinfo.py:51
1200 msgid "Periodic: {}, {}, {}"
1201 msgstr "Periódico: {}, {}, {}"
1202
1203 #: ../quickinfo.py:55
11681204 msgid "Unit cell is fixed."
11691205 msgstr "Celda unidade está fixa."
11701206
1171 #: ../quickinfo.py:9
1207 #: ../quickinfo.py:57
11721208 msgid "Unit cell varies."
11731209 msgstr "A celda unidade varía."
11741210
1175 #: ../quickinfo.py:11
1176 #, python-format
1177 msgid ""
1178 "%s\n"
1179 "\n"
1180 "Number of atoms: %d.\n"
1181 "\n"
1182 "Unit cell:\n"
1183 " %8.3f %8.3f %8.3f\n"
1184 " %8.3f %8.3f %8.3f\n"
1185 " %8.3f %8.3f %8.3f\n"
1186 "\n"
1187 "%s\n"
1188 "%s\n"
1211 #: ../quickinfo.py:60
1212 msgid "Volume: {:.3f} ų"
1213 msgstr "Volume: {:.3f} ų"
1214
1215 #: ../quickinfo.py:88
1216 #, fuzzy
1217 #| msgid "Set _Calculator"
1218 msgid "Calculator: {} (cached)"
1219 msgstr "Fixar _calculador"
1220
1221 #: ../quickinfo.py:90
1222 #, fuzzy
1223 #| msgid "Set _Calculator"
1224 msgid "Calculator: {} (attached)"
1225 msgstr "Fixar _calculador"
1226
1227 #: ../quickinfo.py:97
1228 msgid "Energy: {:.3f} eV"
1229 msgstr "Enerxía: {:.3f} eV"
1230
1231 #: ../quickinfo.py:102
1232 msgid "Max force: {:.3f} eV/Å"
11891233 msgstr ""
1190 "%s\n"
1191 "\n"
1192 "Número de átomos: %d.\n"
1193 "\n"
1194 "Celda unidade:\n"
1195 " %8.3f %8.3f %8.3f\n"
1196 " %8.3f %8.3f %8.3f\n"
1197 " %8.3f %8.3f %8.3f\n"
1198 "\n"
1199 "%s\n"
1200 "%s\n"
1201
1202 #: ../quickinfo.py:33
1203 msgid "This frame has no atoms."
1204 msgstr "Este cadro non ten átomos."
1205
1206 #: ../quickinfo.py:53
1207 msgid "no"
1208 msgstr "no"
1209
1210 #: ../quickinfo.py:53
1211 msgid "yes"
1212 msgstr "sí"
1213
1214 #. TRANSLATORS: This has the form Periodic: no, no, yes
1215 #: ../quickinfo.py:57
1216 #, python-format
1217 msgid "Periodic: %s, %s, %s"
1218 msgstr "Periódico: %s, %s, %s"
1219
1220 #: ../quickinfo.py:61
1221 msgid "Volume: "
1222 msgstr "Volume: "
1234
1235 #: ../quickinfo.py:107
1236 msgid "Magmom: {:.3f} µ"
1237 msgstr ""
12231238
12241239 #: ../render.py:20 ../render.py:190
12251240 msgid "Render current view in povray ... "
12801295 msgstr "Debuxar o cuadro actual"
12811296
12821297 #: ../render.py:60
1283 #, fuzzy
1284 #| msgid "Render all %d frames"
12851298 msgid "Render all frames"
1286 msgstr "Debuxar tódolos %d cadros"
1299 msgstr "Debuxar tódolos cadros"
12871300
12881301 #: ../render.py:65
12891302 msgid "Run povray"
16251638 msgid "FCC(110)"
16261639 msgstr "FCC(110)"
16271640
1628 #: ../surfaceslab.py:26 ../surfaceslab.py:170
1641 #: ../surfaceslab.py:26 ../surfaceslab.py:173
16291642 msgid "FCC(111)"
16301643 msgstr "FCC(111)"
16311644
1632 #: ../surfaceslab.py:27 ../surfaceslab.py:173
1645 #: ../surfaceslab.py:27 ../surfaceslab.py:176
16331646 msgid "FCC(211)"
16341647 msgstr "FCC(211)"
16351648
16411654 msgid "bcc"
16421655 msgstr "bcc"
16431656
1644 #: ../surfaceslab.py:29 ../surfaceslab.py:167
1657 #: ../surfaceslab.py:29 ../surfaceslab.py:170
16451658 msgid "BCC(110)"
16461659 msgstr "BCC(110)"
16471660
1648 #: ../surfaceslab.py:30 ../surfaceslab.py:164
1661 #: ../surfaceslab.py:30 ../surfaceslab.py:167
16491662 msgid "BCC(111)"
16501663 msgstr "BCC(111)"
16511664
1652 #: ../surfaceslab.py:31 ../surfaceslab.py:177
1665 #: ../surfaceslab.py:31 ../surfaceslab.py:180
16531666 msgid "HCP(0001)"
16541667 msgstr "HCP(0001)"
16551668
1656 #: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:131
1657 #: ../surfaceslab.py:187
1669 #: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:134
1670 #: ../surfaceslab.py:190
16581671 msgid "hcp"
16591672 msgstr "hcp"
16601673
1661 #: ../surfaceslab.py:32 ../surfaceslab.py:180
1674 #: ../surfaceslab.py:32 ../surfaceslab.py:183
16621675 msgid "HCP(10-10)"
16631676 msgstr "HCP(10-10)"
16641677
16831696 msgstr "Celda ortogonal:"
16841697
16851698 #: ../surfaceslab.py:72
1686 msgid "Lattice constant:\ta"
1687 msgstr "Constante de rede:\ta"
1699 msgid "Lattice constant:"
1700 msgstr "Constante de rede:"
1701
1702 #: ../surfaceslab.py:73
1703 msgid "\ta"
1704 msgstr "\ta"
16881705
16891706 #: ../surfaceslab.py:74
1690 msgid "\t\tc"
1691 msgstr "\t\tc"
1707 msgid "\tc"
1708 msgstr "\tc"
16921709
16931710 #: ../surfaceslab.py:75
1694 msgid "Size: \tx: "
1695 msgstr "Tamaño\tx: "
1696
1697 #: ../surfaceslab.py:76
1711 msgid "Size:"
1712 msgstr "Tamaño:"
1713
1714 #: ../surfaceslab.py:77
16981715 msgid "\ty: "
16991716 msgstr "\ty: "
17001717
1701 #: ../surfaceslab.py:77
1718 #: ../surfaceslab.py:78
17021719 msgid "\tz: "
17031720 msgstr "\tz: "
17041721
17051722 #. TRANSLATORS: This is a title of a window.
1706 #: ../surfaceslab.py:81
1723 #: ../surfaceslab.py:82
17071724 msgid "Creating a surface."
17081725 msgstr "Creando unha peza de superficie."
17091726
1710 #: ../surfaceslab.py:161
1727 #. TRANSLATORS: E.g. "... assume fcc crystal structure for Au"
1728 #: ../surfaceslab.py:110
1729 msgid "Error: Reference values assume {}crystal structure for {}!"
1730 msgstr ""
1731
1732 #: ../surfaceslab.py:164
17111733 msgid "Please enter an even value for orthogonal cell"
17121734 msgstr "Por favor, escolla un número par para a cela ortogonal"
17131735
1714 #: ../surfaceslab.py:174
1736 #: ../surfaceslab.py:177
17151737 msgid "Please enter a value divisible by 3 for orthogonal cell"
17161738 msgstr "Por favor, escolla un valor divisible por 3 para a cela ortogonal"
17171739
1718 #: ../surfaceslab.py:194
1740 #: ../surfaceslab.py:197
17191741 msgid " Vacuum: {} Å."
17201742 msgstr " Vacío: {} Å."
17211743
17221744 #. TRANSLATORS: e.g. "Au fcc100 surface with 2 atoms."
17231745 #. or "Au fcc100 surface with 2 atoms. Vacuum: 5 Å."
1724 #: ../surfaceslab.py:202
1746 #: ../surfaceslab.py:205
17251747 #, python-brace-format
17261748 msgid "{symbol} {surf} surface with one atom.{vacuum}"
17271749 msgid_plural "{symbol} {surf} surface with {natoms} atoms.{vacuum}"
17441766 msgid "About"
17451767 msgstr "Acerca de ase-gui"
17461768
1747 #: ../ui.py:60 ../ui.py:64
1769 #: ../ui.py:60 ../ui.py:64 ../widgets.py:17
17481770 msgid "Help"
17491771 msgstr "Axuda"
17501772
1751 #: ../widgets.py:11
1773 #: ../widgets.py:14
17521774 msgid "Element:"
17531775 msgstr "Elemento:"
17541776
1755 #: ../widgets.py:39
1777 #. This infobox is indescribably ugly because of the
1778 #. ridiculously large font size used by Tkinter. Ouch!
1779 #: ../widgets.py:34
1780 msgid ""
1781 "Enter a chemical symbol or the name of a molecule from the G2 testset:\n"
1782 "{}"
1783 msgstr ""
1784
1785 #: ../widgets.py:68
17561786 msgid "No element specified!"
17571787 msgstr "¡Non especificou o elemento!"
17581788
1759 #: ../widgets.py:56
1789 #: ../widgets.py:90
17601790 msgid "ERROR: Invalid element!"
17611791 msgstr "ERRO: ¡elemento inválido!"
17621792
1763 #: ../widgets.py:75
1793 #: ../widgets.py:107
17641794 msgid "No Python code"
17651795 msgstr "Non é código de Python"
17661796
1767 #, fuzzy
1768 #~| msgid "Set _Calculator"
1769 #~ msgid "Select calculator"
1770 #~ msgstr "Fixar _calculador"
1771
1772 #, fuzzy
1773 #~| msgid "Set _Calculator"
1774 #~ msgid "Calculator:"
1775 #~ msgstr "Fixar _calculador"
1797 #~ msgid ""
1798 #~ "%s\n"
1799 #~ "\n"
1800 #~ "Number of atoms: %d.\n"
1801 #~ "\n"
1802 #~ "Unit cell:\n"
1803 #~ " %8.3f %8.3f %8.3f\n"
1804 #~ " %8.3f %8.3f %8.3f\n"
1805 #~ " %8.3f %8.3f %8.3f\n"
1806 #~ "\n"
1807 #~ "%s\n"
1808 #~ "%s\n"
1809 #~ msgstr ""
1810 #~ "%s\n"
1811 #~ "\n"
1812 #~ "Número de átomos: %d.\n"
1813 #~ "\n"
1814 #~ "Celda unidade:\n"
1815 #~ " %8.3f %8.3f %8.3f\n"
1816 #~ " %8.3f %8.3f %8.3f\n"
1817 #~ " %8.3f %8.3f %8.3f\n"
1818 #~ "\n"
1819 #~ "%s\n"
1820 #~ "%s\n"
1821
1822 #~ msgid "Volume: "
1823 #~ msgstr "Volume: "
1824
1825 #~ msgid "Size: \tx: "
1826 #~ msgstr "Tamaño\tx: "
17761827
17771828 #~ msgid "None"
17781829 #~ msgstr "Ningún"
20902141 #~ msgid "Density: "
20912142 #~ msgstr "Densidade: "
20922143
2093 #~ msgid "Energy: "
2094 #~ msgstr "Enerxía: "
2095
20962144 #~ msgid "GPAW version: "
20972145 #~ msgstr "Versión de GPAW: "
20982146
0 # -*- encoding: utf-8
01 "Module for displaying information about the system."
12
23 from __future__ import unicode_literals
4
5 import numpy as np
36 from ase.gui.i18n import _
7 import warnings
48
5 singleimage = _('Single image loaded.')
6 multiimage = _('Image %d loaded (0 - %d).')
7 ucconst = _('Unit cell is fixed.')
8 ucvaries = _('Unit cell varies.')
99
10 format = _("""\
11 %s
12
13 Number of atoms: %d.
14
15 Unit cell:
16 %8.3f %8.3f %8.3f
17 %8.3f %8.3f %8.3f
18 %8.3f %8.3f %8.3f
19
20 %s
21 %s
22 """)
10 ucellformat = """\
11 {:8.3f} {:8.3f} {:8.3f}
12 {:8.3f} {:8.3f} {:8.3f}
13 {:8.3f} {:8.3f} {:8.3f}
14 """
2315
2416
2517 def info(gui):
2618 images = gui.images
2719 nimg = len(images)
2820 atoms = gui.atoms
29 natoms = len(atoms)
21
22 tokens = []
23 def add(token=''):
24 tokens.append(token)
3025
3126 if len(atoms) < 1:
32 txt = _('This frame has no atoms.')
27 add(_('This frame has no atoms.'))
3328 else:
3429 img = gui.frame
3530
36 uc = atoms.cell
31 if nimg == 1:
32 add(_('Single image loaded.'))
33 else:
34 add(_('Image {} loaded (0–{}).').format(img, nimg - 1))
35 add()
36 add(_('Number of atoms: {}').format(len(atoms)))
37
38 # We need to write ų further down, so we have no choice but to
39 # use proper subscripts in the chemical formula:
40 formula = atoms.get_chemical_formula()
41 subscripts = dict(zip('0123456789', '₀₁₂₃₄₅₆₇₈₉'))
42 pretty_formula = ''.join(subscripts.get(c, c) for c in formula)
43 add(pretty_formula)
44
45 add()
46 add(_('Unit cell [Å]:'))
47 add(ucellformat.format(*atoms.cell.ravel()))
48 periodic = [[_('no'), _('yes')][periodic] for periodic in atoms.pbc]
49 # TRANSLATORS: This has the form Periodic: no, no, yes
50 add(_('Periodic: {}, {}, {}').format(*periodic))
51
3752 if nimg > 1:
38 equal = True
39 for i in range(nimg):
40 equal = equal and (uc == images[i].cell).all()
41 if equal:
42 uctxt = ucconst
53 if all((atoms.cell == img.cell).all() for img in images):
54 add(_('Unit cell is fixed.'))
4355 else:
44 uctxt = ucvaries
45 else:
46 uctxt = ''
47 if nimg == 1:
48 imgtxt = singleimage
49 else:
50 imgtxt = multiimage % (img, nimg - 1)
56 add(_('Unit cell varies.'))
5157
52 periodic = [[_('no'), _('yes')][periodic]
53 for periodic in atoms.pbc]
58 if atoms.number_of_lattice_vectors == 3:
59 add(_('Volume: {:.3f} ų').format(atoms.get_volume()))
5460
55 # TRANSLATORS: This has the form Periodic: no, no, yes
56 pbcstring = _('Periodic: %s, %s, %s') % tuple(periodic)
57 txt = format % ((imgtxt, natoms) + tuple(uc.flat) +
58 (pbcstring,) + (uctxt,))
59 if atoms.number_of_lattice_vectors == 3:
60 txt += _('Volume: ') + '{:8.3f}'.format(atoms.get_volume())
61 return txt
61 # Print electronic structure information if we have a calculator
62 if atoms.calc:
63 calc = atoms.calc
64
65 def getresult(name, get_quantity):
66 # ase/io/trajectory.py line 170 does this by using
67 # the get_property(prop, atoms, allow_calculation=False)
68 # so that is an alternative option.
69 try:
70 if calc.calculation_required(atoms, [name]):
71 quantity = None
72 else:
73 quantity = get_quantity()
74 except Exception as err:
75 quantity = None
76 errmsg = ('An error occured while retrieving {} '
77 'from the calculator: {}'.format(name, err))
78 warnings.warn(errmsg)
79 return quantity
80
81 # SinglePointCalculators are named after the code which
82 # produced the result, so this will typically list the
83 # name of a code even if they are just cached results.
84 add()
85 from ase.calculators.singlepoint import SinglePointCalculator
86 if isinstance(calc, SinglePointCalculator):
87 add(_('Calculator: {} (cached)').format(calc.name))
88 else:
89 add(_('Calculator: {} (attached)'.format(calc.name)))
90
91 energy = getresult('energy', atoms.get_potential_energy)
92 forces = getresult('forces', atoms.get_forces)
93 magmom = getresult('magmom', atoms.get_magnetic_moment)
94
95 if energy is not None:
96 energy_str = _('Energy: {:.3f} eV'.format(energy))
97 add(energy_str)
98
99 if forces is not None:
100 maxf = np.linalg.norm(forces, axis=1).max()
101 forces_str = _('Max force: {:.3f} eV/Å').format(maxf)
102 add(forces_str)
103
104 if magmom is not None:
105 mag_str = _('Magmom: {:.3f} µ'.format(magmom))
106 add(mag_str)
107
108 return '\n'.join(tokens)
4545 class SetupSurfaceSlab:
4646 '''Window for setting up a surface.'''
4747 def __init__(self, gui):
48 self.element = Element('', self.make)
48 self.element = Element('', self.apply)
4949 self.structure = ui.ComboBox(structures, structures,
5050 self.structure_changed)
5151 self.structure_warn = ui.Label('', 'red')
6868 win.add(self.element)
6969 win.add([_('Structure:'), self.structure, self.structure_warn])
7070 win.add([_('Orthogonal cell:'), self.orthogonal])
71 win.add([_('Lattice constant:\ta'), self.lattice_a, (u'Å'),
72 self.retrieve])
73 win.add([_('\t\tc'), self.lattice_c, (u'Å')])
74 win.add([_('Size: \tx: '), self.x, _(' unit cells'), self.x_warn])
71 win.add([_('Lattice constant:')])
72 win.add([_('\ta'), self.lattice_a, (u'Å'), self.retrieve])
73 win.add([_('\tc'), self.lattice_c, (u'Å')])
74 win.add([_('Size:')])
75 win.add([_('\tx: '), self.x, _(' unit cells'), self.x_warn])
7576 win.add([_('\ty: '), self.y, _(' unit cells'), self.y_warn])
7677 win.add([_('\tz: '), self.z, _(' unit cells')])
7778 win.add([_('Vacuum: '), self.vacuum_check, self.vacuum, (u'Å')])
8182 ui.Button(_('Apply'), self.apply),
8283 ui.Button(_('OK'), self.ok)])
8384
85 self.element.grab_focus()
8486 self.gui = gui
8587 self.atoms = None
8688 self.lattice_c.active = False
103105 if struct[0] == self.structure.value:
104106 symmetry = struct[1]
105107 if ref['symmetry'] != symmetry:
106 self.structure_warn.text = ('Error: Reference values assume {}'
107 'crystal structure for {}!'.
108 # TRANSLATORS: E.g. "... assume fcc crystal structure for Au"
109 self.structure_warn.text = (_('Error: Reference values assume {} '
110 'crystal structure for {}!').
108111 format(ref['symmetry'],
109112 self.element.symbol))
110113 else:
33 import tkinter as tk
44 import tkinter.ttk as ttk
55 from tkinter.messagebox import askokcancel as ask_question
6 from tkinter.messagebox import showerror, showwarning
6 from tkinter.messagebox import showerror, showwarning, showinfo
77 from tkinter.filedialog import LoadFileDialog, SaveFileDialog
88 except ImportError:
99 # Python 2
1313 except ImportError:
1414 ttk = None
1515 from tkMessageBox import (askokcancel as ask_question, showerror,
16 showwarning)
16 showwarning, showinfo)
1717 from FileDialog import LoadFileDialog, SaveFileDialog
1818
1919 import re
3030 'error', 'ask_question', 'MainWindow', 'LoadFileDialog', 'SaveFileDialog',
3131 'ASEGUIWindow', 'Button', 'CheckButton', 'ComboBox', 'Entry', 'Label',
3232 'Window', 'MenuItem', 'RadioButton', 'RadioButtons', 'Rows', 'Scale',
33 'showwarning', 'SpinBox', 'Text']
33 'showinfo', 'showwarning', 'SpinBox', 'Text']
3434
3535
3636 if sys.platform == 'darwin':
190190 self.callback = callback
191191
192192 def create(self, parent):
193 self.check = tk.Checkbutton(parent, text=self.text, var=self.var, command=self.callback)
193 self.check = tk.Checkbutton(parent, text=self.text,
194 var=self.var, command=self.callback)
194195 return self.check
195196
196197 @property
199200
200201
201202 class SpinBox(Widget):
202 def __init__(self, value, start, end, step, callback=None):
203 def __init__(self, value, start, end, step, callback=None,
204 rounding=None, width=6):
203205 self.callback = callback
206 self.rounding = rounding
204207 self.creator = partial(tk.Spinbox,
205208 from_=start,
206209 to=end,
207210 increment=step,
208211 command=callback,
209 width=6)
212 width=width)
210213 self.initial = str(value)
211214
212215 def create(self, parent):
227230 @value.setter
228231 def value(self, x):
229232 self.widget.delete(0, 'end')
233 if '.' in str(x) and self.rounding is not None:
234 try:
235 x = round(float(x), self.rounding)
236 except (ValueError, TypeError):
237 pass
230238 self.widget.insert(0, x)
231239
232240
334342 self.creator = partial(ttk.Combobox,
335343 values=labels)
336344
337 def create(self, parrent):
338 widget = Widget.create(self, parrent)
345 def create(self, parent):
346 widget = Widget.create(self, parent)
339347 widget.current(0)
340348 if self.callback:
341349 def callback(event):
537545 return handle
538546
539547
548 class ASEFileChooser(LoadFileDialog):
549 def __init__(self, win, formatcallback=lambda event: None):
550 from ase.io.formats import all_formats, get_ioformat
551 LoadFileDialog.__init__(self, win, _('Open ...'))
552 labels = [_('Automatic')]
553 values = ['']
554
555 def key(item):
556 return item[1][0]
557
558 for format, (description, code) in sorted(all_formats.items(),
559 key=key):
560 io = get_ioformat(format)
561 if io.read and description != '?':
562 labels.append(_(description))
563 values.append(format)
564
565 self.format = None
566
567 def callback(value):
568 self.format = value
569
570 Label(_('Choose parser:')).pack(self.top)
571 formats = ComboBox(labels, values, callback)
572 formats.pack(self.top)
573
574
575 def show_io_error(filename, err):
576 showerror(_('Read error'),
577 _('Could not read {}: {}'.format(filename, err)))
578
579
540580 class ASEGUIWindow(MainWindow):
541581 def __init__(self, close, menu, config,
542582 scroll, scroll_event,
563603 self.canvas.bind('<Control-ButtonRelease>', bind(release, 'ctrl'))
564604 self.canvas.bind('<Shift-ButtonRelease>', bind(release, 'shift'))
565605 self.canvas.bind('<Configure>', resize)
606 self.canvas.bind('<Shift-B{right}-Motion>'.format(right=right),
607 bind(scroll))
608
566609 self.win.bind('<MouseWheel>', bind(scroll_event))
567 for key in ['Key', 'Next', 'Prior']:
568 # Next and Prior are PageUp/Dn, referring to Z axis.
569 self.win.bind('<{}>'.format(key), bind(scroll))
570 self.win.bind('<Shift-{}>'.format(key), bind(scroll, 'shift'))
571 self.win.bind('<Control-{}>'.format(key), bind(scroll, 'ctrl'))
610 self.win.bind('<Key>', bind(scroll))
611 self.win.bind('<Shift-Key>', bind(scroll, 'shift'))
612 self.win.bind('<Control-Key>', bind(scroll, 'ctrl'))
572613
573614 self.fg = config['gui_foreground_color']
574615 self.bg = config['gui_background_color']
4848 return B1, B2
4949
5050
51
5251 def get_bonds(atoms, covalent_radii):
5352 from ase.neighborlist import NeighborList
5453 nl = NeighborList(covalent_radii * 1.5,
109108 if fname is None:
110109 title = 'ase.gui'
111110 else:
112 title = '{}@{}'.format(basename(fname), frame)
111 title = basename(fname)
113112
114113 self.window.title = title
115114
146145 self.X_cell = self.X[natoms:natoms + len(B1)]
147146 self.X_bonds = self.X[natoms + len(B1):]
148147
149 if 1:#if init or frame != self.frame:
148 if 1: # if init or frame != self.frame:
150149 cell = atoms.cell
151150 ncellparts = len(B1)
152151 nbonds = len(bonds)
153152
154 if 1: #init or (atoms.cell != self.atoms.cell).any():
153 if 1: # init or (atoms.cell != self.atoms.cell).any():
155154 self.X_cell[:] = np.dot(B1, cell)
156155 self.B = np.empty((ncellparts + nbonds, 3))
157156 self.B[:ncellparts] = np.dot(B2, cell)
206205 def toggle_show_velocities(self, key=None):
207206 self.draw()
208207
209 # transitional compat hack
210208 def get_forces(self):
211 return self.images.get_forces(self.atoms)
209 return self.atoms.get_forces()
212210
213211 def toggle_show_forces(self, key=None):
214212 self.draw()
236234 cell = (self.window['toggle-show-unit-cell'] and
237235 self.images[0].cell.any())
238236 if (len(self.atoms) == 0 and not cell):
239 self.scale = 1.0
237 self.scale = 20.0
240238 self.center = np.zeros(3)
241239 self.draw()
242240 return
243241
242 # Get the min and max point of the projected atom positions
243 # including the covalent_radii used for drawing the atoms
244244 P = np.dot(self.X, self.axes)
245245 n = len(self.atoms)
246246 covalent_radii = self.get_covalent_radii()
249249 P[:n] += 2 * covalent_radii[:, None]
250250 P2 = P.max(0)
251251 self.center = np.dot(self.axes, (P1 + P2) / 2)
252 # Add 30% of whitespace on each side of the atoms
252253 S = 1.3 * (P2 - P1)
253254 w, h = self.window.size
254255 if S[0] * h < S[1] * w:
314315 if self.colormode == 'jmol':
315316 return [self.colors[Z] for Z in self.atoms.numbers]
316317
318 if self.colormode == 'neighbors':
319 return [self.colors[Z] for Z in self.get_color_scalars()]
320
317321 colorscale, cmin, cmax = self.colormode_data
318322 N = len(colorscale)
319323 if cmin == cmax:
337341 return self.atoms.get_initial_charges()
338342 elif self.colormode == 'magmom':
339343 return get_magmoms(self.atoms)
344 elif self.colormode == 'neighbors':
345 from ase.neighborlist import NeighborList
346 n = len(self.atoms)
347 nl = NeighborList(self.get_covalent_radii(self.atoms) * 1.5,
348 skin=0, self_interaction=False, bothways=True)
349 nl.update(self.atoms)
350 return [len(nl.get_neighbors(i)[0]) for i in range(n)]
340351
341352 def get_covalent_radii(self, atoms=None):
342353 if atoms is None:
539550 self.draw()
540551
541552 # XXX check bounds
542 indices = np.arange(len(self.atoms))[self.images.selected[:len(self.atoms)]]
553 natoms = len(self.atoms)
554 indices = np.arange(natoms)[self.images.selected[:natoms]]
543555 if len(indices) != len(selected_ordered):
544556 selected_ordered = []
545557 self.images.selected_ordered = selected_ordered
33 import ase.data
44 import ase.gui.ui as ui
55
6 from ase import Atoms
7 from ase.collections import g2
8
69
710 class Element(list):
8 def __init__(self, symbol='', callback=None):
11 def __init__(self, symbol='', callback=None, allow_molecule=False):
912 list.__init__(self,
1013 [_('Element:'),
11 ui.Entry(symbol, 3, self.enter),
14 ui.Entry(symbol, 10 if allow_molecule else 3,
15 self.enter),
16 ui.Button(_('Help'), self.show_help),
1217 ui.Label('', 'red')])
1318 self.callback = callback
14 self._symbol = None
15 self._Z = None
19 self.allow_molecule = allow_molecule
20
21 def grab_focus(self):
22 self[1].entry.focus_set()
23
24 def show_help(self):
25 names = []
26 import re
27 for name in g2.names:
28 if not re.match('^[A-Z][a-z]?$', name): # Not single atoms
29 names.append(name)
30
31 # This infobox is indescribably ugly because of the
32 # ridiculously large font size used by Tkinter. Ouch!
33 msg = _('Enter a chemical symbol or the name of a molecule '
34 'from the G2 testset:\n'
35 '{}'.format(', '.join(names)))
36 ui.showinfo('Info', msg)
37
38 @property
39 def Z(self):
40 assert not self.allow_molecule
41 atoms = self.get_atoms()
42 if atoms is None:
43 return None
44 assert len(atoms) == 1
45 return atoms.numbers[0]
1646
1747 @property
1848 def symbol(self):
19 self.check()
20 return self._symbol
49 Z = self.Z
50 return None if Z is None else ase.data.chemical_symbols[Z]
2151
52 # Used by tests...
2253 @symbol.setter
2354 def symbol(self, value):
2455 self[1].value = value
2556
26 @property
27 def Z(self):
28 self.check()
29 return self._Z
57 def get_atoms(self):
58 val = self._get()
59 if val is not None:
60 self[2].text = ''
61 return val
3062
31 @Z.setter
32 def Z(self, value):
33 self.symbol = ase.data.chemical_symbols[value]
63 def _get(self):
64 txt = self[1].value
3465
35 def check(self):
36 self._symbol = self[1].value
37 if not self._symbol:
66 if not txt:
3867 self.error(_('No element specified!'))
39 return False
40 self._Z = ase.data.atomic_numbers.get(self._symbol)
41 if self._Z is None:
68 return None
69
70 if txt.isdigit():
71 txt = int(txt)
4272 try:
43 self._Z = int(self._symbol)
44 except ValueError:
73 txt = ase.data.chemical_symbols[txt]
74 except KeyError:
4575 self.error()
46 return False
47 self._symbol = ase.data.chemical_symbols[self._Z]
48 self[2].text = ''
49 return True
76 return None
77
78 if txt in ase.data.atomic_numbers:
79 return Atoms(txt)
80
81 if self.allow_molecule and g2.has(txt):
82 return g2[txt]
83
84 self.error()
5085
5186 def enter(self):
52 self.check()
5387 self.callback(self)
5488
5589 def error(self, text=_('ERROR: Invalid element!')):
56 self._symbol = None
57 self._Z = None
5890 self[2].text = text
5991
6092
0 import time
1
02 def read_aims(filename):
13 """Import FHI-aims geometry type files.
24
7072 fix.append(i)
7173 elif xyz.any():
7274 fix_cart.append(FixCartesian(i, xyz))
73
75
7476 if cart_positions and scaled_positions:
7577 raise Exception("Can't specify atom positions with mixture of "
7678 'Cartesian and fractional coordinates')
110112
111113 fd = open(filename, 'w')
112114 fd.write('#=======================================================\n')
113 fd.write('#FHI-aims file: ' + filename + '\n')
114 fd.write('#Created using the Atomic Simulation Environment (ASE)\n')
115 fd.write('# FHI-aims file: ' + filename + '\n')
116 fd.write('# Created using the Atomic Simulation Environment (ASE)\n')
117 fd.write('# ' + time.asctime() + '\n')
115118 fd.write('#=======================================================\n')
116119 i = 0
117120 if atoms.get_pbc().any():
133136 ghosts = np.zeros(len(atoms))
134137 else:
135138 assert len(ghosts) == len(atoms)
136 scaled_positions = atoms.get_scaled_positions()
139 scaled_positions = atoms.get_scaled_positions()
137140 for i, atom in enumerate(atoms):
138141 if ghosts[i] == 1:
139142 atomstring = 'empty '
147147 if atoms is None:
148148 atoms = self.atoms
149149
150 for image in atoms._images_():
150 for image in atoms.iterimages():
151151 self._write_atoms(image)
152152
153153 def _write_atoms(self, atoms):
437437 self.atoms = atoms
438438 if os.path.exists(self.filename):
439439 # The output directory already exists.
440 if not self.is_bundle(self.filename):
440 ase.parallel.barrier() # all must have time to see it exists
441 if not self.is_bundle(self.filename, allowempty=True):
441442 raise IOError(
442443 'Filename "' + self.filename +
443444 '" already exists, but is not a BundleTrajectory.' +
444445 'Cowardly refusing to remove it.')
445 ase.parallel.barrier() # all must have time to see it exists
446446 if self.is_empty_bundle(self.filename):
447447 ase.parallel.barrier()
448448 self.log('Deleting old "%s" as it is empty' % (self.filename,))
594594 return metadata
595595
596596 @staticmethod
597 def is_bundle(filename):
598 """Check if a filename exists and is a BundleTrajectory."""
597 def is_bundle(filename, allowempty=False):
598 """Check if a filename exists and is a BundleTrajectory.
599
600 If allowempty=True, an empty folder is regarded as an
601 empty BundleTrajectory."""
599602 if not os.path.isdir(filename):
600603 return False
604 if allowempty and not os.listdir(filename):
605 return True # An empty BundleTrajectory
601606 metaname = os.path.join(filename, 'metadata.json')
602607 if os.path.isfile(metaname):
603608 f = open(metaname, 'r')
621626 """Check if a filename is an empty bundle.
622627
623628 Assumes that it is a bundle."""
629 if not os.listdir(filename):
630 return True # Empty folders are empty bundles.
624631 f = open(os.path.join(filename, 'frames'), 'rb')
625632 nframes = int(f.read())
626633 f.close()
634641 "Deletes a bundle."
635642 if ase.parallel.rank == 0:
636643 # Only the master deletes
637 if not cls.is_bundle(filename):
644 if not cls.is_bundle(filename, allowempty=True):
638645 raise IOError(
639646 'Cannot remove "%s" as it is not a bundle trajectory.'
640647 % (filename,))
8080 header = []
8181 line = lines.pop().strip()
8282 while line.startswith('_'):
83 header.append(line.lower())
84 line = lines.pop().strip()
83 tokens = line.split()
84 header.append(tokens[0].lower())
85 if len(tokens) == 1:
86 line = lines.pop().strip()
87 else:
88 line = ' '.join(tokens[1:])
89 break
8590 columns = dict([(h, []) for h in header])
91 if len(columns) != len(header):
92 seen = set()
93 dublicates = [h for h in header if h in seen or seen.add(h)]
94 warnings.warn('Duplicated loop tags: {0}'.format(dublicates))
8695
8796 tokens = []
8897 while True:
0 from ase.utils import basestring
1 from ase.atoms import Atoms
2
3
4 def write_crystal(filename, atoms):
5 """Method to write atom structure in crystal format
6 (fort.34 format)
7 """
8
9 myfile = open(filename, 'w')
10
11 ispbc = atoms.get_pbc()
12 box = atoms.get_cell()
13
14 # here it is assumed that the non-periodic direction are z
15 # in 2D case, z and y in the 1D case.
16
17 if ispbc[2]:
18 myfile.write('%2s %2s %2s %23s \n' %
19 ('3', '1', '1', 'E -0.0E+0 DE 0.0E+0( 1)'))
20 elif ispbc[1]:
21 myfile.write('%2s %2s %2s %23s \n' %
22 ('2', '1', '1', 'E -0.0E+0 DE 0.0E+0( 1)'))
23 box[2, 2] = 500.
24 elif ispbc[0]:
25 myfile.write('%2s %2s %2s %23s \n' %
26 ('1', '1', '1', 'E -0.0E+0 DE 0.0E+0( 1)'))
27 box[2, 2] = 500.
28 box[1, 1] = 500.
29 else:
30 myfile.write('%2s %2s %2s %23s \n' %
31 ('0', '1', '1', 'E -0.0E+0 DE 0.0E+0( 1)'))
32 box[2, 2] = 500.
33 box[1, 1] = 500.
34 box[0, 0] = 500.
35
36 # write box
37 # crystal dummy
38 myfile.write(' %.17E %.17E %.17E \n'
39 % (box[0][0], box[0][1], box[0][2]))
40 myfile.write(' %.17E %.17E %.17E \n'
41 % (box[1][0], box[1][1], box[1][2]))
42 myfile.write(' %.17E %.17E %.17E \n'
43 % (box[2][0], box[2][1], box[2][2]))
44
45 # write symmetry operations (not implemented yet for
46 # higher symmetries than C1)
47 myfile.write(' %2s \n' % (1))
48 myfile.write(' %.17E %.17E %.17E \n' % (1, 0, 0))
49 myfile.write(' %.17E %.17E %.17E \n' % (0, 1, 0))
50 myfile.write(' %.17E %.17E %.17E \n' % (0, 0, 1))
51 myfile.write(' %.17E %.17E %.17E \n' % (0, 0, 0))
52
53 # write coordinates
54 myfile.write(' %8s \n' % (len(atoms)))
55 coords = atoms.get_positions()
56 tags = atoms.get_tags()
57 atomnum = atoms.get_atomic_numbers()
58 for iatom, coord in enumerate(coords):
59 myfile.write('%5i %19.16f %19.16f %19.16f \n'
60 % (atomnum[iatom] + tags[iatom],
61 coords[iatom][0], coords[iatom][1], coords[iatom][2]))
62
63 if isinstance(filename, basestring):
64 myfile.close()
65
66
67 def read_crystal(filename):
68 """Method to read coordinates form 'fort.34' files
69 additionally read information about
70 periodic boundary condition
71 """
72 with open(filename, 'r') as myfile:
73 lines = myfile.readlines()
74
75 atoms_pos = []
76 anumber_list = []
77 my_pbc = [False, False, False]
78 mycell = []
79
80 if float(lines[4]) != 1:
81 raise ValueError('High symmetry geometry is not allowed.')
82
83 if float(lines[1].split()[0]) < 500.0:
84 cell = [float(c) for c in lines[1].split()]
85 mycell.append(cell)
86 my_pbc[0] = True
87 else:
88 mycell.append([1, 0, 0])
89
90 if float(lines[2].split()[1]) < 500.0:
91 cell = [float(c) for c in lines[2].split()]
92 mycell.append(cell)
93 my_pbc[1] = True
94 else:
95 mycell.append([0, 1, 0])
96
97 if float(lines[3].split()[2]) < 500.0:
98 cell = [float(c) for c in lines[3].split()]
99 mycell.append(cell)
100 my_pbc[2] = True
101 else:
102 mycell.append([0, 0, 1])
103
104 natoms = int(lines[9].split()[0])
105 for i in range(natoms):
106 index = 10 + i
107 anum = int(lines[index].split()[0]) % 100
108 anumber_list.append(anum)
109
110 position = [float(p) for p in lines[index].split()[1:]]
111 atoms_pos.append(position)
112
113 atoms = Atoms(positions=atoms_pos, numbers=anumber_list,
114 cell=mycell, pbc=my_pbc)
115
116 return atoms
110110 last_lines = lines_ok[-natoms:]
111111 for iline, line in enumerate(last_lines):
112112 inp = line.split()
113 velocities.append([float(inp[4])*AngdivPs2ASE,
114 float(inp[5])*AngdivPs2ASE,
115 float(inp[6])*AngdivPs2ASE])
113 velocities.append([float(inp[5])*AngdivPs2ASE,
114 float(inp[6])*AngdivPs2ASE,
115 float(inp[7])*AngdivPs2ASE])
116116
117117 atoms.set_velocities(velocities)
118118 return atoms
119
120
121 def read_dftb_lattice(fileobj='md.out',images=None):
122 """
123 Read lattice vectors from MD and return them as a list. If a molecules are parsed add them there.
124 """
125 if isinstance(fileobj, basestring):
126 fileobj = open(fileobj)
127
128 if images is not None:
129 append = True
130 if hasattr(images, 'get_positions'):
131 images = [images]
132 else:
133 append = False
134
135 fileobj.seek(0)
136 lattices = []
137 for line in fileobj:
138 if 'Lattice vectors' in line:
139 vec = []
140 for i in range(3): #DFTB+ only supports 3D PBC
141 line = fileobj.readline().split()
142 try:
143 line = [float(x) for x in line]
144 except ValueError:
145 raise ValueError('Lattice vector elements should be of type float.')
146 vec.extend(line)
147 lattices.append(np.array(vec).reshape((3,3)))
148
149 if append:
150 if len(images) != len(lattices):
151 raise ValueError('Length of images given does not match number of cell vectors found')
152
153 for i,atoms in enumerate(images):
154 atoms.set_cell(lattices[i])
155 #DFTB+ only supports 3D PBC
156 atoms.set_pbc(True)
157 return
158 else:
159 return lattices
160
161
119162
120163
121164 def write_dftb_velocities(atoms, filename='velocities.txt'):
7171
7272 symbols = atoms.get_chemical_symbols()
7373 if np.all(atoms.pbc):
74 # Rotate positions so they will allign with cellpar cell
74 # Rotate positions so they will align with cellpar cell
7575 cellpar = cell_to_cellpar(atoms.cell)
7676 new_cell = cellpar_to_cell(cellpar)
77 lstsq_fit = np.linalg.lstsq(atoms.cell, new_cell)
77 lstsq_fit = np.linalg.lstsq(atoms.cell, new_cell, rcond=-1)
78 # rcond=-1 silences FutureWarning in numpy 1.14
7879 R = lstsq_fit[0]
7980 positions = np.dot(atoms.positions, R)
8081
222223 if np.all(atoms.pbc):
223224 cellpar = cell_to_cellpar(atoms.cell)
224225 new_cell = cellpar_to_cell(cellpar)
225 lstsq_fit = np.linalg.lstsq(atoms.cell, new_cell)
226 lstsq_fit = np.linalg.lstsq(atoms.cell, new_cell, rcond=-1)
226227 R = lstsq_fit[0]
227228 f.write('!DATE %s\n' % dt.strftime('%b %d %H:%m:%S %Y'))
228229 f.write('PBC %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f\n'
44
55 class EPS:
66 def __init__(self, atoms,
7 rotation='', show_unit_cell=False, radii=None,
7 rotation='', show_unit_cell=0, radii=None,
88 bbox=None, colors=None, scale=20, maxwidth=500):
9 """Encapsulated PostScript writer.
10
11 show_unit_cell: int
12 0: Don't show unit cell (default). 1: Show unit cell.
13 2: Show unit cell and make sure all of it is visible.
14 """
915 generate_writer_variables(
1016 self, atoms, rotation=rotation,
1117 show_unit_cell=show_unit_cell,
4242 UNPROCESSED_KEYS = ['uid']
4343
4444
45 def key_val_str_to_dict(s):
45 def key_val_str_to_dict(string, sep=None):
46 """
47 Parse an xyz properties string in a key=value and return a dict with
48 various values parsed to native types.
49
50 Accepts brackets or quotes to delimit values. Parses integers, floats
51 booleans and arrays thereof. Arrays with 9 values are converted to 3x3
52 arrays with Fortran ordering.
53
54 If sep is None, string will split on whitespace, otherwise will split
55 key value pairs with the given separator.
56
57 """
58 # store the closing delimiters to match opening ones
59 delimiters = {
60 "'": "'",
61 '"': '"',
62 '(': ')',
63 '{': '}',
64 '[': ']',
65 }
66
67 # Make pairs and process afterwards
68 kv_pairs = [
69 [[]]] # List of characters for each entry, add a new list for new value
70 delimiter_stack = [] # push and pop closing delimiters
71 escaped = False # add escaped sequences verbatim
72
73 # parse character-by-character unless someone can do nested brackets
74 # and escape sequences in a regex
75 for char in string.strip():
76 if escaped: # bypass everything if escaped
77 kv_pairs[-1][-1].extend(['\\', char])
78 escaped = False
79 elif delimiter_stack: # inside brackets
80 if char == delimiter_stack[-1]: # find matching delimiter
81 delimiter_stack.pop()
82 elif char in delimiters:
83 delimiter_stack.append(delimiters[char]) # nested brackets
84 elif char == '\\':
85 escaped = True # so escaped quotes can be ignored
86 else:
87 kv_pairs[-1][-1].append(char) # inside quotes, add verbatim
88 elif char == '\\':
89 escaped = True
90 elif char in delimiters:
91 delimiter_stack.append(delimiters[char]) # brackets or quotes
92 elif (sep is None and char.isspace()) or char == sep:
93 if kv_pairs == [[[]]]: # empty, beginning of string
94 continue
95 elif kv_pairs[-1][-1] == []:
96 continue
97 else:
98 kv_pairs.append([[]])
99 elif char == '=':
100 if kv_pairs[-1] == [[]]:
101 del kv_pairs[-1]
102 kv_pairs[-1].append([]) # value
103 else:
104 kv_pairs[-1][-1].append(char)
105
106 kv_dict = {}
107
108 for kv_pair in kv_pairs:
109 if len(kv_pair) == 0: # empty line
110 continue
111 elif len(kv_pair) == 1: # default to True
112 key, value = ''.join(kv_pair[0]), 'T'
113 else: # Smush anything else with kv-splitter '=' between them
114 key, value = ''.join(kv_pair[0]), '='.join(
115 ''.join(x) for x in kv_pair[1:])
116
117 if key.lower() not in UNPROCESSED_KEYS:
118 # Try to convert to (arrays of) floats, ints
119 split_value = re.findall(r'[^\s,]+', value)
120 try:
121 try:
122 numvalue = np.array(split_value, dtype=int)
123 except (ValueError, OverflowError):
124 # don't catch errors here so it falls through to bool
125 numvalue = np.array(split_value, dtype=float)
126 if len(numvalue) == 1:
127 numvalue = numvalue[0] # Only one number
128 elif len(numvalue) == 9:
129 # special case: 3x3 matrix, fortran ordering
130 numvalue = np.array(numvalue).reshape((3, 3), order='F')
131 value = numvalue
132 except (ValueError, OverflowError):
133 pass # value is unchanged
134
135 # Parse boolean values: 'T' -> True, 'F' -> False,
136 # 'T T F' -> [True, True, False]
137 if isinstance(value, basestring):
138 str_to_bool = {'T': True, 'F': False}
139
140 try:
141 boolvalue = [str_to_bool[vpart] for vpart in
142 re.findall(r'[^\s,]+', value)]
143 if len(boolvalue) == 1:
144 value = boolvalue[0]
145 else:
146 value = boolvalue
147 except KeyError:
148 pass # value is unchanged
149
150 kv_dict[key] = value
151
152 return kv_dict
153
154
155 def key_val_str_to_dict_regex(s):
46156 """
47157 Parse strings in the form 'key1=value1 key2="quoted value"'
48158 """
199309 return properties, properties_list, dtype, converters
200310
201311
202 def _read_xyz_frame(lines, natoms):
312 def _read_xyz_frame(lines, natoms, properties_parser=key_val_str_to_dict, nvec=0):
203313 # comment line
204314 line = next(lines)
205 info = key_val_str_to_dict(line)
315 if nvec > 0:
316 info = {'comment': line.strip()}
317 else:
318 info = properties_parser(line)
206319
207320 pbc = None
208321 if 'pbc' in info:
212325 # default pbc for extxyz file containing Lattice
213326 # is True in all directions
214327 pbc = [True, True, True]
328 elif nvec > 0:
329 #cell information given as pseudo-Atoms
330 pbc = [False, False, False]
215331
216332 cell = None
217333 if 'Lattice' in info:
218334 # NB: ASE cell is transpose of extended XYZ lattice
219335 cell = info['Lattice'].T
220336 del info['Lattice']
337 elif nvec > 0:
338 #cell information given as pseudo-Atoms
339 cell = np.zeros((3,3))
221340
222341 if 'Properties' not in info:
223342 # Default set of properties is atomic symbols and positions only
227346
228347 data = []
229348 for ln in range(natoms):
230 line = next(lines)
349 try:
350 line = next(lines)
351 except StopIteration:
352 raise XYZError('ase.io.extxyz: Frame has {} atoms, expected {}'
353 .format(len(data), natoms))
231354 vals = line.split()
232355 row = tuple([conv(val) for conv, val in zip(convs, vals)])
233356 data.append(row)
235358 try:
236359 data = np.array(data, dtype)
237360 except TypeError:
238 raise IOError('Badly formatted data, ' +
239 'or end of file reached before end of frame')
361 raise XYZError('Badly formatted data '
362 'or end of file reached before end of frame')
363
364 #Read VEC entries if present
365 if nvec > 0:
366 for ln in range(nvec):
367 try:
368 line = next(lines)
369 except StopIteration:
370 raise XYZError('ase.io.adfxyz: Frame has {} cell vectors, expected {}'
371 .format(len(cell), nvec))
372 entry = line.split()
373
374 if not entry[0].startswith('VEC'):
375 raise XYZError('Expected cell vector, got {}'.format(entry[0]))
376 try:
377 n = int(entry[0][3:])
378 if n != ln + 1:
379 raise XYZError('Expected VEC{}, got VEC{}'
380 .format(ln+1,n))
381 except:
382 raise XYZError('Expected VEC{}, got VEC{}'.format(ln+1,entry[0][3:]))
383
384 cell[ln] = np.array([float(x) for x in entry[1:]])
385 pbc[ln] = True
386 if nvec != pbc.count(True):
387 raise XYZError('Problem with number of cell vectors')
388 pbc = tuple(pbc)
240389
241390 arrays = {}
242391 for name in names:
250399
251400 symbols = None
252401 if 'symbols' in arrays:
253 symbols = arrays['symbols']
402 symbols = [s.capitalize() for s in arrays['symbols']]
254403 del arrays['symbols']
255404
256405 numbers = None
376525 iread_xyz = ImageIterator(ixyzchunks)
377526
378527
379 def read_xyz(fileobj, index=-1):
528 def read_xyz(fileobj, index=-1, properties_parser=key_val_str_to_dict):
380529 """
381530 Read from a file in Extended XYZ format
382531
383532 index is the frame to read, default is last frame (index=-1).
533 properties_parser is the parse to use when converting the properties line
534 to a dictionary, ``extxyz.key_val_str_to_dict`` is the default and can
535 deal with most use cases, ``extxyz.key_val_str_to_dict_regex`` is slightly
536 faster but has fewer features.
384537 """
385538 if isinstance(fileobj, basestring):
386539 fileobj = open(fileobj)
399552 # scan through file to find where the frames start
400553 fileobj.seek(0)
401554 frames = []
402 while fileobj:
555 while True:
403556 frame_pos = fileobj.tell()
404557 line = fileobj.readline()
405558 if line.strip() == '':
406559 break
407 natoms = int(line)
408 frames.append((frame_pos, natoms))
409 if last_frame is not None and len(frames) > last_frame:
410 break
560 try:
561 natoms = int(line)
562 except ValueError as err:
563 raise XYZError('ase.io.extxyz: Expected xyz header but got: {}'
564 .format(err))
411565 fileobj.readline() # read comment line
412566 for i in range(natoms):
413567 fileobj.readline()
568 #check for VEC
569 nvec = 0
570 while True:
571 lastPos = fileobj.tell()
572 line = fileobj.readline()
573 if line.lstrip().startswith('VEC'):
574 nvec += 1
575 if nvec > 3:
576 raise XYZError('ase.io.extxyz: More than 3 VECX entries')
577 else:
578 fileobj.seek(lastPos)
579 break
580 frames.append((frame_pos, natoms, nvec))
581 if last_frame is not None and len(frames) > last_frame:
582 break
414583
415584 if isinstance(index, int):
416585 if index < 0:
441610 trbl.reverse()
442611
443612 for index in trbl:
444 frame_pos, natoms = frames[index]
613 frame_pos, natoms, nvec = frames[index]
445614 fileobj.seek(frame_pos)
446615 # check for consistency with frame index table
447616 assert int(fileobj.readline()) == natoms
448 yield _read_xyz_frame(fileobj, natoms)
617 yield _read_xyz_frame(fileobj, natoms, properties_parser, nvec)
449618
450619
451620 def output_column_format(atoms, columns, arrays,
520689
521690
522691 def write_xyz(fileobj, images, comment='', columns=None, write_info=True,
523 write_results=True, plain=False):
692 write_results=True, plain=False, vec_cell=False, append=False):
524693 """
525694 Write output in extended XYZ format
526695
530699 calculator attached to this Atoms.
531700 """
532701 if isinstance(fileobj, basestring):
533 fileobj = paropen(fileobj, 'w')
702 mode = 'w'
703 if append:
704 mode = 'a'
705 fileobj = paropen(fileobj, mode)
534706
535707 if hasattr(images, 'get_positions'):
536708 images = [images]
548720 [key for key in atoms.arrays.keys() if
549721 key not in ['symbols', 'positions',
550722 'species', 'pos']])
723
724 if vec_cell:
725 plain = True
551726
552727 if plain:
553728 fr_cols = ['symbols', 'positions']
602777 if pos.shape != (natoms, 3) or pos.dtype.kind != 'f':
603778 raise ValueError('Second column must be position-like')
604779
780 #if vec_cell add cell information as pseudo-atoms
781 if vec_cell:
782 pbc = list(atoms.get_pbc())
783 cell = atoms.get_cell()
784
785 if True in pbc:
786 nPBC = 0
787 for i,b in enumerate(pbc):
788 if b:
789 nPBC += 1
790 symbols.append('VEC'+str(nPBC))
791 pos = np.vstack((pos, cell[i]))
792 #add to natoms
793 natoms += nPBC
794 if pos.shape != (natoms, 3) or pos.dtype.kind != 'f':
795 raise ValueError('Pseudo Atoms containing cell have bad coords')
796
797
798
605799 # Collect data to be written out
606800 arrays = {}
607801 for column in fr_cols:
608 if column in atoms.arrays:
802 if column == 'positions':
803 arrays[column] = pos
804 elif column in atoms.arrays:
609805 arrays[column] = atoms.arrays[column]
610806 elif column == 'symbols':
611807 arrays[column] = np.array(symbols)
635831 for c in range(ncol):
636832 data[column + str(c)] = value[:, c]
637833
834 nat = natoms
835 if vec_cell: nat -= nPBC
638836 # Write the output
639 fileobj.write('%d\n' % natoms)
837 fileobj.write('%d\n' % nat)
640838 fileobj.write('%s\n' % comm)
641839 for i in range(natoms):
642840 fileobj.write(fmt % tuple(data[i]))
3030 import sys
3131
3232 from ase.atoms import Atoms
33 from ase.utils import import_module, basestring
33 from ase.utils import import_module, basestring, PurePath
3434 from ase.parallel import parallel_function, parallel_generator
3535
36 IOFormat = collections.namedtuple('IOFormat', 'read, write, single, acceptsfd')
36
37 class UnknownFileTypeError(Exception):
38 pass
39
40
41 IOFormat = collections.namedtuple('IOFormat',
42 'read, write, single, acceptsfd, isbinary')
3743 ioformats = {} # will be filled at run-time
3844
39 # 1=single, +=multiple, F=accepts a file-descriptor, S=needs a file-name str
45 # 1=single, +=multiple, F=accepts a file-descriptor, S=needs a file-name str,
46 # B=like F, but opens in binary mode
4047 all_formats = {
4148 'abinit': ('ABINIT input file', '1F'),
4249 'aims': ('FHI-aims geometry file', '1S'),
5057 'cfg': ('AtomEye configuration', '1F'),
5158 'cif': ('CIF-file', '+F'),
5259 'cmdft': ('CMDFT-file', '1F'),
60 'crystal': ('Crystal fort.34 format', '1S'),
5361 'cube': ('CUBE file', '1F'),
5462 'dacapo': ('Dacapo netCDF output file', '1F'),
5563 'dacapo-text': ('Dacapo text output', '1F'),
7583 'gpw': ('GPAW restart-file', '1S'),
7684 'gromacs': ('Gromacs coordinates', '1S'),
7785 'gromos': ('Gromos96 geometry file', '1F'),
78 'html': ('X3DOM HTML', '1S'),
86 'html': ('X3DOM HTML', '1F'),
7987 'iwm': ('?', '1F'),
8088 'json': ('ASE JSON database file', '+F'),
8189 'jsv': ('JSV file format', '1F'),
8290 'lammps-dump': ('LAMMPS dump file', '+F'),
8391 'lammps-data': ('LAMMPS data file', '1F'),
84 'magres': ('MAGRES ab initio NMR data file', '1S'),
92 'magres': ('MAGRES ab initio NMR data file', '1F'),
8593 'mol': ('MDL Molfile', '1F'),
94 'mustem': ('muSTEM xtl file', '1F'),
95 'netcdftrajectory': ('AMBER NetCDF trajectory file', '+S'),
8696 'nwchem': ('NWChem input file', '1F'),
8797 'octopus': ('Octopus input file', '1F'),
8898 'proteindatabank': ('Protein Data Bank', '+F'),
95105 'sdf': ('SDF format', '1F'),
96106 'struct': ('WIEN2k structure file', '1S'),
97107 'struct_out': ('SIESTA STRUCT file', '1F'),
98 'traj': ('ASE trajectory', '+S'),
108 'traj': ('ASE trajectory', '+B'),
99109 'trj': ('Old ASE pickle trajectory', '+S'),
100110 'turbomole': ('TURBOMOLE coord file', '1F'),
101111 'turbomole-gradient': ('TURBOMOLE gradient file', '+F'),
152162 'con': 'eon',
153163 'config': 'dlp4',
154164 'exi': 'exciting',
165 'f34': 'crystal',
166 '34': 'crystal',
155167 'g96': 'gromos',
156168 'geom': 'castep-geom',
157169 'gro': 'gromacs',
165177 'shelx': 'res',
166178 'in': 'aims',
167179 'poscar': 'vasp',
168 'phonon': 'castep-phonon'}
180 'phonon': 'castep-phonon',
181 'xtl': 'mustem'}
182
183 netcdfconventions2format = {
184 'http://www.etsf.eu/fileformats': 'etsf',
185 'AMBER': 'netcdftrajectory'
186 }
169187
170188
171189 def initialize(format):
191209 raise ValueError('File format not recognized: ' + format)
192210 code = all_formats[format][1]
193211 single = code[0] == '1'
194 acceptsfd = code[1] == 'F'
195 ioformats[format] = IOFormat(read, write, single, acceptsfd)
212 assert code[1] in 'BFS'
213 acceptsfd = code[1] != 'S'
214 isbinary = code[1] == 'B'
215 ioformats[format] = IOFormat(read, write, single, acceptsfd, isbinary)
196216
197217
198218 def get_ioformat(format):
273293 mode = 'rt'
274294 elif mode == 'w':
275295 mode = 'wt'
296 elif mode == 'a':
297 mode = 'at'
276298 else:
277299 # The version of gzip in Anaconda Python 2 on Windows forcibly
278300 # adds a 'b', so strip any 't' and let the string conversions
296318 fd = bz2.BZ2File(filename, mode=mode)
297319 elif compression == 'xz':
298320 try:
299 import lzma
321 from lzma import open as lzma_open
300322 except ImportError:
301 from backports import lzma
302 fd = lzma.open(filename, mode)
323 from backports.lzma import open as lzma_open
324 fd = lzma_open(filename, mode)
303325 else:
304326 fd = open(filename, mode)
305327
315337 yield atoms
316338
317339
318 def write(filename, images, format=None, parallel=True, **kwargs):
340 def write(filename, images, format=None, parallel=True, append=False, **kwargs):
319341 """Write Atoms object(s) to file.
320342
321343 filename: str or file
329351 parallel: bool
330352 Default is to write on master only. Use parallel=False to write
331353 from all slaves.
354 append: bool
355 Default is to open files in 'w' or 'wb' mode, overwriting existing files.
356 In some cases opening the file in 'a' or 'ab' mode (appending) is usefull,
357 e.g. writing trajectories or saving multiple Atoms objects in one file.
358 WARNING: If the file format does not support multiple entries without
359 additional keywords/headers, files created using 'append=True'
360 might not be readable by any program! They will nevertheless be
361 written without error message.
332362
333363 The use of additional keywords is format specific."""
334364
348378
349379 io = get_ioformat(format)
350380
351 _write(filename, fd, format, io, images, parallel=parallel, **kwargs)
381 _write(filename, fd, format, io, images, parallel=parallel, append=append, **kwargs)
352382
353383
354384 @parallel_function
355 def _write(filename, fd, format, io, images, parallel=None, **kwargs):
385 def _write(filename, fd, format, io, images, parallel=None, append=False, **kwargs):
356386 if isinstance(images, Atoms):
357387 images = [images]
358388
376406 if io.acceptsfd:
377407 open_new = (fd is None)
378408 if open_new:
379 fd = open_with_compression(filename, 'w')
409 mode = 'wb' if io.isbinary else 'w'
410 if append:
411 mode = mode.replace('w','a')
412 fd = open_with_compression(filename, mode)
380413 io.write(fd, images, **kwargs)
381414 if open_new:
382415 fd.close()
384417 if fd is not None:
385418 raise ValueError("Can't write {}-format to file-descriptor"
386419 .format(format))
387 io.write(filename, images, **kwargs)
420 if 'append' in io.write.__code__.co_varnames:
421 io.write(filename, images, append=append, **kwargs)
422 elif append:
423 raise ValueError("Cannot append to {}-format, write-function "
424 "does not support the append keyword.".format(format))
425 else:
426 io.write(filename, images, **kwargs)
388427
389428
390429 def read(filename, index=None, format=None, parallel=True, **kwargs):
412451 of ``filename``. In this case the format cannot be auto-decected,
413452 so the ``format`` argument should be explicitly given."""
414453
454 if isinstance(filename, PurePath):
455 filename = str(filename)
415456 if isinstance(index, basestring):
416457 index = string2index(index)
417458 filename, index = parse_filename(filename, index)
471512 must_close_fd = False
472513 if isinstance(filename, basestring):
473514 if io.acceptsfd:
474 fd = open_with_compression(filename)
515 mode = 'rb' if io.isbinary else 'r'
516 fd = open_with_compression(filename, mode)
475517 must_close_fd = True
476518 else:
477519 fd = filename
568610 return 'vasp-xml'
569611 if basename == 'coord':
570612 return 'turbomole'
613 if basename == 'f34':
614 return 'crystal'
615 if basename == '34':
616 return 'crystal'
571617 if basename == 'gradient':
572618 return 'turbomole-gradient'
573619 if basename.endswith('I_info'):
578624 return 'dlp4'
579625
580626 if not read:
627 if ext is None:
628 raise UnknownFileTypeError('Could not guess file type')
581629 return extension2format.get(ext, ext)
582630
583631 fd = open_with_compression(filename, 'rb')
593641 fd.seek(0)
594642
595643 if len(data) == 0:
596 raise IOError('Empty file: ' + filename)
644 raise UnknownFileTypeError('Empty file: ' + filename)
645
646 if data.startswith(b'CDF'):
647 # We can only recognize these if we actually have the netCDF4 module.
648 try:
649 import netCDF4
650 except ImportError:
651 pass
652 else:
653 nc = netCDF4.Dataset(filename)
654 if 'Conventions' in nc.ncattrs():
655 if nc.Conventions in netcdfconventions2format:
656 return netcdfconventions2format[nc.Conventions]
657 else:
658 raise UnknownFileTypeError(
659 "Unsupported NetCDF convention: "
660 "'{}'".format(nc.Conventions))
661 else:
662 raise UnknownFileTypeError("NetCDF file does not have a "
663 "'Conventions' attribute.")
597664
598665 for format, magic in [('traj', b'- of UlmASE-Trajectory'),
599666 ('traj', b'AFFormatASE-Trajectory'),
600667 ('gpw', b'- of UlmGPAW'),
601668 ('gpw', b'AFFormatGPAW'),
602669 ('trj', b'PickleTrajectory'),
603 ('etsf', b'CDF'),
604670 ('turbomole', b'$coord'),
605671 ('turbomole-gradient', b'$grad'),
606672 ('dftb', b'Geometry')]:
613679 ('espresso-out', b'Program PWSCF'),
614680 ('aims-output', b'Invoking FHI-aims ...'),
615681 ('lammps-dump', b'\nITEM: TIMESTEP\n'),
616 ('qbox', b'<fpmd:simulation'),
682 ('qbox', b':simulation xmlns:'),
617683 ('xsf', b'\nANIMSTEPS'),
618684 ('xsf', b'\nCRYSTAL'),
619685 ('xsf', b'\nSLAB'),
628694 format = extension2format.get(ext)
629695 if format is None and guess:
630696 format = ext
697 if format is None:
698 # Do quick xyz check:
699 lines = data.splitlines()
700 if lines and lines[0].strip().isdigit():
701 return 'xyz'
702
703 raise UnknownFileTypeError('Could not guess file type')
704
631705 return format
3737
3838
3939 def read_gaussian_out(filename, index=-1, quantity='atoms'):
40 """"Interface to GaussianReader and returns various quantities"""
40 """"Interface to GaussianReader and returns various quantities.
41 No support for multiple images in one file!
42 - quantity = 'structures' -> all structures from the file
43 - quantity = 'atoms' -> structure from the archive section
44 - quantity = 'energy' -> from the archive section
45 - quantity = 'force' -> last entry from the file
46 - quantity = 'dipole' -> from the archive section
47 - quantity = 'version' -> from the archive section
48 - quantity = 'multiplicity' -> from the archive section
49 - quantity = 'charge' -> from the archive section"""
4150 energy = 0.0
4251
43 data = GR(filename)[index]
44 if isinstance(data, list):
52 tmpGR = GR(filename, read_structures=bool(quantity == 'structures'))
53
54 if quantity == 'structures':
55 structures = tmpGR.get_structures()
56
57 data = tmpGR[index]
58 #fix: io.formats passes a slice as index, resulting in data beeing a list
59 if isinstance(data, list) and len(data) > 1:
4560 msg = 'Cannot parse multiple images from Gaussian out files at this'
4661 msg += ' time. Please select a single image.'
4762 raise RuntimeError(msg)
63 elif isinstance(data,list):
64 data = data[-1]
4865
4966 atomic_numbers = data['Atomic_numbers']
5067 formula = str()
107124 return multiplicity
108125 elif (quantity == 'charge'):
109126 return charge
127 elif (quantity == 'structures'):
128 return structures
110129
111130
112131 def read_gaussian(filename):
4040
4141 return data
4242
43 def __init__(self, filename):
44 """filename is optional; if not set, use parse to set the content"""
43 def __init__(self, filename, read_structures=False):
44 """filename is NOT optional"""
4545 if isinstance(filename, basestring):
4646 fileobj = open(filename, 'r')
47 else:
47 elif hasattr(filename,'seek'):
4848 fileobj = filename
4949 fileobj.seek(0) # Re-wind fileobj
50 else:
51 msg = 'Cannot use given filename, make sure it is a string or a fileobject'
52 raise RuntimeError(msg)
5053
5154 content = fileobj.read()
5255
5558
5659 self.parse(content)
5760
61 #read structures from file
62 if read_structures:
63 self.read_structures(content)
64
65
66 def get_structures(self, content=None):
67 """Get Structures"""
68 if hasattr(self,'structures'):
69 return self.structures
70 elif content is None:
71 raise RuntimeError('Images not available and no content parsed!')
72 else:
73 self.read_structures(content)
74 return self.structures
75
76
77 def read_structures(self, content=None):
78 """Read Structures from file and wirte them to self.structures"""
79 from ase.atoms import Atoms
80 from ase.atom import Atom
81 images = []
82 temp_items = content.split('Standard orientation')[1:]
83 for item_i in temp_items:
84 lines = [ line for line in item_i.split('\n') if len(line) > 0 ]
85 #first 5 lines are headers
86 del lines[:5]
87 images.append(Atoms())
88 for line in lines:
89 #if only - in line it is the end
90 if set(line).issubset(set('- ')):
91 break
92 tmp_line = line.strip().split()
93 if not len(tmp_line) == 6:
94 raise RuntimeError('Length of line does not match structure!')
95
96 #read atom
97 try:
98 atN = int(tmp_line[1])
99 pos = tuple(float(x) for x in tmp_line[3:])
100 except ValueError:
101 raise ValueError('Expected a line with three integers and three floats.')
102 images[-1].append(Atom(atN,pos))
103 self.structures = images
104 return
105
106
107
58108 def parse(self, content):
59109 from ase.data import atomic_numbers
110 chg_mult = charge_multiplicity
60111 self.data = []
61112 temp_items = content.split(PARA_START)
62113 seq_count = 0
73124 seq_count += 1
74125 for pos in range(len(names)):
75126 if names[pos] != "":
127 #hack, since this section is too short if there is no title
128 if names[pos] == "Title" and i[pos] == "":
129 chg_mult -= 1
130 break
76131 new_dict[names[pos]] = self.auto_type(i[pos])
77132
78 chm = i[charge_multiplicity].split(",")
133 chm = i[chg_mult].split(",")
79134 new_dict["Charge"] = int(chm[0])
80135 new_dict["Multiplicity"] = int(chm[1])
81136
82137 # Read atoms
83138 atoms = []
84139 positions = []
85 position = charge_multiplicity + 1
140 position = chg_mult + 1
86141 while position < len(i) and i[position] != "":
87142 s = i[position].split(",")
88 atoms.append(atomic_numbers[s[0]])
143 atoms.append(atomic_numbers[s[0].capitalize()])
89144 positions.append([float(s[1]), float(s[2]), float(s[3])])
90145 position = position + 1
91146
7676 positions = []
7777 for line in lines[i + 1:]:
7878 words = line.split()
79 if len(words) != 5:
79 if len(words) < 5:
8080 break
81 n, symbol, x, y, z = words
81 n, symbol, x, y, z = words[:5]
8282 symbols.append(symbol.split('.')[0].title())
8383 positions.append([float(x), float(y), float(z)])
8484 if len(symbols):
111111 else:
112112 energy_contributions = {}
113113 for line in lines[i + 2:i + 8]:
114 fields = line.split(':')
115 energy_contributions[fields[0]] = float(fields[1])
114 fields = line.split(':')
115 energy_contributions[fields[0]] = float(fields[1])
116116 line = lines[i + 10]
117117 assert (line.startswith('zero kelvin:') or
118118 line.startswith('extrapolated:'))
188188 else:
189189 magmoms = []
190190 for j in range(ii + 1, ii + 1 + len(atoms)):
191 magmom = lines[j].split()[-1]
191 magmom = lines[j].split()[-1].rstrip(')')
192192 magmoms.append(float(magmom))
193193
194194 try:
55 from ase.utils import basestring
66
77
8 def read_lammps_data(fileobj, Z_of_type=None, style='full'):
8 def read_lammps_data(fileobj, Z_of_type=None, style='full', sort_by_id=False):
99 """Method which reads a LAMMPS data file.
1010
11 order: Order the particles according to their id. Might be faster to
11 sort_by_id: Order the particles according to their id. Might be faster to
1212 switch it off.
1313 """
1414 if isinstance(fileobj, basestring):
161161 int(fields[6]),
162162 int(fields[7]))
163163 else:
164 raise RuntimeError("Style '%s' not supported or invalid" +
165 " number of fields %d" %
166 (style, len(fields)))
164 raise RuntimeError("Style '{}' not supported or invalid "
165 "number of fields {}"
166 "".format(style, len(fields)))
167167 elif section == "Velocities": # id vx vy vz
168168 vel_in[int(fields[0])] = (float(fields[1]),
169169 float(fields[2]),
227227 for (i, id) in enumerate(pos_in.keys()):
228228 # by id
229229 ind_of_id[id] = i
230 if sort_by_id:
231 ind = id-1
232 else:
233 ind = i
230234 type = pos_in[id][0]
231 positions[i, :] = [pos_in[id][1], pos_in[id][2], pos_in[id][3]]
235 positions[ind, :] = [pos_in[id][1], pos_in[id][2], pos_in[id][3]]
232236 if velocities is not None:
233 velocities[i, :] = [vel_in[id][0], vel_in[id][1], vel_in[id][2]]
237 velocities[ind, :] = [vel_in[id][0], vel_in[id][1], vel_in[id][2]]
234238 if travel is not None:
235 travel[i] = travel_in[id]
239 travel[ind] = travel_in[id]
236240 if mol_id is not None:
237 mol_id[i] = mol_id_in[id]
238 ids[i] = id
241 mol_id[ind] = mol_id_in[id]
242 ids[ind] = id
239243 # by type
240 types[i] = type
244 types[ind] = type
241245 if Z_of_type is None:
242 numbers[i] = type
246 numbers[ind] = type
243247 else:
244 numbers[i] = Z_of_type[type]
248 numbers[ind] = Z_of_type[type]
245249 if masses is not None:
246 masses[i] = mass_in[type]
250 masses[ind] = mass_in[type]
247251
248252 # create ase.Atoms
249253 at = Atoms(positions=positions,
1313 from ase.spacegroup import Spacegroup
1414
1515
16 def read_magres(filename, include_unrecognised=False):
16 def read_magres(fd, include_unrecognised=False):
1717 """
1818 Reader function for magres files.
1919 """
223223 'atoms': parse_atoms_block,
224224 'calculation': parse_generic_block, }
225225
226 with open(filename) as f:
227 file_contents = f.read()
226 file_contents = fd.read()
228227
229228 # This works as a validity check
230229 version = get_version(file_contents)
386385 return ' '.join(' '.join(str(x) for x in xs) for xs in tensor)
387386
388387
389 def write_magres(filename, image):
388 def write_magres(fd, image):
390389 """
391390 A writing function for magres files. Two steps: first data are arranged
392391 into structures, then dumped to the actual file
559558 ('atoms', write_atoms_block),
560559 ('magres', write_magres_block)])
561560
562 # Opening the file
563 ofile = open(filename, 'w')
564
565561 # First, write the header
566 ofile.write('#$magres-abinitio-v1.0\n')
567 ofile.write('# Generated by the Atomic Simulation Environment library\n')
562 fd.write('#$magres-abinitio-v1.0\n')
563 fd.write('# Generated by the Atomic Simulation Environment library\n')
568564
569565 for b in block_writers:
570566 if b in image_data:
571 ofile.write('[{0}]\n'.format(b))
572 ofile.write(block_writers[b](image_data[b]))
573 ofile.write('\n[/{0}]\n'.format(b))
567 fd.write('[{0}]\n'.format(b))
568 fd.write(block_writers[b](image_data[b]))
569 fd.write('\n[/{0}]\n'.format(b))
574570
575571 # Now on to check for any non-standard blocks...
576572 for i in image.info:
577573 if '_' in i:
578574 ismag, b = i.split('_', 1)
579575 if ismag == 'magresblock' and b not in block_writers:
580 ofile.write('[{0}]\n'.format(b))
581 ofile.write(image.info[i])
582 ofile.write('[/{0}]\n'.format(b))
576 fd.write('[{0}]\n'.format(b))
577 fd.write(image.info[i])
578 fd.write('[/{0}]\n'.format(b))
0 """Module to read and write atoms in xtl file format for the muSTEM software.
1
2 See http://tcmp.ph.unimelb.edu.au/mustem/muSTEM.html for a few examples of
3 this format and the documentation of muSTEM.
4
5 See https://github.com/HamishGBrown/MuSTEM for the source code of muSTEM.
6 """
7
8 import numpy as np
9
10 from ase.atoms import symbols2numbers
11 from ase.utils import basestring
12
13
14 def read_mustem(filename):
15 """Import muSTEM input file.
16
17 Reads cell, atom positions, etc. from muSTEM xtl file
18 """
19
20 from ase import Atoms
21 from ase.geometry import cellpar_to_cell
22
23 if isinstance(filename, basestring):
24 f = open(filename)
25 else: # Assume it's a file-like object
26 f = filename
27
28 # Read comment:
29 f.readline()
30
31 # Parse unit cell parameter
32 cellpar = [float(i) for i in f.readline().strip().split()[:3]]
33 cell = cellpar_to_cell(cellpar)
34
35 # beam energy
36 f.readline()
37
38 # Number of different type of atoms
39 element_number = int(f.readline().strip())
40
41 symbols = []
42 positions = []
43
44 for i in range(element_number):
45 # Read the element
46 symbol = str(f.readline().strip())
47 atoms_number = int(f.readline().split()[0])
48 # read all the position for each element
49 for j in range(atoms_number):
50 line = f.readline()
51 positions.append([float(i) for i in line.strip().split()])
52 symbols.append(symbol)
53
54 f.close()
55
56 atoms = Atoms(cell=cell, scaled_positions=positions)
57 atoms.set_chemical_symbols(symbols)
58
59 return atoms
60
61
62 class XtlmuSTEMWriter:
63 """Write muSTEM input file.
64
65 Parameters:
66
67 atoms: Atoms object
68
69 keV: float
70 Energy of the electron beam required for the image simulation.
71
72 DW: float or dictionary of float with atom type as key
73 Debye-Waller factor of each atoms.
74
75 occupancy: float or dictionary of float with atom type as key (optional)
76 Occupancy of each atoms. Default value is `1.0`.
77
78 comment: str (optional)
79 Comments to be writen in the first line of the file. If not
80 provided, write the total number of atoms and the chemical formula.
81
82 fit_cell_to_atoms: bool (optional)
83 If `True`, fit the cell to the atoms positions. If negative coordinates
84 are present in the cell, the atoms are translated, so that all
85 positions are positive. If `False` (default), the atoms positions and
86 the cell are unchanged.
87 """
88
89 def __init__(self, atoms, keV, DW, comment=None, occupancy=1.0,
90 fit_cell_to_atoms=False):
91 self.atoms = atoms.copy()
92 from collections import OrderedDict
93 self.atom_types = list(OrderedDict((element, None)
94 for element in self.atoms.get_chemical_symbols()))
95 self.keV = keV
96 self.DW = DW
97 self._check_key_dictionary(self.DW, 'DW')
98 self.comment = comment
99 if np.isscalar(occupancy):
100 self.occupancy = dict(zip(self.atom_types,
101 [occupancy] * len(self.atom_types)))
102 else:
103 self.occupancy = occupancy
104 self._check_key_dictionary(self.occupancy, 'occupancy')
105 self.numbers = symbols2numbers(self.atom_types)
106 if fit_cell_to_atoms:
107 self.atoms.translate(-self.atoms.positions.min(axis=0))
108 self.atoms.set_cell(self.atoms.positions.max(axis=0))
109
110 def _check_key_dictionary(self, d, dict_name):
111 # Check if we have enough key
112 for key in self.atom_types:
113 if not key in d:
114 raise ValueError('Missing the {0} key in the `{1}` dictionary.'
115 ''.format(key, dict_name))
116
117 def _get_position_array_single_atom_type(self, number):
118 self._check_cell_is_orthorhombic()
119 # Get the scaled (reduced) position for a single atom type
120 return self.atoms.get_scaled_positions()[np.where(
121 self.atoms.numbers == number)]
122
123 def _check_cell_is_orthorhombic(self):
124 cell = self.atoms.get_cell()
125 # Diagonal element must different from 0
126 # Non-diagonal element must be zero
127 if ((cell != 0) != np.eye(3)).any():
128 raise ValueError('To export to this format, the cell need to be '
129 'orthorhombic.')
130
131 def _get_file_header(self):
132 # 1st line: comment line
133 if self.comment is None:
134 s = "{0} atoms with chemical formula: {1}\n".format(
135 self.atoms.get_number_of_atoms(),
136 self.atoms.get_chemical_formula())
137 else:
138 s = self.comment
139 # 2nd line: lattice parameter
140 s += "{} {} {} {} {} {}\n".format(
141 *self.atoms.get_cell_lengths_and_angles().tolist())
142 # 3td line: acceleration voltage
143 s += "{}\n".format(self.keV)
144 # 4th line: number of different atom
145 s += "{}\n".format(len(self.atom_types))
146 return s
147
148 def _get_element_header(self, atom_type, number, atom_type_number,
149 occupancy, DW):
150 return "{0}\n{1} {2} {3} {4}\n".format(atom_type, number,
151 atom_type_number, occupancy, DW)
152
153 def _get_file_end(self):
154 return "Orientation\n 1 0 0\n 0 1 0\n 0 0 1\n"
155
156 def write_to_file(self, f):
157 if isinstance(f, basestring):
158 f = open(f, 'w')
159
160 f.write(self._get_file_header())
161 for atom_type, number, occupancy in zip(self.atom_types,
162 self.numbers,
163 self.occupancy):
164 positions = self._get_position_array_single_atom_type(number)
165 atom_type_number = positions.shape[0]
166 f.write(self._get_element_header(atom_type, atom_type_number,
167 number, self.occupancy[atom_type],
168 self.DW[atom_type]))
169 for pos in positions:
170 f.write('{0} {1} {2}\n'.format(pos[0], pos[1], pos[2]))
171
172 f.write(self._get_file_end())
173
174
175 def write_mustem(filename, *args, **kwargs):
176
177 writer = XtlmuSTEMWriter(*args, **kwargs)
178 writer.write_to_file(filename)
55 these conventions, such as writing of additional fields and writing to
66 HDF5 (NetCDF-4) files.
77
8 A Python NetCDF module is required. Supported are
9
10 netCDF4-python - http://code.google.com/p/netcdf4-python/
11
12 scipy.io.netcdf - http://docs.scipy.org/doc/scipy/reference/io.html
13
14 Availability is checked in the above order of preference. Note that
15 scipy.io.netcdf cannot write HDF5 NetCDF-4 files.
8 A netCDF4-python is required by this module:
9
10 netCDF4-python - https://github.com/Unidata/netcdf4-python
1611
1712 NetCDF files can be directly visualized using the libAtoms flavor of
1813 AtomEye (http://www.libatoms.org/),
2015 or Ovito (http://www.ovito.org/, starting with version 2.3).
2116 """
2217
18 from __future__ import division
19
2320 import os
2421 import warnings
2522
2825 import ase
2926
3027 from ase.data import atomic_masses
31 from ase.geometry import cellpar_to_cell, cell_to_cellpar
28 from ase.geometry import cellpar_to_cell
3229 import collections
3330 from functools import reduce
34
35 NC_NOT_FOUND = 0
36 NC_IS_NETCDF4 = 1
37 NC_IS_SCIPY = 2
38
39 have_nc = NC_NOT_FOUND
40 # Check if we have netCDF4-python
41 try:
42 from netCDF4 import Dataset
43 have_nc = NC_IS_NETCDF4
44 except:
45 pass
46
47 if not have_nc:
48 # Check for scipy
49 netcdf_file = None # Someone should fix scipy support or remove it
50 # try:
51 # from scipy.io.netcdf import netcdf_file
52 # have_nc = NC_IS_SCIPY
53 # except:
54 # pass
5531
5632
5733 class NetCDFTrajectory:
5834 """
5935 Reads/writes Atoms objects into an AMBER-style .nc trajectory file.
6036 """
61
62 # netCDF4-python format strings to scipy.io.netcdf version numbers
63 _netCDF4_to_scipy = {'NETCDF3_CLASSIC': 1, 'NETCDF3_64BIT': 2}
6437
6538 # Default dimension names
6639 _frame_dim = 'frame'
9164
9265 def __init__(self, filename, mode='r', atoms=None, types_to_numbers=None,
9366 double=True, netcdf_format='NETCDF3_CLASSIC', keep_open=True,
94 index_var='id', index_offset=-1):
67 index_var='id', index_offset=-1, chunk_size=1000000):
9568 """
9669 A NetCDFTrajectory can be created in read, write or append mode.
9770
150123 index_offset=-1:
151124 Set to 0 if atom index is zero based, set to -1 if atom index is
152125 one based. Default value is for LAMMPS output.
153 """
154 if not have_nc:
155 raise RuntimeError('NetCDFTrajectory requires a NetCDF Python '
156 'module.')
157
126
127 chunk_size=1000000:
128 Maximum size of consecutive number of records (along the 'atom')
129 dimension read when reading from a NetCDF file. This is used to
130 reduce the memory footprint of a read operation on very large files.
131 """
158132 self.nc = None
133 self.chunk_size = chunk_size
159134
160135 self.numbers = None
161136 self.pre_observers = [] # Callback functions before write
196171 self.filename = filename
197172 if keep_open is None:
198173 # Only netCDF4-python supports append to files
199 self.keep_open = self.mode == 'r' or have_nc != NC_IS_NETCDF4
174 self.keep_open = self.mode == 'r'
200175 else:
201176 self.keep_open = keep_open
202 if (mode == 'a' or not self.keep_open) and have_nc != NC_IS_NETCDF4:
203 raise RuntimeError('netCDF4-python is required for append mode.')
204177
205178 def __del__(self):
206179 self.close()
211184
212185 For internal use only.
213186 """
187 import netCDF4
214188 if self.nc is not None:
215189 return
216190 if self.mode == 'a' and not os.path.exists(self.filename):
217191 self.mode = 'w'
218 if have_nc == NC_IS_NETCDF4:
219 self.nc = Dataset(self.filename, self.mode,
220 format=self.netcdf_format)
221 elif have_nc == NC_IS_SCIPY:
222 if self.netcdf_format not in self._netCDF4_to_scipy:
223 raise ValueError("NetCDF format '%s' not supported by "
224 "scipy.io.netcdf." % self.netcdf_format)
225 version = self._netCDF4_to_scipy[self.netcdf_format]
226 if version == 1:
227 # This supports older scipy.io.netcdf versions that do not
228 # support the 'version' argument
229 self.nc = netcdf_file(self.filename, self.mode)
230 else:
231 self.nc = netcdf_file(
232 self.filename, self.mode,
233 version=self._netCDF4_to_scipy[self.netcdf_format]
234 )
235 else:
236 # Should not happen
237 raise RuntimeError('Internal error: Unknown *have_nc* value.')
192 self.nc = netCDF4.Dataset(self.filename, self.mode,
193 format=self.netcdf_format)
238194
239195 self.frame = 0
240196 if self.mode == 'r' or self.mode == 'a':
253209
254210 def _read_header(self):
255211 if not self.n_atoms:
256 if have_nc == NC_IS_NETCDF4:
257 self.n_atoms = len(self.nc.dimensions[self._atom_dim])
258 else:
259 self.n_atoms = self.nc.dimensions[self._atom_dim]
212 self.n_atoms = len(self.nc.dimensions[self._atom_dim])
260213
261214 for name, var in self.nc.variables.items():
262215 # This can be unicode which confuses ASE
325278 self._add_velocities()
326279 self._get_variable(self._velocities_var)[i] = \
327280 atoms.get_momenta() / atoms.get_masses().reshape(-1, 1)
328 a, b, c, alpha, beta, gamma = cell_to_cellpar(atoms.get_cell())
281 a, b, c, alpha, beta, gamma = atoms.get_cell_lengths_and_angles()
329282 if np.any(np.logical_not(atoms.pbc)):
330283 warnings.warn('Atoms have nonperiodic directions. Cell lengths in '
331284 'these directions are lost and will be '
333286 cell_lengths = np.array([a, b, c]) * atoms.pbc
334287 self._get_variable(self._cell_lengths_var)[i] = cell_lengths
335288 self._get_variable(self._cell_angles_var)[i] = [alpha, beta, gamma]
289 self._get_variable(self._cell_origin_var)[i] = \
290 atoms.get_celldisp().reshape(3)
336291 if arrays is not None:
337292 for array in arrays:
338293 data = atoms.get_array(array)
431386 self.nc.createVariable(self._cell_angles_var, 'd',
432387 (self._frame_dim, self._cell_angular_dim))
433388 self.nc.variables[self._cell_angles_var].units = 'degree'
389 if not self._has_variable(self._cell_origin_var):
390 self.nc.createVariable(self._cell_origin_var, 'd',
391 (self._frame_dim, self._cell_spatial_dim))
392 self.nc.variables[self._cell_origin_var].units = 'Angstrom'
393 self.nc.variables[self._cell_origin_var].scale_factor = 1.
434394
435395 def _add_time(self):
436396 if not self._has_variable(self._time_var):
493453 else:
494454 return name in self.nc.variables
495455
496 def _get_data(self, name, frame, exc=True):
456 def _get_data(self, name, frame, index, exc=True):
497457 var = self._get_variable(name, exc=exc)
498458 if var is None:
499459 return None
500460 if var.dimensions[0] == self._frame_dim:
501 return var[frame, ...]
502 else:
503 return var[...]
461 data = np.zeros(var.shape[1:], dtype=var.dtype)
462 s = var.shape[1]
463 if s < self.chunk_size:
464 data[index] = var[frame]
465 else:
466 # If this is a large data set, only read chunks from it to
467 # reduce memory footprint of the NetCDFTrajectory reader.
468 for i in range((s - 1) // self.chunk_size + 1):
469 sl = slice(i * self.chunk_size,
470 min((i + 1) * self.chunk_size, s))
471 data[index[sl]] = var[frame, sl]
472 else:
473 data = np.zeros(var.shape, dtype=var.dtype)
474 s = var.shape[0]
475 if s < self.chunk_size:
476 data[index] = var
477 else:
478 # If this is a large data set, only read chunks from it to
479 # reduce memory footprint of the NetCDFTrajectory reader.
480 for i in range((s-1)//self.chunk_size+1):
481 sl = slice(i*self.chunk_size,
482 min((i+1)*self.chunk_size, s))
483 data[index[sl]] = var[sl]
484 return data
504485
505486 def close(self):
506487 """Close the trajectory file."""
545526 index = np.arange(self.n_atoms)
546527
547528 # Read element numbers
548 self.numbers = self._get_data(self._numbers_var, i, exc=False)
529 self.numbers = self._get_data(self._numbers_var, i, index,
530 exc=False)
549531 if self.numbers is None:
550532 self.numbers = np.ones(self.n_atoms, dtype=int)
551 else:
552 self.numbers = np.array(self.numbers[index])
553533 if self.types_to_numbers is not None:
554534 self.numbers = self.types_to_numbers[self.numbers]
555535 self.masses = atomic_masses[self.numbers]
556536
557537 # Read positions
558 positions = np.array(self._get_data(self._positions_var, i)[index])
538 positions = self._get_data(self._positions_var, i, index)
559539
560540 # Determine cell size for non-periodic directions from shrink
561541 # wrapped cell.
570550 )
571551
572552 # Compute momenta from velocities (if present)
573 momenta = self._get_data(self._velocities_var, i, exc=False)
553 momenta = self._get_data(self._velocities_var, i, index,
554 exc=False)
574555 if momenta is not None:
575 momenta = momenta[index] * self.masses.reshape(-1, 1)
556 momenta *= self.masses.reshape(-1, 1)
576557
577558 # Fill info dict with additional data found in the NetCDF file
578559 info = {}
593574
594575 # Attach additional arrays found in the NetCDF file
595576 for name in self.extra_per_frame_vars:
596 atoms.set_array(name, self.nc.variables[name][i][index])
577 atoms.set_array(name, self._get_data(name, i, index))
597578 for name in self.extra_per_file_vars:
598 atoms.set_array(name, self.nc.variables[name][:])
579 atoms.set_array(name, self._get_data(name, i, index))
599580 self._close()
600581 return atoms
601582
650631 for function, interval, args, kwargs in obs:
651632 if self.write_counter % interval == 0:
652633 function(*args, **kwargs)
634
635
636 def read_netcdftrajectory(filename, index=-1):
637 traj = NetCDFTrajectory(filename, mode='r')
638 return traj[index]
639
640
641 def write_netcdftrajectory(filename, images):
642 traj = NetCDFTrajectory(filename, mode='w')
643
644 if hasattr(images, 'get_positions'):
645 images = [images]
646
647 for atoms in images:
648 traj.write(atoms)
649 traj.close()
176176 if atoms is None:
177177 atoms = self.atoms
178178
179 for image in atoms._images_():
179 for image in atoms.iterimages():
180180 self._write_atoms(image)
181181
182182 def _write_atoms(self, atoms):
317317 if self.transmittances is not None:
318318 trans = self.transmittances[a]
319319 w('constrain(%s, %.2f, Black, %s, %s) // #%i \n' % (
320 pa(loc), dia / 2., tex, a, trans))
320 pa(loc), dia / 2., trans, tex, a))
321321
322322
323323 def write_pov(filename, atoms, run_povray=False,
1616 from ase.parallel import paropen
1717 from ase.geometry import cellpar_to_cell
1818 from ase.utils import basestring
19 from ase.io.espresso import label_to_symbol
1920
2021
21 def read_proteindatabank(fileobj, index=-1):
22 def read_proteindatabank(fileobj, index=-1, read_arrays=True):
2223 """Read PDB files."""
2324
2425 if isinstance(fileobj, basestring):
2829 orig = np.identity(3)
2930 trans = np.zeros(3)
3031 atoms = Atoms()
32 occ = []
33 bfactor = []
3134 for line in fileobj.readlines():
3235 if line.startswith('CRYST1'):
33 cellpar = [float(word) for word in line[6:54].split()]
36 cellpar = [float(line[6:15]), # a
37 float(line[15:24]), # b
38 float(line[24:33]), # c
39 float(line[33:40]), # alpha
40 float(line[40:47]), # beta
41 float(line[47:54])] # gamma
3442 atoms.set_cell(cellpar_to_cell(cellpar))
3543 atoms.pbc = True
3644 for c in range(3):
3745 if line.startswith('ORIGX' + '123'[c]):
38 pars = [float(word) for word in line[10:55].split()]
39 orig[c] = pars[:3]
40 trans[c] = pars[3]
46 orig[c] = [float(line[10:20]),
47 float(line[20:30]),
48 float(line[30:40])]
49 trans[c] = float(line[45:55])
4150
4251 if line.startswith('ATOM') or line.startswith('HETATM'):
4352 try:
4453 # Atom name is arbitrary and does not necessarily
4554 # contain the element symbol. The specification
4655 # requires the element symbol to be in columns 77+78.
47 symbol = line[76:78].strip().lower().capitalize()
48 words = line[30:55].split()
49 position = np.array([float(words[0]),
50 float(words[1]),
51 float(words[2])])
56 # Fall back to Atom name for files that do not follow
57 # the spec, e.g. packmol.
58 try:
59 symbol = label_to_symbol(line[76:78].strip())
60 except (KeyError, IndexError):
61 symbol = label_to_symbol(line[12:16].strip())
62 # Don't use split() in case there are no spaces
63 position = np.array([float(line[30:38]), # x
64 float(line[38:46]), # y
65 float(line[46:54])]) # z
66 try:
67 occ.append(float(line[54:60]))
68 bfactor.append(float(line[60:66]))
69 except (IndexError, ValueError):
70 pass
5271 position = np.dot(orig, position) + trans
5372 atoms.append(Atom(symbol, position))
5473 except Exception as ex:
55 warnings.warn('Discarding atom when reading PDB file: {}'
56 .format(ex))
57 if line.startswith('ENDMDL'):
74 warnings.warn('Discarding atom when reading PDB file: {}\n{}'
75 .format(line.strip(), ex))
76 if line.startswith('END'):
77 # End of configuration reached
78 # According to the latest PDB file format (v3.30),
79 # this line should start with 'ENDMDL' (not 'END'),
80 # but in this way PDB trajectories from e.g. CP2K
81 # are supported (also VMD supports this format).
82 if read_arrays and len(occ) == len(atoms):
83 atoms.set_array('occupancy', np.array(occ))
84 if read_arrays and len(bfactor) == len(atoms):
85 atoms.set_array('bfactor', np.array(bfactor))
5886 images.append(atoms)
5987 atoms = Atoms()
88 occ = []
89 bfactor = []
6090 if len(images) == 0:
91 # Single configuration with no 'END' or 'ENDMDL'
92 if read_arrays and len(occ) == len(atoms):
93 atoms.set_array('occupancy', np.array(occ))
94 if read_arrays and len(bfactor) == len(atoms):
95 atoms.set_array('bfactor', np.array(bfactor))
6196 images.append(atoms)
6297 return images[index]
6398
6499
65 def write_proteindatabank(fileobj, images):
100 def write_proteindatabank(fileobj, images, write_arrays=True):
66101 """Write images to PDB-file."""
67102 if isinstance(fileobj, basestring):
68103 fileobj = paropen(fileobj, 'w')
85120 cellpar[3], cellpar[4], cellpar[5]))
86121
87122 # 1234567 123 6789012345678901 89 67 456789012345678901234567 890
88 format = ('ATOM %5d %4s MOL 1 %8.3f%8.3f%8.3f 1.00 0.00'
123 format = ('ATOM %5d %4s MOL 1 %8.3f%8.3f%8.3f%6.2f%6.2f'
89124 ' %2s \n')
90125
91126 # RasMol complains if the atom index exceeds 100000. There might
98133 for n, atoms in enumerate(images):
99134 fileobj.write('MODEL ' + str(n + 1) + '\n')
100135 p = atoms.get_positions()
136 occupancy = np.ones(len(atoms))
137 bfactor = np.zeros(len(atoms))
138 if write_arrays:
139 if 'occupancy' in atoms.arrays:
140 occupancy = atoms.get_array('occupancy')
141 if 'bfactor' in atoms.arrays:
142 bfactor = atoms.get_array('bfactor')
101143 if rotation is not None:
102144 p = p.dot(rotation)
103145 for a in range(natoms):
104146 x, y, z = p[a]
147 occ = occupancy[a]
148 bf = bfactor[a]
105149 fileobj.write(format % (a % MAXNUM, symbols[a],
106 x, y, z, symbols[a].upper()))
150 x, y, z, occ, bf, symbols[a].upper()))
107151 fileobj.write('ENDMDL\n')
11
22 from ase import Atom, Atoms
33 from ase.calculators.singlepoint import SinglePointCalculator
4 from ase.utils import basestring
45
6 import re
57 import xml.etree.ElementTree as ET
68
79
8 def read_qbox(file, index=-1):
10 def read_qbox(f, index=-1):
911 """Read data from QBox output file
1012
1113 Inputs:
12 file - str or fileobj, path to file or file object to read from
14 f - str or fileobj, path to file or file object to read from
1315 index - int or slice, which frames to return
1416 Returns:
1517 list of Atoms or atoms, requested frame(s)
1618 """
1719
18 # Read in the output file
19 tree = ET.parse(file)
20 if isinstance(f, basestring):
21 f = open(f, 'r')
22
23 # Check whether this is a QB@all output
24 version = None
25 for line in f:
26 if '<release>' in line:
27 version = ET.fromstring(line)
28 break
29 if version is None:
30 raise Exception('Parse Error: Version not found')
31 is_qball = 'qb@LL' in version.text or 'qball' in version.text
2032
2133 # Load in atomic species
2234 species = dict()
23 for spec in tree.findall('species'):
24 name = spec.get('name')
25 spec_data = dict(
26 symbol=spec.find('symbol').text,
27 mass=float(spec.find('mass').text),
28 number=int(spec.find('atomic_number').text))
29 species[name] = spec_data
35 if is_qball:
36 # Read all of the lines between release and the first call to `run`
37 species_data = []
38 for line in f:
39 if '<run' in line:
40 break
41 species_data.append(line)
42 species_data = '\n'.join(species_data)
43
44 # Read out the species information with regular expressions
45 symbols = re.findall('symbol_ = ([A-Z][a-z]?)', species_data)
46 masses = re.findall('mass_ = ([0-9.]+)', species_data)
47 names = re.findall('name_ = ([a-z]+)', species_data)
48 numbers = re.findall('atomic_number_ = ([0-9]+)', species_data)
49
50 # Compile them into a dictionary
51 for name, symbol, mass, number in zip(names, symbols, masses, numbers):
52 spec_data = dict(
53 symbol=symbol,
54 mass=float(mass),
55 number=float(number)
56 )
57 species[name] = spec_data
58 else:
59 # Find all species
60 species_blocks = _find_blocks(f, 'species', '[qbox]')
61
62 for spec in species_blocks:
63 name = spec.get('name')
64 spec_data = dict(
65 symbol=spec.find('symbol').text,
66 mass=float(spec.find('mass').text),
67 number=int(spec.find('atomic_number').text))
68 species[name] = spec_data
3069
3170 # Find all of the frames
32 frames = tree.findall("iteration")
71 frames = _find_blocks(f, 'iteration', None)
3372
3473 # If index is an int, return one frame
3574 if isinstance(index, int):
3675 return _parse_frame(frames[index], species)
3776 else:
3877 return [_parse_frame(frame, species) for frame in frames[index]]
78
79
80 def _find_blocks(fp, tag, stopwords='[qbox]'):
81 """Find and parse a certain block of the file.
82
83 Reads a file sequentially and stops when it either encounters the end of the file, or until the it encounters a line
84 that contains a user-defined string *after it has already found at least one desired block*. Use the stopwords
85 ``[qbox]`` to read until the next command is issued.
86
87 Groups the text between the first line that contains <tag> and the next line that contains </tag>, inclusively. The
88 function then parses the XML and returns the Element object.
89
90 Inputs:
91 fp - file-like object, file to be read from
92 tag - str, tag to search for (e.g., 'iteration'). `None` if you want to read until the end of the file
93 stopwords - str, halt parsing if a line containing this string is encountered
94
95 Returns:
96 list of xml.ElementTree, parsed XML blocks found by this class
97 """
98
99 start_tag = '<%s'%tag
100 end_tag = '</%s>'%tag
101
102 blocks = [] # Stores all blocks
103 cur_block = [] # Block being filled
104 in_block = False # Whether we are currently parsing
105 for line in fp:
106
107 # Check if the block has started
108 if start_tag in line:
109 if in_block:
110 raise Exception('Parsing failed: Encountered nested block')
111 else:
112 in_block = True
113
114 # Add data to block
115 if in_block:
116 cur_block.append(line)
117
118 # Check for stopping conditions
119 if stopwords is not None:
120 if stopwords in line and len(blocks) > 0:
121 break
122
123 if end_tag in line:
124 if in_block:
125 blocks.append(cur_block)
126 cur_block = []
127 in_block = False
128 else:
129 raise Exception('Parsing failed: End tag found before start tag')
130
131 # Parse the blocks
132 return [ET.fromstring(''.join(b)) for b in blocks]
39133
40134
41135 def _parse_frame(tree, species):
118118 if atoms is None:
119119 atoms = self.atoms
120120
121 for image in atoms._images_():
121 for image in atoms.iterimages():
122122 self._write_atoms(image, **kwargs)
123123
124124 def _write_atoms(self, atoms, **kwargs):
217217
218218 def _open(self, filename):
219219 import ase.io.ulm as ulm
220 try:
221 self.backend = ulm.open(filename, 'r')
222 except ulm.InvalidULMFileError:
223 raise RuntimeError('This is not a valid ASE trajectory file. '
224 'If this is an old-format (version <3.9) '
225 'PickleTrajectory file you can convert it '
226 'with ase.io.trajectory.convert("%s") '
227 'or:\n\n $ python -m ase.io.trajectory %s'
228 % (filename, filename))
220 self.backend = ulm.open(filename, 'r')
229221 self._read_header()
230222
231223 def _read_header(self):
340332 b.write(charges=atoms.get_initial_charges())
341333
342334
343 def read_traj(filename, index):
344 trj = TrajectoryReader(filename)
335 def read_traj(fd, index):
336 trj = TrajectoryReader(fd)
345337 for i in range(*index.indices(len(trj))):
346338 yield trj[i]
347339
348340
349 def write_traj(filename, images):
341 def write_traj(fd, images):
350342 """Write image(s) to trajectory."""
351 trj = TrajectoryWriter(filename, mode='w')
343 trj = TrajectoryWriter(fd)
352344 if isinstance(images, Atoms):
353345 images = [images]
354346 for atoms in images:
355347 trj.write(atoms)
356 trj.close()
357348
358349
359350 class OldCalculatorWrapper:
3232
3333 To see what's inside 'x.ulm' do this::
3434
35 $ alias ulm="python -m ase.io.ulm"
36 $ ulm x.ulm
35 $ ase ulm x.ulm
3736 x.ulm (tag: "", 1 item)
3837 item #0:
3938 {
5655 from __future__ import print_function
5756 import os
5857 import sys
58 import numbers
5959
6060 import numpy as np
6161
101101 a = np.array(n, np.int64)
102102 if not np.little_endian:
103103 a.byteswap(True)
104 a.tofile(fd)
104 fd.write(a.tobytes())
105105
106106
107107 def readints(fd, n):
108 a = np.fromfile(fd, np.int64, n)
108 a = np.fromstring(string=fd.read(int(n * 8)), dtype=np.int64, count=n)
109109 if not np.little_endian:
110110 a.byteswap(True)
111111 return a
112
113
114 def file_has_fileno(fd):
115 """Tell whether file implements fileio() or not.
116
117 array.tofile(fd) works only on files with fileno().
118 numpy may write faster to physical files using fileno().
119
120 For files without fileno() we use instead fd.write(array.tobytes()).
121 Either way we need to distinguish."""
122
123 try:
124 fno = fd.fileno # AttributeError?
125 fno() # IOError/OSError? (Newer python: OSError is IOError)
126 except (AttributeError, IOError):
127 return False
128 return True
112129
113130
114131 class Writer:
134151 data = {}
135152 else:
136153 data = {'_little_endian': False}
137 if mode == 'w' or not os.path.isfile(fd):
154 fd_is_string = isinstance(fd, basestring)
155 if mode == 'w' or (fd_is_string and
156 not (os.path.isfile(fd) and
157 os.path.getsize(fd) > 0)):
138158 self.nitems = 0
139159 self.pos0 = 48
140160 self.offsets = np.array([-1], np.int64)
141161
142 fd = builtins.open(fd, 'wb')
162 if fd_is_string:
163 fd = builtins.open(fd, 'wb')
143164
144165 # File format identifier and other stuff:
145166 a = np.array([VERSION, self.nitems, self.pos0], np.int64)
149170 a.tostring() +
150171 self.offsets.tostring())
151172 else:
152 fd = builtins.open(fd, 'r+b')
173 if fd_is_string:
174 fd = builtins.open(fd, 'r+b')
153175
154176 version, self.nitems, self.pos0, offsets = read_header(fd)[1:]
155177 assert version == VERSION
161183 fd.seek(0, 2)
162184
163185 self.fd = fd
186 self.hasfileno = file_has_fileno(fd)
187
164188 self.data = data
165189
166190 # date for array being filled:
207231 self.nmissing -= a.size
208232 assert self.nmissing >= 0
209233
210 a.tofile(self.fd)
234 if self.hasfileno:
235 a.tofile(self.fd)
236 else:
237 self.fd.write(a.tobytes())
211238
212239 def sync(self):
213240 """Write data dictionary.
228255 offsets = np.zeros(n * N1, np.int64)
229256 offsets[:n] = self.offsets
230257 self.pos0 = align(self.fd)
231 if np.little_endian:
232 offsets.tofile(self.fd)
258
259 buf = offsets if np.little_endian else offsets.byteswap()
260
261 if self.hasfileno:
262 buf.tofile(self.fd)
233263 else:
234 offsets.byteswap().tofile(self.fd)
264 self.fd.write(buf.tobytes())
235265 writeint(self.fd, self.pos0, 40)
236266 self.offsets = offsets
237267
333363 return tag, version, nitems, pos0, offsets
334364
335365
336 class InvalidULMFileError(Exception):
366 class InvalidULMFileError(IOError):
337367 pass
338368
339369
435465
436466 def _read_data(self, index):
437467 self._fd.seek(self._offsets[index])
438 size = readints(self._fd, 1)[0]
468 size = int(readints(self._fd, 1)[0])
439469 data = decode(self._fd.read(size).decode())
440470 return data
441471
470500 class NDArrayReader:
471501 def __init__(self, fd, shape, dtype, offset, little_endian):
472502 self.fd = fd
503 self.hasfileno = file_has_fileno(fd)
473504 self.shape = tuple(shape)
474505 self.dtype = dtype
475506 self.offset = offset
490521 return self[:]
491522
492523 def __getitem__(self, i):
493 if isinstance(i, int):
524 if isinstance(i, numbers.Integral):
494525 if i < 0:
495526 i += len(self)
496527 return self[i:i + 1][0]
499530 offset = self.offset + start * self.itemsize * stride
500531 self.fd.seek(offset)
501532 count = (stop - start) * stride
502 try:
533 if self.hasfileno:
503534 a = np.fromfile(self.fd, self.dtype, count)
504 except (AttributeError, IOError):
535 else:
505536 # Not as fast, but works for reading from tar-files:
506 a = np.fromstring(self.fd.read(count * self.itemsize), self.dtype)
537 a = np.fromstring(self.fd.read(int(count * self.itemsize)),
538 self.dtype)
507539 a.shape = (stop - start,) + self.shape[1:]
508540 if step != 1:
509541 a = a[::step].copy()
55 from ase.utils import basestring
66
77
8 def generate_writer_variables(writer, atoms, rotation='', show_unit_cell=False,
8 def generate_writer_variables(writer, atoms, rotation='', show_unit_cell=0,
99 radii=None, bbox=None, colors=None, scale=20,
1010 maxwidth=500, extra_offset=(0., 0.)):
1111 writer.numbers = atoms.get_atomic_numbers()
2828 cell = atoms.get_cell()
2929 disp = atoms.get_celldisp().flatten()
3030
31 if show_unit_cell:
31 if show_unit_cell > 0:
3232 L, T, D = cell_to_lines(writer, cell)
3333 cell_vertices = np.empty((2, 2, 2, 3))
3434 for c1 in range(2):
44 """
55
66 import os
7 import re
78 import ase.units
89
910 from ase.utils import basestring
260261 ecount = 0
261262 poscount = 0
262263 magnetization = []
263
264 magmom = None
265
266 for n, line in enumerate(data):
267 if re.search('[0-9]-[0-9]',line):
268 data[n] = re.sub('([0-9])-([0-9])',r'\1 -\2',line)
264269 for n, line in enumerate(data):
265270 if 'POTCAR:' in line:
266271 temp = line.split()[2]
301306 magnetization = []
302307 for i in range(natoms):
303308 magnetization += [float(data[n + 4 + i].split()[4])]
309 if 'number of electron' in line:
310 parts = line.split()
311 if len(parts) > 5 and parts[0].strip() != "NELECT":
312 magmom = float(parts[5])
304313 if 'in kB ' in line:
305314 stress = -np.array([float(a) for a in line.split()[2:]])
306315 stress = stress[[0, 1, 2, 4, 5, 3]] * 1e-1 * ase.units.GPa
322331 mag = np.array(magnetization, float)
323332 images[-1].calc.magmoms = mag
324333 images[-1].calc.results['magmoms'] = mag
334 if magmom:
335 images[-1].calc.results['magmom'] = magmom
325336 atoms = Atoms(pbc=True, constraint=constr)
326337 poscount += 1
327338
436447 var_type = to_type[par.attrib.get('type', 'float')]
437448
438449 if par.tag == 'v':
439 return map(var_type, text.split())
450 return list(map(var_type, text.split()))
440451 else:
441452 return var_type(text.strip())
442453
682693 'one image to VASP input')
683694 else:
684695 atoms = atoms[0]
696
697 # Check lattice vectors are finite
698 if np.any(atoms.get_cell_lengths_and_angles() == 0.):
699 raise RuntimeError(
700 'Lattice vectors must be finite and not coincident. '
701 'At least one lattice length or angle is zero.')
685702
686703 # Write atom positions in scaled or cartesian coordinates
687704 if direct:
44 modern web browsers.
55 """
66
7 from ase.parallel import paropen
7 from __future__ import print_function
88 from ase.data import covalent_radii
99 from ase.data.colors import jmol_colors
10 from ase.utils import basestring
1011
1112
12 def write_x3d(filename, atoms):
13 """Writes to html using X3DOM."""
14 X3D(atoms).write(filename)
13 def write_x3d(filename, atoms, format=None):
14 """Writes to html using X3DOM.
15
16 Args:
17 filename - str or file-like object, filename or output file object
18 atoms - Atoms object to be rendered
19 format - str, either 'X3DOM' for web-browser compatibility or 'X3D'
20 to be readable by Blender. `None` to detect format based on file extension
21 ('.html' -> 'X3DOM', '.x3d' -> 'X3D')"""
22 X3D(atoms).write(filename, datatype=format)
1523
24 def write_html(filename, atoms):
25 """Writes to html using X3DOM
1626
17 write_html = write_x3d
27 Args:
28 filename - str or file-like object, filename or output file object
29 atoms - Atoms object to be rendered"""
30 write_x3d(filename, atoms, format='X3DOM')
1831
1932
2033 class X3D:
2639 def __init__(self, atoms):
2740 self._atoms = atoms
2841
29 def write(self, filename):
42 def write(self, filename, datatype=None):
3043 """Writes output to either an 'X3D' or an 'X3DOM' file, based on
3144 the extension. For X3D, filename should end in '.x3d'. For X3DOM,
32 filename should end in '.html'."""
33 if filename.endswith('.x3d'):
34 datatype = 'X3D'
35 elif filename.endswith('.html'):
36 datatype = 'X3DOM'
37 else:
38 raise ValueError("filename must end in '.x3d' or '.html'.")
45 filename should end in '.html'.
46
47 Args:
48 filename - str or file-like object, output file name or writer
49 datatype - str, output format. 'X3D' or 'X3DOM'. If `None`, format
50 will be determined from the filename"""
51
52 # Detect the format, if not stated
53 if datatype is None:
54 if filename.endswith('.x3d'):
55 datatype = 'X3D'
56 elif filename.endswith('.html'):
57 datatype = 'X3DOM'
58 else:
59 raise ValueError("filename must end in '.x3d' or '.html'.")
60
61 # Write the header
3962 w = WriteToFile(filename, 'w')
4063 if datatype == 'X3DOM':
4164 w(0, '<html>')
5982 'xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" '
6083 'xsd:noNamespaceSchemaLocation='
6184 '"http://www.web3d.org/specifications/x3d-3.2.xsd">')
85 else:
86 raise ValueError("datatype not supported: " + str(datatype))
6287
6388 w(3, '<Scene>')
6489
80105 """Creates convenience function to write to a file."""
81106
82107 def __init__(self, filename, mode='w'):
83 self._f = paropen(filename, mode)
108 if isinstance(filename, basestring):
109 self._f = open(filename, mode)
110 else:
111 self._f = filename
84112
85113 def __call__(self, indent, line):
86114 text = ' ' * indent
87 self._f.write(text + line + '\n')
115 print('%s%s\n'%(text,line), file=self._f)
88116
89117 def close(self):
90118 self._f.close()
7979 return visualization_choice
8080
8181
82 def write_xsd(filename, atoms):
82 def write_xsd(filename, atoms, connectivity = None):
8383 """Takes Atoms object, and write materials studio file
8484 atoms: Atoms object
8585 filename: path of the output file
86 connectivity: number of atoms by number of atoms matrix for connectivity between atoms (0 not connected, 1 connected)
8687
8788 note: material studio file cannot use a partial periodic system. If partial
8889 perodic system was inputted, full periodicity was assumed.
300301 Property40.set('DefinedOn', 'SymmetrySystem')
301302 Property40.set('Name', '_Stress')
302303 Property40.set('Type', 'Matrix')
303
304 # Set up bonds
305 bonds = list()
306 if connectivity is not None:
307 for i in range(0,connectivity.shape[0]):
308 for j in range(i+1,connectivity.shape[0]):
309 if connectivity[i,j]:
310 bonds.append([i,j])
311
304312 # non-periodic system
305313 if not atoms.pbc.all():
306314 Molecule = ET.SubElement(AtomisticTreeRootElement, 'Molecule')
307315 Molecule.set('ID', '2')
308 Molecule.set('NumChildren', str(natoms))
316 Molecule.set('NumChildren', str(natoms+len(bonds)))
309317 Molecule.set('Name', 'Lattice=&quot1.0')
310318
311319 # writing atoms
320328 tmpstr += '%1.16f,' % atom_positions[x, y]
321329 NewAtom.set('XYZ', tmpstr[0:-1])
322330 NewAtom.set('Components', atom_element[x])
323
331 tmpstr = ''
332 for ibond in range(0,len(bonds)):
333 if x in bonds[ibond]:
334 tmpstr += '%i,' % (ibond + 3 + natoms)
335 if tmpstr != '':
336 NewAtom.set('Connections', tmpstr[0:-1])
337 for x in range(0, len(bonds)):
338 NewBond = ET.SubElement(Molecule, 'Bond')
339 NewBond.set('ID', str(x + 3 + natoms))
340 tmpstr = '%i,%i'%(bonds[x][0] + 3,bonds[x][1] + 3)
341 NewBond.set('Connects', tmpstr)
324342 # periodic system
325343 else:
326344 atom_positions = np.dot(atom_positions, np.linalg.inv(atom_cell))
328346 SymmSys.set('ID', '2')
329347 SymmSys.set('Mapping', '3')
330348 tmpstr = ''
331 for x in range(4, natoms + 4):
349 for x in range(4, natoms + len(bonds) + 4):
332350 tmpstr += '%1.0f,' % (x)
333 tmpstr += str(natoms + 5)
351 tmpstr += str(natoms + len(bonds) + 4)
334352 SymmSys.set('Children', tmpstr)
335353 SymmSys.set('Normalized', '1')
336354 SymmSys.set('Name', 'SymmSys')
341359 SymmSys.set('PeriodicDisplayType', 'Original')
342360
343361 MappngSet = ET.SubElement(SymmSys, 'MappingSet')
344 MappngSet.set('ID', str(natoms + 4))
345 MappngSet.set('SymmetryDefinition', str(natoms + 5))
362 MappngSet.set('ID', str(natoms + len(bonds) + 5))
363 MappngSet.set('SymmetryDefinition', str(natoms + 4))
346364 MappngSet.set('ActiveSystem', '2')
347365 MappngSet.set('NumFamilies', '1')
348366 MappngSet.set('OwnsTotalConstraintMapping', '1')
349367 MappngSet.set('TotalConstraintMapping', '3')
350368
351369 MappngFamily = ET.SubElement(MappngSet, 'MappingFamily')
352 MappngFamily.set('ID', str(natoms + 6))
370 MappngFamily.set('ID', str(natoms + len(bonds) + 6))
353371 MappngFamily.set('NumImageMappings', '0')
354372
355373 IdentMappng = ET.SubElement(MappngFamily, 'IdentityMapping')
356 IdentMappng.set('ID', str(natoms + 7))
374 IdentMappng.set('ID', str(natoms + len(bonds) + 7))
357375 IdentMappng.set('Element', '1,0,0,0,0,1,0,0,0,0,1,0')
358376 IdentMappng.set('Constraint', '1,0,0,0,0,1,0,0,0,0,1,0')
359377 tmpstr = ''
360 for x in range(4, natoms + 4):
378 for x in range(4, natoms + len(bonds) + 4):
361379 tmpstr += '%1.0f,' % (x)
362380 IdentMappng.set('MappedObjects', tmpstr[0:-1])
363 tmpstr = str(natoms + 5) + ',' + str(natoms + 8)
381 tmpstr = str(natoms + len(bonds) + 4) + ',' + str(natoms + len(bonds) + 8)
364382 IdentMappng.set('DefectObjects', tmpstr)
365 IdentMappng.set('NumImages', str(natoms))
383 IdentMappng.set('NumImages', str(natoms + len(bonds)))
366384 IdentMappng.set('NumDefects', '2')
367385
368386 MappngRepairs = ET.SubElement(MappngFamily, 'MappingRepairs')
372390 for x in range(natoms):
373391 NewAtom = ET.SubElement(IdentMappng, 'Atom3d')
374392 NewAtom.set('ID', str(x + 4))
375 NewAtom.set('Mapping', str(natoms + 7))
393 NewAtom.set('Mapping', str(natoms + len(bonds) + 7))
376394 NewAtom.set('Parent', '2')
377395 NewAtom.set('Name', (atom_element[x] + str(x + 1)))
378396 NewAtom.set('UserID', str(x + 1))
382400 tmpstr += '%1.16f,' % atom_positions[x, y]
383401 NewAtom.set('XYZ', tmpstr[0:-1])
384402 NewAtom.set('Components', atom_element[x])
403 tmpstr = ''
404 for ibond in range(0,len(bonds)):
405 if x in bonds[ibond]:
406 tmpstr += '%i,' % (ibond + 4 + natoms + 1)
407 if tmpstr != '':
408 NewAtom.set('Connections', tmpstr[0:-1])
409 for x in range(0, len(bonds)):
410 NewBond = ET.SubElement(IdentMappng, 'Bond')
411 NewBond.set('ID', str(x + 4 + natoms + 1))
412 NewBond.set('Mapping', str(natoms + len(bonds) + 7))
413 NewBond.set('Parent', '2')
414 tmpstr = '%i,%i'%(bonds[x][0] + 4,bonds[x][1] + 4)
415 NewBond.set('Connects', tmpstr)
385416
386417 SpaceGrp = ET.SubElement(IdentMappng, 'SpaceGroup')
387 SpaceGrp.set('ID', str(natoms + 5))
418 SpaceGrp.set('ID', str(natoms + 4))
388419 SpaceGrp.set('Parent', '2')
389 SpaceGrp.set('Children', str(natoms + 8))
420 SpaceGrp.set('Children', str(natoms + len(bonds) + 8))
390421 SpaceGrp.set('DisplayStyle', 'Solid')
391422 SpaceGrp.set('XYZ', '0.00,0.00,0.00')
392423 SpaceGrp.set('Color', '0,0,0,0')
420451 SpaceGrp.set('Class', '1')
421452
422453 RecLattc = ET.SubElement(IdentMappng, 'ReciprocalLattice3D')
423 RecLattc.set('ID', str(natoms + 8))
424 RecLattc.set('Parent', str(natoms + 5))
454 RecLattc.set('ID', str(natoms + len(bonds) + 8))
455 RecLattc.set('Parent', str(natoms + 4))
425456
426457 InfiniteMappng = ET.SubElement(MappngSet, 'InfiniteMapping')
427458 InfiniteMappng.set('ID', '3')
206206 if symbol.isdigit():
207207 numbers.append(int(symbol))
208208 else:
209 numbers.append(atomic_numbers[symbol])
209 numbers.append(atomic_numbers[symbol.capitalize()])
210210 positions.append([float(x) for x in tokens[1:]])
211211
212212 positions = np.array(positions)
5353 self.pressure = pressure
5454 self.compressibility = compressibility
5555
56 def set_taup(self, taut):
57 self.taut = taut
56 def set_taup(self, taup):
57 self.taup = taup
5858
5959 def get_taup(self):
60 return self.taut
60 return self.taup
6161
6262 def set_pressure(self, pressure):
6363 self.pressure = pressure
133133 n2 = n1 + self.natoms
134134 image.set_positions(positions[n1:n2])
135135 n1 = n2
136
137 # Parallel NEB with Jacapo needs this:
138 try:
139 image.get_calculator().set_atoms(image)
140 except AttributeError:
141 pass
142136
143137 def get_forces(self):
144138 """Evaluate and return the forces."""
309303 # virtual atom count for the optimization algorithm.
310304 return (self.nimages - 2) * self.natoms
311305
312 def _images_(self):
306 def iterimages(self):
313307 # Allows trajectory to convert NEB into several images
314308 assert not self.parallel or self.world.size == 1
315309 # (We could collect the atoms objects on master here!)
455449 self.images[i].set_calculator(
456450 SinglePointCalculator(
457451 image,
458 energy=image.get_potential_energy(),
459 forces=image.get_forces()))
452 energy=image.get_potential_energy(
453 apply_constraint=False),
454 forces=image.get_forces(apply_constraint=False)))
460455 self.emax = min(self.emax, image.get_potential_energy())
461456
462457 if self.first:
630625 d /= (len(images) - 1.0)
631626 for i in range(1, len(images) - 1):
632627 images[i].set_positions(pos1 + i * d)
633 # Parallel NEB with Jacapo needs this:
634 try:
635 images[i].get_calculator().set_atoms(images[i])
636 except AttributeError:
637 pass
638
639628
640629 if __name__ == '__main__':
641630 # This stuff is used by ASE's GUI
11
22 import numpy as np
33
4
5 class NeighborList:
6 """Neighbor list object.
4 from ase.data import atomic_numbers
5 from ase.geometry import complete_cell
6
7
8 def mic(dr, cell, pbc=None):
9 """
10 Apply minimum image convention to an array of distance vectors.
11
12 Parameters
13 ----------
14 dr : array_like
15 Array of distance vectors.
16 cell : array_like
17 Simulation cell.
18 pbc : array_like, optional
19 Periodic boundary conditions in x-, y- and z-direction. Default is to
20 assume periodic boundaries in all directions.
21
22 Returns
23 -------
24 dr : array
25 Array of distance vectors, wrapped according to the minimum image
26 convention.
27 """
28 # Check where distance larger than 1/2 cell. Particles have crossed
29 # periodic boundaries then and need to be unwrapped.
30 icell = np.linalg.pinv(cell)
31 if pbc is not None:
32 icell *= np.array(pbc, dtype=int).reshape(3,1)
33 cell_shift_vectors = np.round(np.dot(dr, icell))
34
35 # Unwrap
36 return dr - np.dot(cell_shift_vectors, cell)
37
38
39 def primitive_neighbor_list(quantities, pbc, cell, positions, cutoff,
40 numbers=None, self_interaction=False,
41 use_scaled_positions=False, max_nbins=1e6):
42 """Compute a neighbor list for an atomic configuration.
43
44 Atoms outside periodic boundaries are mapped into the box. Atoms
45 outside nonperiodic boundaries are included in the neighbor list
46 but complexity of neighbor list search for those can become n^2.
47
48 The neighbor list is sorted by first atom index 'i', but not by second
49 atom index 'j'.
50
51 Parameters:
52
53 quantities: str
54 Quantities to compute by the neighbor list algorithm. Each character
55 in this string defines a quantity. They are returned in a tuple of
56 the same order. Possible quantities are
57
58 * 'i' : first atom index
59 * 'j' : second atom index
60 * 'd' : absolute distance
61 * 'D' : distance vector
62 * 'S' : shift vector (number of cell boundaries crossed by the bond
63 between atom i and j). With the shift vector S, the
64 distances D between atoms can be computed from:
65 D = positions[j]-positions[i]+S.dot(cell)
66 pbc: array_like
67 3-tuple indicating giving periodic boundaries in the three Cartesian
68 directions.
69 cell: 3x3 matrix
70 Unit cell vectors.
71 positions: list of xyz-positions
72 Atomic positions. Anything that can be converted to an ndarray of
73 shape (n, 3) will do: [(x1,y1,z1), (x2,y2,z2), ...]. If
74 use_scaled_positions is set to true, this must be scaled positions.
75 cutoff: float or dict
76 Cutoff for neighbor search. It can be:
77
78 * A single float: This is a global cutoff for all elements.
79 * A dictionary: This specifies cutoff values for element
80 pairs. Specification accepts element numbers of symbols.
81 Example: {(1, 6): 1.1, (1, 1): 1.0, ('C', 'C'): 1.85}
82 * A list/array with a per atom value: This specifies the radius of
83 an atomic sphere for each atoms. If spheres overlap, atoms are
84 within each others neighborhood.
85 self_interaction: bool
86 Return the atom itself as its own neighbor if set to true.
87 Default: False
88 use_scaled_positions: bool
89 If set to true, positions are expected to be scaled positions.
90 max_nbins: int
91 Maximum number of bins used in neighbor search. This is used to limit
92 the maximum amount of memory required by the neighbor list.
93
94 Returns:
95
96 i, j, ... : array
97 Tuple with arrays for each quantity specified above. Indices in `i`
98 are returned in ascending order 0..len(a)-1, but the order of (i,j)
99 pairs is not guaranteed.
100
101 """
102
103 # Naming conventions: Suffixes indicate the dimension of an array. The
104 # following convention is used here:
105 # c: Cartesian index, can have values 0, 1, 2
106 # i: Global atom index, can have values 0..len(a)-1
107 # xyz: Bin index, three values identifying x-, y- and z-component of a
108 # spatial bin that is used to make neighbor search O(n)
109 # b: Linearized version of the 'xyz' bin index
110 # a: Bin-local atom index, i.e. index identifying an atom *within* a bin
111 # p: Pair index, can have value 0 or 1
112 # n: (Linear) neighbor index
113
114 # Return empty neighbor list if no atoms are passed here
115 if len(positions) == 0:
116 retvals = []
117 for i in quantities:
118 retvals += [np.array([])]
119 return retvals
120
121 # Compute reciprocal lattice vectors.
122 b1_c, b2_c, b3_c = np.linalg.pinv(cell).T
123
124 # Compute distances of cell faces.
125 l1 = np.linalg.norm(b1_c)
126 l2 = np.linalg.norm(b2_c)
127 l3 = np.linalg.norm(b3_c)
128 face_dist_c = np.array([1 / l1 if l1 > 0 else 1,
129 1 / l2 if l2 > 0 else 1,
130 1 / l3 if l3 > 0 else 1])
131
132 if isinstance(cutoff, dict):
133 max_cutoff = max(cutoff.values())
134 else:
135 if np.isscalar(cutoff):
136 max_cutoff = cutoff
137 else:
138 cutoff = np.asarray(cutoff)
139 max_cutoff = 2*np.max(cutoff)
140
141 # We use a minimum bin size of 3 A
142 bin_size = max(max_cutoff, 3)
143 # Compute number of bins such that a sphere of radius cutoff fit into eight
144 # neighboring bins.
145 nbins_c = np.maximum((face_dist_c / bin_size).astype(int), [1, 1, 1])
146 nbins = np.prod(nbins_c)
147 # Make sure we limit the amount of memory used by the explicit bins.
148 while nbins > max_nbins:
149 nbins_c = np.maximum(nbins_c // 2, [1, 1, 1])
150 nbins = np.prod(nbins_c)
151
152 # Compute over how many bins we need to loop in the neighbor list search.
153 neigh_search_x, neigh_search_y, neigh_search_z = \
154 np.ceil(bin_size * nbins_c / face_dist_c).astype(int)
155
156 # Sort atoms into bins.
157 if use_scaled_positions:
158 scaled_positions_ic = positions
159 positions = np.dot(scaled_positions_ic, cell)
160 else:
161 scaled_positions_ic = np.linalg.solve(complete_cell(cell).T,
162 positions.T).T
163 bin_index_ic = np.floor(scaled_positions_ic*nbins_c).astype(int)
164 cell_shift_ic = np.zeros_like(bin_index_ic)
165 for c in range(3):
166 if pbc[c]:
167 cell_shift_ic[:, c], bin_index_ic[:, c] = \
168 np.divmod(bin_index_ic[:, c], nbins_c[c])
169 else:
170 bin_index_ic[:, c] = np.clip(bin_index_ic[:, c], 0, nbins_c[c]-1)
171
172 # Convert Cartesian bin index to unique scalar bin index.
173 bin_index_i = bin_index_ic[:, 0] + \
174 nbins_c[0] * (bin_index_ic[:, 1] + \
175 nbins_c[1] * bin_index_ic[:, 2])
176
177 # atom_i contains atom index in new sort order.
178 atom_i = np.argsort(bin_index_i)
179 bin_index_i = bin_index_i[atom_i]
180
181 # Find max number of atoms per bin
182 max_natoms_per_bin = np.bincount(bin_index_i).max()
183
184 # Sort atoms into bins: atoms_in_bin_ba contains for each bin (identified
185 # by its scalar bin index) a list of atoms inside that bin. This list is
186 # homogeneous, i.e. has the same size *max_natoms_per_bin* for all bins.
187 # The list is padded with -1 values.
188 atoms_in_bin_ba = -np.ones([nbins, max_natoms_per_bin], dtype=int)
189 for i in range(max_natoms_per_bin):
190 # Create a mask array that identifies the first atom of each bin.
191 mask = np.append([True], bin_index_i[:-1] != bin_index_i[1:])
192 # Assign all first atoms.
193 atoms_in_bin_ba[bin_index_i[mask], i] = atom_i[mask]
194
195 # Remove atoms that we just sorted into atoms_in_bin_ba. The next
196 # "first" atom will be the second and so on.
197 mask = np.logical_not(mask)
198 atom_i = atom_i[mask]
199 bin_index_i = bin_index_i[mask]
200
201 # Make sure that all atoms have been sorted into bins.
202 assert len(atom_i) == 0
203 assert len(bin_index_i) == 0
204
205 # Now we construct neighbor pairs by pairing up all atoms within a bin or
206 # between bin and neighboring bin. atom_pairs_pn is a helper buffer that
207 # contains all potential pairs of atoms between two bins, i.e. it is a list
208 # of length max_natoms_per_bin**2.
209 atom_pairs_pn = np.indices((max_natoms_per_bin, max_natoms_per_bin),
210 dtype=int)
211 atom_pairs_pn = atom_pairs_pn.reshape(2, -1)
212
213 # Initialized empty neighbor list buffers.
214 first_at_neightuple_nn = []
215 secnd_at_neightuple_nn = []
216 cell_shift_vector_x_n = []
217 cell_shift_vector_y_n = []
218 cell_shift_vector_z_n = []
219
220 # This is the main neighbor list search. We loop over neighboring bins and
221 # then construct all possible pairs of atoms between two bins, assuming
222 # that each bin contains exactly max_natoms_per_bin atoms. We then throw
223 # out pairs involving pad atoms with atom index -1 below.
224 binz_xyz, biny_xyz, binx_xyz = np.meshgrid(np.arange(nbins_c[2]),
225 np.arange(nbins_c[1]),
226 np.arange(nbins_c[0]),
227 indexing='ij')
228 # The memory layout of binx_xyz, biny_xyz, binz_xyz is such that computing
229 # the respective bin index leads to a linearly increasing consecutive list.
230 # The following assert statement succeeds:
231 # b_b = (binx_xyz + nbins_c[0] * (biny_xyz + nbins_c[1] * binz_xyz)).ravel()
232 # assert (b_b == np.arange(np.prod(nbins_c))).all()
233
234 # First atoms in pair.
235 _first_at_neightuple_n = atoms_in_bin_ba[:, atom_pairs_pn[0]]
236 for dz in range(-neigh_search_z, neigh_search_z+1):
237 for dy in range(-neigh_search_y, neigh_search_y+1):
238 for dx in range(-neigh_search_x, neigh_search_x+1):
239 # Bin index of neighboring bin and shift vector.
240 shiftx_xyz, neighbinx_xyz = np.divmod(binx_xyz + dx, nbins_c[0])
241 shifty_xyz, neighbiny_xyz = np.divmod(biny_xyz + dy, nbins_c[1])
242 shiftz_xyz, neighbinz_xyz = np.divmod(binz_xyz + dz, nbins_c[2])
243 neighbin_b = (neighbinx_xyz + nbins_c[0] *
244 (neighbiny_xyz + nbins_c[1] * neighbinz_xyz)).ravel()
245
246 # Second atom in pair.
247 _secnd_at_neightuple_n = \
248 atoms_in_bin_ba[neighbin_b][:, atom_pairs_pn[1]]
249
250 # Shift vectors.
251 _cell_shift_vector_x_n = \
252 np.resize(shiftx_xyz.reshape(-1, 1),
253 (max_natoms_per_bin**2, shiftx_xyz.size)).T
254 _cell_shift_vector_y_n = \
255 np.resize(shifty_xyz.reshape(-1, 1),
256 (max_natoms_per_bin**2, shifty_xyz.size)).T
257 _cell_shift_vector_z_n = \
258 np.resize(shiftz_xyz.reshape(-1, 1),
259 (max_natoms_per_bin**2, shiftz_xyz.size)).T
260
261 # We have created too many pairs because we assumed each bin
262 # has exactly max_natoms_per_bin atoms. Remove all surperfluous
263 # pairs. Those are pairs that involve an atom with index -1.
264 mask = np.logical_and(_first_at_neightuple_n != -1,
265 _secnd_at_neightuple_n != -1)
266 if mask.sum() > 0:
267 first_at_neightuple_nn += [_first_at_neightuple_n[mask]]
268 secnd_at_neightuple_nn += [_secnd_at_neightuple_n[mask]]
269 cell_shift_vector_x_n += [_cell_shift_vector_x_n[mask]]
270 cell_shift_vector_y_n += [_cell_shift_vector_y_n[mask]]
271 cell_shift_vector_z_n += [_cell_shift_vector_z_n[mask]]
272
273 # Flatten overall neighbor list.
274 first_at_neightuple_n = np.concatenate(first_at_neightuple_nn)
275 secnd_at_neightuple_n = np.concatenate(secnd_at_neightuple_nn)
276 cell_shift_vector_n = np.transpose([np.concatenate(cell_shift_vector_x_n),
277 np.concatenate(cell_shift_vector_y_n),
278 np.concatenate(cell_shift_vector_z_n)])
279
280 # Add global cell shift to shift vectors
281 cell_shift_vector_n += cell_shift_ic[first_at_neightuple_n] - \
282 cell_shift_ic[secnd_at_neightuple_n]
283
284 # Remove all self-pairs that do not cross the cell boundary.
285 if not self_interaction:
286 m = np.logical_not(np.logical_and(
287 first_at_neightuple_n == secnd_at_neightuple_n,
288 (cell_shift_vector_n == 0).all(axis=1)))
289 first_at_neightuple_n = first_at_neightuple_n[m]
290 secnd_at_neightuple_n = secnd_at_neightuple_n[m]
291 cell_shift_vector_n = cell_shift_vector_n[m]
292
293 # For nonperiodic directions, remove any bonds that cross the domain
294 # boundary.
295 for c in range(3):
296 if not pbc[c]:
297 m = cell_shift_vector_n[:, c] == 0
298 first_at_neightuple_n = first_at_neightuple_n[m]
299 secnd_at_neightuple_n = secnd_at_neightuple_n[m]
300 cell_shift_vector_n = cell_shift_vector_n[m]
301
302 # Sort neighbor list.
303 i = np.argsort(first_at_neightuple_n)
304 first_at_neightuple_n = first_at_neightuple_n[i]
305 secnd_at_neightuple_n = secnd_at_neightuple_n[i]
306 cell_shift_vector_n = cell_shift_vector_n[i]
307
308 # Compute distance vectors.
309 distance_vector_nc = positions[secnd_at_neightuple_n] - \
310 positions[first_at_neightuple_n] + \
311 cell_shift_vector_n.dot(cell)
312 abs_distance_vector_n = \
313 np.sqrt(np.sum(distance_vector_nc*distance_vector_nc, axis=1))
314
315 # We have still created too many pairs. Only keep those with distance
316 # smaller than max_cutoff.
317 mask = abs_distance_vector_n < max_cutoff
318 first_at_neightuple_n = first_at_neightuple_n[mask]
319 secnd_at_neightuple_n = secnd_at_neightuple_n[mask]
320 cell_shift_vector_n = cell_shift_vector_n[mask]
321 distance_vector_nc = distance_vector_nc[mask]
322 abs_distance_vector_n = abs_distance_vector_n[mask]
323
324 if isinstance(cutoff, dict) and numbers is not None:
325 # If cutoff is a dictionary, then the cutoff radii are specified per
326 # element pair. We now have a list up to maximum cutoff.
327 per_pair_cutoff_n = np.zeros_like(abs_distance_vector_n)
328 for (atomic_number1, atomic_number2), c in cutoff.items():
329 try:
330 atomic_number1 = atomic_numbers[atomic_number1]
331 except KeyError:
332 pass
333 try:
334 atomic_number2 = atomic_numbers[atomic_number2]
335 except KeyError:
336 pass
337 if atomic_number1 == atomic_number2:
338 mask = np.logical_and(
339 numbers[first_at_neightuple_n] == atomic_number1,
340 numbers[secnd_at_neightuple_n] == atomic_number2)
341 else:
342 mask = np.logical_or(
343 np.logical_and(
344 numbers[first_at_neightuple_n] == atomic_number1,
345 numbers[secnd_at_neightuple_n] == atomic_number2),
346 np.logical_and(
347 numbers[first_at_neightuple_n] == atomic_number2,
348 numbers[secnd_at_neightuple_n] == atomic_number1))
349 per_pair_cutoff_n[mask] = c
350 mask = abs_distance_vector_n < per_pair_cutoff_n
351 first_at_neightuple_n = first_at_neightuple_n[mask]
352 secnd_at_neightuple_n = secnd_at_neightuple_n[mask]
353 cell_shift_vector_n = cell_shift_vector_n[mask]
354 distance_vector_nc = distance_vector_nc[mask]
355 abs_distance_vector_n = abs_distance_vector_n[mask]
356 elif not np.isscalar(cutoff):
357 # If cutoff is neither a dictionary nor a scalar, then we assume it is
358 # a list or numpy array that contains atomic radii. Atoms are neighbors
359 # if their radii overlap.
360 mask = abs_distance_vector_n < \
361 cutoff[first_at_neightuple_n] + cutoff[secnd_at_neightuple_n]
362 first_at_neightuple_n = first_at_neightuple_n[mask]
363 secnd_at_neightuple_n = secnd_at_neightuple_n[mask]
364 cell_shift_vector_n = cell_shift_vector_n[mask]
365 distance_vector_nc = distance_vector_nc[mask]
366 abs_distance_vector_n = abs_distance_vector_n[mask]
367
368 # Assemble return tuple.
369 retvals = []
370 for q in quantities:
371 if q == 'i':
372 retvals += [first_at_neightuple_n]
373 elif q == 'j':
374 retvals += [secnd_at_neightuple_n]
375 elif q == 'D':
376 retvals += [distance_vector_nc]
377 elif q == 'd':
378 retvals += [abs_distance_vector_n]
379 elif q == 'S':
380 retvals += [cell_shift_vector_n]
381 else:
382 raise ValueError('Unsupported quantity specified.')
383 if len(retvals) == 1:
384 return retvals[0]
385 else:
386 return tuple(retvals)
387
388
389 def neighbor_list(quantities, a, cutoff, self_interaction=False, max_nbins=1e6):
390 """Compute a neighbor list for an atomic configuration.
391
392 Atoms outside periodic boundaries are mapped into the box. Atoms
393 outside nonperiodic boundaries are included in the neighbor list
394 but complexity of neighbor list search for those can become n^2.
395
396 The neighbor list is sorted by first atom index 'i', but not by second
397 atom index 'j'.
398
399 Parameters:
400
401 quantities: str
402 Quantities to compute by the neighbor list algorithm. Each character
403 in this string defines a quantity. They are returned in a tuple of
404 the same order. Possible quantities are:
405
406 * 'i' : first atom index
407 * 'j' : second atom index
408 * 'd' : absolute distance
409 * 'D' : distance vector
410 * 'S' : shift vector (number of cell boundaries crossed by the bond
411 between atom i and j). With the shift vector S, the
412 distances D between atoms can be computed from:
413 D = a.positions[j]-a.positions[i]+S.dot(a.cell)
414 a: ase.Atoms
415 Atomic configuration.
416 cutoff: float or dict
417 Cutoff for neighbor search. It can be:
418
419 * A single float: This is a global cutoff for all elements.
420 * A dictionary: This specifies cutoff values for element
421 pairs. Specification accepts element numbers of symbols.
422 Example: {(1, 6): 1.1, (1, 1): 1.0, ('C', 'C'): 1.85}
423 * A list/array with a per atom value: This specifies the radius of
424 an atomic sphere for each atoms. If spheres overlap, atoms are
425 within each others neighborhood.
426
427 self_interaction: bool
428 Return the atom itself as its own neighbor if set to true.
429 Default: False
430 max_nbins: int
431 Maximum number of bins used in neighbor search. This is used to limit
432 the maximum amount of memory required by the neighbor list.
433
434 Returns:
435
436 i, j, ...: array
437 Tuple with arrays for each quantity specified above. Indices in `i`
438 are returned in ascending order 0..len(a), but the order of (i,j)
439 pairs is not guaranteed.
440
441 Examples:
442
443 Examples assume Atoms object *a* and numpy imported as *np*.
444
445 1. Coordination counting::
446
447 i = neighbor_list('i', a, 1.85)
448 coord = np.bincount(i)
449
450 2. Coordination counting with different cutoffs for each pair of species::
451
452 i = neighbor_list('i', a,
453 {('H', 'H'): 1.1, ('C', 'H'): 1.3, ('C', 'C'): 1.85})
454 coord = np.bincount(i)
455
456 3. Pair distribution function::
457
458 d = neighbor_list('d', a, 10.00)
459 h, bin_edges = np.histogram(d, bins=100)
460 pdf = h/(4*np.pi/3*(bin_edges[1:]**3 - bin_edges[:-1]**3)) * a.get_volume()/len(a)
461
462 4. Pair potential::
463
464 i, j, d, D = neighbor_list('ijdD', a, 5.0)
465 energy = (-C/d**6).sum()
466 pair_forces = (6*C/d**5 * (D/d).T).T
467 forces_x = np.bincount(j, weights=pair_forces[:, 0], minlength=len(a)) - \
468 np.bincount(i, weights=pair_forces[:, 0], minlength=len(a))
469 forces_y = np.bincount(j, weights=pair_forces[:, 1], minlength=len(a)) - \
470 np.bincount(i, weights=pair_forces[:, 1], minlength=len(a))
471 forces_z = np.bincount(j, weights=pair_forces[:, 2], minlength=len(a)) - \
472 np.bincount(i, weights=pair_forces[:, 2], minlength=len(a))
473
474 5. Dynamical matrix for a pair potential stored in a block sparse format::
475
476 from scipy.sparse import bsr_matrix
477 i, j, dr, abs_dr = neighbor_list('ijDd', atoms)
478 energy = (dr.T / abs_dr).T
479 dynmat = -(dde * (energy.reshape(-1, 3, 1) * energy.reshape(-1, 1, 3)).T).T \
480 -(de / abs_dr * (np.eye(3, dtype=energy.dtype) - \
481 (energy.reshape(-1, 3, 1) * energy.reshape(-1, 1, 3))).T).T
482 dynmat_bsr = bsr_matrix((dynmat, j, first_i), shape=(3*len(a), 3*len(a)))
483
484 dynmat_diag = np.empty((len(a), 3, 3))
485 for x in range(3):
486 for y in range(3):
487 dynmat_diag[:, x, y] = -np.bincount(i, weights=dynmat[:, x, y])
488
489 dynmat_bsr += bsr_matrix((dynmat_diag, np.arange(len(a)),
490 np.arange(len(a) + 1)),
491 shape=(3 * len(a), 3 * len(a)))
492
493 """
494 return primitive_neighbor_list(quantities, a.pbc, a.get_cell(complete=True),
495 a.positions, cutoff, numbers=a.numbers,
496 self_interaction=self_interaction,
497 max_nbins=max_nbins)
498
499 def first_neighbors(natoms, first_atom):
500 """
501 Compute an index array pointing to the ranges within the neighbor list that
502 contain the neighbors for a certain atom.
503
504 Parameters
505 ----------
506 natoms : int
507 Total number of atom.
508 first_atom : array_like
509 Array containing the first atom 'i' of the neighbor tuple returned
510 by the neighbor list.
511
512 Returns
513 -------
514 seed : array
515 Array containing pointers to the start and end location of the neighbors
516 of a certain atom. Neighbors of atom k have indices from s[k] to
517 s[k+1]-1.
518 """
519 if len(first_atom) == 0:
520 return np.zeros(natoms+1, dtype=int)
521 # Create a seed array (which is returned by this function) populated with
522 # -1.
523 seed = -np.ones(natoms+1, dtype=int)
524
525 first_atom = np.asarray(first_atom)
526
527 # Mask array contains all position where the number in the (sorted) array
528 # with first atoms (in the neighbor pair) changes.
529 mask = first_atom[:-1] != first_atom[1:]
530
531 # Seed array needs to start at 0
532 seed[first_atom[0]] = 0
533 # Seed array needs to stop at the length of the neighbor list
534 seed[-1] = len(first_atom)
535 # Populate all intermediate seed with the index of where the mask array is
536 # true, i.e. the index where the first_atom array changes.
537 seed[first_atom[1:][mask]] = (np.arange(len(mask))+1)[mask]
538
539 # Now fill all remaining -1 value with the value in the seed array right
540 # behind them. (There are no neighbor so seed[i] and seed[i+1] must point)
541 # to the same index.
542 mask = seed == -1
543 while mask.any():
544 seed[mask] = seed[np.arange(natoms+1)[mask]+1]
545 mask = seed == -1
546 return seed
547
548
549 class NewPrimitiveNeighborList:
550 """Neighbor list object. Wrapper around neighbor_list and first_neighbors.
7551
8552 cutoffs: list of float
9553 List of cutoff radii - one for each atom. If the spheres (defined by
15559 can be reused. This will save some expensive rebuilds of
16560 the list, but extra neighbors outside the cutoff will be
17561 returned.
562 sorted: bool
563 Sort neighbor list.
18564 self_interaction: bool
19565 Should an atom return itself as a neighbor?
20566 bothways: bool
26572 nl = NeighborList([2.3, 1.7])
27573 nl.update(atoms)
28574 indices, offsets = nl.get_neighbors(0)
29
30575 """
31576
32577 def __init__(self, cutoffs, skin=0.3, sorted=False, self_interaction=True,
33 bothways=False):
578 bothways=False, use_scaled_positions=False):
34579 self.cutoffs = np.asarray(cutoffs) + skin
35580 self.skin = skin
36581 self.sorted = sorted
37582 self.self_interaction = self_interaction
38583 self.bothways = bothways
39584 self.nupdates = 0
40
41 def update(self, atoms):
585 self.use_scaled_positions = use_scaled_positions
586 self.nneighbors = 0
587 self.npbcneighbors = 0
588
589 def update(self, pbc, cell, positions, numbers=None):
42590 """Make sure the list is up to date."""
591
43592 if self.nupdates == 0:
44 self.build(atoms)
593 self.build(pbc, cell, positions, numbers=numbers)
45594 return True
46595
47 if ((self.pbc != atoms.get_pbc()).any() or
48 (self.cell != atoms.get_cell()).any() or
49 ((self.positions - atoms.get_positions())**2).sum(1).max() >
596 if ((self.pbc != pbc).any() or
597 (self.cell != cell).any() or
598 ((self.positions - positions)**2).sum(1).max() >
50599 self.skin**2):
51 self.build(atoms)
600 self.build(pbc, cell, positions, numbers=numbers)
52601 return True
53602
54603 return False
55604
56 def build(self, atoms):
57 """Build the list."""
58 self.positions = atoms.get_positions()
59 self.pbc = atoms.get_pbc()
60 self.cell = atoms.get_cell()
61
62 if len(self.cutoffs) != len(atoms):
605 def build(self, pbc, cell, positions, numbers=None):
606 """Build the list.
607 """
608 self.pbc = np.array(pbc, copy=True)
609 self.cell = np.array(cell, copy=True)
610 self.positions = np.array(positions, copy=True)
611
612 self.pair_first, self.pair_second, self.offset_vec = \
613 primitive_neighbor_list(
614 'ijS', pbc, cell, positions, self.cutoffs, numbers=numbers,
615 self_interaction=self.self_interaction,
616 use_scaled_positions=self.use_scaled_positions)
617
618 if len(positions) > 0 and not self.bothways:
619 mask = np.logical_or(
620 np.logical_and(self.pair_first <= self.pair_second,
621 (self.offset_vec == 0).all(axis=1)),
622 np.logical_or(self.offset_vec[:, 0] > 0,
623 np.logical_and(self.offset_vec[:, 0] == 0,
624 np.logical_or(self.offset_vec[:, 1] > 0,
625 np.logical_and(self.offset_vec[:, 1] == 0,
626 self.offset_vec[:, 2] > 0)))))
627 self.pair_first = self.pair_first[mask]
628 self.pair_second = self.pair_second[mask]
629 self.offset_vec = self.offset_vec[mask]
630
631 if len(positions) > 0 and self.sorted:
632 mask = np.argsort(self.pair_first * len(self.pair_first) +
633 self.pair_second)
634 self.pair_first = self.pair_first[mask]
635 self.pair_second = self.pair_second[mask]
636 self.offset_vec = self.offset_vec[mask]
637
638 # Compute the index array point to the first neighbor
639 self.first_neigh = first_neighbors(len(positions), self.pair_first)
640
641 self.nupdates += 1
642
643 def get_neighbors(self, a):
644 """Return neighbors of atom number a.
645
646 A list of indices and offsets to neighboring atoms is
647 returned. The positions of the neighbor atoms can be
648 calculated like this:
649
650 indices, offsets = nl.get_neighbors(42)
651 for i, offset in zip(indices, offsets):
652 print(atoms.positions[i] + dot(offset, atoms.get_cell()))
653
654 Notice that if get_neighbors(a) gives atom b as a neighbor,
655 then get_neighbors(b) will not return a as a neighbor - unless
656 bothways=True was used."""
657
658 return (self.pair_second[self.first_neigh[a]:self.first_neigh[a+1]],
659 self.offset_vec[self.first_neigh[a]:self.first_neigh[a+1]])
660
661
662 class PrimitiveNeighborList:
663 """Neighbor list that works without Atoms objects.
664
665 This is less fancy, but can be used to avoid conversions between
666 scaled and non-scaled coordinates which may affect cell offsets
667 through rounding errors.
668 """
669 def __init__(self, cutoffs, skin=0.3, sorted=False, self_interaction=True,
670 bothways=False, use_scaled_positions=False):
671 self.cutoffs = np.asarray(cutoffs) + skin
672 self.skin = skin
673 self.sorted = sorted
674 self.self_interaction = self_interaction
675 self.bothways = bothways
676 self.nupdates = 0
677 self.use_scaled_positions = use_scaled_positions
678 self.nneighbors = 0
679 self.npbcneighbors = 0
680
681 def update(self, pbc, cell, coordinates):
682 """Make sure the list is up to date."""
683
684 if self.nupdates == 0:
685 self.build(pbc, cell, coordinates)
686 return True
687
688 if ((self.pbc != pbc).any() or
689 (self.cell != cell).any() or
690 ((self.coordinates - coordinates)**2).sum(1).max() >
691 self.skin**2):
692 self.build(pbc, cell, coordinates)
693 return True
694
695 return False
696
697 def build(self, pbc, cell, coordinates):
698 """Build the list.
699
700 Coordinates are taken to be scaled or not according
701 to self.use_scaled_positions.
702 """
703 self.pbc = pbc = np.array(pbc, copy=True)
704 self.cell = cell = np.array(cell, copy=True)
705 self.coordinates = coordinates = np.array(coordinates, copy=True)
706
707 if len(self.cutoffs) != len(coordinates):
63708 raise ValueError('Wrong number of cutoff radii: {0} != {1}'
64 .format(len(self.cutoffs), len(atoms)))
709 .format(len(self.cutoffs), len(coordinates)))
65710
66711 if len(self.cutoffs) > 0:
67712 rcmax = self.cutoffs.max()
68713 else:
69714 rcmax = 0.0
70715
71 icell = np.linalg.pinv(self.cell)
72 scaled = np.dot(self.positions, icell)
716 icell = np.linalg.pinv(cell)
717
718 if self.use_scaled_positions:
719 scaled = coordinates
720 positions = np.dot(scaled, cell)
721 else:
722 positions = coordinates
723 scaled = np.dot(positions, icell)
724
73725 scaled0 = scaled.copy()
74726
75727 N = []
84736 N.append(n)
85737
86738 offsets = (scaled0 - scaled).round().astype(int)
87 positions0 = atoms.positions + np.dot(offsets, self.cell)
88 natoms = len(atoms)
739 positions0 = positions + np.dot(offsets, self.cell)
740 natoms = len(positions)
89741 indices = np.arange(natoms)
90742
91743 self.nneighbors = 0
165817 bothways=True was used."""
166818
167819 return self.neighbors[a], self.displacements[a]
820
821
822 class NeighborList:
823 """Neighbor list object.
824
825 cutoffs: list of float
826 List of cutoff radii - one for each atom. If the spheres (defined by
827 their cutoff radii) of two atoms overlap, they will be counted as
828 neighbors.
829 skin: float
830 If no atom has moved more than the skin-distance since the
831 last call to the ``update()`` method, then the neighbor list
832 can be reused. This will save some expensive rebuilds of
833 the list, but extra neighbors outside the cutoff will be
834 returned.
835 self_interaction: bool
836 Should an atom return itself as a neighbor?
837 bothways: bool
838 Return all neighbors. Default is to return only "half" of
839 the neighbors.
840
841 Example::
842
843 nl = NeighborList([2.3, 1.7])
844 nl.update(atoms)
845 indices, offsets = nl.get_neighbors(0)
846 """
847
848 def __init__(self, cutoffs, skin=0.3, sorted=False, self_interaction=True,
849 bothways=False, primitive=PrimitiveNeighborList):
850 self.nl = primitive(cutoffs, skin, sorted,
851 self_interaction=self_interaction,
852 bothways=bothways)
853
854 def update(self, atoms):
855 return self.nl.update(atoms.pbc, atoms.get_cell(complete=True),
856 atoms.positions)
857
858 def get_neighbors(self, a):
859 return self.nl.get_neighbors(a)
860
861 @property
862 def nupdates(self):
863 return self.nl.nupdates
864
865 @property
866 def nneighbors(self):
867 return self.nl.nneighbors
868
869 @property
870 def npbcneighbors(self):
871 return self.nl.npbcneighbors
119119 r = atoms.get_positions()
120120 atoms.set_positions(r + dr)
121121 self.dump((self.v, self.dt))
122
2626 """
2727
2828 from __future__ import print_function
29 import logging
30 logger = logging.getLogger(__name__)
3129
3230 from ase.optimize.precon.precon import Precon, Exp, C1, Pfrommer, FF, Exp_FF
3331 from ase.optimize.precon.lbfgs import PreconLBFGS
11
22 from ase.optimize.optimize import Optimizer
33 from ase.constraints import UnitCellFilter
4
4 import time
55
66 class PreconFIRE(Optimizer):
77
6060 def initialize(self):
6161 self.v = None
6262 self.skip_flag = False
63 self.e1 = None
6364
6465 def read(self):
6566 self.v, self.dt = self.load()
8687 r_test = r + self.dt * v_test
8788
8889 self.skip_flag = False
89 if (self.func(r_test) > self.func(r) -
90 self.theta * self.dt * np.vdot(v_test, f)):
90 func_val = self.func(r_test)
91 self.e1 = func_val
92 if (func_val > self.func(r) -
93 self.theta * self.dt * np.vdot(v_test, f)):
9194 self.v[:] *= 0.0
9295 self.a = self.astart
9396 self.dt *= self.fdec
136139 self.atoms.set_positions(x.reshape(-1, 3))
137140 potl = self.atoms.get_potential_energy()
138141 return potl
142
143 def run(self, fmax=0.05, steps=100000000, smax=None):
144 if smax is None:
145 smax = fmax
146 self.smax = smax
147 return Optimizer.run(self, fmax, steps)
148
149 def converged(self, forces=None):
150 """Did the optimization converge?"""
151 if forces is None:
152 forces = self.atoms.get_forces()
153 if isinstance(self.atoms, UnitCellFilter):
154 natoms = len(self.atoms.atoms)
155 forces, stress = forces[:natoms], self.atoms.stress
156 fmax_sq = (forces**2).sum(axis=1).max()
157 smax_sq = (stress**2).max()
158 return (fmax_sq < self.fmax**2 and smax_sq < self.smax**2)
159 else:
160 fmax_sq = (forces**2).sum(axis=1).max()
161 return fmax_sq < self.fmax**2
162
163 def log(self, forces):
164 if isinstance(self.atoms, UnitCellFilter):
165 natoms = len(self.atoms.atoms)
166 forces, stress = forces[:natoms], self.atoms.stress
167 fmax = np.sqrt((forces**2).sum(axis=1).max())
168 smax = np.sqrt((stress**2).max())
169 else:
170 fmax = np.sqrt((forces**2).sum(axis=1).max())
171 if self.e1 is not None:
172 # reuse energy at end of line search to avoid extra call
173 e = self.e1
174 else:
175 e = self.atoms.get_potential_energy()
176 T = time.localtime()
177 if self.logfile is not None:
178 name = self.__class__.__name__
179 if isinstance(self.atoms, UnitCellFilter):
180 self.logfile.write(
181 '%s: %3d %02d:%02d:%02d %15.6f %12.4f %12.4f\n' %
182 (name, self.nsteps, T[3], T[4], T[5], e, fmax, smax))
183
184 else:
185 self.logfile.write(
186 '%s: %3d %02d:%02d:%02d %15.6f %12.4f\n' %
187 (name, self.nsteps, T[3], T[4], T[5], e, fmax))
188 self.logfile.flush()
0 # @Author: James Kermode <jameskermode>
1 # @Date: 2016-09-15T09:37:09+01:00
2 # @Email: james.kermode@gmail.com
3 # @Project: f90wrap
4 # @Last modified by: jameskermode
5 # @Last modified time: 2016-09-15T11:07:36+01:00
6 # @License: f90wrap - F90 to Python interface generator with derived type
7 # support
8
9
100 import time
1 import warnings
112
123 from math import sqrt
134 import numpy as np
156 from ase.utils import basestring
167 from ase.optimize.optimize import Optimizer
178 from ase.constraints import UnitCellFilter
18 from ase.optimize.precon import C1, Exp, Pfrommer, logger
199
2010 from ase.utils.linesearch import LineSearch
2111 from ase.utils.linesearcharmijo import LineSearchArmijo
2212
13 from ase.optimize.precon import Exp, C1, Pfrommer
2314
2415 class PreconLBFGS(Optimizer):
2516 """Preconditioned version of the Limited memory BFGS optimizer.
4233 # CO : added parameters rigid_units and rotation_factors
4334 def __init__(self, atoms, restart=None, logfile='-', trajectory=None,
4435 maxstep=None, memory=100, damping=1.0, alpha=70.0,
45 master=None, precon='Exp',
46 use_armijo=True, c1=0.23, c2=0.46, variable_cell=False,
36 master=None, precon='Exp', variable_cell=False,
37 use_armijo=True, c1=0.23, c2=0.46, a_min=None,
4738 rigid_units=None, rotation_factors=None, Hinv=None):
4839 """Parameters:
4940
10394
10495 c2: float
10596 c2 parameter for the line search. Default is c2=0.46.
97
98 a_min: float
99 minimal value for the line search step parameter. Default is
100 a_min=1e-8 (use_armijo=False) or 1e-10 (use_armijo=True).
101 Higher values can be useful to avoid performing many
102 line searches for comparatively small changes in geometry.
106103
107104 variable_cell: bool
108105 If True, wrap atoms an ase.constraints.UnitCellFilter to
154151 self.use_armijo = use_armijo
155152 self.c1 = c1
156153 self.c2 = c2
154 self.a_min = a_min
155 if self.a_min is None:
156 self.a_min = 1e-10 if use_armijo else 1e-8
157157
158158 # CO
159159 self.rigid_units = rigid_units
313313 # out using some extrapolation tricks?
314314 ls = LineSearchArmijo(self.func, c1=self.c1, tol=1e-14)
315315 step, func_val, no_update = ls.run(
316 r, self.p, func_start=e,
316 r, self.p, a_min=self.a_min,
317 func_start=e,
317318 func_prime_start=g,
318319 func_old=self.e0,
319320 rigid_units=self.rigid_units,
320 rotation_factors=self.rotation_factors)
321 rotation_factors=self.rotation_factors,
322 maxstep=self.maxstep)
321323 self.e0 = e
322324 self.e1 = func_val
323325 self.alpha_k = step
324326 except (ValueError, RuntimeError):
325327 if not previously_reset_hessian:
326 logger.warning(
328 warnings.warn(
327329 'Armijo linesearch failed, resetting Hessian and '
328330 'trying again')
329331 self.reset_hessian()
330332 self.alpha_k = 0.0
331333 else:
332 logger.error(
334 raise RuntimeError(
333335 'Armijo linesearch failed after reset of Hessian, '
334336 'aborting')
335 raise
336337
337338 else:
338339 ls = LineSearch()
339340 self.alpha_k, e, self.e0, self.no_update = \
340341 ls._line_search(self.func, self.fprime, r, self.p, g,
341 e, self.e0,
342 e, self.e0, stpmin=self.a_min,
342343 maxstep=self.maxstep, c1=self.c1,
343344 c2=self.c2, stpmax=50.)
344345 self.e1 = e
0 import time
0 #import time
11
22 import numpy as np
33
44 from ase.constraints import Filter, FixAtoms
55 from ase.geometry.cell import cell_to_cellpar
6
7 from ase.optimize.precon import logger
86
97 try:
108 from matscipy.neighbours import neighbour_list
7977 for constraint in atoms.constraints:
8078 if isinstance(constraint, FixAtoms):
8179 fixed_atoms.extend(list(constraint.index))
82 else:
83 raise TypeError(
84 'only FixAtoms constraints are supported by Precon class')
8580
8681 return i_list, j_list, d_list, fixed_atoms
8782
10196 if isinstance(atoms, Filter):
10297 atoms = atoms.atoms
10398
104 start_time = time.time()
99 #start_time = time.time()
105100 # compute number of neighbours of each atom. If any atom doesn't
106101 # have a neighbour we increase the cutoff and try again, until our
107102 # cutoff exceeds the size of the sytem
111106 # cell lengths and angles
112107 a, b, c, alpha, beta, gamma = cell_to_cellpar(atoms.cell)
113108 extent = [a, b, c]
114 logger.debug('estimate_nearest_neighbour_distance(): extent=%r',
115 extent)
109 #print('estimate_nearest_neighbour_distance(): extent=%r' % extent)
116110
117111 while r_cut < 2.0 * max(extent):
118 logger.info('estimate_nearest_neighbour_distance(): '
119 'calling neighbour_list with r_cut=%.2f A', r_cut)
112 #print('estimate_nearest_neighbour_distance(): '
113 # 'calling neighbour_list with r_cut=%.2f A' % r_cut)
120114 i, j, rij, fixed_atoms = get_neighbours(
121115 atoms, r_cut, self_interaction=True)
122116 if len(i) != 0:
134128 nn_distances = [np.min(rij[i == I]) for I in range(len(atoms))]
135129 r_NN = np.max(nn_distances)
136130
137 logger.info('estimate_nearest_neighbour_distance(): got r_NN=%.3f in %s s',
138 r_NN, time.time() - start_time)
131 #print('estimate_nearest_neighbour_distance(): got r_NN=%.3f in %s s' %
132 # (r_NN, time.time() - start_time))
139133 return r_NN
00 """
11 Implementation of the Precon abstract base class and subclasses
22 """
3 import time
3 from __future__ import print_function
4
5 #import time
6 import warnings
47
58 import numpy as np
69 from scipy import sparse, rand
1114 from ase.geometry import wrap_positions
1215 import ase.utils.ff as ff
1316 import ase.units as units
14 from ase.optimize.precon import logger
15 from ase.optimize.precon.neighbors import (get_neighbours, have_matscipy,
17 from ase.optimize.precon.neighbors import (get_neighbours,
1618 estimate_nearest_neighbour_distance)
1719 try:
1820 from pyamg import smoothed_aggregation_solver
2931 mu=None, mu_c=None,
3032 dim=3, c_stab=0.1, force_stab=False,
3133 recalc_mu=False, array_convention='C',
32 use_pyamg=True, solve_tol=1e-8,
34 solver="auto", solve_tol=1e-8,
3335 apply_positions=True, apply_cell=True,
3436 estimate_mu_eigmode=False):
3537 """Initialise a preconditioner object based on passed parameters.
7375 vector will be arranged atom-by-atom (ie [x1, y1, z1, x2, ...])
7476 while the F convention assumes it will be arranged component
7577 by component (ie [x1, x2, ..., y1, y2, ...]).
76 use_pyamg: use PyAMG to solve P x = y, if available.
78 solver: One of "auto", "direct" or "pyamg", specifying whether to use
79 a direst sparse solver or PyAMG to solve P x = y. Default is "auto" which
80 uses PyAMG if available, falling back to sparse solver if not.
7781 solve_tol: tolerance used for PyAMG sparse linear solver,
7882 if available.
7983 apply_positions: if True, apply preconditioner to position DoF
96100 self.P = None
97101 self.old_positions = None
98102
99 if use_pyamg and not have_pyamg:
103 use_pyamg = False
104 if solver == "auto":
105 use_pyamg = have_pyamg
106 elif solver == "direct":
100107 use_pyamg = False
101 logger.warning('use_pyamg=True but PyAMG cannot be imported! '
102 'falling back on direct inversion of '
103 'preconditioner, may be slow for large systems')
108 elif solver == "pyamg":
109 if not have_pyamg:
110 raise RuntimeError('solver="pyamg" but PyAMG cannot be imported!')
111 use_pyamg = True
112 else:
113 raise ValueError('unknown solver - should be "auto", "direct" or "pyamg"')
104114
105115 self.use_pyamg = use_pyamg
106116 self.solve_tol = solve_tol
111121 raise ValueError('Dimension must be at least 1')
112122 self.dim = dim
113123
114 if not have_matscipy:
115 logger.info('Unable to import Matscipy. Neighbour list '
116 'calculations may be very slow.')
124 #if not have_matscipy:
125 # warnings.warn('Unable to import Matscipy. Neighbour list '
126 # 'calculations may be very slow.')
117127
118128 def make_precon(self, atoms, recalc_mu=None):
119129 """Create a preconditioner matrix based on the passed set of atoms.
152162 'increasing to 1.1*r_NN = %.2f' % (self.r_cut,
153163 self.r_NN,
154164 1.1 * self.r_NN))
155 logger.info(warning)
156 print(warning)
165 warnings.warn(warning)
157166 self.r_cut = 1.1 * self.r_NN
158167
159168 if recalc_mu is None:
180189 real_atoms.cell) - self.old_positions
181190 self.old_positions = real_atoms.get_positions()
182191 max_abs_displacement = abs(displacement).max()
183 logger.info('max(abs(displacements)) = %.2f A (%.2f r_NN)',
184 max_abs_displacement, max_abs_displacement / self.r_NN)
192 #print('max(abs(displacements)) = %.2f A (%.2f r_NN)' %
193 # (max_abs_displacement, max_abs_displacement / self.r_NN))
185194 if max_abs_displacement < 0.5 * self.r_NN:
186195 return self.P
187196
188 start_time = time.time()
197 #start_time = time.time()
189198
190199 # Create the preconditioner:
191200 self._make_sparse_precon(atoms, force_stab=self.force_stab)
192201
193 logger.info('--- Precon created in %s seconds ---',
194 time.time() - start_time)
202 #print('--- Precon created in %s seconds ---' %
203 # (time.time() - start_time))
195204 return self.P
196205
197206 def _make_sparse_precon(self, atoms, initial_assembly=False,
214223 sparse matrix instead.
215224
216225 """
217 logger.info('creating sparse precon: initial_assembly=%r, '
218 'force_stab=%r, apply_positions=%r, apply_cell=%r',
219 initial_assembly, force_stab, self.apply_positions,
220 self.apply_cell)
226 # print('creating sparse precon: initial_assembly=%r, '
227 # 'force_stab=%r, apply_positions=%r, apply_cell=%r' %
228 # (initial_assembly, force_stab, self.apply_positions,
229 # self.apply_cell))
221230
222231 N = len(atoms)
223232 diag_i = np.arange(N, dtype=int)
224 start_time = time.time()
233 #start_time = time.time()
225234 if self.apply_positions:
226235 # compute neighbour list
227236 i, j, rij, fixed_atoms = get_neighbours(atoms, self.r_cut)
228 logger.info('--- neighbour list created in %s s ---' %
229 (time.time() - start_time))
237 #print('--- neighbour list created in %s s ---' %
238 # ((time.time() - start_time)))
230239
231240 # compute entries in triplet format: without the constraints
232 start_time = time.time()
241 #start_time = time.time()
233242 coeff = self.get_coeff(rij)
234243 diag_coeff = np.bincount(i, -coeff, minlength=N).astype(np.float64)
235244 if force_stab or len(fixed_atoms) == 0:
236 logger.info('adding stabilisation to preconditioner')
245 #print('adding stabilisation to preconditioner')
237246 diag_coeff += self.mu * self.c_stab
238247 else:
239248 diag_coeff = np.ones(N)
248257 diag_coeff[-3] = 1.0
249258 diag_coeff[-2] = 1.0
250259 diag_coeff[-1] = 1.0
251 logger.info('--- computed triplet format in %s s ---' %
252 (time.time() - start_time))
260 #print('--- computed triplet format in %s s ---' %
261 # (time.time() - start_time))
253262
254263 if self.apply_positions and not initial_assembly:
255264 # apply the constraints
256 start_time = time.time()
265 #start_time = time.time()
257266 mask = np.ones(N)
258267 mask[fixed_atoms] = 0.0
259268 coeff *= mask[i] * mask[j]
260269 diag_coeff[fixed_atoms] = 1.0
261 logger.info('--- applied fixed_atoms in %s s ---' %
262 (time.time() - start_time))
270 #print('--- applied fixed_atoms in %s s ---' %
271 # (time.time() - start_time))
263272
264273 if self.apply_positions:
265274 # remove zeros
266 start_time = time.time()
275 #start_time = time.time()
267276 inz = np.nonzero(coeff)
268277 i = np.hstack((i[inz], diag_i))
269278 j = np.hstack((j[inz], diag_i))
270279 coeff = np.hstack((coeff[inz], diag_coeff))
271 logger.info('--- remove zeros in %s s ---' %
272 (time.time() - start_time))
280 #print('--- remove zeros in %s s ---' %
281 # (time.time() - start_time))
273282 else:
274283 i = diag_i
275284 j = diag_i
276285 coeff = diag_coeff
277286
278287 # create the matrix
279 start_time = time.time()
288 #start_time = time.time()
280289 csc_P = sparse.csc_matrix((coeff, (i, j)), shape=(N, N))
281 logger.info('--- created CSC matrix in %s s ---' %
282 (time.time() - start_time))
290 #print('--- created CSC matrix in %s s ---' %
291 # (time.time() - start_time))
283292
284293 self.csc_P = csc_P
285294
286 start_time = time.time()
295 #start_time = time.time()
287296 if self.dim == 1:
288297 self.P = csc_P
289298 elif self.array_convention == 'F':
305314 self.P = sparse.csc_matrix((Z, (I, J)),
306315 shape=(self.dim * N, self.dim * N))
307316 self.P = self.P.tocsr()
308 logger.info('--- N-dim precon created in %s s ---' %
309 (time.time() - start_time))
317 #print('--- N-dim precon created in %s s ---' %
318 # (time.time() - start_time))
310319
311320 # Create solver
312321 if self.use_pyamg and have_pyamg:
313 start_time = time.time()
322 #start_time = time.time()
314323 self.ml = smoothed_aggregation_solver(
315324 self.P, B=None,
316325 strength=('symmetric', {'theta': 0.0}),
328337 max_levels=15,
329338 max_coarse=300,
330339 coarse_solver='pinv')
331 logger.info('--- multi grid solver created in %s s ---' %
332 (time.time() - start_time))
340 #print('--- multi grid solver created in %s s ---' %
341 # (time.time() - start_time))
333342
334343 return self.P
335344
345354 """
346355 Solve the (sparse) linear system P x = y and return y
347356 """
348 start_time = time.time()
357 #start_time = time.time()
349358 if self.use_pyamg and have_pyamg:
350359 y = self.ml.solve(x, x0=rand(self.P.shape[0]),
351360 tol=self.solve_tol,
354363 cycle='W')
355364 else:
356365 y = spsolve(self.P, x)
357 logger.info('--- Precon applied in %s seconds ---',
358 time.time() - start_time)
366 #print('--- Precon applied in %s seconds ---' %
367 # (time.time() - start_time))
359368 return y
360369
361370 def get_coeff(self, r):
424433 :3 * n]
425434 eigvals, eigvecs = sparse.linalg.eigsh(P0, k=4, which='SM')
426435
427 logger.debug('estimate_mu(): lowest 4 eigvals = %f %f %f %f'
428 % (eigvals[0], eigvals[1], eigvals[2], eigvals[3]))
436 #print('estimate_mu(): lowest 4 eigvals = %f %f %f %f'
437 # % (eigvals[0], eigvals[1], eigvals[2], eigvals[3]))
429438 # check eigenvalues
430439 if any(eigvals[0:3] > 1e-6):
431440 raise ValueError('First 3 eigenvalues of preconditioner matrix'
453462 self.c_stab = c_stab
454463 else:
455464 Lx, Ly, Lz = [p[:, i].max() - p[:, i].min() for i in range(3)]
456 logger.debug('estimate_mu(): Lx=%.1f Ly=%.1f Lz=%.1f',
457 Lx, Ly, Lz)
465 #print('estimate_mu(): Lx=%.1f Ly=%.1f Lz=%.1f' % (Lx, Ly, Lz))
458466
459467 x, y, z = p.T
460468 # sine_vr = [np.sin(x/Lx), np.sin(y/Ly), np.sin(z/Lz)], but we need
464472
465473 for i, L in enumerate([Lx, Ly, Lz]):
466474 if L == 0:
467 logger.warning(
475 warnings.warn(
468476 'Cell length L[%d] == 0. Setting H[%d,%d] = 0.' %
469477 (i, i, i))
470478 H[i, i] = 0.0
507515 # use partial sums to compute separate mu for positions and cell DoFs
508516 self.mu = longsum(LHS[:3 * natoms]) / longsum(RHS[:3 * natoms])
509517 if self.mu < 1.0:
510 logger.info('mu (%.3f) < 1.0, capping at mu=1.0', self.mu)
518 warnings.warn('mu (%.3f) < 1.0, capping at mu=1.0' % self.mu)
511519 self.mu = 1.0
512520
513521 if isinstance(atoms, Filter):
514522 self.mu_c = longsum(LHS[3 * natoms:]) / longsum(RHS[3 * natoms:])
515523 if self.mu_c < 1.0:
516 logger.info(
517 'mu_c (%.3f) < 1.0, capping at mu_c=1.0', self.mu_c)
524 print(
525 'mu_c (%.3f) < 1.0, capping at mu_c=1.0' % self.mu_c)
518526 self.mu_c = 1.0
519527
520 logger.info('estimate_mu(): mu=%r, mu_c=%r', self.mu, self.mu_c)
528 print('estimate_mu(): mu=%r, mu_c=%r' % (self.mu, self.mu_c))
521529
522530 self.P = None # force a rebuild with new mu (there may be fixed atoms)
523531 return (self.mu, self.mu_c)
591599 def __init__(self, r_cut=None, mu=None, mu_c=None, dim=3, c_stab=0.1,
592600 force_stab=False,
593601 recalc_mu=False, array_convention='C',
594 use_pyamg=True, solve_tol=1e-9,
602 solver="auto", solve_tol=1e-9,
595603 apply_positions=True, apply_cell=True):
596604 Precon.__init__(self, r_cut=r_cut, mu=mu, mu_c=mu_c,
597605 dim=dim, c_stab=c_stab,
598606 force_stab=force_stab,
599607 recalc_mu=recalc_mu,
600608 array_convention=array_convention,
601 use_pyamg=use_pyamg, solve_tol=solve_tol,
609 solver=solver, solve_tol=solve_tol,
602610 apply_positions=apply_positions,
603611 apply_cell=apply_cell)
604612
613621 def __init__(self, A=3.0, r_cut=None, r_NN=None, mu=None, mu_c=None,
614622 dim=3, c_stab=0.1,
615623 force_stab=False, recalc_mu=False, array_convention='C',
616 use_pyamg=True, solve_tol=1e-9,
624 solver="auto", solve_tol=1e-9,
617625 apply_positions=True, apply_cell=True,
618626 estimate_mu_eigmode=False):
619627 """Initialise an Exp preconditioner with given parameters.
628636 force_stab=force_stab,
629637 recalc_mu=recalc_mu,
630638 array_convention=array_convention,
631 use_pyamg=use_pyamg,
639 solver=solver,
632640 solve_tol=solve_tol,
633641 apply_positions=apply_positions,
634642 apply_cell=apply_cell,
645653 """
646654
647655 def __init__(self, dim=3, c_stab=0.1, force_stab=False,
648 array_convention='C', use_pyamg=True, solve_tol=1e-9,
656 array_convention='C', solver="auto", solve_tol=1e-9,
649657 apply_positions=True, apply_cell=True,
650658 hessian='reduced', morses=None, bonds=None, angles=None,
651659 dihedrals=None):
670678 dim=dim, c_stab=c_stab,
671679 force_stab=force_stab,
672680 array_convention=array_convention,
673 use_pyamg=use_pyamg,
681 solver=solver,
674682 solve_tol=solve_tol,
675683 apply_positions=apply_positions,
676684 apply_cell=apply_cell)
683691
684692 def make_precon(self, atoms):
685693
686 start_time = time.time()
687
694 #start_time = time.time()
688695 # Create the preconditioner:
689696 self._make_sparse_precon(atoms, force_stab=self.force_stab)
690
691 logger.info('--- Precon created in %s seconds ---',
692 time.time() - start_time)
697 #print('--- Precon created in %s seconds ---' % time.time() - start_time)
693698 return self.P
694699
695700 def _make_sparse_precon(self, atoms, initial_assembly=False,
696701 force_stab=False):
697702 """ """
698703
699 start_time = time.time()
704 #start_time = time.time()
700705
701706 N = len(atoms)
702707
777782 data.extend([self.c_stab] * self.dim * N)
778783
779784 # create the matrix
780 start_time = time.time()
785 #start_time = time.time()
781786 self.P = sparse.csc_matrix(
782787 (data, (row, col)), shape=(self.dim * N, self.dim * N))
783 logger.info('--- created CSC matrix in %s s ---' %
784 (time.time() - start_time))
788 #print('--- created CSC matrix in %s s ---' %
789 # (time.time() - start_time))
785790
786791 fixed_atoms = []
787792 for constraint in atoms.constraints:
799804
800805 self.P = self.P.tocsr()
801806
802 logger.info('--- N-dim precon created in %s s ---' %
803 (time.time() - start_time))
807 #print('--- N-dim precon created in %s s ---' %
808 # (time.time() - start_time))
804809
805810 # Create solver
806 if self.use_pyamg and have_pyamg:
807 start_time = time.time()
811 if self.use_pyamg:
812 #start_time = time.time()
808813 self.ml = smoothed_aggregation_solver(
809814 self.P, B=None,
810815 strength=('symmetric', {'theta': 0.0}),
822827 max_levels=15,
823828 max_coarse=300,
824829 coarse_solver='pinv')
825 logger.info('--- multi grid solver created in %s s ---' %
826 (time.time() - start_time))
830 #print('--- multi grid solver created in %s s ---' %
831 # (time.time() - start_time))
827832
828833 return self.P
829834
835840 def __init__(self, A=3.0, r_cut=None, r_NN=None, mu=None, mu_c=None,
836841 dim=3, c_stab=0.1,
837842 force_stab=False, recalc_mu=False, array_convention='C',
838 use_pyamg=True, solve_tol=1e-9,
843 solver="auto", solve_tol=1e-9,
839844 apply_positions=True, apply_cell=True,
840845 estimate_mu_eigmode=False,
841846 hessian='reduced', morses=None, bonds=None, angles=None,
858863 force_stab=force_stab,
859864 recalc_mu=recalc_mu,
860865 array_convention=array_convention,
861 use_pyamg=use_pyamg,
866 solver=solver,
862867 solve_tol=solve_tol,
863868 apply_positions=apply_positions,
864869 apply_cell=apply_cell,
885890 'increasing to 1.1*r_NN = %.2f' % (self.r_cut,
886891 self.r_NN,
887892 1.1 * self.r_NN))
888 logger.info(warning)
889 print(warning)
893 warnings.warn(warning)
890894 self.r_cut = 1.1 * self.r_NN
891895
892896 if recalc_mu is None:
913917 real_atoms.cell) - self.old_positions
914918 self.old_positions = real_atoms.get_positions()
915919 max_abs_displacement = abs(displacement).max()
916 logger.info('max(abs(displacements)) = %.2f A (%.2f r_NN)',
917 max_abs_displacement,
918 max_abs_displacement / self.r_NN)
920 print('max(abs(displacements)) = %.2f A (%.2f r_NN)' %
921 (max_abs_displacement,
922 max_abs_displacement / self.r_NN))
919923 if max_abs_displacement < 0.5 * self.r_NN:
920924 return self.P
921925
922 start_time = time.time()
926 #start_time = time.time()
923927
924928 # Create the preconditioner:
925929 self._make_sparse_precon(atoms, force_stab=self.force_stab)
926930
927 logger.info('--- Precon created in %s seconds ---',
928 time.time() - start_time)
931 #print('--- Precon created in %s seconds ---' % (time.time() - start_time))
929932 return self.P
930933
931934 def _make_sparse_precon(self, atoms, initial_assembly=False,
943946 sparse matrix instead.
944947
945948 """
946 logger.info('creating sparse precon: initial_assembly=%r, '
947 'force_stab=%r, apply_positions=%r, apply_cell=%r',
948 initial_assembly, force_stab, self.apply_positions,
949 self.apply_cell)
949 #print('creating sparse precon: initial_assembly=%r, '
950 # 'force_stab=%r, apply_positions=%r, apply_cell=%r' %
951 # (initial_assembly, force_stab, self.apply_positions,
952 # self.apply_cell))
950953
951954 N = len(atoms)
952 start_time = time.time()
955 #start_time = time.time()
953956 if self.apply_positions:
954957 # compute neighbour list
955958 i_list, j_list, rij_list, fixed_atoms = get_neighbours(
956959 atoms, self.r_cut)
957 logger.info('--- neighbour list created in %s s ---' %
958 (time.time() - start_time))
960 #print('--- neighbour list created in %s s ---' %
961 # (time.time() - start_time))
959962
960963 row = []
961964 col = []
974977 data.extend(np.repeat(self.mu_c, 9))
975978 else:
976979 data.extend(np.repeat(self.mu_c, 9))
977 logger.info('--- computed triplet format in %s s ---' %
978 (time.time() - start_time))
980 #print('--- computed triplet format in %s s ---' %
981 # (time.time() - start_time))
979982
980983 conn = sparse.lil_matrix((N, N), dtype=bool)
981984
10811084 data.extend([self.c_stab] * self.dim * N)
10821085
10831086 # create the matrix
1084 start_time = time.time()
1087 #start_time = time.time()
10851088 self.P = sparse.csc_matrix(
10861089 (data, (row, col)), shape=(self.dim * N, self.dim * N))
1087 logger.info('--- created CSC matrix in %s s ---' %
1088 (time.time() - start_time))
1090 #print('--- created CSC matrix in %s s ---' %
1091 # (time.time() - start_time))
10891092
10901093 if not initial_assembly:
10911094 if len(fixed_atoms) != 0:
10981101 self.P = self.P.tocsr()
10991102
11001103 # Create solver
1101 if self.use_pyamg and have_pyamg:
1102 start_time = time.time()
1104 if self.use_pyamg:
1105 #start_time = time.time()
11031106 self.ml = smoothed_aggregation_solver(
11041107 self.P, B=None,
11051108 strength=('symmetric', {'theta': 0.0}),
11171120 max_levels=15,
11181121 max_coarse=300,
11191122 coarse_solver='pinv')
1120 logger.info('--- multi grid solver created in %s s ---' %
1121 (time.time() - start_time))
1123 #print('--- multi grid solver created in %s s ---' %
1124 # (time.time() - start_time))
11221125
11231126 return self.P
5151 pass
5252 else:
5353 return a
54
55 def product(self, a):
56 """Do nothing ing the same way as sum."""
57 return self.sum(a)
5458
5559 def barrier(self):
5660 pass
0 from __future__ import division, print_function
0 from __future__ import division, print_function, absolute_import
11 import fractions
22 import functools
33 import re
4 from collections import OrderedDict
45
56 import numpy as np
67 from scipy.spatial import ConvexHull
3031 n = f.numerator
3132 d = f.denominator
3233 if abs(n / d - f) > 1e-6:
33 return '{0:.3f}'.format(f)
34 return '{:.3f}'.format(f)
3435 if d == 0:
3536 return '0'
3637 if f.denominator == 1:
3738 return str(n)
38 return '{0}/{1}'.format(f.numerator, f.denominator)
39 return '{}/{}'.format(f.numerator, f.denominator)
3940
4041
4142 def solvated(symbols):
117118 total_energy += coef * energy
118119 if abs(coef) < 1e-7:
119120 continue
120 print('{0:14}{1:>10}{2:12.3f}'.format(name, float2str(coef), energy))
121 print('{:14}{:>10}{:12.3f}'.format(name, float2str(coef), energy))
121122 print('------------------------------------')
122 print('Total energy: {0:22.3f}'.format(total_energy))
123 print('Total energy: {:22.3f}'.format(total_energy))
123124 print('------------------------------------')
124125
125126
217218 if aq:
218219 energy -= entropy
219220 if verbose:
220 print('{0:<5}{1:10}{2:10.3f}'.format(len(energies),
221 print('{:<5}{:10}{:10.3f}'.format(len(energies),
221222 name, energy))
222223 energies.append(energy)
223224 names.append(name)
324325
325326 self.verbose = verbose
326327
327 self.species = {}
328 self.species = OrderedDict()
328329 self.references = []
329330 for name, energy in references:
330331 if isinstance(name, basestring):
351352 print('Species:', ', '.join(self.symbols))
352353 print('References:', len(self.references))
353354 for i, (count, energy, name, natoms) in enumerate(self.references):
354 print('{0:<5}{1:10}{2:10.3f}'.format(i, name, energy))
355 print('{:<5}{:10}{:10.3f}'.format(i, name, energy))
355356
356357 self.points = np.zeros((len(self.references), len(self.species) + 1))
357358 for s, (count, energy, name, natoms) in enumerate(self.references):
358359 for symbol, n in count.items():
359360 self.points[s, self.species[symbol]] = n / natoms
360361 self.points[s, -1] = energy / natoms
362
363 if len(self.points) == 2:
364 self.simplices = np.array([[0, 1]])
365 self.hull = np.ones(2, bool)
366 return
361367
362368 hull = ConvexHull(self.points[:, 1:])
363369
433439
434440 return energy, indices, np.array(coefs)
435441
436 def plot(self, ax=None, dims=None, show=True,
437 only_label_simplices=False, only_plot_simplices=False):
442 def plot(self, ax=None, dims=None, show=True):
438443 """Make 2-d or 3-d plot of datapoints and convex hull.
439444
440445 Default is 2-d for 2- and 3-component diagrams and 3-d for a
456461 projection = '3d'
457462 from mpl_toolkits.mplot3d import Axes3D
458463 Axes3D # silence pyflakes
459 ax = plt.gca(projection=projection)
464 fig = plt.figure()
465 ax = fig.gca(projection=projection)
460466 else:
461467 if dims == 3 and not hasattr(ax, 'set_zlim'):
462468 raise ValueError('Cannot make 3d plot unless axes projection '
464470
465471 if dims == 2:
466472 if N == 2:
467 self.plot2d2(ax, only_label_simplices, only_plot_simplices)
473 self.plot2d2(ax)
468474 elif N == 3:
469475 self.plot2d3(ax)
470476 else:
482488 plt.show()
483489 return ax
484490
485 def plot2d2(self, ax, only_label_simplices, only_plot_simplices):
491 def plot2d2(self, ax=None):
486492 x, e = self.points[:, 1:].T
487 for i, j in self.simplices:
488 ax.plot(x[[i, j]], e[[i, j]], '-b')
489 ax.plot(x[self.hull], e[self.hull], 'og')
490 if not only_plot_simplices:
491 ax.plot(x[~self.hull], e[~self.hull], 'sr')
492
493 refs = self.references
494 if only_plot_simplices or only_label_simplices:
495 x = x[self.hull]
496 e = e[self.hull]
497 refs = np.array(refs)[self.hull]
498 for a, b, ref in zip(x, e, refs):
499 name = re.sub('(\d+)', r'$_{\1}$', ref[2])
500 ax.text(a, b, name,
501 horizontalalignment='center', verticalalignment='bottom')
502
503 ax.set_xlabel(self.symbols[1])
504 ax.set_ylabel('energy [eV/atom]')
505
506 def plot2d3(self, ax):
493 names = [re.sub('(\d+)', r'$_{\1}$', ref[2])
494 for ref in self.references]
495 hull = self.hull
496 simplices = self.simplices
497 xlabel = self.symbols[1]
498 ylabel = 'energy [eV/atom]'
499
500 if ax:
501 for i, j in simplices:
502 ax.plot(x[[i, j]], e[[i, j]], '-b')
503 ax.plot(x[hull], e[hull], 'sg')
504 ax.plot(x[~hull], e[~hull], 'or')
505
506 for a, b, name in zip(x, e, names):
507 ax.text(a, b, name, ha='center', va='top')
508
509 ax.set_xlabel(xlabel)
510 ax.set_ylabel(ylabel)
511
512 return (x, e, names, hull, simplices, xlabel, ylabel)
513
514 def plot2d3(self, ax=None):
507515 x, y = self.points[:, 1:-1].T.copy()
508516 x += y / 2
509517 y *= 3**0.5 / 2
510 for i, j, k in self.simplices:
511 ax.plot(x[[i, j, k, i]], y[[i, j, k, i]], '-b')
512 ax.plot(x[self.hull], y[self.hull], 'og')
513 ax.plot(x[~self.hull], y[~self.hull], 'sr')
514 for a, b, ref in zip(x, y, self.references):
515 name = re.sub('(\d+)', r'$_{\1}$', ref[2])
516 ax.text(a, b, name,
517 horizontalalignment='center', verticalalignment='bottom')
518 names = [re.sub('(\d+)', r'$_{\1}$', ref[2])
519 for ref in self.references]
520 hull = self.hull
521 simplices = self.simplices
522
523 if ax:
524 for i, j, k in simplices:
525 ax.plot(x[[i, j, k, i]], y[[i, j, k, i]], '-b')
526 ax.plot(x[hull], y[hull], 'og')
527 ax.plot(x[~hull], y[~hull], 'sr')
528 for a, b, name in zip(x, y, names):
529 ax.text(a, b, name, ha='center', va='top')
530
531 return (x, y, names, hull, simplices)
518532
519533 def plot3d3(self, ax):
520534 x, y, e = self.points[:, 1:].T
430430
431431 # Add mass prefactor
432432 m_a = self.atoms.get_masses()
433 print(m_a.shape, self.indices)
434433 self.m_inv_x = np.repeat(m_a[self.indices]**-0.5, 3)
435434 M_inv = np.outer(self.m_inv_x, self.m_inv_x)
436435 for D in self.D_N:
451450 if self.offset == 0:
452451 C_lmn = fft.fftshift(C_lmn, axes=(0, 1, 2)).copy()
453452 # Make force constants symmetric in indices -- in case of an even
454 # number of unit cells don't include the first
455 i, j, k = np.asarray(self.N_c) % 2 - 1
453 # number of unit cells don't include the first cell
454 i, j, k = 1 - np.asarray(self.N_c) % 2
456455 C_lmn[i:, j:, k:] *= 0.5
457456 C_lmn[i:, j:, k:] += \
458457 C_lmn[i:, j:, k:][::-1, ::-1, ::-1].transpose(0, 1, 2, 4, 3).copy()
643642
644643 return omega_kl
645644
646 def dos(self, kpts=(10, 10, 10), npts=1000, delta=1e-3,
647 indices=None, verbose=True):
645 def dos(self, kpts=(10, 10, 10), npts=1000, delta=1e-3, indices=None):
648646 """Calculate phonon dos as a function of energy.
649647
650648 Parameters:
658656 indices: list
659657 If indices is not None, the atomic-partial dos for the specified
660658 atoms will be calculated.
661 verbose: bool
662 Print warnings when imaginary frequncies are detected.
663659
664660 """
665661
667663 kpts_kc = monkhorst_pack(kpts)
668664 N = np.prod(kpts)
669665 # Get frequencies
670 omega_kl = self.band_structure(kpts_kc, verbose=verbose)
666 omega_kl = self.band_structure(kpts_kc)
671667 # Energy axis and dos
672668 omega_e = np.linspace(0., np.amax(omega_kl) + 5e-3, num=npts)
673669 dos_e = np.zeros_like(omega_e)
811811
812812 # use spglib when it is available (and return)
813813 if has_spglib and method in ['phonopy', 'spglib']:
814 sg = spglib.get_spacegroup(atoms)
814 sg = spglib.get_spacegroup(atoms, symprec=symprec)
815815 sg_no = int(sg[sg.find('(') + 1:sg.find(')')])
816816 return Spacegroup(sg_no)
817817
820820 # spacegroup of highest symmetry
821821 found = None
822822 for kind, pos in enumerate(atoms.get_scaled_positions()):
823 sg = _get_spacegroup(atoms, symprec=1e-5, center=kind)
823 sg = _get_spacegroup(atoms, symprec=symprec, center=kind)
824824 if found is None or sg.no > found.no:
825825 found = sg
826826
00 from __future__ import print_function
11 import os
22 import sys
3 import shutil
43 import subprocess
54 import tempfile
65 import unittest
76 from glob import glob
7 from distutils.version import LooseVersion
8
9 import numpy as np
810
911 from ase.calculators.calculator import names as calc_names, get_calculator
1012 from ase.parallel import paropen
1113 from ase.utils import devnull
1214 from ase.cli.info import print_info
1315
14
1516 NotAvailable = unittest.SkipTest
16
1717
1818 test_calculator_names = []
1919
5050 except ImportError as ex:
5151 module = ex.args[0].split()[-1].replace("'", '').split('.')[0]
5252 if module in ['scipy', 'matplotlib', 'Scientific', 'lxml',
53 'flask', 'gpaw', 'GPAW']:
53 'flask', 'gpaw', 'GPAW', 'netCDF4']:
5454 raise unittest.SkipTest('no {} module'.format(module))
5555 else:
5656 raise
8989
9090
9191 def test(verbosity=1, calculators=[],
92 testdir=None, stream=sys.stdout, files=None):
92 stream=sys.stdout, files=None):
93 """Main test-runner for ASE."""
94
95 if LooseVersion(np.__version__) >= '1.14':
96 # Our doctests need this (spacegroup.py)
97 np.set_printoptions(legacy='1.13')
98
9399 test_calculator_names.extend(calculators)
94100 disable_calculators([name for name in calc_names
95101 if name not in calculators])
112118
113119 origcwd = os.getcwd()
114120
115 if testdir is None:
116 testdir = tempfile.mkdtemp(prefix='ase-test-')
117 else:
118 if os.path.isdir(testdir):
119 shutil.rmtree(testdir) # clean before running tests!
120 os.mkdir(testdir)
121 testdir = tempfile.mkdtemp(prefix='ase-test-')
121122 os.chdir(testdir)
122123 if verbosity:
123 print('test-dir ', testdir, '\n', file=sys.__stdout__)
124 print('{:25}{}\n'.format('test-dir', testdir), file=sys.__stdout__)
124125 try:
125126 results = ttr.run(ts)
126127 finally:
229230
230231
231232 if __name__ == '__main__':
232 # Run pyflakes3 on all code in ASE:
233 # Run pyflakes on all code in ASE:
233234 try:
234 output = subprocess.check_output(['pyflakes3', 'ase', 'doc'],
235 output = subprocess.check_output(['pyflakes', 'ase', 'doc'],
235236 stderr=subprocess.STDOUT)
236237 except subprocess.CalledProcessError as ex:
237238 output = ex.output.decode()
77 write('x.json', Atoms('X'))
88
99 # Make sure ASE's gui can run in terminal mode without $DISPLAY and tkinter:
10 cli('ase gui --terminal x.json@id=1')
10 cli('ase -T gui --terminal x.json@id=1')
1111 assert 'tkinter' not in sys.modules
1212 assert 'Tkinter' not in sys.modules # legacy Python
0 import tempfile
1 import os
2
3 from ase.calculators.aims import Aims
4 from ase import Atoms
5
6 # test the new command handling + legacy behavior
7 aims_command = 'aims.x'
8 aims_command_alternative = 'mpirun -np 4 fhiaims.x'
9 outfilename = 'alternative_aims.out'
10 outfilename_default = 'aims.out'
11 command = '{0:s} > {1:s}'.format(aims_command, outfilename)
12 command_alternative = '{0:s} > {1:s}'.format(aims_command_alternative, outfilename)
13 command_default = '{0:s} > {1:s}'.format(aims_command, outfilename_default)
14 legacy_command = 'aims.version.serial.x > aims.out'
15 legacy_aims_command = legacy_command.split('>')[0].strip()
16 legacy_outfilename = legacy_command.split('>')[-1].strip()
17
18 # legacy behavior of empty init
19 calc = Aims()
20 assert calc.command == legacy_command
21 assert calc.outfilename == legacy_outfilename
22 assert calc.aims_command == legacy_aims_command
23
24 # behavior of empty init with env variable
25 os.environ['ASE_AIMS_COMMAND'] = aims_command_alternative
26 calc = Aims()
27 assert calc.command == '{0} > {1}'.format(aims_command_alternative, outfilename_default)
28 assert calc.outfilename == outfilename_default
29 assert calc.aims_command == aims_command_alternative
30
31 # legacy behavior of "proper" command
32 calc = Aims(run_command=command)
33 assert calc.command == command
34 assert calc.outfilename == outfilename
35 assert calc.aims_command == aims_command
36
37 # legacy behavior of an "improper" command
38 calc = Aims(run_command=aims_command)
39 assert calc.command == command_default
40 assert calc.aims_command == aims_command
41 assert calc.outfilename == outfilename_default
42
43 # fixed "command" behavior
44 calc = Aims(command=command)
45 assert calc.command == command
46 assert calc.outfilename == outfilename
47 assert calc.aims_command == aims_command
48
49 # novel way to use aims_command, no specific outfile
50 calc = Aims(aims_command=aims_command)
51 assert calc.command == command_default
52 assert calc.outfilename == outfilename_default
53 assert calc.aims_command == aims_command
54
55 calc = Aims(aims_command=aims_command,
56 outfilename=outfilename)
57 assert calc.command == command
58 assert calc.outfilename == outfilename
59 assert calc.aims_command == aims_command
60
61 # # testing the setters
62 calc.command = command_default
63 assert calc.outfilename == outfilename_default
64 assert calc.aims_command == aims_command
65 assert calc.command == command_default
66
67 #calc.set_aims_command(aims_command_alternative)
68 calc.aims_command = aims_command_alternative
69 assert calc.aims_command == aims_command_alternative
70 assert calc.outfilename == outfilename_default
71 assert calc.command == '{} > {}'.format(aims_command_alternative, outfilename_default)
72
73 calc.outfilename = outfilename
74 assert calc.command == '{} > {}'.format(aims_command_alternative, outfilename)
75 assert calc.aims_command == aims_command_alternative
76 assert calc.outfilename == outfilename
77
78
79 # test writing files
80 tmp_dir = tempfile.mkdtemp()
81 water = Atoms('HOH', [(1, 0, 0), (0, 0, 0), (0, 1, 0)])
82 calc = Aims(xc='PBE',
83 output=['dipole'],
84 sc_accuracy_etot=1e-6,
85 sc_accuracy_eev=1e-3,
86 sc_accuracy_rho=1e-6,
87 species_dir="/data/rittmeyer/FHIaims/species_defaults/light/",
88 sc_accuracy_forces=1e-4,
89 label=tmp_dir,
90 )
91 try:
92 calc.prepare_input_files()
93 raise AssertionError
94 except ValueError:
95 pass
96
97 calc.atoms = water
98 calc.prepare_input_files()
99 for f in ['control.in', 'geometry.in']:
100 assert os.path.isfile(os.path.join(tmp_dir,f))
4444 (0, (0, None), (0, None)), (0, (0, None), (0, None)),
4545 (2, (1, 0), (1, 1)), (3, (1, 0), (1, 0))]
4646 r = test([[[-1, 5], [-2, 2]], [[-2, 4], [-4, 1]]])
47 assert r == [(2, (0, 0), (1, 1)), (4, (0, 1), (0, 1)),
47 assert r == [(2, (0, 0), (1, 1)), (3, (0, 1), (1, 1)),
4848 (3, (0, 0), (0, 1)), (4, (0, 1), (0, 1)),
4949 (3, (1, 0), (1, 1)), (5, (1, 1), (1, 1))]
7979 a2.rattle(0.05)
8080
8181 # geometry optimisation with FF based preconditioner
82 precon = FF(morses=morses, angles=angles, dihedrals=dihedrals, use_pyamg=False)
82 precon = FF(morses=morses, angles=angles, dihedrals=dihedrals)
8383
8484 opt = PreconLBFGS(a2, use_armijo=True, precon=precon)
8585 opt.run(fmax=0.1)
3131 pseudopotentials={'H': 'H.pbe-rrkjus_psl.0.1.UPF'})}
3232
3333 for name in test_calculator_names + ['emt']:
34 if name in ['cp2k', 'gromacs', 'lammpslib', 'mopac', 'turbomole', 'amber']:
34 if name in ['cp2k', 'gromacs', 'lammpslib', 'lammpsrun', 'mopac', 'turbomole', 'amber', 'asap']:
3535 continue
3636 par = parameters.get(name, {})
3737 os.mkdir(name + '-test')
11 import os
22 import shutil
33 import tempfile
4
4 import ase
5 import re
56 import ase.lattice.cubic
67 from ase.calculators.castep import (Castep, CastepParam,
78 create_castep_keywords,
5455
5556 c.prepare_input_files(lattice)
5657
58
59 # detecting pseudopotentials tests
60
61 # typical filenames
62 files = ['Ag_00PBE.usp',
63 'Ag_00.recpot',
64 'Ag_C18_PBE_OTF.usp',
65 'ag-optgga1.recpot',
66 'Ag_OTF.usp',
67 'ag_pbe_v1.4.uspp.F.UPF',
68 'Ni_OTF.usp',
69 'fe_pbe_v1.5.uspp.F.UPF',
70 'Cu_01.recpot']
71
72 pp_path = os.path.join(tmp_dir, 'test_pp')
73 os.makedirs(pp_path)
74
75 for f in files:
76 with open(os.path.join(pp_path, f), 'w') as _f:
77 _f.write('DUMMY PP')
78
79
80 c = Castep(directory=tmp_dir, label='test_label_pspots', castep_pp_path=pp_path)
81 c._pedantic = True
82 atoms = ase.build.bulk('Ag')
83 atoms.set_calculator(c)
84
85 # I know, unittest would be nicer... maybe at a later point
86
87 # disabled, but may be useful still
88 # try:
89 # # this should yield no files
90 # atoms.calc.find_pspots(suffix='uspp')
91 # raise AssertionError
92 # except RuntimeError as e:
93 # #print(e)
94 # pass
95
96 try:
97 # this should yield non-unique files
98 atoms.calc.find_pspots(suffix='recpot')
99 raise AssertionError
100 except RuntimeError as e:
101 #print(e)
102 pass
103
104
105 # now let's see if we find all...
106 atoms.calc.find_pspots(pspot='00PBE', suffix='usp')
107 assert atoms.calc.cell.species_pot.value.split()[-1] == 'Ag_00PBE.usp'
108
109 atoms.calc.find_pspots(pspot='00', suffix='recpot')
110 assert atoms.calc.cell.species_pot.value.split()[-1] == 'Ag_00.recpot'
111
112 atoms.calc.find_pspots(pspot='C18_PBE_OTF', suffix='usp')
113 assert atoms.calc.cell.species_pot.value.split()[-1] == 'Ag_C18_PBE_OTF.usp'
114
115 atoms.calc.find_pspots(pspot='optgga1', suffix='recpot')
116 assert atoms.calc.cell.species_pot.value.split()[-1] == 'ag-optgga1.recpot'
117
118 atoms.calc.find_pspots(pspot='OTF', suffix='usp')
119 assert atoms.calc.cell.species_pot.value.split()[-1] == 'Ag_OTF.usp'
120
121 atoms.calc.find_pspots(suffix='UPF')
122 assert atoms.calc.cell.species_pot.value.split()[-1] == 'ag_pbe_v1.4.uspp.F.UPF'
123
124
125 # testing regular workflow
126 c = Castep(directory=tmp_dir, label='test_label_pspots',
127 castep_pp_path=pp_path, find_pspots=True)
128 c._build_missing_pspots = False
129 atoms = ase.build.bulk('Ag')
130 atoms.set_calculator(c)
131
132 # this should raise an error due to ambuiguity
133 try:
134 c._fetch_pspots()
135 raise AssertionError
136 except RuntimeError as e:
137 #print(e)
138 pass
139
140 for e in ['Ni', 'Fe', 'Cu']:
141 atoms = ase.build.bulk(e)
142 atoms.set_calculator(c)
143 c._fetch_pspots()
144
145 # test writing to file
146 tmp_dir = os.path.join(tmp_dir, 'input_files')
147 c = Castep(directory=tmp_dir, label='test_label_pspots',
148 find_pspots=True, castep_pp_path=pp_path)
149 c._label = 'test'
150 atoms = ase.build.bulk('Cu')
151 atoms.set_calculator(c)
152 c.prepare_input_files()
153
154 with open(os.path.join(tmp_dir, 'test.cell'), 'r') as f:
155 assert re.search('Cu Cu_01\.recpot', ''.join(f.readlines())) is not None
156
157
57158 os.chdir(cwd)
58159 shutil.rmtree(tmp_dir)
160
0 from ase import Atoms
1 from ase.calculators.emt import EMT
2 from ase.constraints import Hookean
3
4 L = 8. # length of the cubic box
5 d = 2.3 # Au-Au distance
6 cell = [L]*3
7 positions = [[(L - d/2) % L , L/2, L/2], [(L + d/2) % L, L/2, L/2]]
8 a = Atoms('AuAu', cell=[L]*3, positions=positions, pbc=True)
9
10 a.set_calculator(EMT())
11 e1 = a.get_potential_energy()
12
13 constraint = Hookean(a1=0, a2=1, rt=1.1*d, k=10.)
14 a.set_constraint(constraint)
15 e2 = a.get_potential_energy()
16
17 a.set_pbc([False, True, True])
18 e3 = a.get_potential_energy()
19
20 assert abs(e1 - e2) < 1e-8
21 assert not abs(e1 - e3) < 1e-8
0 6 4
1 0 0 6 2.0 1.0
2 3048.0 0.001826
3 456.4 0.01406
4 103.7 0.06876
5 29.23 0.2304
6 9.349 0.4685
7 3.189 0.3628
8 0 1 2 4.0 1.0
9 3.665 -0.3959 0.2365
10 0.7705 1.216 0.8606
11 0 1 1 0.0 1.0
12 0.26 1.0 1.0
13 0 3 1 0.0 1.0
14 0.8 1.0
0 from ase import Atoms
1 from ase.calculators.crystal import CRYSTAL
2
3 a0 = 5.43
4 bulk = Atoms('Si2', [(0, 0, 0),
5 (0.25, 0.25, 0.25)],
6 pbc=True)
7 b = a0 / 2
8 bulk.set_cell([(0, b, b),
9 (b, 0, b),
10 (b, b, 0)], scale_atoms=True)
11
12 bulk.set_calculator(CRYSTAL(label='Si2',
13 guess=True,
14 basis='sto-3g',
15 xc='PBE',
16 kpts=(2, 2, 2),
17 otherkeys=['scfdir', 'anderson',
18 ['maxcycles', '500'],
19 ['toldee', '6'],
20 ['tolinteg', '7 7 7 7 14'],
21 ['fmixing', '50']]))
22
23 final_energy = bulk.get_potential_energy()
24 assert abs(final_energy + 15564.787949) < 1.0
0 from ase import Atoms
1 from ase.calculators.crystal import CRYSTAL
2
3
4 geom = Atoms('C2',
5 cell=[[0.21680326E+01, -0.12517142E+01, 0.000000000E+00],
6 [0.00000000E+00, 0.25034284E+01, 0.000000000E+00],
7 [0.00000000E+00, 0.00000000E+00, 0.50000000E+03]],
8 positions=[(-0.722677550504, -1.251714234963, 0.),
9 (-1.445355101009, 0., 0.)],
10 pbc=[True, True, False])
11
12 geom.set_calculator(CRYSTAL(label='graphene',
13 guess=True,
14 xc='PBE',
15 kpts=(1, 1, 1),
16 otherkeys=['scfdir', 'anderson',
17 ['maxcycles', '500'],
18 ['toldee', '6'],
19 ['tolinteg', '7 7 7 7 14'],
20 ['fmixing', '95']]))
21
22 final_energy = geom.get_potential_energy()
23 assert abs(final_energy + 2063.13266758) < 1.0
0 from ase.optimize import BFGS
1 from ase.atoms import Atoms
2 from ase.calculators.crystal import CRYSTAL
3
4 geom = Atoms('OHH',
5 positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0)])
6
7 geom.set_calculator(CRYSTAL(label='water',
8 guess=True,
9 basis='sto-3g',
10 xc='PBE',
11 otherkeys=['scfdir', 'anderson',
12 ['maxcycles', '500'],
13 ['toldee', '6'],
14 ['tolinteg', '7 7 7 7 14'],
15 ['fmixing', '90']]))
16
17 opt = BFGS(geom)
18 opt.run(fmax=0.05)
19
20 final_energy = geom.get_potential_energy()
21 assert abs(final_energy + 2047.34531091) < 1.0
2424 plt.savefig('abc.png')
2525
2626
27 @creates('table.csv')
28 def table(row):
29 with open('table.csv', 'w') as f:
30 f.write('# Title\n')
31 f.write('<a href="/id/{}">link</a>, 27.2, eV\n'
32 .format(3 - row.id))
33
34
2735 stuff = ('Stuff', ['energy', 'fmax', 'charge', 'mass', 'magmom', 'volume'])
2836 things = ('Things', ['answer', 'kind'])
2937 calc = ('Calculator Setting', ['calculator'])
3038
3139 layout = [
3240 ('Basic properties',
33 [stuff, 'ATOMS',
34 things, 'CELL']),
41 [[stuff, 'ATOMS'],
42 [things, 'CELL']]),
3543 ('Calculation details',
36 [calc, None,
37 'FORCES', None,
38 'xy.png', 'abc.png'])]
44 [[calc, 'FORCES'],
45 ['xy.png', 'abc.png', 'table.csv']])]
6565 with must_raise(ValueError):
6666 c.write(Atoms(), S=42) # chemical symbol as key
6767
68 id = c.write(Atoms(), b=np.bool_(True))
68 id = c.write(Atoms(), b=np.bool_(True), i=np.int64(42))
6969 assert isinstance(c[id].b, bool)
70 assert isinstance(c[id].i, int)
7071
7172 # Make sure deleting a single sey works:
7273 id = c.write(Atoms(), key=7)
3838 print('diff from reference:')
3939 print(error)
4040
41 tol = 1.0e-6
4142 assert(error < tol)
4243
4344 # dipole
5051 print('diff from reference:')
5152 print(error)
5253
54 tol = 1.0e-4
5355 assert(error < tol)
5456
5557
6668 print('diff from reference:')
6769 print(error)
6870
71 tol = 1.0e-4
6972 assert(error < tol)
7073
7174
8285 print('diff from reference:')
8386 print(error)
8487
88 tol = 1.0e-3
8589 assert(error < tol)
8690
8791 # optimize geometry
100104 print('diff from reference:')
101105 print(error)
102106
107 tol = 1.0e-3
103108 assert(error < tol)
104109
105110 print('tests passed')
0 import ase.calculators.demon as demon
1 from ase import Atoms
2 #from ase.optimize import BFGS
3 import numpy as np
4
5 # d = 0.9575
6 d = 0.9775
7 # t = np.pi / 180 * 104.51
8 t = np.pi / 180 * 110.51
9 atoms = Atoms('H2O',
10 positions=[(d, 0, 0),
11 (d * np.cos(t), d * np.sin(t), 0),
12 (0, 0, 0)])
13
14 # set up deMon calculator
15 basis = {'all': 'aug-cc-pvdz'}
16 auxis = {'all': 'GEN-A2*'}
17
18
19 # XAS hch
20 input_arguments = {'GRID': 'FINE',
21 'MOMODIFY': [[1,0],
22 [1,0.5]],
23 'CHARGE':0,
24 'XRAY':'XAS'}
25
26 calc = demon.Demon(basis=basis,
27 auxis=auxis,
28 scftype='UKS TOL=1.0E-6 CDF=1.0E-5',
29 guess='TB',
30 xc=['BLYP', 'BASIS'],
31 input_arguments=input_arguments)
32
33 atoms.set_calculator(calc)
34
35 # energy
36 print('XAS hch')
37 print('energy')
38 energy = atoms.get_potential_energy()
39 print(energy)
40 ref = -1815.44708987 #-469.604737006
41 error = np.sqrt(np.sum((energy - ref)**2))
42 print('diff from reference:')
43 print(error)
44
45 tol = 1.0e-4
46 assert(error < tol)
47
48 # check xas
49 results = calc.results
50
51 print('xray, first transition, energy')
52 value =results['xray']['E_trans'][0]
53 print(value)
54 ref = 539.410015646
55 error = np.sqrt(np.sum((value- ref)**2))
56 print('diff from reference:')
57 print(error)
58
59 tol = 1.0e-4
60 assert(error < tol)
61
62 print('xray, first transition, transition dipole moments')
63 value = results['xray']['trans_dip'][0]
64 print(value)
65 ref = np.array([1.11921906e-02, 1.61393975e-02, 1.70983631e-07])
66 error = np.sqrt(np.sum((value- ref)**2))
67 print('diff from reference:')
68 print(error)
69
70 tol = 1.0e-4
71 assert(error < tol)
72
73
74 # XES
75 input_arguments = {'GRID': 'FINE',
76 'CHARGE':0,
77 'XRAY':'XES ALPHA=1-1'}
78
79 calc = demon.Demon(basis=basis,
80 auxis=auxis,
81 scftype='UKS TOL=1.0E-6 CDF=1.0E-5',
82 guess='TB',
83 xc=['BLYP', 'BASIS'],
84 input_arguments=input_arguments)
85
86 atoms.set_calculator(calc)
87
88 # energy
89 print('')
90 print('XES')
91 print('energy')
92 energy = atoms.get_potential_energy()
93 print(energy)
94 ref = -2079.6635944
95 error = np.sqrt(np.sum((energy - ref)**2))
96 print('diff from reference:')
97 print(error)
98
99 tol = 1.0e-4
100 assert(error < tol)
101
102 # check xes
103 results = calc.results
104
105 print('xray, first transition, energy')
106 value =results['xray']['E_trans'][0]
107 print(value)
108 ref = 486.862715888 #539.410015646
109 error = np.sqrt(np.sum((value- ref)**2))
110 print('diff from reference:')
111 print(error)
112
113 tol = 1.0e-4
114 assert(error < tol)
115
116 print('xray, first transition, transition dipole moments')
117 value = results['xray']['trans_dip'][0]
118 print(value)
119 ref = np.array([6.50528073e-03, 9.37895253e-03, 6.99433480e-09])
120 error = np.sqrt(np.sum((value- ref)**2))
121 print('diff from reference:')
122 print(error)
123
124 tol = 1.0e-4
125 assert(error < tol)
126
127 # and XPS
128 input_arguments = {'GRID': 'FINE',
129 'MOMODIFY': [[1,0],
130 [1,0.0]],
131 'CHARGE':0,
132 'XRAY':'XAS'}
133
134 calc = demon.Demon(basis=basis,
135 auxis=auxis,
136 scftype='UKS TOL=1.0E-6 CDF=1.0E-5',
137 guess='TB',
138 xc=['BLYP', 'BASIS'],
139 input_arguments=input_arguments)
140
141 atoms.set_calculator(calc)
142
143
144 # energy
145 print('')
146 print('XPS')
147 print('energy')
148 energy = atoms.get_potential_energy()
149 print(energy)
150 ref = -1536.9295935
151 error = np.sqrt(np.sum((energy - ref)**2))
152 print('diff from reference:')
153 print(error)
154
155 tol = 1.0e-4
156 assert(error < tol)
157
158 # First excited state
159 input_arguments = {'GRID': 'FINE',
160 'MOMODIFY': [[1,0],
161 [1,0.0]],
162 'CHARGE':-1}
163
164 calc = demon.Demon(basis=basis,
165 auxis=auxis,
166 scftype='UKS TOL=1.0E-6 CDF=1.0E-5',
167 guess='TB',
168 xc=['BLYP', 'BASIS'],
169 input_arguments=input_arguments)
170
171 atoms.set_calculator(calc)
172
173
174 # energy
175 print('')
176 print('EXC')
177 print('energy')
178 energy = atoms.get_potential_energy()
179 print(energy)
180 ref = -1543.18092135
181 error = np.sqrt(np.sum((energy - ref)**2))
182 print('diff from reference:')
183 print(error)
184
185 tol = 1.0e-4
186 assert(error < tol)
187
188
189 print('tests passed')
190
191
1414 return 0.5
1515
1616
17 gaps = [2, 11, 1, 2, 11, 2]
17 gaps = [2, 11, 1, 2, 11, 1]
1818
1919 calc = Test()
2020 for direct in [0, 1]:
88 par = cell_to_cellpar(mc1)
99 mc2 = cellpar_to_cell(par)
1010 mc3 = [[1, 0, 0], [0, 1, 0], [-0.2, 0, 1]]
11 mc4 = [[1, 0, 0], [-0.2, 1, 0], [0, 0, 1]]
1112 path = 'GYHCEM1AXH1'
1213
1314 firsttime = True
14 for cell in [mc1, mc2, mc3]:
15 for cell in [mc1, mc2, mc3, mc4]:
1516 a = Atoms(cell=cell, pbc=True)
1617 a.cell *= 3
1718 a.calc = FreeElectrons(nvalence=1, kpts={'path': path})
18 print(crystal_structure_from_cell(a.cell))
19 cs = crystal_structure_from_cell(a.cell)
20 assert cs == 'monoclinic'
1921 r = a.get_reciprocal_cell()
2022 k = get_special_points(a.cell)['H']
2123 print(np.dot(k, r))
00 import os
11
2 from ase.test import NotAvailable
2 from ase.test import require
33 from ase.build import bulk
44 from ase.calculators.calculator import kpts2mp
55 from ase.calculators.elk import ELK
6
7 require('elk')
68
79 atoms = bulk('Al', 'bcc', a=4.0)
810
911 # save ELK_SPECIES_PATH
1012 ELK_SPECIES_PATH = os.environ.get('ELK_SPECIES_PATH', None)
11 if ELK_SPECIES_PATH is None:
12 raise NotAvailable('ELK_SPECIES_PATH not set.')
13 assert ELK_SPECIES_PATH is not None
1314
1415 # find rmt of the default species
1516 sfile = os.path.join(os.environ['ELK_SPECIES_PATH'], 'elk.in')
0 # additional tests of the dftb I/O
1 import numpy as np
2 from ase.io.dftb import read_dftb_lattice
3 from ase.atoms import Atoms
4 from io import StringIO
5
6 #test ase.io.dftb.read_dftb_lattice
7 fd = StringIO(u"""
8 MD step: 0
9 Lattice vectors (A)
10 26.1849388999576 5.773808884828536E-006 9.076696618724854E-006
11 0.115834159141441 26.1947703089401 9.372892011565608E-006
12 0.635711495837792 0.451552307731081 9.42069476334197
13 Volume: 0.436056E+05 au^3 0.646168E+04 A^3
14 Pressure: 0.523540E-04 au 0.154031E+10 Pa
15 Gibbs free energy: -374.4577147047 H -10189.5129 eV
16 Gibbs free energy including KE -374.0819244147 H -10179.2871 eV
17 Potential Energy: -374.4578629171 H -10189.5169 eV
18 MD Kinetic Energy: 0.3757902900 H 10.2258 eV
19 Total MD Energy: -374.0820726271 H -10179.2911 eV
20 MD Temperature: 0.0009525736 au 300.7986 K
21 MD step: 10
22 Lattice vectors (A)
23 26.1852379966047 5.130835479368833E-005 5.227350674663197E-005
24 0.115884270570380 26.1953147133737 7.278784404810537E-005
25 0.635711495837792 0.451552307731081 9.42069476334197
26 Volume: 0.436085E+05 au^3 0.646211E+04 A^3
27 Pressure: 0.281638E-04 au 0.828608E+09 Pa
28 Gibbs free energy: -374.5467030749 H -10191.9344 eV
29 Gibbs free energy including KE -374.1009478784 H -10179.8047 eV
30 Potential Energy: -374.5468512972 H -10191.9384 eV
31 MD Kinetic Energy: 0.4457551965 H 12.1296 eV
32 Total MD Energy: -374.1010961007 H -10179.8088 eV
33 MD Temperature: 0.0011299245 au 356.8015 K
34 """)
35
36 vectors = read_dftb_lattice(fd)
37 mols = [Atoms(),Atoms()]
38 read_dftb_lattice(fd,mols)
39
40 compareVec = np.array([[26.1849388999576,5.773808884828536E-006,9.076696618724854E-006],[0.115834159141441,26.1947703089401,9.372892011565608E-006],[0.635711495837792,0.451552307731081,9.42069476334197]])
41
42 assert (vectors[0] == compareVec).all()
43 assert len(vectors) == 2
44 assert len(vectors[1]) == 3
45 assert (mols[0].get_cell() == compareVec).all()
46 assert mols[1].get_pbc().all() == True
66 import numpy as np
77
88 import ase.io
9 from ase.io import extxyz
910 from ase.atoms import Atoms
1011 from ase.build import bulk
1112
2324 os.unlink('to.xyz')
2425 os.unlink('to_new.xyz')
2526
27 #test comment read/write with vec_cell
28 at.info['comment'] = 'test comment'
29 ase.io.write('comment.xyz', at, comment=at.info['comment'], vec_cell=True)
30 r = ase.io.read('comment.xyz')
31 assert at == r
32 os.unlink('comment.xyz')
33
2634 # write sequence of images with different numbers of atoms -- bug fixed
2735 # in commit r4542
2836 images = [at, at * (2, 1, 1), at * (3, 1, 1)]
2937 ase.io.write('multi.xyz', images, format='extxyz')
3038 read_images = ase.io.read('multi.xyz@:')
3139 assert read_images == images
40
41 #test vec_cell writing and reading
42 images[1].set_pbc([True,True,False])
43 images[2].set_pbc([True,False,False])
44 ase.io.write('multi.xyz', images, vec_cell=True)
45 cell = images[1].get_cell()
46 cell[-1] = [0.0, 0.0, 0.0]
47 images[1].set_cell(cell)
48 cell = images[2].get_cell()
49 cell[-1] = [0.0, 0.0, 0.0]
50 cell[-2] = [0.0, 0.0, 0.0]
51 images[2].set_cell(cell)
52 read_images = ase.io.read('multi.xyz@:')
53 assert read_images == images
3254 os.unlink('multi.xyz')
55 # also test for vec_cell with whitespaces
56 f = open('structure.xyz', 'w')
57 f.write("""1
58 Coordinates
59 C -7.28250 4.71303 -3.82016
60 VEC1 1.0 0.1 1.1
61 1
62
63 C -7.28250 4.71303 -3.82016
64 VEC1 1.0 0.1 1.1
65 """)
66 f.close()
67 a = ase.io.read('structure.xyz',index=0)
68 b = ase.io.read('structure.xyz',index=1)
69 assert a == b
70 os.unlink('structure.xyz')
3371
3472 # read xyz containing trailing blank line
73 # also test for upper case elements
3574 f = open('structure.xyz', 'w')
3675 f.write("""4
3776 Coordinates
38 Mg -4.25650 3.79180 -2.54123
77 MG -4.25650 3.79180 -2.54123
3978 C -1.15405 2.86652 -1.26699
4079 C -5.53758 3.70936 0.63504
4180 C -7.28250 4.71303 -3.82016
4382 """)
4483 f.close()
4584 a = ase.io.read('structure.xyz')
85 assert a[0].symbol == 'Mg'
4686 os.unlink('structure.xyz')
4787
4888 # read xyz with / and @ signs in key value
68108
69109 ase.io.write('tmp.xyz', struct)
70110 os.unlink('tmp.xyz')
111
112 # Complex properties line. Keys and values that break with a regex parser.
113 # see https://gitlab.com/ase/ase/issues/53 for more info
114
115 complex_xyz_string = (
116 ' ' # start with a separator
117 'str=astring '
118 'quot="quoted value" '
119 u'quote_special="a_to_Z_$%%^&*\xfc\u2615" '
120 r'escaped_quote="esc\"aped" '
121 'true_value '
122 'false_value = F '
123 'integer=22 '
124 'floating=1.1 '
125 'int_array={1 2 3} '
126 'float_array="3.3 4.4" '
127 'a3x3_array="1 4 7 2 5 8 3 6 9" ' # fortran ordering
128 'Lattice=" 4.3 0.0 0.0 0.0 3.3 0.0 0.0 0.0 7.0 " ' # spaces in array
129 'scientific_float=1.2e7 '
130 'scientific_float_2=5e-6 '
131 'scientific_float_array="1.2 2.2e3 4e1 3.3e-1 2e-2" '
132 'not_array="1.2 3.4 text" '
133 'nested_brackets=[[1,2],[3,4]] ' # gets flattented if not 3x3
134 'bool_array={T F T F} '
135 'bool_array_2=" T, F, T " ' # leading spaces
136 'not_bool_array=[T F S] '
137 # read and write
138 u'\xfcnicode_key=val\xfce '
139 u'unquoted_special_value=a_to_Z_$%%^&*\xfc\u2615 '
140 '2body=33.3 '
141 'hyphen-ated '
142 # parse only
143 'many_other_quotes=({[4 8 12]}) '
144 'comma_separated="7, 4, -1" '
145 'bool_array_commas=[T, T, F, T] '
146 'Properties=species:S:1:pos:R:3 '
147 'multiple_separators '
148 'double_equals=abc=xyz '
149 'trailing'
150 )
151
152 expected_dict = {
153 'str': 'astring',
154 'quot': "quoted value",
155 'quote_special': u"a_to_Z_$%%^&*\xfc\u2615",
156 'escaped_quote': r"esc\"aped",
157 'true_value': True,
158 'false_value': False,
159 'integer': 22,
160 'floating': 1.1,
161 'int_array': np.array([1, 2, 3]),
162 'float_array': np.array([3.3, 4.4]),
163 'a3x3_array': np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
164 'Lattice': np.array([[4.3, 0.0, 0.0], [0.0, 3.3, 0.0], [0.0, 0.0, 7.0]]),
165 'scientific_float': 1.2e7,
166 'scientific_float_2': 5e-6,
167 'scientific_float_array': np.array([1.2, 2200, 40, 0.33, 0.02]),
168 'not_array': "1.2 3.4 text",
169 'nested_brackets': np.array([1, 2, 3, 4]),
170 'bool_array': np.array([True, False, True, False]),
171 'bool_array_2': np.array([True, False, True]),
172 'not_bool_array': 'T F S',
173 u'\xfcnicode_key': u'val\xfce',
174 'unquoted_special_value': u'a_to_Z_$%%^&*\xfc\u2615',
175 '2body': 33.3,
176 'hyphen-ated': True,
177 'many_other_quotes': np.array([4, 8, 12]),
178 'comma_separated': np.array([7, 4, -1]),
179 'bool_array_commas': np.array([True, True, False, True]),
180 'Properties': 'species:S:1:pos:R:3',
181 'multiple_separators': True,
182 'double_equals': 'abc=xyz',
183 'trailing': True
184 }
185
186 parsed_dict = extxyz.key_val_str_to_dict(complex_xyz_string)
187 np.testing.assert_equal(parsed_dict, expected_dict)
188
189 # Round trip through a file with complex line.
190 # Create file with the complex line and re-read it afterwards.
191 # Test is disabled as it requires that file io defaults to utf-8 encoding
192 # which is not guaranteed on Python 2 and varies with LC_ variables
193 # on linux. Test can be enabled if ase ever strongly enforces utf-8
194 # everywhere.
195 if False:
196 with open('complex.xyz', 'w', encoding='utf-8') as f_out:
197 f_out.write('1\n{}\nH 1.0 1.0 1.0'.format(complex_xyz_string))
198 complex_atoms = ase.io.read('complex.xyz')
199
200 # test all keys end up in info, as expected
201 for key, value in expected_dict.items():
202 if key in ['Properties']:
203 continue # goes elsewhere
204 else:
205 np.testing.assert_equal(complex_atoms.info[key], value)
206
207 os.unlink('complex.xyz')
208
209 #write multiple atoms objects to one xyz
210 frames = [at, at * (2, 1, 1), at * (3, 1, 1)]
211 for atoms in frames:
212 atoms.write('append.xyz',append=True)
213 atoms.write('append.xyz.gz',append=True)
214 atoms.write('not_append.xyz',append=False)
215 readFrames = ase.io.read('append.xyz',index=slice(0,None))
216 assert readFrames == frames
217 readFrames = ase.io.read('append.xyz.gz',index=slice(0,None))
218 assert readFrames == frames
219 singleFrame = ase.io.read('not_append.xyz',index=slice(0,None))
220 assert singleFrame[-1] == frames[-1]
221 os.unlink('append.xyz')
222 os.unlink('append.xyz.gz')
223 os.unlink('not_append.xyz')
0 #!/usr/bin/env python3
1 # -*- coding: utf-8 -*-
2 """Check writing and reading a xtl mustem file."""
3
4 from ase import Atoms
5 from ase.io import read
6 from ase.test import must_raise
7
8 # Reproduce the sto xtl file distributed with muSTEM
9 atoms = Atoms(['Sr', 'Ti', 'O', 'O', 'O'],
10 scaled_positions=[[0, 0, 0],
11 [0.5, 0.5, 0.5],
12 [0.5, 0.5, 0],
13 [0.5, 0, 0.5],
14 [0, 0.5, 0.5]],
15 cell=[3.905, 3.905, 3.905],
16 pbc=True)
17
18 filename = 'sto_mustem.xtl'
19
20 with must_raise(TypeError):
21 atoms.write(filename)
22
23 with must_raise(TypeError):
24 atoms.write(filename, keV=300)
25
26 with must_raise(TypeError):
27 atoms.write(filename,
28 DW={'Sr': 0.78700E-02, 'O': 0.92750E-02, 'Ti': 0.55700E-02})
29
30 atoms.write(filename, keV=300,
31 DW={'Sr': 0.78700E-02, 'O': 0.92750E-02, 'Ti': 0.55700E-02})
32
33 atoms2 = read(filename, format='mustem')
34
35 tol = 1E-6
36 assert sum(abs((atoms.positions - atoms2.positions).ravel())) < tol
37 assert sum(abs((atoms.cell - atoms2.cell).ravel())) < tol
38
39 atoms3 = read(filename)
40 assert sum(abs((atoms.positions - atoms3.positions).ravel())) < tol
41 assert sum(abs((atoms.cell - atoms3.cell).ravel())) < tol
42
43 with must_raise(ValueError):
44 # Raise an error if there is a missing key.
45 atoms.write(filename, keV=300, DW={'Sr': 0.78700E-02, 'O': 0.92750E-02})
46
47 atoms.write(filename, keV=300,
48 DW={'Sr': 0.78700E-02, 'O': 0.92750E-02, 'Ti': 0.55700E-02},
49 occupancy={'Sr': 1.0, 'O': 0.5, 'Ti': 0.9})
50
51 with must_raise(ValueError):
52 # Raise an error if there is a missing key.
53 atoms.write(filename, keV=300,
54 DW={'Sr': 0.78700E-02, 'O': 0.92750E-02, 'Ti': 0.55700E-02},
55 occupancy={'O': 0.5, 'Ti': 0.9})
56
57 with must_raise(ValueError):
58 # Raise an error if the unit cell is not defined.
59 atoms4 = Atoms(['Sr', 'Ti', 'O', 'O', 'O'],
60 positions=[[0, 0, 0],
61 [0.5, 0.5, 0.5],
62 [0.5, 0.5, 0],
63 [0.5, 0, 0.5],
64 [0, 0.5, 0.5]])
65 atoms4.write(filename, keV=300,
66 DW={'Sr': 0.78700E-02, 'O': 0.92750E-02, 'Ti': 0.55700E-02})
0 from ase.test import NotAvailable
0 import os
1 import warnings
12
23 import numpy as np
3 import ase.io.netcdftrajectory as netcdftrajectory
44
5 if not netcdftrajectory.have_nc:
6 raise NotAvailable('No NetCDF module available (netCDF4-python, '
7 'scipy.io.netcdf)')
8
9 import os
105 from ase import Atom, Atoms
6 from ase.io import read
117 from ase.io import NetCDFTrajectory
128
139 co = Atoms([Atom('C', (0, 0, 0)),
1915 co.positions[:, 2] += 0.1
2016 traj.write()
2117 del traj
22 if netcdftrajectory.have_nc == netcdftrajectory.NC_IS_NETCDF4:
23 traj = NetCDFTrajectory('1.nc', 'a')
24 co = traj[-1]
25 print(co.positions)
26 co.positions[:] += 1
27 traj.write(co)
28 del traj
29 t = NetCDFTrajectory('1.nc', 'a')
30 else:
31 t = NetCDFTrajectory('1.nc', 'r')
18 traj = NetCDFTrajectory('1.nc', 'a')
19 co = traj[-1]
20 print(co.positions)
21 co.positions[:] += 1
22 traj.write(co)
23 del traj
24 t = NetCDFTrajectory('1.nc', 'a')
3225
3326 print(t[-1].positions)
3427 print('.--------')
4134 print(1, a.positions[-1, 2], 1.7 + i - 4)
4235 assert abs(a.positions[-1, 2] - 1.7 - i + 4) < 1e-6
4336 assert a.pbc.all()
44 if netcdftrajectory.have_nc == netcdftrajectory.NC_IS_NETCDF4:
45 co.positions[:] += 1
46 t.write(co)
47 for i, a in enumerate(t):
48 if i < 4:
49 print(2, a.positions[-1, 2], 1.3 + i * 0.1)
50 assert abs(a.positions[-1, 2] - 1.3 - i * 0.1) < 1e-6
51 else:
52 print(2, a.positions[-1, 2], 1.7 + i - 4)
53 assert abs(a.positions[-1, 2] - 1.7 - i + 4) < 1e-6
54 assert len(t) == 7
55 else:
56 assert len(t) == 5
37 co.positions[:] += 1
38 t.write(co)
39 for i, a in enumerate(t):
40 if i < 4:
41 print(2, a.positions[-1, 2], 1.3 + i * 0.1)
42 assert abs(a.positions[-1, 2] - 1.3 - i * 0.1) < 1e-6
43 else:
44 print(2, a.positions[-1, 2], 1.7 + i - 4)
45 assert abs(a.positions[-1, 2] - 1.7 - i + 4) < 1e-6
46 assert len(t) == 7
5747
5848 # Change atom type and append
5949 co[0].number = 1
6353 assert (co2.numbers == co.numbers).all()
6454 del t2
6555
66 if netcdftrajectory.have_nc == netcdftrajectory.NC_IS_NETCDF4:
67 co[0].number = 6
68 co.pbc = True
56 co[0].number = 6
57 co.pbc = True
58 t.write(co)
59
60 co.pbc = False
61 o = co.pop(1)
62 try:
6963 t.write(co)
64 except ValueError:
65 pass
66 else:
67 assert False
7068
71 co.pbc = False
72 o = co.pop(1)
73 try:
74 t.write(co)
75 except ValueError:
76 pass
77 else:
78 assert False
79
80 co.append(o)
81 co.pbc = True
82 t.write(co)
69 co.append(o)
70 co.pbc = True
71 t.write(co)
8372 del t
8473
8574 # append to a nonexisting file
86 if netcdftrajectory.have_nc == netcdftrajectory.NC_IS_NETCDF4:
87 fname = '2.nc'
88 if os.path.isfile(fname):
89 os.remove(fname)
90 t = NetCDFTrajectory(fname, 'a', co)
91 del t
75 fname = '2.nc'
76 if os.path.isfile(fname):
77 os.remove(fname)
78 t = NetCDFTrajectory(fname, 'a', co)
79 del t
9280
9381 fname = '3.nc'
9482 t = NetCDFTrajectory(fname, 'w', co)
9583 # File is not created before first write
9684 co.set_pbc([True, False, False])
9785 d = co.get_distance(0, 1)
98 t.write(co)
86 with warnings.catch_warnings():
87 warnings.simplefilter('ignore', UserWarning)
88 t.write(co)
9989 del t
10090 # Check pbc
101 t = NetCDFTrajectory(fname)
102 a = t[-1]
103 assert a.pbc[0] and not a.pbc[1] and not a.pbc[2]
104 assert abs(a.get_distance(0, 1) - d) < 1e-6
105 del t
91 for c in [1, 1000]:
92 t = NetCDFTrajectory(fname, chunk_size=c)
93 a = t[-1]
94 assert a.pbc[0] and not a.pbc[1] and not a.pbc[2]
95 assert abs(a.get_distance(0, 1) - d) < 1e-6
96 del t
10697 # Append something in Voigt notation
10798 t = NetCDFTrajectory(fname, 'a')
10899 for frame, a in enumerate(t):
111102 t.write_arrays(a, frame, ['test'])
112103 del t
113104 os.remove(fname)
105
106 # Check cell origin
107 co.set_pbc(True)
108 co.set_celldisp([1,2,3])
109 traj = NetCDFTrajectory('4.nc', 'w', co)
110 traj.write(co)
111 traj.close()
112
113 traj = NetCDFTrajectory('4.nc', 'r')
114 a = traj[0]
115 assert np.all(abs(a.get_celldisp() - np.array([1,2,3])) < 1e-12)
116 traj.close()
117
118 os.remove('4.nc')
119
120 # Add 'id' field and check if it is read correctly
121 co.set_array('id', np.array([2, 1]))
122 traj = NetCDFTrajectory('5.nc', 'w', co)
123 traj.write(co, arrays=['id'])
124 traj.close()
125
126 traj = NetCDFTrajectory('5.nc', 'r')#
127 assert np.all(traj[0].numbers == [8, 6])
128 assert np.all(np.abs(traj[0].positions - np.array([[2, 2, 3.7], [2., 2., 2.5]])) < 1e-6)
129 traj.close()
130
131 a = read('5.nc')
132 assert(len(a) == 2)
133
134 os.remove('5.nc')
2020 import Scientific
2121 except ImportError:
2222 Scientific = 0
23
24 try:
25 import netCDF4
26 except ImportError:
27 netCDF4 = 0
2328
2429
2530 def get_atoms():
7479 # Someone should do something ...
7580 continue
7681
77 if format in ['v-sim']:
82 if format in ['v-sim', 'mustem']:
7883 # Standalone test used as not compatible with 1D periodicity
84 continue
85
86 if format in ['mustem']:
87 # Standalone test used as specific arguments are required
7988 continue
8089
8190 if format in ['dmol-arc', 'dmol-car', 'dmol-incoor']:
93102 continue
94103
95104 if not Scientific and format == 'etsf':
105 continue
106
107 if not netCDF4 and format == 'netcdftrajectory':
96108 continue
97109
98110 atoms = get_atoms()
0 """PDB parser
1
2 Test dealing with files that are not fully
3 compliant with the specification.
4
5 """
6
7 import os
8
9 import numpy as np
10
11 from ase import io
12
13 # Some things tested:
14 # Giant cell that would fail for split()
15 # No element field
16 # positions with no spaces
17
18 test_pdb = """REMARK Not a real pdb file
19 CRYST1 30.00015000.00015000.000 90.00 90.00 90.00 P1
20 ATOM 1 C 1 X 1 1.000 8.000 12.000 0.00 0.00 C
21 ATOM 1 C 1 X 1 2.000 6.000 4.000 0.00 0.00
22 ATOM 1 SI1 SIO 1 2.153 14.096 3.635 1.00 0.00 SIO
23 ATOM 1 O 1 1 3.846 5.672 1.323 0.40 38.51 0
24 ATOM 1 C1' T A 1 -2.481 5.354 0.000
25 ATOM 1 SIO SIO 1 -11.713-201.677 9.060************ SIO2Si
26 """
27
28
29 def test_pdb_read():
30 """Read information from pdb file."""
31 with open('pdb_test.pdb', 'w') as pdb_file:
32 pdb_file.write(test_pdb)
33 expected_cell = [[30.0, 0.0, 0.0],
34 [0.0, 15000.0, 0.0],
35 [0.0, 0.0, 15000.0]]
36 expected_positions = [[1.000, 8.000, 12.000],
37 [2.000, 6.000, 4.000],
38 [2.153, 14.096, 3.635],
39 [3.846, 5.672, 1.323],
40 [-2.481, 5.354, 0.000],
41 [-11.713, -201.677, 9.060]]
42 expected_species = ['C', 'C', 'Si', 'O', 'C', 'Si']
43
44 try:
45 pdb_atoms = io.read('pdb_test.pdb')
46 assert len(pdb_atoms) == 6
47 assert np.allclose(pdb_atoms.cell, expected_cell)
48 assert np.allclose(pdb_atoms.positions, expected_positions)
49 assert pdb_atoms.get_chemical_symbols() == expected_species
50 assert 'occupancy' not in pdb_atoms.arrays
51 finally:
52 os.unlink('pdb_test.pdb')
53
54
55 def test_pdb_read_with_arrays():
56 """Read information from pdb file. Includes occupancy."""
57 with open('pdb_test_2.pdb', 'w') as pdb_file:
58 # only write lines with occupancy and bfactor
59 pdb_file.write('\n'.join(test_pdb.splitlines()[:6]))
60 expected_occupancy = [0.0, 0.0, 1.0, 0.4]
61 expected_bfactor = [0.0, 0.0, 0.0, 38.51]
62
63 try:
64 pdb_atoms = io.read('pdb_test_2.pdb')
65 assert len(pdb_atoms) == 4
66 assert np.allclose(pdb_atoms.arrays['occupancy'], expected_occupancy)
67 assert np.allclose(pdb_atoms.arrays['bfactor'], expected_bfactor)
68 finally:
69 os.unlink('pdb_test_2.pdb')
70
71
72 if __name__ in ('__main__', '__builtin__'):
73 test_pdb_read()
74 test_pdb_read_with_arrays()
75
0 from ase.io import iread, write
1 from ase.build import bulk
2 from ase.collections import g2
3 import io
4
5 images = [bulk('Si') + bulk('Fe')] + list(g2)
6
7 buf = io.BytesIO()
8 write(buf, images, format='traj')
9 txt = buf.getvalue()
10
11 buf = io.BytesIO()
12 buf.write(txt)
13 buf.seek(0)
14
15 images2 = list(iread(buf, format='traj'))
16
17 for atoms1, atoms2 in zip(images, images2):
18 assert atoms1 == atoms2
1010 a = A()
1111 a.x = reader.x
1212 return a
13
1314
1415 w = open('a.ulm', 'w')
1516 w.write(a=A(), y=9)
0 # This writes xsd example with bond connectivity information, and checks
1 # bond formats.
2
3
4 from ase import Atoms
5 from ase.io import write
6 import numpy as np
7 from collections import OrderedDict
8 import re
9 # Example molecule
10 atoms = Atoms('CH4',[[ 1.08288111e-09, 1.74602682e-09,-1.54703448e-09],
11 [-6.78446715e-01, 8.73516584e-01,-8.63073811e-02],
12 [-4.09602527e-01,-8.46016530e-01,-5.89280858e-01],
13 [ 8.52016070e-02,-2.98243876e-01, 1.06515792e+00],
14 [ 1.00284763e+00, 2.70743821e-01,-3.89569679e-01]])
15 connectivitymatrix = np.array([[0, 1, 1, 1, 1], # Carbon(index 0), is connected to other hydrogen atoms (index 1-4)
16 [1, 0, 0, 0, 0],
17 [1, 0, 0, 0, 0],
18 [1, 0, 0, 0, 0],
19 [1, 0, 0, 0, 0]])
20 write('xsd_test_CH4.xsd',atoms,connectivity = connectivitymatrix)
21
22 # Read and see if the atom information and bond information matches.
23 AtomIdsToBondIds = OrderedDict()
24 BondIdsToConnectedAtomIds = OrderedDict()
25 with open('xsd_test_CH4.xsd','r') as f:
26 for i,line in enumerate(f):
27 if '<Atom3d ' in line:
28 AtomId = int(re.search(r'ID="(.*?)"', line).group(1))
29 ConnectedBondIds = [int(a) for a in re.search(r'Connections="(.*?)"', line).group(1).split(',')]
30 AtomIdsToBondIds[AtomId] = ConnectedBondIds
31 elif '<Bond ' in line:
32 BondId = int(re.search(r'ID="(.*?)"', line).group(1))
33 ConnectedAtomIds = [int(a) for a in re.search(r'Connects="(.*?)"', line).group(1).split(',')]
34 BondIdsToConnectedAtomIds[BondId] = ConnectedAtomIds
35 # check if atom ids have been correctly assigned for each bond
36 for AtomId in AtomIdsToBondIds:
37 for BondId in AtomIdsToBondIds[AtomId]:
38 assert AtomId in BondIdsToConnectedAtomIds[BondId]
39
40 # make connectivity graph and see if it matches with input.
41 AtomIds = list(AtomIdsToBondIds.keys())
42 Newconnectivitymatrix = np.zeros((5,5))
43 for AtomId in AtomIdsToBondIds:
44 for BondId in AtomIdsToBondIds[AtomId]:
45 OtherAtomId = [a for a in BondIdsToConnectedAtomIds[BondId] if a != AtomId]
46 i = AtomIds.index(AtomId)
47 j = AtomIds.index(OtherAtomId[0])
48 Newconnectivitymatrix[i,j] = 1
49 for i in range(0,4):
50 for j in range(0,4):
51 assert connectivitymatrix[i,j] == Newconnectivitymatrix[i,j]
52
53
2424 forces2 = water2.get_forces()
2525 energy2 = water2.get_potential_energy()
2626 positions2 = water2.get_positions()
27 #compare distances since positions are different in standard orientation
28 dist = water.get_all_distances()
29 dist2 = read('water.log', quantity='structures')[-1].get_all_distances()
2730
2831 assert abs(energy - energy2) < 1e-7
2932 assert abs(forces - forces2).max() < 1e-9
3033 assert abs(positions - positions2).max() < 1e-6
34 assert abs(dist - dist2).max() < 1e-6
163163 assert crystal_structure_from_cell(cell) == 'orthorhombic'
164164 cell = [[1, 0, 0], [0, 2, 0], [0.5, 0, 3]]
165165 assert crystal_structure_from_cell(cell) == 'monoclinic'
166 cell = [[1, 0, 0], [0.5, 3**0.5 / 2, 0], [0, 0, 3]]
167 assert crystal_structure_from_cell(cell) == 'hexagonal'
0 from ase.build import graphene_nanoribbon
1 import numpy as np
2
3 g = graphene_nanoribbon(3, 2, type="zigzag", vacuum=5)
4
5 test_set = [[0, 1, x] for x in range(2, len(g))]
6
7 manual_results = [g.get_angle(a1, a2, a3, mic=True)
8 for a1, a2, a3 in test_set]
9
10 set_results = g.get_angles(test_set, mic=True)
11
12 assert(np.allclose(manual_results, set_results))
0 import unittest
1
02 from ase.build import molecule
13 from ase import io
2 from gpaw import GPAW
4 try:
5 from gpaw import GPAW
6 except ImportError:
7 # Skip test if GPAW installation is broken:
8 raise unittest.SkipTest
39
410 txt = 'out.txt'
511 if 1:
713 atoms = molecule('H2', calculator=calculator)
814 atoms.center(vacuum=3)
915 atoms.get_potential_energy()
10
1116 atoms.set_initial_magnetic_moments([0.5, 0.5])
1217 calculator.set(charge=1)
1318 atoms.get_potential_energy()
8686 c = gui.colors_window()
8787 c.toggle('force')
8888 text = c.toggle('magmom')
89 assert [button.active for button in c.radio.buttons] == [1, 0, 1, 0, 0, 1]
89 activebuttons = [button.active for button in c.radio.buttons]
90 assert activebuttons == [1, 0, 1, 0, 0, 1, 1], activebuttons
9091 assert text.rsplit('[', 1)[1].startswith('-1.000000,1.000000]')
9192
9293
100101
101102 @test
102103 def rotate(gui):
104 gui.window['toggle-show-bonds'] = True
103105 gui.new_atoms(molecule('H2O'))
104106 gui.rotate_window()
105107
0 # test some functionality of the interace
1 import numpy as np
2 from ase.calculators.lammpslib import is_upper_triangular
3
4 m = np.ones((3,3))
5 assert not is_upper_triangular(m)
6
7 m[2,0:2] = 0
8 m[1,0] = 0
9 assert is_upper_triangular(m)
0 """Get energy from a LAMMPS calculation"""
1
2 from __future__ import print_function
3
4 import os
5 import numpy as np
6 from ase import Atom
7 from ase.build import bulk
8 from ase.calculators.lammpslib import LAMMPSlib
9
10 potential_path = os.environ.get('LAMMPS_POTENTIALS_PATH', '.')
11
12 cmds = ["pair_style eam/alloy",
13 "pair_coeff * * {path}/NiAlH_jea.eam.alloy Ni H"
14 "".format(path=potential_path)]
15
16 nickel = bulk('Ni', cubic=True)
17 nickel += Atom('H', position=nickel.cell.diagonal()/2)
18 # Bit of distortion
19 nickel.set_cell(nickel.cell + [[0.1, 0.2, 0.4],
20 [0.3, 0.2, 0.0],
21 [0.1, 0.1, 0.1]], scale_atoms=True)
22
23 lammps = LAMMPSlib(lmpcmds=cmds,
24 atom_types={'Ni': 1, 'H': 2},
25 log_file='test.log', keep_alive=True)
26
27 nickel.set_calculator(lammps)
28
29 E = nickel.get_potential_energy()
30 F = nickel.get_forces()
31 S = nickel.get_stress()
32
33 print('Energy: ', E)
34 print('Forces:', F)
35 print('Stress: ', S)
36 print()
37
38 E = nickel.get_potential_energy()
39 F = nickel.get_forces()
40 S = nickel.get_stress()
41
42
43 lammps = LAMMPSlib(lmpcmds=cmds,
44 log_file='test.log', keep_alive=True)
45 nickel.set_calculator(lammps)
46
47 E2 = nickel.get_potential_energy()
48 F2 = nickel.get_forces()
49 S2 = nickel.get_stress()
50
51 assert np.allclose(E, E2)
52 assert np.allclose(F, F2)
53 assert np.allclose(S, S2)
54
55 nickel.rattle(stdev=0.2)
56 E3 = nickel.get_potential_energy()
57 F3 = nickel.get_forces()
58 S3 = nickel.get_stress()
59
60 print('rattled atoms')
61 print('Energy: ', E3)
62 print('Forces:', F3)
63 print('Stress: ', S3)
64 print()
65
66 assert not np.allclose(E, E3)
67 assert not np.allclose(F, F3)
68 assert not np.allclose(S, S3)
69
70 nickel += Atom('H', position=nickel.cell.diagonal()/4)
71 E4 = nickel.get_potential_energy()
72 F4 = nickel.get_forces()
73 S4 = nickel.get_stress()
74
75 assert not np.allclose(E4, E3)
76 assert not np.allclose(F4[:-1,:], F3)
77 assert not np.allclose(S4, S3)
78
79
80 # the example from the docstring
81
82 cmds = ["pair_style eam/alloy",
83 "pair_coeff * * {path}/NiAlH_jea.eam.alloy Al H".format(path=potential_path)]
84
85 Ni = bulk('Ni', cubic=True)
86 H = Atom('H', position=Ni.cell.diagonal()/2)
87 NiH = Ni + H
88
89 lammps = LAMMPSlib(lmpcmds=cmds, log_file='test.log')
90
91 NiH.set_calculator(lammps)
92 print("Energy ", NiH.get_potential_energy())
0 from ase.calculators.lammpsrun import LAMMPS
1 from ase.cluster.icosahedron import Icosahedron
2 from ase.data import atomic_numbers, atomic_masses
3 import numpy as np
4 from ase.optimize import LBFGS
5
6
7 ar_nc = Icosahedron('Ar', noshells=2)
8 ar_nc.cell = [[300, 0, 0], [0, 300, 0], [0, 0, 300]]
9 ar_nc.pbc = True
10
11 params = {}
12 params['pair_style'] = 'lj/cut 8.0'
13 params['pair_coeff'] = ['1 1 0.0108102 3.345']
14 params['mass'] = ['1 {}'.format(atomic_masses[atomic_numbers['Ar']])]
15
16 calc = LAMMPS(specorder=['Ar'], parameters=params)
17
18 ar_nc.set_calculator(calc)
19
20 E = ar_nc.get_potential_energy()
21 F = ar_nc.get_forces()
22
23 assert abs(E - -0.47) < 1E-2
24 assert abs(np.linalg.norm(F) - 0.0574) < 1E-4
25
26 dyn = LBFGS(ar_nc, force_consistent=False)
27 dyn.run(fmax=1E-6)
28
29 E = round(ar_nc.get_potential_energy(), 2)
30 F = ar_nc.get_forces()
31
32 assert abs(E - -0.48) < 1E-2
33 assert abs(np.linalg.norm(F) - 0.0) < 1E-5
0 from ase.calculators.lammpsrun import LAMMPS
1 from ase.cluster.icosahedron import Icosahedron
2 from ase.data import atomic_numbers, atomic_masses
3 from numpy.linalg import norm
4
5 ar_nc = Icosahedron('Ar', noshells=2)
6 ar_nc.cell = [[300, 0, 0], [0, 300, 0], [0, 0, 300]]
7 ar_nc.pbc = True
8
9 params = {}
10 params['pair_style'] = 'lj/cut 8.0'
11 params['pair_coeff'] = ['1 1 0.0108102 3.345']
12 params['mass'] = ['1 {}'.format(atomic_masses[atomic_numbers['Ar']])]
13
14 calc = LAMMPS(specorder=['Ar'], parameters=params)
15
16 ar_nc.set_calculator(calc)
17
18 E = ar_nc.get_potential_energy()
19 F = ar_nc.get_forces()
20
21 assert abs(E - -0.47) < 1E-2
22 assert abs(norm(F) - 0.0574) < 1E-4
23 assert abs(norm(ar_nc.positions) - 23.588) < 1E-3
24
25
26 params['minimize'] = '1.0e-15 1.0e-6 2000 4000' # add minimize
27 calc.params = params
28
29 # set_atoms=True to read final coordinates after minimization
30 calc.run(set_atoms=True)
31
32 # get final coordinates after minimization
33 ar_nc.set_positions(calc.atoms.positions)
34
35 E = ar_nc.get_potential_energy()
36 F = ar_nc.get_forces()
37
38 assert abs(E - -0.48) < 1E-2
39 assert abs(norm(F) - 0.0) < 1E-6
40 assert abs(norm(ar_nc.positions) - 23.399) < 1E-3
0 from ase.calculators.lammpsrun import LAMMPS
1 from numpy.linalg import norm
2 from ase.test.eam_pot import Pt_u3
3 from ase.build import fcc111
4 import os
5
6
7 pot_fn = 'Pt_u3.eam'
8 f = open(pot_fn, 'w')
9 f.write(Pt_u3)
10 f.close()
11
12 slab = fcc111('Pt', size=(10, 10, 5), vacuum=30.0)
13
14 params = {}
15 params['pair_style'] = 'eam'
16 params['pair_coeff'] = ['1 1 {}'.format(pot_fn)]
17
18 calc = LAMMPS(specorder=['Pt'], parameters=params, files=[pot_fn])
19 slab.set_calculator(calc)
20 E = slab.get_potential_energy()
21 F = slab.get_forces()
22
23 assert abs(E - -2758.63) < 1E-2
24 assert abs(norm(F) - 11.3167) < 1E-4
25 assert abs(norm(slab.positions) - 955.259) < 1E-3
26
27 params['group'] = ['lower_atoms id '
28 + ' '.join([str(i+1) for i,
29 tag in enumerate(slab.get_tags()) if tag >= 4])]
30 params['fix'] = ['freeze_lower_atoms lower_atoms setforce 0.0 0.0 0.0']
31 params['run'] = 100
32 params['timestep'] = 0.0005
33 calc.parameters = params
34 calc.write_velocities = True
35 calc.dump_period = 10
36 # set_atoms=True to read final coordinates and velocities after NVE simulation
37 calc.run(set_atoms=True)
38
39 new_slab = calc.atoms.copy()
40
41 Ek = new_slab.get_kinetic_energy()
42 Ek2 = calc.thermo_content[-1]['ke']
43 # do not use slab.get_potential_energy()
44 # because it will run NVE simulation again
45 E = calc.thermo_content[-1]['pe']
46 T = calc.thermo_content[-1]['temp']
47
48 assert abs(Ek - Ek2) < 1E-4
49 assert abs(Ek - 2.53) < 1E-2
50 assert abs(E - -2761.17) < 1E-2
51 assert abs(norm(new_slab.positions) - 871.993) < 1E-3
52
53 os.remove(pot_fn)
0 from __future__ import print_function
1 import numpy as np
2 from ase import Atoms
3 from ase.calculators.emt import EMT
4 from ase.optimize import BFGS, BFGSLineSearch
5 from ase.optimize.precon import Exp, PreconLBFGS
6
7 positions = [
8 [5.8324672234339969, 8.5510800490537271, 5.686535793302002 ],
9 [7.3587688835494625, 5.646353802990923, 6.8378173997818958],
10 [7.9908510609316235, 5.4456005797117335, 4.5249260246251213],
11 [9.7103024117445145, 6.4768915365291466, 4.6502022197421278],
12 [9.5232482249292509, 8.7417754382952051, 4.6747936030744448],
13 [8.2738330473112036, 7.640248516254645, 6.1624124370797215],
14 [7.4198265919217921, 9.2882534361810016, 4.3654132356242874],
15 [6.8506783463494623, 9.2004422130272605, 8.611538688631887 ],
16 [5.9081131977596133, 5.6951755645279949, 5.4134092632199602],
17 [9.356736354387575, 9.2718534012646359, 8.491942486888524 ],
18 [9.0390271264592403, 9.5752757925665453, 6.4771649275571779],
19 [7.0554382804264533, 7.0016335250680779, 8.418151938177477 ],
20 [9.4855926945401272, 5.5650406772147694, 6.8445655410690591],
21 ]
22 atoms = Atoms('Pt13', positions=positions, cell=[15]*3)
23
24 maxstep = 0.2
25 longest_steps = []
26
27 labels = ['BFGS', 'BFGSLineSearch', 'PreconLBFGS_Armijo', 'PreconLBFGS_Wolff']
28 optimizers = [BFGS, BFGSLineSearch, PreconLBFGS, PreconLBFGS]
29
30 for i,Optimizer in enumerate(optimizers):
31 a = atoms.copy()
32 a.set_calculator(EMT())
33
34 kwargs = {'maxstep':maxstep, 'logfile':None}
35 if 'Precon' in labels[i]:
36 kwargs['precon'] = Exp(A=3)
37 kwargs['use_armijo'] = 'Armijo' in labels[i]
38
39 opt = Optimizer(a, **kwargs)
40 opt.run(steps=1)
41
42 dr = a.get_positions() - positions
43 steplengths = (dr**2).sum(1)**0.5
44 longest_step = np.max(steplengths)
45
46 print('%s: longest step = %.4f' % (labels[i], longest_step))
47 longest_steps.append(longest_step)
48
49 longest_steps = np.array(longest_steps)
50 assert (longest_steps < maxstep + 1e-8).all()
00 import numpy.random as random
11 import numpy as np
22 from ase import Atoms
3 from ase.neighborlist import NeighborList
3 from ase.neighborlist import (NeighborList, PrimitiveNeighborList,
4 NewPrimitiveNeighborList)
45 from ase.build import bulk
56
67 atoms = Atoms(numbers=range(10),
4041 d2, c2 = count(nl2, atoms2)
4142 c2.shape = (-1, 10)
4243 dd = d * (p1 + 1) * (p2 + 1) * (p3 + 1) - d2
43 # print(dd)
44 # print(c2 - c)
4544 assert abs(dd) < 1e-10
4645 assert not (c2 - c).any()
4746
7978 assert len(nl.get_neighbors(a)[0]) == 12
8079 assert not np.any(nl.get_neighbors(13)[1])
8180
81 c = 0.0058
82 for NeighborListClass in [PrimitiveNeighborList, NewPrimitiveNeighborList]:
83 nl = NeighborListClass([c, c],
84 skin=0.0,
85 sorted=True,
86 self_interaction=False,
87 use_scaled_positions=True)
88 nl.update([True, True, True],
89 np.eye(3) * 7.56,
90 np.array([[0, 0, 0],
91 [0, 0, 0.99875]]))
92 n0, d0 = nl.get_neighbors(0)
93 n1, d1 = nl.get_neighbors(1)
94 # != is xor
95 assert (np.all(n0 == [0]) and np.all(d0 == [0, 0, 1])) != \
96 (np.all(n1 == [1]) and np.all(d1 == [0, 0, -1]))
97
98 # Test empty neighbor list
99 nl = PrimitiveNeighborList([])
100 nl.update([True, True, True],
101 np.eye(3) * 7.56,
102 np.zeros((0, 3)))
103
104 # Test hexagonal cell and large cutoff
105 pbc_c = np.array([True, True, True])
106 cutoff_a = np.array([8.0, 8.0])
107 cell_cv = np.array([[0., 3.37316113, 3.37316113],
108 [3.37316113, 0., 3.37316113],
109 [3.37316113, 3.37316113, 0.]])
110 spos_ac = np.array([[0., 0., 0.],
111 [0.25, 0.25, 0.25]])
112
113 nl = PrimitiveNeighborList(cutoff_a, skin=0.0, sorted=True, use_scaled_positions=True)
114 nl2 = NewPrimitiveNeighborList(cutoff_a, skin=0.0, sorted=True, use_scaled_positions=True)
115 nl.update(pbc_c, cell_cv, spos_ac)
116 nl2.update(pbc_c, cell_cv, spos_ac)
117
118 a0, offsets0 = nl.get_neighbors(0)
119 b0 = np.zeros_like(a0)
120 d0 = np.dot(spos_ac[a0] + offsets0 - spos_ac[0], cell_cv)
121 a1, offsets1 = nl.get_neighbors(1)
122 d1 = np.dot(spos_ac[a1] + offsets1 - spos_ac[1], cell_cv)
123 b1 = np.ones_like(a1)
124
125 a = np.concatenate([a0, a1])
126 b = np.concatenate([b0, b1])
127 d = np.concatenate([d0, d1])
128 _a = np.concatenate([a, b])
129 _b = np.concatenate([b, a])
130 a = _a
131 b = _b
132 d = np.concatenate([d, -d])
133
134 a0, offsets0 = nl2.get_neighbors(0)
135 d0 = np.dot(spos_ac[a0] + offsets0 - spos_ac[0], cell_cv)
136 b0 = np.zeros_like(a0)
137 a1, offsets1 = nl2.get_neighbors(1)
138 d1 = np.dot(spos_ac[a1] + offsets1 - spos_ac[1], cell_cv)
139 b1 = np.ones_like(a1)
140
141 a2 = np.concatenate([a0, a1])
142 b2 = np.concatenate([b0, b1])
143 d2 = np.concatenate([d0, d1])
144 _a2 = np.concatenate([a2, b2])
145 _b2 = np.concatenate([b2, a2])
146 a2 = _a2
147 b2 = _b2
148 d2 = np.concatenate([d2, -d2])
149
150 i = np.argsort(d[:, 0]+d[:, 1]*1e2+d[:, 2]*1e4+a*1e6)
151 i2 = np.argsort(d2[:, 0]+d2[:, 1]*1e2+d2[:, 2]*1e4+a2*1e6)
152
153 assert np.all(a[i] == a2[i2])
154 assert np.all(b[i] == b2[i2])
155 assert np.allclose(d[i], d2[i2])
0 from __future__ import division
1
2 import numpy as np
3
4 import ase
5 import ase.lattice.hexagonal
6 from ase.build import bulk, molecule
7
8 from ase.neighborlist import (mic, neighbor_list, primitive_neighbor_list,
9 first_neighbors)
10
11 tol = 1e-7
12
13 # two atoms
14 a = ase.Atoms('CC', positions=[[0.5, 0.5, 0.5], [1,1,1]], cell=[10, 10, 10],
15 pbc=True)
16 i, j, d = neighbor_list("ijd", a, 1.1)
17 assert (i == np.array([0, 1])).all()
18 assert (j == np.array([1, 0])).all()
19 assert np.abs(d - np.array([np.sqrt(3/4), np.sqrt(3/4)])).max() < tol
20
21 # test_neighbor_list
22 for pbc in [True, False, [True, False, True]]:
23 a = ase.Atoms('4001C', cell=[29, 29, 29])
24 a.set_scaled_positions(np.transpose([np.random.random(len(a)),
25 np.random.random(len(a)),
26 np.random.random(len(a))]))
27 j, dr, i, abs_dr, shift = neighbor_list("jDidS", a, 1.85)
28
29 assert (np.bincount(i) == np.bincount(j)).all()
30
31 r = a.get_positions()
32 dr_direct = mic(r[j]-r[i], a.cell)
33 assert np.abs(r[j]-r[i]+shift.dot(a.cell) - dr_direct).max() < tol
34
35 abs_dr_from_dr = np.sqrt(np.sum(dr*dr, axis=1))
36 abs_dr_direct = np.sqrt(np.sum(dr_direct*dr_direct, axis=1))
37
38 assert np.all(np.abs(abs_dr-abs_dr_from_dr) < 1e-12)
39 assert np.all(np.abs(abs_dr-abs_dr_direct) < 1e-12)
40
41 assert np.all(np.abs(dr-dr_direct) < 1e-12)
42
43 # test_neighbor_list_atoms_outside_box
44 for pbc in [True, False, [True, False, True]]:
45 a = ase.Atoms('4001C', cell=[29, 29, 29])
46 a.set_scaled_positions(np.transpose([np.random.random(len(a)),
47 np.random.random(len(a)),
48 np.random.random(len(a))]))
49 a.set_pbc(pbc)
50 a.positions[100, :] += a.cell[0, :]
51 a.positions[200, :] += a.cell[1, :]
52 a.positions[300, :] += a.cell[2, :]
53 j, dr, i, abs_dr, shift = neighbor_list("jDidS", a, 1.85)
54
55 assert (np.bincount(i) == np.bincount(j)).all()
56
57 r = a.get_positions()
58 dr_direct = mic(r[j]-r[i], a.cell)
59 assert np.abs(r[j]-r[i]+shift.dot(a.cell) - dr_direct).max() < tol
60
61 abs_dr_from_dr = np.sqrt(np.sum(dr*dr, axis=1))
62 abs_dr_direct = np.sqrt(np.sum(dr_direct*dr_direct, axis=1))
63
64 assert np.all(np.abs(abs_dr-abs_dr_from_dr) < 1e-12)
65 assert np.all(np.abs(abs_dr-abs_dr_direct) < 1e-12)
66
67 assert np.all(np.abs(dr-dr_direct) < 1e-12)
68
69 # test_small_cell
70 a = ase.Atoms('C', positions=[[0.5, 0.5, 0.5]], cell=[1, 1, 1],
71 pbc=True)
72 i, j, dr, shift = neighbor_list("ijDS", a, 1.1)
73 assert np.bincount(i)[0] == 6
74 assert (dr == shift).all()
75
76 i, j = neighbor_list("ij", a, 1.5)
77 assert np.bincount(i)[0] == 18
78
79 a.set_pbc(False)
80 i = neighbor_list("i", a, 1.1)
81 assert len(i) == 0
82
83 a.set_pbc([True, False, False])
84 i = neighbor_list("i", a, 1.1)
85 assert np.bincount(i)[0] == 2
86
87 a.set_pbc([True, False, True])
88 i = neighbor_list("i", a, 1.1)
89 assert np.bincount(i)[0] == 4
90
91 # test_out_of_cell_small_cell
92 a = ase.Atoms('CC', positions=[[0.5, 0.5, 0.5],
93 [1.1, 0.5, 0.5]],
94 cell=[1, 1, 1], pbc=False)
95 i1, j1, r1 = neighbor_list("ijd", a, 1.1)
96 a.set_cell([2, 1, 1])
97 i2, j2, r2 = neighbor_list("ijd", a, 1.1)
98
99 assert (i1 == i2).all()
100 assert (j1 == j2).all()
101 assert np.abs(r1 - r2).max() < tol
102
103 # test_out_of_cell_large_cell
104 a = ase.Atoms('CC', positions=[[9.5, 0.5, 0.5],
105 [10.1, 0.5, 0.5]],
106 cell=[10, 10, 10], pbc=False)
107 i1, j1, r1 = neighbor_list("ijd", a, 1.1)
108 a.set_cell([20, 10, 10])
109 i2, j2, r2 = neighbor_list("ijd", a, 1.1)
110
111 assert (i1 == i2).all()
112 assert (j1 == j2).all()
113 assert np.abs(r1 - r2).max() < tol
114
115 # test_hexagonal_cell
116 for sx in range(3):
117 a = ase.lattice.hexagonal.Graphite('C', latticeconstant=(2.5, 10.0),
118 size=[sx+1,sx+1,1])
119 i = neighbor_list("i", a, 1.85)
120 assert np.all(np.bincount(i)==3)
121
122 # test_first_neighbors
123 i = [1,1,1,1,3,3,3]
124 assert (first_neighbors(5, i) == np.array([0,0,4,4,7,7])).all()
125 i = [0,1,2,3,4,5]
126 assert (first_neighbors(6, i) == np.array([0,1,2,3,4,5,6])).all()
127
128 # test_multiple_elements
129 a = molecule('HCOOH')
130 a.center(vacuum=5.0)
131 i = neighbor_list("i", a, 1.85)
132 assert (np.bincount(i) == np.array([2,3,1,1,1])).all()
133
134 cutoffs = {(1, 6): 1.2}
135 i = neighbor_list("i", a, cutoffs)
136 assert (np.bincount(i) == np.array([0,1,0,0,1])).all()
137
138 cutoffs = {(6, 8): 1.4}
139 i = neighbor_list("i", a, cutoffs)
140 assert (np.bincount(i) == np.array([1,2,1])).all()
141
142 cutoffs = {('H', 'C'): 1.2, (6, 8): 1.4}
143 i = neighbor_list("i", a, cutoffs)
144 assert (np.bincount(i) == np.array([1,3,1,0,1])).all()
145
146 cutoffs = [0.0, 0.9, 0.0, 0.5, 0.5]
147 i = neighbor_list("i", a, cutoffs)
148 assert (np.bincount(i) == np.array([0,1,0,0,1])).all()
149
150 cutoffs = [0.7, 0.9, 0.7, 0.5, 0.5]
151 i = neighbor_list("i", a, cutoffs)
152 assert (np.bincount(i) == np.array([2,3,1,1,1])).all()
153
154 # test_noncubic
155 a = bulk("Al", cubic=False)
156 i, j, d = neighbor_list("ijd", a, 3.1)
157 assert (np.bincount(i) == np.array([12])).all()
158 assert np.abs(d - [2.86378246]*12).max() < tol
159
160 # test pbc
161 nat = 10
162 atoms = ase.Atoms(numbers=range(nat),
163 cell=[(0.2, 1.2, 1.4),
164 (1.4, 0.1, 1.6),
165 (1.3, 2.0, -0.1)])
166 atoms.set_scaled_positions(3 * np.random.random((nat, 3)) - 1)
167
168 for p1 in range(2):
169 for p2 in range(2):
170 for p3 in range(2):
171 atoms.set_pbc((p1, p2, p3))
172 i, j, d, D, S = neighbor_list("ijdDS", atoms, atoms.numbers * 0.2 + 0.5)
173 c = np.bincount(i)
174 atoms2 = atoms.repeat((p1 + 1, p2 + 1, p3 + 1))
175 i2, j2, d2, D2, S2 = neighbor_list("ijdDS", atoms2, atoms2.numbers * 0.2 + 0.5)
176 c2 = np.bincount(i2)
177 c2.shape = (-1, nat)
178 dd = d.sum() * (p1 + 1) * (p2 + 1) * (p3 + 1) - d2.sum()
179 dr = np.linalg.solve(atoms.cell.T, (atoms.positions[1]-atoms.positions[0]).T).T+np.array([0,0,3])
180 assert abs(dd) < 1e-10
181 assert not (c2 - c).any()
182
183 c = 0.0058
184 i, j, d = primitive_neighbor_list('ijd',
185 [True, True, True],
186 np.eye(3) * 7.56,
187 np.array([[0, 0, 0],
188 [0, 0, 0.99875]]),
189 [c, c],
190 self_interaction=False,
191 use_scaled_positions=True)
192 assert np.all(i == [0, 1])
193 assert np.all(j == [1, 0])
194 assert np.allclose(d, [0.00945, 0.00945])
0 import numpy as np
1
2 from ase.build import bulk
3 from ase.calculators.lj import LennardJones
4 from ase.optimize.precon import Exp, PreconLBFGS
5
6 cu0 = bulk("Cu") * (2, 2, 2)
7 sigma = cu0.get_distance(0,1)*(2.**(-1./6))
8 lj = LennardJones(sigma=sigma)
9
10 # perturb the cell
11 cell = cu0.get_cell()
12 cell *= 0.95
13 cell[1,0] += 0.2
14 cell[2,1] += 0.5
15 cu0.set_cell(cell, scale_atoms=True)
16
17 energies = []
18 for use_armijo in [True, False]:
19 for a_min in [None, 1e-3]:
20 atoms = cu0.copy()
21 atoms.set_calculator(lj)
22 opt = PreconLBFGS(atoms, precon=Exp(A=3), use_armijo=use_armijo,
23 a_min=a_min, variable_cell=True)
24 opt.run(fmax=1e-3, smax=1e-4)
25 energies.append(atoms.get_potential_energy())
26
27 # check we get the expected energy for all methods
28 assert np.abs(np.array(energies) - -63.5032311942).max() < 1e-4
22 from ase.build import bulk
33 from ase.calculators.emt import EMT
44 from ase.optimize.precon import Exp, PreconLBFGS, PreconFIRE
5 from ase.constraints import FixBondLength, FixAtoms
56
67 N = 1
78 a0 = bulk('Cu', cubic=True)
1516 nsteps = []
1617 energies = []
1718 for OPT in [PreconLBFGS, PreconFIRE]:
18 for precon in [None, Exp(A=3, use_pyamg=False)]:
19 for precon in [None, Exp(A=3, mu=1.0)]:
1920 atoms = a0.copy()
2021 atoms.set_calculator(EMT())
2122 opt = OPT(atoms, precon=precon, use_armijo=True)
2526
2627 # check we get the expected energy for all methods
2728 assert np.abs(np.array(energies) - -0.022726045433998365).max() < 1e-4
29
30 # test with fixed bondlength and fixed atom constraints
31 cu0 = bulk("Cu") * (5, 5, 5)
32 cu0.rattle(0.01)
33 a0 = cu0.get_distance(0, 1)
34 cons = [FixBondLength(0,1), FixAtoms([2,3])]
35 for precon in [None, Exp(mu=1.0)]:
36 cu = cu0.copy()
37 cu.set_calculator(EMT())
38 cu.set_distance(0, 1, a0*1.2)
39 cu.set_constraint(cons)
40 opt = PreconLBFGS(cu, precon=precon, use_armijo=True)
41 opt.run(fmax=1e-3)
42
43 assert abs(cu.get_distance(0, 1)/a0 - 1.2) < 1e-3
44 assert np.all(abs(cu.positions[2] - cu0.positions[2]) < 1e-3)
45 assert np.all(abs(cu.positions[3] - cu0.positions[3]) < 1e-3)
0 import numpy as np
1
2 from ase.build import bulk
3 from ase.calculators.lj import LennardJones
4 from ase.optimize.precon import PreconLBFGS, Exp
5 from ase.constraints import UnitCellFilter
6
7 cu0 = bulk("Cu") * (2, 2, 2)
8 lj = LennardJones(sigma=cu0.get_distance(0,1))
9
10 cu = cu0.copy()
11 cu.set_cell(1.2*cu.get_cell())
12 cu.set_calculator(lj)
13
14 ucf = UnitCellFilter(cu, constant_volume=True)
15 opt = PreconLBFGS(ucf, precon=Exp(mu=1.0, mu_c=1.0))
16 opt.run(fmax=1e-3)
17
18 assert abs(np.linalg.det(cu.cell)/np.linalg.det(cu0.cell) - 1.2**3) < 1e-3
(New empty file)
00 """Tests related to QBOX"""
11
2 import os
32 import numpy as np
43
54 from ase import Atoms
65 from ase.io import qbox
76 from ase.io import formats
8 import ase
97
10 test_file = os.path.join(os.path.dirname(ase.__file__), 'test', 'qbox',
11 'test.xml')
8 # We don't like shipping raw datafiles, because they must all be listed
9 # in the manifest. So we invoke a function that prepares the files that
10 # we need:
11 from ase.test.qbox.qboxdata import writefiles
12 writefiles()
13
14 test_qbox = 'test.xml'
15 test_qball = '04_md_ntc.reference.xml'
1216
1317
1418 def read_output():
1519 """Test reading the output file"""
1620
1721 # Read only one frame
18 atoms = qbox.read_qbox(test_file)
22 atoms = qbox.read_qbox(test_qbox)
1923
2024 assert isinstance(atoms, Atoms)
2125 assert np.allclose(atoms.cell, np.diag([16, 16, 16]))
3640 0.00001786, -0.00002405, -0.00000014])
3741
3842 # Read all the frames
39 atoms = qbox.read_qbox(test_file, slice(None))
43 atoms = qbox.read_qbox(test_qbox, slice(None))
4044
4145 assert isinstance(atoms, list)
4246 assert len(atoms) == 5
5357 def test_format():
5458 """Make sure the `formats.py` operations work"""
5559
56 atoms = formats.read(test_file)
60 atoms = formats.read(test_qbox)
5761 assert len(atoms) == 4
5862
59 atoms = formats.read(test_file, index=slice(None), format='qbox')
63 atoms = formats.read(test_qbox, index=slice(None), format='qbox')
6064 assert len(atoms) == 5
6165
66 atoms = formats.read(test_qball)
67 assert len(atoms) == 32
6268
63 if __name__ == '__main__':
64 read_output()
65 test_format()
69
70
71 read_output()
72 test_format()
0 def writefiles():
1 with open('04_md_ntc.reference.xml', 'w') as fd:
2 fd.write("""<?xml version="1.0" encoding="UTF-8"?>
3 <!--
4
5 ___________________________
6 | |
7 | qball alsos |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | Lawrence Livermore |
17 | National Laboratory |
18 | |
19 | Copyright (c) 2003-2016 |
20 |_________________________|
21
22 -->
23 <qbox:simulation xmlns:qbox="http://www.quantum-simulation.org/ns/fpmd/fpmd-1.0">
24 <release> qball alsos </release>
25 <npes> 4 </npes>
26 <nthreads> 1 </nthreads>
27 <user> xavier </user>
28 <sysname> Linux </sysname>
29 <nodename> refri </nodename>
30 <start_time> 2016-11-26T06:40:35Z </start_time>
31 <!-- [qball] md.sys -->
32 <!-- [qball][md.sys] set cell 15.30600000 0.00000000 0.00000000 0.00000000 15.30600000 0.00000000 0.00000000 0.00000000 15.30600000 -->
33 <unitcell>
34 <unit_cell
35 a="15.30600000 0.00000000 0.00000000 "
36 b="0.00000000 15.30600000 0.00000000 "
37 c="0.00000000 0.00000000 15.30600000 " />
38 </unitcell>
39 <!-- [qball][md.sys] species aluminum Al.xml -->
40 <!-- SpeciesCmd: defining species aluminum as Al.xml -->
41 <!-- SpeciesReader opening file Al.xml size: 76072 -->
42 <!-- SpeciesReader::readSpecies: potential type: norm-conserving -->
43 <!-- SpeciesReader::readSpecies: read description
44 PSGen-1.6.1 pseudopotential: HSCV Al xc=LDA
45 Generated by PSGen-1.6.1 on 2009-10-11T04:37:45Z
46 psgen arguments:
47 -element Al -xc LDA -smooth_v -bound l=0:rc=1.3 -bound l=1:rc=1.6
48 -scat l=2:rc=1.6
49 -->
50 <!-- SpeciesReader::readSpecies: read symbol Al -->
51 <!-- SpeciesReader::readSpecies: read atomic_number 13 -->
52 <!-- SpeciesReader::readSpecies: read mass 26.98150000 -->
53 <!-- SpeciesReader::readSpecies: read valence_charge 3 -->
54 <!-- SpeciesReader::readSpecies: read lmax 2 -->
55 <!-- SpeciesReader::readSpecies: read llocal 2 -->
56 <!-- SpeciesReader::readSpecies: read nquad 0 -->
57 <!-- SpeciesReader::readSpecies: read rquad 0.00000000 -->
58 <!-- SpeciesReader::readSpecies: read mesh_spacing 0.01000000 -->
59 <!-- SpeciesReader::readSpecies: read radial_potential l=0 size=1087 -->
60 <!-- SpeciesReader::readSpecies: read radial_function l=0 size=1087 -->
61 <!-- SpeciesReader::readSpecies: read radial_potential l=1 size=1087 -->
62 <!-- SpeciesReader::readSpecies: read radial_function l=1 size=1087 -->
63 <!-- SpeciesReader::readSpecies: read radial_potential l=2 size=1087 -->
64 <!-- Species aluminum: extending grid to rmax = 40.00000000 to increase vnlg resolution (4096 pts) -->
65 SPECIES.ndft = 4096, np = 1087, rmax = 40.96000000, gmax = 314.08256632, hubbard_l = -1
66 <!-- Kleinman-Bylander normalization term wsg[0] = 5.29180491 -->
67 <!-- Kleinman-Bylander normalization term wsg[1] = 15.25266347 -->
68
69 species aluminum:
70 name_ = aluminum
71 description_ =
72 PSGen-1.6.1 pseudopotential: HSCV Al xc=LDA
73 Generated by PSGen-1.6.1 on 2009-10-11T04:37:45Z
74 psgen arguments:
75 -element Al -xc LDA -smooth_v -bound l=0:rc=1.3 -bound l=1:rc=1.6
76 -scat l=2:rc=1.6
77
78 uri_ = Al.xml
79 symbol_ = Al
80 atomic_number_ = 13
81 Kleinman-Bylander potential
82 valence charge = 3 / ionic mass_ = 26.98150000 (amu)
83 lmax_ = 2
84 llocal_ = 2
85 rcps_ = 1.50000000
86 <!-- [qball][md.sys] atom Al1 aluminum 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 -->
87 <!-- [qball][md.sys] atom Al2 aluminum 3.82650000 3.82650000 0.00000000 0.00000000 0.00000000 0.00000000 -->
88 <!-- [qball][md.sys] atom Al3 aluminum 3.82650000 0.00000000 3.82650000 0.00000000 0.00000000 0.00000000 -->
89 <!-- [qball][md.sys] atom Al4 aluminum 0.00000000 3.82650000 3.82650000 0.00000000 0.00000000 0.00000000 -->
90 <!-- [qball][md.sys] atom Al5 aluminum -7.65300000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 -->
91 <!-- [qball][md.sys] atom Al6 aluminum -3.82650000 3.82650000 0.00000000 0.00000000 0.00000000 0.00000000 -->
92 <!-- [qball][md.sys] atom Al7 aluminum -3.82650000 0.00000000 3.82650000 0.00000000 0.00000000 0.00000000 -->
93 <!-- [qball][md.sys] atom Al8 aluminum -7.65300000 3.82650000 3.82650000 0.00000000 0.00000000 0.00000000 -->
94 <!-- [qball][md.sys] atom Al9 aluminum 0.00000000 -7.65300000 0.00000000 0.00000000 0.00000000 0.00000000 -->
95 <!-- [qball][md.sys] atom Al10 aluminum 3.82650000 -3.82650000 0.00000000 0.00000000 0.00000000 0.00000000 -->
96 <!-- [qball][md.sys] atom Al11 aluminum 3.82650000 -7.65300000 3.82650000 0.00000000 0.00000000 0.00000000 -->
97 <!-- [qball][md.sys] atom Al12 aluminum 0.00000000 -3.82650000 3.82650000 0.00000000 0.00000000 0.00000000 -->
98 <!-- [qball][md.sys] atom Al13 aluminum 0.00000000 0.00000000 -7.65300000 0.00000000 0.00000000 0.00000000 -->
99 <!-- [qball][md.sys] atom Al14 aluminum 3.82650000 3.82650000 -7.65300000 0.00000000 0.00000000 0.00000000 -->
100 <!-- [qball][md.sys] atom Al15 aluminum 3.82650000 0.00000000 -3.82650000 0.00000000 0.00000000 0.00000000 -->
101 <!-- [qball][md.sys] atom Al16 aluminum 0.00000000 3.82650000 -3.82650000 0.00000000 0.00000000 0.00000000 -->
102 <!-- [qball][md.sys] atom Al17 aluminum 0.00000000 -7.65300000 -7.65300000 0.00000000 0.00000000 0.00000000 -->
103 <!-- [qball][md.sys] atom Al18 aluminum 3.82650000 -3.82650000 -7.65300000 0.00000000 0.00000000 0.00000000 -->
104 <!-- [qball][md.sys] atom Al19 aluminum 3.82650000 -7.65300000 -3.82650000 0.00000000 0.00000000 0.00000000 -->
105 <!-- [qball][md.sys] atom Al20 aluminum 0.00000000 -3.82650000 -3.82650000 0.00000000 0.00000000 0.00000000 -->
106 <!-- [qball][md.sys] atom Al21 aluminum -7.65300000 0.00000000 -7.65300000 0.00000000 0.00000000 0.00000000 -->
107 <!-- [qball][md.sys] atom Al22 aluminum -3.82650000 3.82650000 -7.65300000 0.00000000 0.00000000 0.00000000 -->
108 <!-- [qball][md.sys] atom Al23 aluminum -3.82650000 0.00000000 -3.82650000 0.00000000 0.00000000 0.00000000 -->
109 <!-- [qball][md.sys] atom Al24 aluminum -7.65300000 3.82650000 -3.82650000 0.00000000 0.00000000 0.00000000 -->
110 <!-- [qball][md.sys] atom Al25 aluminum -7.65300000 -7.65300000 0.00000000 0.00000000 0.00000000 0.00000000 -->
111 <!-- [qball][md.sys] atom Al26 aluminum -3.82650000 -3.82650000 0.00000000 0.00000000 0.00000000 0.00000000 -->
112 <!-- [qball][md.sys] atom Al27 aluminum -3.82650000 -7.65300000 3.82650000 0.00000000 0.00000000 0.00000000 -->
113 <!-- [qball][md.sys] atom Al28 aluminum -7.65300000 -3.82650000 3.82650000 0.00000000 0.00000000 0.00000000 -->
114 <!-- [qball][md.sys] atom Al29 aluminum -7.65300000 -7.65300000 -7.65300000 0.00000000 0.00000000 0.00000000 -->
115 <!-- [qball][md.sys] atom Al30 aluminum -3.82650000 -3.82650000 -7.65300000 0.00000000 0.00000000 0.00000000 -->
116 <!-- [qball][md.sys] atom Al31 aluminum -3.82650000 -7.65300000 -3.82650000 0.00000000 0.00000000 0.00000000 -->
117 <!-- [qball][md.sys] atom Al32 aluminum -7.65300000 -3.82650000 -3.82650000 0.00000000 0.00000000 0.00000000 -->
118 <!-- [qball][md.sys] -->
119 <!-- end of command stream -->
120 <!-- [qball] -->
121 <!-- [qball] set ecut 30 -->
122 <!-- [qball] set ecutprec 4.0 -->
123 <!-- [qball] set threshold_scf 1.E-6 5 -->
124 <!-- [qball] -->
125 <!-- [qball] set wf_dyn PSDA -->
126 <!-- [qball] set nempty 12 -->
127 <!-- [qball] set smearing fermi -->
128 <!-- [qball] set smearing_width 0.006333621 -->
129 <!-- [qball] set charge_mix_coeff 0.6 -->
130 <!-- [qball] -->
131 <!-- [qball] set wf_extrapolation NTC -->
132 <!-- [qball] -->
133 <!-- [qball] set atoms_dyn MD -->
134 <!-- [qball] set dt 41.341373 -->
135 <!-- [qball] -->
136 <!-- [qball] randomize_v 1000 -->
137 <WARNING> no such command or file name: randomize_v </WARNING>
138 <!-- [qball] reset_vcm -->
139 <!-- [qball] -->
140 <!-- [qball] load -states restart/md -->
141 <!-- Creating SlaterDet context 4x1 from spincontext, ispin = 0 -->
142 SlaterDet.resize: new c dimensions = 5020x60 (1255x60 blocks, local data size on pe 0 = 1255x60) -->
143 <!-- Updated occupation of wf -->
144 <!-- LoadCmd: setting MD iteration count to 1. -->
145 ChargeDensity: vbasis = 56 56 56, resize to 60 60 60
146 <!-- total_electronic_charge: 96.00000000, spin = 0 -->
147 <!-- LoadCmd: loading mixed charge density from file. -->
148 <!-- load timing : 0.1437 0.1459 -->
149 <!-- [qball] -->
150 <!-- [qball] run 20 200 5 -->
151 SlaterDet.resize: new c dimensions = 5020x60 (1255x60 blocks, local data size on pe 0 = 1255x60) -->
152 ChargeDensity: vbasis = 56 56 56, resize to 60 60 60
153 <!-- EnergyFunctional: charge density basis: 39799 plane waves, ngloc = 9942 -->
154 <!-- EnergyFunctional: np0v,np1v,np2v: 60 60 60 -->
155 <!-- EnergyFunctional: vft->np012(): 216000 -->
156 <!-- AtomSet.set_rcps: Ewald width for species aluminum is too small for reciprocal sum convergence, increasing rcps from 1.5000 to 1.0500 -->
157 <!-- Species aluminum: extending grid to rmax = 40.0000 to increase vnlg resolution (4096 pts) -->
158 SPECIES.ndft = 4096, np = 1087, rmax = 40.9600, gmax = 314.0826, hubbard_l = -1
159 <!-- Kleinman-Bylander normalization term wsg[0] = 5.2918 -->
160 <!-- Kleinman-Bylander normalization term wsg[1] = 15.2527 -->
161 <!-- AtomSet.set_rcps: Ewald width for species aluminum = 1.0500 -->
162 <!-- EnergyFunctional: number of images in real-space ewald sum = 0 for rckj = 1.4849 -->
163 <run niter_ionic="20" niter_scf="200" niter_nonscf="5">
164 <wavefunction ecut="15.0000" nspin="1" nel="96" nempty="12">
165 <cell a0="15.306000 0.000000 0.000000"
166 a1="0.000000 15.306000 0.000000"
167 a2="0.000000 0.000000 15.306000"/>
168 <reciprocal_lattice b0="0.410505 0.000000 0.000000"
169 b1="0.000000 0.410505 0.000000"
170 b2="0.000000 0.000000 0.410505"/>
171 <refcell a0="0.000000 0.000000 0.000000"
172 a1="0.000000 0.000000 0.000000"
173 a2="0.000000 0.000000 0.000000"/>
174 <slater_determinant kpoint="0.000000 0.000000 0.000000" weight="1.000000" size="60">
175 <!-- sdcontext: 4x1 -->
176 <grid nx="28" ny="28" nz="28"/>
177 <!-- basis size: 4970 -->
178 <!-- c dimensions: 5020x60 (1255x60 blocks) -->
179 <density_matrix form="diagonal" size="60">
180 </density_matrix>
181 </slater_determinant>
182 </wavefunction>
183 <!-- BOSampleStepper: fractional occupation detected. -->
184 SlaterDet.resize: new c dimensions = 5020x60 (1255x60 blocks, local data size on pe 0 = 1255x60) -->
185 <!-- Wavefunction::update_occ: sum = 96.000000 -->
186 <!-- Wavefunction::update_occ: using Fermi smearing, mu = 5.2701 eV, ispin = 0 -->
187 SlaterDet.resize: new c dimensions = 5020x60 (1255x60 blocks, local data size on pe 0 = 1255x60) -->
188 SlaterDet.resize: new c dimensions = 5020x60 (1255x60 blocks, local data size on pe 0 = 1255x60) -->
189 SlaterDet.resize: new c dimensions = 5020x60 (1255x60 blocks, local data size on pe 0 = 1255x60) -->
190 <iteration count="1">
191 <!-- total_electronic_charge: 96.00000000, spin = 0 -->
192 <ekin> 27.68898842 </ekin>
193 <eps> -5.91921370 </eps>
194 <enl> 11.87213023 </enl>
195 <ecoul> -74.73821340 </ecoul>
196 <exc> -25.63679332 </exc>
197 <esr> 0.00008151 </esr>
198 <eself> 109.42416834 </eself>
199 <ets> -0.02644462 </ets>
200 <etotal> -66.75954638 </etotal>
201 <atomset>
202 <unit_cell
203 a=" 15.30600000 0.00000000 0.00000000"
204 b=" 0.00000000 15.30600000 0.00000000"
205 c=" 0.00000000 0.00000000 15.30600000" />
206 <atom name="Al1" species="aluminum">
207 <position> 0.00000000 0.00000000 0.00000000 </position>
208 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
209 <force> 0.00000092 0.00000198 -0.00000107 </force>
210 </atom>
211 <atom name="Al2" species="aluminum">
212 <position> 3.82650000 3.82650000 0.00000000 </position>
213 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
214 <force> -0.00000026 -0.00000085 0.00000007 </force>
215 </atom>
216 <atom name="Al3" species="aluminum">
217 <position> 3.82650000 0.00000000 3.82650000 </position>
218 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
219 <force> 0.00000003 -0.00000241 -0.00000050 </force>
220 </atom>
221 <atom name="Al4" species="aluminum">
222 <position> 0.00000000 3.82650000 3.82650000 </position>
223 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
224 <force> -0.00000422 0.00000064 0.00000011 </force>
225 </atom>
226 <atom name="Al5" species="aluminum">
227 <position> -7.65300000 0.00000000 0.00000000 </position>
228 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
229 <force> -0.00000028 0.00000132 -0.00000007 </force>
230 </atom>
231 <atom name="Al6" species="aluminum">
232 <position> -3.82650000 3.82650000 0.00000000 </position>
233 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
234 <force> 0.00000026 -0.00000043 0.00000042 </force>
235 </atom>
236 <atom name="Al7" species="aluminum">
237 <position> -3.82650000 0.00000000 3.82650000 </position>
238 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
239 <force> 0.00000007 0.00000223 0.00000071 </force>
240 </atom>
241 <atom name="Al8" species="aluminum">
242 <position> -7.65300000 3.82650000 3.82650000 </position>
243 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
244 <force> 0.00000420 0.00000104 -0.00000012 </force>
245 </atom>
246 <atom name="Al9" species="aluminum">
247 <position> 0.00000000 -7.65300000 0.00000000 </position>
248 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
249 <force> 0.00000042 0.00000180 0.00000103 </force>
250 </atom>
251 <atom name="Al10" species="aluminum">
252 <position> 3.82650000 -3.82650000 0.00000000 </position>
253 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
254 <force> 0.00000020 -0.00000060 -0.00000004 </force>
255 </atom>
256 <atom name="Al11" species="aluminum">
257 <position> 3.82650000 -7.65300000 3.82650000 </position>
258 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
259 <force> -0.00000013 0.00000233 -0.00000075 </force>
260 </atom>
261 <atom name="Al12" species="aluminum">
262 <position> 0.00000000 -3.82650000 3.82650000 </position>
263 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
264 <force> 0.00000162 -0.00000010 -0.00000045 </force>
265 </atom>
266 <atom name="Al13" species="aluminum">
267 <position> 0.00000000 0.00000000 -7.65300000 </position>
268 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
269 <force> -0.00000067 -0.00000127 0.00000034 </force>
270 </atom>
271 <atom name="Al14" species="aluminum">
272 <position> 3.82650000 3.82650000 -7.65300000 </position>
273 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
274 <force> 0.00000030 0.00000060 -0.00000010 </force>
275 </atom>
276 <atom name="Al15" species="aluminum">
277 <position> 3.82650000 0.00000000 -3.82650000 </position>
278 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
279 <force> 0.00000026 -0.00000242 0.00000019 </force>
280 </atom>
281 <atom name="Al16" species="aluminum">
282 <position> 0.00000000 3.82650000 -3.82650000 </position>
283 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
284 <force> -0.00000180 -0.00000060 -0.00000033 </force>
285 </atom>
286 <atom name="Al17" species="aluminum">
287 <position> 0.00000000 -7.65300000 -7.65300000 </position>
288 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
289 <force> -0.00000135 -0.00000147 -0.00000054 </force>
290 </atom>
291 <atom name="Al18" species="aluminum">
292 <position> 3.82650000 -3.82650000 -7.65300000 </position>
293 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
294 <force> 0.00000020 0.00000118 0.00000081 </force>
295 </atom>
296 <atom name="Al19" species="aluminum">
297 <position> 3.82650000 -7.65300000 -3.82650000 </position>
298 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
299 <force> 0.00000030 0.00000289 -0.00000019 </force>
300 </atom>
301 <atom name="Al20" species="aluminum">
302 <position> 0.00000000 -3.82650000 -3.82650000 </position>
303 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
304 <force> 0.00000387 0.00000008 -0.00000021 </force>
305 </atom>
306 <atom name="Al21" species="aluminum">
307 <position> -7.65300000 0.00000000 -7.65300000 </position>
308 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
309 <force> -0.00000054 -0.00000264 -0.00000025 </force>
310 </atom>
311 <atom name="Al22" species="aluminum">
312 <position> -3.82650000 3.82650000 -7.65300000 </position>
313 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
314 <force> 0.00000039 0.00000123 -0.00000093 </force>
315 </atom>
316 <atom name="Al23" species="aluminum">
317 <position> -3.82650000 0.00000000 -3.82650000 </position>
318 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
319 <force> 0.00000021 0.00000206 0.00000002 </force>
320 </atom>
321 <atom name="Al24" species="aluminum">
322 <position> -7.65300000 3.82650000 -3.82650000 </position>
323 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
324 <force> 0.00000131 -0.00000054 0.00000079 </force>
325 </atom>
326 <atom name="Al25" species="aluminum">
327 <position> -7.65300000 -7.65300000 0.00000000 </position>
328 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
329 <force> 0.00000043 0.00000109 0.00000036 </force>
330 </atom>
331 <atom name="Al26" species="aluminum">
332 <position> -3.82650000 -3.82650000 0.00000000 </position>
333 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
334 <force> -0.00000036 -0.00000068 0.00000013 </force>
335 </atom>
336 <atom name="Al27" species="aluminum">
337 <position> -3.82650000 -7.65300000 3.82650000 </position>
338 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
339 <force> 0.00000009 -0.00000298 0.00000033 </force>
340 </atom>
341 <atom name="Al28" species="aluminum">
342 <position> -7.65300000 -3.82650000 3.82650000 </position>
343 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
344 <force> -0.00000169 -0.00000007 0.00000048 </force>
345 </atom>
346 <atom name="Al29" species="aluminum">
347 <position> -7.65300000 -7.65300000 -7.65300000 </position>
348 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
349 <force> 0.00000022 -0.00000153 0.00000049 </force>
350 </atom>
351 <atom name="Al30" species="aluminum">
352 <position> -3.82650000 -3.82650000 -7.65300000 </position>
353 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
354 <force> 0.00000019 0.00000063 0.00000014 </force>
355 </atom>
356 <atom name="Al31" species="aluminum">
357 <position> -3.82650000 -7.65300000 -3.82650000 </position>
358 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
359 <force> 0.00000015 -0.00000228 -0.00000033 </force>
360 </atom>
361 <atom name="Al32" species="aluminum">
362 <position> -7.65300000 -3.82650000 -3.82650000 </position>
363 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
364 <force> -0.00000438 0.00000059 -0.00000050 </force>
365 </atom>
366 </atomset>
367 <econst> -66.75954638 </econst>
368 <ekin_ion> 0.00000000 </ekin_ion>
369 <temp_ion> 0.00000000 </temp_ion>
370 <!-- EnergyFunctional: number of images in real-space ewald sum = 0 for rckj = 1.48492424 -->
371 Extrapolating wavefunction using NTC algorithm.
372 <!-- BOSampleStepper: start scf iteration -->
373 <!-- total_electronic_charge: 96.00000000, spin = 0 -->
374 <eigenvalue_sum> 4.10150168 </eigenvalue_sum>
375 <etotal_int scf_iter="0"> -66.75954638 </etotal_int>
376 <eharris> -66.75954638 </eharris>
377 <eigenvalue_sum> 4.10148751 </eigenvalue_sum>
378 <!-- Anderson extrapolation: theta = 5.70200055 ( using 2.00000000 ) -->
379 <etotal_int scf_iter="0"> -66.75954714 </etotal_int>
380 <eigenvalue_sum> 4.10144502 </eigenvalue_sum>
381 <!-- Anderson extrapolation: theta = 1.61523684 ( using 1.61523684 ) -->
382 <etotal_int scf_iter="0"> -66.75954876 </etotal_int>
383 <eigenvalue_sum> 4.10136224 </eigenvalue_sum>
384 <!-- Anderson extrapolation: theta = 0.35699216 ( using 0.35699216 ) -->
385 <etotal_int scf_iter="0"> -66.75955070 </etotal_int>
386 <eigenvalue_sum> 4.10131852 </eigenvalue_sum>
387 <!-- Anderson extrapolation: theta = 5.17847633 ( using 2.00000000 ) -->
388 <etotal_int scf_iter="0"> -66.75955072 </etotal_int>
389 <eigenvalues spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
390 -6.01941 -3.77018 -3.77016 -3.77015 -3.77014 -3.77014 -3.77011 -1.56567
391 -1.56567 -1.56567 -1.56565 -1.56564 -1.56563 -1.56563 -1.56563 -1.56563
392 -1.56562 -1.56561 -1.56561 0.55800 0.55800 0.55800 0.55801 0.64516
393 0.64517 0.64517 0.64518 2.19316 2.19316 2.19316 3.41195 3.41196
394 3.41197 4.23705 4.23706 4.23708 4.23708 4.23708 4.23709 4.23709
395 4.23710 4.23710 4.23710 4.23710 4.23711 5.27016 5.27018 5.27018
396 5.27018 5.27018 5.27020 5.95408 5.95409 5.95411 5.96335 5.97193
397 6.25325 6.29425 6.29425 6.29426
398 </eigenvalues>
399 <!-- Wavefunction::update_occ: sum = 96.00000 -->
400 <!-- Wavefunction::update_occ: using Fermi smearing, mu = 5.2701 eV, ispin = 0 -->
401 <occupation spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
402 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
403 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
404 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
405 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
406 2.0000 2.0000 2.0000 2.0000 2.0000 0.9996 0.9995 0.9995 0.9995 0.9994
407 0.9993 0.0007 0.0007 0.0007 0.0006 0.0006 0.0000 0.0000 0.0000 0.0000
408 </occupation>
409 <!-- Wavefunction entropy: 8.35076163 -->
410 <!-- Entropy contribution to free energy: -0.10578112 -->
411 <!-- BOSampleStepper: end scf iteration -->
412 <!-- BOSampleStepper: start scf iteration -->
413 <!-- total_electronic_charge: 96.00000000, spin = 0 -->
414 <eigenvalue_sum> 4.10121661 </eigenvalue_sum>
415 <etotal_int scf_iter="1"> -66.75954511 </etotal_int>
416 <eharris> -66.75954647 </eharris>
417 <eigenvalue_sum> 4.10120243 </eigenvalue_sum>
418 <!-- Anderson extrapolation: theta = 6.69459583 ( using 2.00000000 ) -->
419 <etotal_int scf_iter="1"> -66.75954471 </etotal_int>
420 <eigenvalue_sum> 4.10115985 </eigenvalue_sum>
421 <!-- Anderson extrapolation: theta = 2.00766753 ( using 2.00000000 ) -->
422 <etotal_int scf_iter="1"> -66.75954378 </etotal_int>
423 <eigenvalue_sum> 4.10106040 </eigenvalue_sum>
424 <!-- Anderson extrapolation: theta = 0.31723118 ( using 0.31723118 ) -->
425 <etotal_int scf_iter="1"> -66.75954216 </etotal_int>
426 <eigenvalue_sum> 4.10101456 </eigenvalue_sum>
427 <!-- Anderson extrapolation: theta = 5.39166432 ( using 2.00000000 ) -->
428 <etotal_int scf_iter="1"> -66.75954191 </etotal_int>
429 <eigenvalues spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
430 -6.01941 -3.77020 -3.77014 -3.77014 -3.77014 -3.77013 -3.77012 -1.56569
431 -1.56568 -1.56567 -1.56565 -1.56563 -1.56563 -1.56562 -1.56562 -1.56562
432 -1.56562 -1.56561 -1.56561 0.55799 0.55800 0.55800 0.55801 0.64516
433 0.64516 0.64516 0.64520 2.19316 2.19316 2.19316 3.41195 3.41196
434 3.41197 4.23705 4.23706 4.23707 4.23708 4.23708 4.23709 4.23709
435 4.23710 4.23711 4.23711 4.23711 4.23711 5.27016 5.27018 5.27018
436 5.27018 5.27019 5.27019 5.95409 5.95409 5.95411 5.96220 5.96971
437 6.24822 6.29424 6.29425 6.29426
438 </eigenvalues>
439 <!-- Wavefunction::update_occ: sum = 96.00000 -->
440 <!-- Wavefunction::update_occ: using Fermi smearing, mu = 5.2701 eV, ispin = 0 -->
441 <occupation spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
442 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
443 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
444 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
445 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
446 2.0000 2.0000 2.0000 2.0000 2.0000 0.9996 0.9995 0.9995 0.9995 0.9994
447 0.9994 0.0007 0.0007 0.0007 0.0006 0.0006 0.0000 0.0000 0.0000 0.0000
448 </occupation>
449 <!-- Wavefunction entropy: 8.35096795 -->
450 <!-- Entropy contribution to free energy: -0.10578373 -->
451 <!-- BOSampleStepper: end scf iteration -->
452 <!-- BOSampleStepper: start scf iteration -->
453 <!-- total_electronic_charge: 96.00000000, spin = 0 -->
454 AndersonMixer: theta = 0.39164250
455 <eigenvalue_sum> 4.10090858 </eigenvalue_sum>
456 <etotal_int scf_iter="2"> -66.75953866 </etotal_int>
457 <eharris> -66.75954655 </eharris>
458 <eigenvalue_sum> 4.10089424 </eigenvalue_sum>
459 <!-- Anderson extrapolation: theta = 8.26400053 ( using 2.00000000 ) -->
460 <etotal_int scf_iter="2"> -66.75953884 </etotal_int>
461 <eigenvalue_sum> 4.10085119 </eigenvalue_sum>
462 <!-- Anderson extrapolation: theta = 2.72962226 ( using 2.00000000 ) -->
463 <etotal_int scf_iter="2"> -66.75953921 </etotal_int>
464 <eigenvalue_sum> 4.10075049 </eigenvalue_sum>
465 <!-- Anderson extrapolation: theta = 0.80153834 ( using 0.80153834 ) -->
466 <etotal_int scf_iter="2"> -66.75953970 </etotal_int>
467 <eigenvalue_sum> 4.10065506 </eigenvalue_sum>
468 <!-- Anderson extrapolation: theta = 1.50926656 ( using 1.50926656 ) -->
469 <etotal_int scf_iter="2"> -66.75953975 </etotal_int>
470 <eigenvalues spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
471 -6.01941 -3.77018 -3.77016 -3.77014 -3.77014 -3.77014 -3.77012 -1.56568
472 -1.56566 -1.56566 -1.56565 -1.56565 -1.56563 -1.56563 -1.56563 -1.56562
473 -1.56562 -1.56562 -1.56561 0.55799 0.55800 0.55800 0.55801 0.64516
474 0.64516 0.64516 0.64519 2.19316 2.19316 2.19316 3.41195 3.41196
475 3.41197 4.23706 4.23707 4.23707 4.23708 4.23709 4.23709 4.23709
476 4.23710 4.23710 4.23710 4.23711 4.23711 5.27017 5.27018 5.27018
477 5.27018 5.27018 5.27019 5.95408 5.95409 5.95411 5.96086 5.96720
478 6.24086 6.29425 6.29425 6.29425
479 </eigenvalues>
480 <!-- Wavefunction::update_occ: sum = 96.00000 -->
481 <!-- Wavefunction::update_occ: using Fermi smearing, mu = 5.2701 eV, ispin = 0 -->
482 <occupation spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
483 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
484 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
485 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
486 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
487 2.0000 2.0000 2.0000 2.0000 2.0000 0.9995 0.9995 0.9995 0.9994 0.9994
488 0.9994 0.0007 0.0007 0.0007 0.0007 0.0006 0.0000 0.0000 0.0000 0.0000
489 </occupation>
490 <!-- Wavefunction entropy: 8.35121662 -->
491 <!-- Entropy contribution to free energy: -0.10578688 -->
492 <!-- BOSampleStepper: end scf iteration -->
493 <!-- BOSampleStepper: start scf iteration -->
494 <!-- total_electronic_charge: 96.00000000, spin = 0 -->
495 AndersonMixer: theta = 0.49266292 0.22500301
496 <eigenvalue_sum> 4.10049589 </eigenvalue_sum>
497 <etotal_int scf_iter="3"> -66.75953421 </etotal_int>
498 <eharris> -66.75954664 </eharris>
499 <eigenvalue_sum> 4.10048119 </eigenvalue_sum>
500 <!-- Anderson extrapolation: theta = 6.65291036 ( using 2.00000000 ) -->
501 <etotal_int scf_iter="3"> -66.75953394 </etotal_int>
502 <eigenvalue_sum> 4.10043699 </eigenvalue_sum>
503 <!-- Anderson extrapolation: theta = 1.94870971 ( using 1.94870971 ) -->
504 <etotal_int scf_iter="3"> -66.75953329 </etotal_int>
505 <eigenvalue_sum> 4.10033577 </eigenvalue_sum>
506 <!-- Anderson extrapolation: theta = 0.30628959 ( using 0.30628959 ) -->
507 <etotal_int scf_iter="3"> -66.75953216 </etotal_int>
508 <eigenvalue_sum> 4.10028973 </eigenvalue_sum>
509 <!-- Anderson extrapolation: theta = 6.70052592 ( using 2.00000000 ) -->
510 <etotal_int scf_iter="3"> -66.75953196 </etotal_int>
511 <eigenvalues spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
512 -6.01941 -3.77018 -3.77015 -3.77014 -3.77014 -3.77014 -3.77012 -1.56568
513 -1.56567 -1.56566 -1.56565 -1.56565 -1.56563 -1.56562 -1.56562 -1.56562
514 -1.56562 -1.56562 -1.56561 0.55799 0.55800 0.55800 0.55801 0.64516
515 0.64516 0.64516 0.64519 2.19316 2.19316 2.19316 3.41195 3.41196
516 3.41197 4.23706 4.23707 4.23708 4.23708 4.23708 4.23709 4.23709
517 4.23710 4.23710 4.23710 4.23711 4.23711 5.27017 5.27018 5.27018
518 5.27018 5.27018 5.27019 5.95408 5.95409 5.95410 5.96002 5.96560
519 6.23476 6.29425 6.29425 6.29426
520 </eigenvalues>
521 <!-- Wavefunction::update_occ: sum = 96.00000 -->
522 <!-- Wavefunction::update_occ: using Fermi smearing, mu = 5.2701 eV, ispin = 0 -->
523 <occupation spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
524 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
525 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
526 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
527 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
528 2.0000 2.0000 2.0000 2.0000 2.0000 0.9995 0.9995 0.9995 0.9994 0.9994
529 0.9994 0.0007 0.0007 0.0007 0.0007 0.0006 0.0000 0.0000 0.0000 0.0000
530 </occupation>
531 <!-- Wavefunction entropy: 8.35138168 -->
532 <!-- Entropy contribution to free energy: -0.10578897 -->
533 <!-- BOSampleStepper: end scf iteration -->
534 <!-- BOSampleStepper: start scf iteration -->
535 <!-- total_electronic_charge: 96.00000000, spin = 0 -->
536 AndersonMixer: theta = -0.61089823 0.34695262 0.57008570
537 <eigenvalue_sum> 4.10018240 </eigenvalue_sum>
538 <etotal_int scf_iter="4"> -66.75952718 </etotal_int>
539 <eharris> -66.75954671 </eharris>
540 <eigenvalue_sum> 4.10016729 </eigenvalue_sum>
541 <!-- Anderson extrapolation: theta = 8.02944050 ( using 2.00000000 ) -->
542 <etotal_int scf_iter="4"> -66.75952727 </etotal_int>
543 <eigenvalue_sum> 4.10012185 </eigenvalue_sum>
544 <!-- Anderson extrapolation: theta = 2.64681535 ( using 2.00000000 ) -->
545 <etotal_int scf_iter="4"> -66.75952745 </etotal_int>
546 <eigenvalue_sum> 4.10001534 </eigenvalue_sum>
547 <!-- Anderson extrapolation: theta = 0.78177714 ( using 0.78177714 ) -->
548 <etotal_int scf_iter="4"> -66.75952766 </etotal_int>
549 <eigenvalue_sum> 4.09991622 </eigenvalue_sum>
550 <!-- Anderson extrapolation: theta = 1.76833136 ( using 1.76833136 ) -->
551 <etotal_int scf_iter="4"> -66.75952763 </etotal_int>
552 <eigenvalues spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
553 -6.01941 -3.77017 -3.77016 -3.77014 -3.77014 -3.77014 -3.77012 -1.56567
554 -1.56566 -1.56565 -1.56565 -1.56565 -1.56563 -1.56563 -1.56563 -1.56562
555 -1.56562 -1.56562 -1.56561 0.55799 0.55800 0.55800 0.55801 0.64516
556 0.64516 0.64517 0.64519 2.19316 2.19316 2.19316 3.41195 3.41196
557 3.41197 4.23706 4.23707 4.23707 4.23708 4.23709 4.23709 4.23709
558 4.23710 4.23710 4.23710 4.23711 4.23711 5.27017 5.27018 5.27018
559 5.27018 5.27018 5.27019 5.95408 5.95409 5.95410 5.95899 5.96364
560 6.22528 6.29425 6.29425 6.29425
561 </eigenvalues>
562 <!-- Wavefunction::update_occ: sum = 96.00000 -->
563 <!-- Wavefunction::update_occ: using Fermi smearing, mu = 5.2701 eV, ispin = 0 -->
564 <occupation spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
565 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
566 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
567 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
568 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
569 2.0000 2.0000 2.0000 2.0000 2.0000 0.9995 0.9995 0.9994 0.9994 0.9994
570 0.9994 0.0007 0.0007 0.0007 0.0007 0.0006 0.0000 0.0000 0.0000 0.0000
571 </occupation>
572 <!-- Wavefunction entropy: 8.35159730 -->
573 <!-- Entropy contribution to free energy: -0.10579170 -->
574 <!-- BOSampleStepper: end scf iteration -->
575 <!-- BOSampleStepper: start scf iteration -->
576 <!-- total_electronic_charge: 95.99999999, spin = 0 -->
577 AndersonMixer: theta = 0.31564175 0.69739118 0.16503012
578 <eigenvalue_sum> 4.09972400 </eigenvalue_sum>
579 <etotal_int scf_iter="5"> -66.75952475 </etotal_int>
580 <eharris> -66.75954679 </eharris>
581 <eigenvalue_sum> 4.09970819 </eigenvalue_sum>
582 <!-- Anderson extrapolation: theta = 5.90720698 ( using 2.00000000 ) -->
583 <etotal_int scf_iter="5"> -66.75952460 </etotal_int>
584 <eigenvalue_sum> 4.09966063 </eigenvalue_sum>
585 <!-- Anderson extrapolation: theta = 1.58220995 ( using 1.58220995 ) -->
586 <etotal_int scf_iter="5"> -66.75952422 </etotal_int>
587 <eigenvalue_sum> 4.09956910 </eigenvalue_sum>
588 <!-- Anderson extrapolation: theta = 0.26624188 ( using 0.26624188 ) -->
589 <etotal_int scf_iter="5"> -66.75952363 </etotal_int>
590 <eigenvalue_sum> 4.09952854 </eigenvalue_sum>
591 <!-- Anderson extrapolation: theta = 6.82547046 ( using 2.00000000 ) -->
592 <etotal_int scf_iter="5"> -66.75952350 </etotal_int>
593 <eigenvalues spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
594 -6.01941 -3.77018 -3.77015 -3.77014 -3.77014 -3.77014 -3.77012 -1.56568
595 -1.56567 -1.56566 -1.56565 -1.56564 -1.56563 -1.56563 -1.56562 -1.56562
596 -1.56562 -1.56562 -1.56561 0.55799 0.55800 0.55800 0.55801 0.64516
597 0.64516 0.64516 0.64519 2.19316 2.19316 2.19316 3.41195 3.41196
598 3.41197 4.23705 4.23706 4.23708 4.23708 4.23708 4.23709 4.23709
599 4.23710 4.23710 4.23710 4.23711 4.23711 5.27017 5.27018 5.27018
600 5.27018 5.27018 5.27019 5.95408 5.95409 5.95410 5.95847 5.96261
601 6.21886 6.29425 6.29425 6.29426
602 </eigenvalues>
603 <!-- Wavefunction::update_occ: sum = 96.00000 -->
604 <!-- Wavefunction::update_occ: using Fermi smearing, mu = 5.2701 eV, ispin = 0 -->
605 <occupation spin="0" kpoint="0.00000000 0.00000000 0.00000000" n="60">
606 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
607 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
608 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
609 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000
610 2.0000 2.0000 2.0000 2.0000 2.0000 0.9995 0.9994 0.9994 0.9994 0.9994
611 0.9994 0.0007 0.0007 0.0007 0.0007 0.0006 0.0000 0.0000 0.0000 0.0000
612 </occupation>
613 <!-- Wavefunction entropy: 8.35171796 -->
614 <!-- Entropy contribution to free energy: -0.10579323 -->
615 <!-- BOSampleStepper: end scf iteration -->
616 <!-- BOSampleStepper: scf convergence at itscf = 6, Harris-Foulkes energy varied by less than 1.00e-06 a.u. over 5 scf steps. -->
617 <timing where="run" name=" iteration" min="4.585e+00" max="4.585e+00" count="1 "/>
618 </iteration>
619 <!-- memory nlp.twnl : 0.152 MB (0.038 MB local) -->
620 <!-- memory sd.psi : 4.550 MB (1.133 MB local) -->
621 <!-- memory sd.hpsi : 4.550 MB (1.133 MB local) -->
622 <!-- memory cd.rhor : 1.648 MB (0.412 MB local) -->
623 <!-- memory cd.rhog : 0.607 MB (0.152 MB local) -->
624 <!-- memory total : 11.507 MB (2.866 MB local) -->
625 <!-- total_electronic_charge: 96.00000000, spin = 0 -->
626 <!-- total_electronic_charge: 96.00000000, spin = 0 -->
627 </run>
628 <!-- [qball] -->
629 <!-- end of command stream -->
630 <real_time> 104.00126290 </real_time>
631 <end_time> 2016-11-26T06:42:19Z </end_time>
632 </qbox:simulation>
633 """)
634
635 with open('test.xml', 'w') as fd:
636 fd.write("""<?xml version="1.0" encoding="UTF-8"?>
637 <fpmd:simulation xmlns:fpmd="http://www.quantum-simulation.org/ns/fpmd/fpmd-1.0">
638 <uuid> 5bd1acfc-88da-11e7-bb1d-fa163ec3a82b </uuid>
639
640 ============================
641 I qbox 1.63.8 I
642 I I
643 I I
644 I I
645 I I
646 I I
647 I I
648 I I
649 I I
650 I I
651 I I
652 I I
653 I http://qboxcode.org I
654 ============================
655
656
657 <release> 1.63.8 centos7 </release>
658 <user> wardlt </user>
659 <sysname> Linux </sysname>
660 <nodename> js-168-106.jetstream-cloud.org </nodename>
661 <start_time> 2017-08-24T14:41:48Z </start_time>
662 <mpi_processes count="24">
663 <process id="0"> js-168-106.jetstream-cloud.org </process>
664 <process id="1"> js-168-106.jetstream-cloud.org </process>
665 <process id="2"> js-168-106.jetstream-cloud.org </process>
666 <process id="3"> js-168-106.jetstream-cloud.org </process>
667 <process id="4"> js-168-106.jetstream-cloud.org </process>
668 <process id="5"> js-168-106.jetstream-cloud.org </process>
669 <process id="6"> js-168-106.jetstream-cloud.org </process>
670 <process id="7"> js-168-106.jetstream-cloud.org </process>
671 <process id="8"> js-168-106.jetstream-cloud.org </process>
672 <process id="9"> js-168-106.jetstream-cloud.org </process>
673 <process id="10"> js-168-106.jetstream-cloud.org </process>
674 <process id="11"> js-168-106.jetstream-cloud.org </process>
675 <process id="12"> js-168-106.jetstream-cloud.org </process>
676 <process id="13"> js-168-106.jetstream-cloud.org </process>
677 <process id="14"> js-168-106.jetstream-cloud.org </process>
678 <process id="15"> js-168-106.jetstream-cloud.org </process>
679 <process id="16"> js-168-106.jetstream-cloud.org </process>
680 <process id="17"> js-168-106.jetstream-cloud.org </process>
681 <process id="18"> js-168-106.jetstream-cloud.org </process>
682 <process id="19"> js-168-106.jetstream-cloud.org </process>
683 <process id="20"> js-168-106.jetstream-cloud.org </process>
684 <process id="21"> js-168-106.jetstream-cloud.org </process>
685 <process id="22"> js-168-106.jetstream-cloud.org </process>
686 <process id="23"> js-168-106.jetstream-cloud.org </process>
687 </mpi_processes>
688 [qbox] <cmd># Si4 CP dynamics</cmd>
689 [qbox] <cmd>load ../si4gs/test.xml</cmd>
690 LoadCmd: loading from ../si4gs/test.xml
691 XMLGFPreprocessor: reading from ../si4gs/test.xml size: 358009
692 XMLGFPreprocessor: read time: 0.00014
693 XMLGFPreprocessor: local read rate: 101.6 MB/s aggregate read rate: 2440 MB/s
694 XMLGFPreprocessor: tag fixing time: 8.607e-05
695 XMLGFPreprocessor: segment definition time: 0.001074
696 XMLGFPreprocessor: boundary adjustment time: 4.053e-06
697 XMLGFPreprocessor: transcoding time: 3.099e-06
698 XMLGFPreprocessor: data redistribution time: 0.001073
699 XMLGFPreprocessor: XML compacting time: 0.0005789
700 XMLGFPreprocessor: total time: 0.003368
701 xmlcontent.size(): 120537
702 Starting XML parsing
703
704 species silicon:
705 <species name="silicon">
706 <description>
707 Translated from UPF format by upf2qso
708 Generated using unknown code
709 Author: Von Barth-Car ( 1984)
710 Info: automatically converted from PWSCF format
711 0 The Pseudo was generated with a Non-Relativistic Calculation
712 0.00000000000E+00 Local Potential cutoff radius
713 nl pn l occ Rcut Rcut US E pseu
714 3S 0 0 2.00 0.00000000000 0.00000000000 0.00000000000
715 3P 0 1 2.00 0.00000000000 0.00000000000 0.00000000000
716 SLA PZ NOGX NOGC
717 </description>
718 <symbol>Si</symbol>
719 <atomic_number>14</atomic_number>
720 <mass>28.09</mass>
721 <norm_conserving_pseudopotential>
722 <valence_charge>4</valence_charge>
723 <lmax>2</lmax>
724 <llocal>2</llocal>
725 <nquad>0</nquad>
726 <rquad>0</rquad>
727 <mesh_spacing>0.01</mesh_spacing>
728 </norm_conserving_pseudopotential>
729 </species>
730 Kleinman-Bylander potential
731 rcps_ = 1.5
732 WavefunctionHandler::startElement: wavefunction nspin=1 nel=16 nempty=0
733 WavefunctionHandler::startElement: slater_determinant
734 kpoint=0 0 0 weight=1 size=8
735 WavefunctionHandler::endElement: slater_determinant
736 XML parsing done
737 SampleReader: read time: 0.03573 s
738 [qbox] <cmd>set wf_dyn MD</cmd>
739 [qbox] <cmd>set atoms_dyn MD</cmd>
740 [qbox] <cmd>set dt 4</cmd>
741 [qbox] <cmd>set stress ON</cmd>
742 [qbox] <cmd>run 5</cmd>
743 EnergyFunctional: np0v,np1v,np2v: 30 30 30
744 EnergyFunctional: vft->np012(): 27000
745 <wavefunction ecut="3" nspin="1" nel="16" nempty="0">
746 <cell a="16.000000 0.000000 0.000000"
747 b="0.000000 16.000000 0.000000"
748 c="0.000000 0.000000 16.000000"/>
749 reciprocal lattice vectors
750 0.392699 0.000000 0.000000
751 0.000000 0.392699 0.000000
752 0.000000 0.000000 0.392699
753 <refcell a="0.000000 0.000000 0.000000"
754 b="0.000000 0.000000 0.000000"
755 c="0.000000 0.000000 0.000000"/>
756 <grid nx="14" ny="14" nz="14"/>
757 kpoint: 0.000000 0.000000 0.000000 weight: 1.000000
758 <slater_determinant kpoint="0.000000 0.000000 0.000000" size="8">
759 sdcontext: 24x1
760 basis size: 511
761 c dimensions: 696x8 (29x8 blocks)
762 <density_matrix form="diagonal" size="8">
763 </density_matrix>
764 </slater_determinant>
765 </wavefunction>
766 total_electronic_charge: 16.00000000
767 <iteration count="1">
768 <ekin> 5.34839594 </ekin>
769 <econf> 0.00000000 </econf>
770 <eps> -5.48138503 </eps>
771 <enl> 4.77521434 </enl>
772 <ecoul> -15.60248424 </ecoul>
773 <exc> -4.41268616 </exc>
774 <esr> 0.07326880 </esr>
775 <eself> 17.02153730 </eself>
776 <ets> 0.00000000 </ets>
777 <eexf> 0.00000000 </eexf>
778 <etotal> -15.37294515 </etotal>
779 <epv> 0.00000000 </epv>
780 <eefield> 0.00000000 </eefield>
781 <enthalpy> -15.37294515 </enthalpy>
782 <atomset>
783 <unit_cell
784 a=" 16.00000000 0.00000000 0.00000000"
785 b=" 0.00000000 16.00000000 0.00000000"
786 c=" 0.00000000 0.00000000 16.00000000" />
787 <atom name="Si1" species="silicon">
788 <position> 3.70000044 -0.00000000 -0.00000000 </position>
789 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
790 <force> 0.00284439 -0.00000004 -0.00000759 </force>
791 </atom>
792 <atom name="Si2" species="silicon">
793 <position> -0.00000000 2.20000267 0.00000000 </position>
794 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
795 <force> -0.00000030 0.01705795 0.00000984 </force>
796 </atom>
797 <atom name="Si3" species="silicon">
798 <position> -3.70000044 -0.00000000 -0.00000000 </position>
799 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
800 <force> -0.00284289 -0.00000006 -0.00000896 </force>
801 </atom>
802 <atom name="Si4" species="silicon">
803 <position> -0.00000000 -2.20000267 0.00000000 </position>
804 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
805 <force> -0.00000029 -0.01705787 0.00000764 </force>
806 </atom>
807 </atomset>
808 <ekin_e> 0.00000000 </ekin_e>
809 <ekin_ion> 0.00000000 </ekin_ion>
810 <temp_ion> 0.00000000 </temp_ion>
811 <eta_ion> 0.00000000 </eta_ion>
812 <econst> -15.37294515 </econst>
813 <ekin_ec> -15.37294515 </ekin_ec>
814 <stress_tensor unit="GPa">
815 <sigma_eks_xx> -0.40316092 </sigma_eks_xx>
816 <sigma_eks_yy> -1.11691203 </sigma_eks_yy>
817 <sigma_eks_zz> -1.39125067 </sigma_eks_zz>
818 <sigma_eks_xy> -0.00000015 </sigma_eks_xy>
819 <sigma_eks_yz> 0.00001892 </sigma_eks_yz>
820 <sigma_eks_xz> -0.00002269 </sigma_eks_xz>
821
822 <sigma_kin_xx> 0.00000000 </sigma_kin_xx>
823 <sigma_kin_yy> 0.00000000 </sigma_kin_yy>
824 <sigma_kin_zz> 0.00000000 </sigma_kin_zz>
825 <sigma_kin_xy> 0.00000000 </sigma_kin_xy>
826 <sigma_kin_yz> 0.00000000 </sigma_kin_yz>
827 <sigma_kin_xz> 0.00000000 </sigma_kin_xz>
828
829 <sigma_ext_xx> 0.00000000 </sigma_ext_xx>
830 <sigma_ext_yy> 0.00000000 </sigma_ext_yy>
831 <sigma_ext_zz> 0.00000000 </sigma_ext_zz>
832 <sigma_ext_xy> 0.00000000 </sigma_ext_xy>
833 <sigma_ext_yz> 0.00000000 </sigma_ext_yz>
834 <sigma_ext_xz> 0.00000000 </sigma_ext_xz>
835
836 <sigma_xx> -0.40316092 </sigma_xx>
837 <sigma_yy> -1.11691203 </sigma_yy>
838 <sigma_zz> -1.39125067 </sigma_zz>
839 <sigma_xy> -0.00000015 </sigma_xy>
840 <sigma_yz> 0.00001892 </sigma_yz>
841 <sigma_xz> -0.00002269 </sigma_xz>
842 </stress_tensor>
843 total_electronic_charge: 16.00000000
844 </iteration>
845 <timing name="iteration" min="0.003" max="0.003"/>
846 <iteration count="2">
847 <ekin> 5.34839594 </ekin>
848 <econf> 0.00000000 </econf>
849 <eps> -5.48138456 </eps>
850 <enl> 4.77521478 </enl>
851 <ecoul> -15.60248525 </ecoul>
852 <exc> -4.41268616 </exc>
853 <esr> 0.07326840 </esr>
854 <eself> 17.02153730 </eself>
855 <ets> 0.00000000 </ets>
856 <eexf> 0.00000000 </eexf>
857 <etotal> -15.37294524 </etotal>
858 <epv> 0.00000000 </epv>
859 <eefield> 0.00000000 </eefield>
860 <enthalpy> -15.37294524 </enthalpy>
861 <atomset>
862 <unit_cell
863 a=" 16.00000000 0.00000000 0.00000000"
864 b=" 0.00000000 16.00000000 0.00000000"
865 c=" 0.00000000 0.00000000 16.00000000" />
866 <atom name="Si1" species="silicon">
867 <position> 3.70000178 -0.00000000 -0.00000000 </position>
868 <velocity> 0.00000022 -0.00000000 -0.00000000 </velocity>
869 <force> 0.00284244 -0.00000004 -0.00000759 </force>
870 </atom>
871 <atom name="Si2" species="silicon">
872 <position> -0.00000000 2.20001066 0.00000001 </position>
873 <velocity> -0.00000000 0.00000133 0.00000000 </velocity>
874 <force> -0.00000030 0.01705370 0.00000982 </force>
875 </atom>
876 <atom name="Si3" species="silicon">
877 <position> -3.70000178 -0.00000000 -0.00000001 </position>
878 <velocity> -0.00000022 -0.00000000 -0.00000000 </velocity>
879 <force> -0.00284094 -0.00000006 -0.00000895 </force>
880 </atom>
881 <atom name="Si4" species="silicon">
882 <position> -0.00000000 -2.20001066 0.00000000 </position>
883 <velocity> -0.00000000 -0.00000133 0.00000000 </velocity>
884 <force> -0.00000029 -0.01705361 0.00000763 </force>
885 </atom>
886 </atomset>
887 <ekin_e> 0.00000000 </ekin_e>
888 <ekin_ion> 0.00000009 </ekin_ion>
889 <temp_ion> 0.00491777 </temp_ion>
890 <eta_ion> 0.00000000 </eta_ion>
891 <econst> -15.37294515 </econst>
892 <ekin_ec> -15.37294515 </ekin_ec>
893 <stress_tensor unit="GPa">
894 <sigma_eks_xx> -0.40318581 </sigma_eks_xx>
895 <sigma_eks_yy> -1.11691708 </sigma_eks_yy>
896 <sigma_eks_zz> -1.39122938 </sigma_eks_zz>
897 <sigma_eks_xy> -0.00000015 </sigma_eks_xy>
898 <sigma_eks_yz> 0.00001885 </sigma_eks_yz>
899 <sigma_eks_xz> -0.00002278 </sigma_eks_xz>
900
901 <sigma_kin_xx> 0.00000004 </sigma_kin_xx>
902 <sigma_kin_yy> 0.00000131 </sigma_kin_yy>
903 <sigma_kin_zz> 0.00000000 </sigma_kin_zz>
904 <sigma_kin_xy> -0.00000000 </sigma_kin_xy>
905 <sigma_kin_yz> 0.00000000 </sigma_kin_yz>
906 <sigma_kin_xz> 0.00000000 </sigma_kin_xz>
907
908 <sigma_ext_xx> 0.00000000 </sigma_ext_xx>
909 <sigma_ext_yy> 0.00000000 </sigma_ext_yy>
910 <sigma_ext_zz> 0.00000000 </sigma_ext_zz>
911 <sigma_ext_xy> 0.00000000 </sigma_ext_xy>
912 <sigma_ext_yz> 0.00000000 </sigma_ext_yz>
913 <sigma_ext_xz> 0.00000000 </sigma_ext_xz>
914
915 <sigma_xx> -0.40318578 </sigma_xx>
916 <sigma_yy> -1.11691578 </sigma_yy>
917 <sigma_zz> -1.39122938 </sigma_zz>
918 <sigma_xy> -0.00000015 </sigma_xy>
919 <sigma_yz> 0.00001885 </sigma_yz>
920 <sigma_xz> -0.00002278 </sigma_xz>
921 </stress_tensor>
922 total_electronic_charge: 16.00000000
923 </iteration>
924 <timing name="iteration" min="0.002" max="0.002"/>
925 <iteration count="3">
926 <ekin> 5.34839575 </ekin>
927 <econf> 0.00000000 </econf>
928 <eps> -5.48138300 </eps>
929 <enl> 4.77521599 </enl>
930 <ecoul> -15.60248818 </ecoul>
931 <exc> -4.41268608 </exc>
932 <esr> 0.07326719 </esr>
933 <eself> 17.02153730 </eself>
934 <ets> 0.00000000 </ets>
935 <eexf> 0.00000000 </eexf>
936 <etotal> -15.37294552 </etotal>
937 <epv> 0.00000000 </epv>
938 <eefield> 0.00000000 </eefield>
939 <enthalpy> -15.37294552 </enthalpy>
940 <atomset>
941 <unit_cell
942 a=" 16.00000000 0.00000000 0.00000000"
943 b=" 0.00000000 16.00000000 0.00000000"
944 c=" 0.00000000 0.00000000 16.00000000" />
945 <atom name="Si1" species="silicon">
946 <position> 3.70000400 -0.00000000 -0.00000001 </position>
947 <velocity> 0.00000044 -0.00000000 -0.00000000 </velocity>
948 <force> 0.00283676 -0.00000004 -0.00000758 </force>
949 </atom>
950 <atom name="Si2" species="silicon">
951 <position> -0.00000000 2.20002398 0.00000001 </position>
952 <velocity> -0.00000000 0.00000266 0.00000000 </velocity>
953 <force> -0.00000029 0.01704131 0.00000976 </force>
954 </atom>
955 <atom name="Si3" species="silicon">
956 <position> -3.70000399 -0.00000000 -0.00000001 </position>
957 <velocity> -0.00000044 -0.00000000 -0.00000000 </velocity>
958 <force> -0.00283528 -0.00000006 -0.00000889 </force>
959 </atom>
960 <atom name="Si4" species="silicon">
961 <position> -0.00000000 -2.20002398 0.00000001 </position>
962 <velocity> -0.00000000 -0.00000266 0.00000000 </velocity>
963 <force> -0.00000028 -0.01704123 0.00000759 </force>
964 </atom>
965 </atomset>
966 <ekin_e> 0.00000000 </ekin_e>
967 <ekin_ion> 0.00000037 </ekin_ion>
968 <temp_ion> 0.01966104 </temp_ion>
969 <eta_ion> 0.00000000 </eta_ion>
970 <econst> -15.37294515 </econst>
971 <ekin_ec> -15.37294515 </ekin_ec>
972 <stress_tensor unit="GPa">
973 <sigma_eks_xx> -0.40325935 </sigma_eks_xx>
974 <sigma_eks_yy> -1.11693283 </sigma_eks_yy>
975 <sigma_eks_zz> -1.39116835 </sigma_eks_zz>
976 <sigma_eks_xy> -0.00000015 </sigma_eks_xy>
977 <sigma_eks_yz> 0.00001865 </sigma_eks_yz>
978 <sigma_eks_xz> -0.00002306 </sigma_eks_xz>
979
980 <sigma_kin_xx> 0.00000014 </sigma_kin_xx>
981 <sigma_kin_yy> 0.00000522 </sigma_kin_yy>
982 <sigma_kin_zz> 0.00000000 </sigma_kin_zz>
983 <sigma_kin_xy> -0.00000000 </sigma_kin_xy>
984 <sigma_kin_yz> 0.00000000 </sigma_kin_yz>
985 <sigma_kin_xz> 0.00000000 </sigma_kin_xz>
986
987 <sigma_ext_xx> 0.00000000 </sigma_ext_xx>
988 <sigma_ext_yy> 0.00000000 </sigma_ext_yy>
989 <sigma_ext_zz> 0.00000000 </sigma_ext_zz>
990 <sigma_ext_xy> 0.00000000 </sigma_ext_xy>
991 <sigma_ext_yz> 0.00000000 </sigma_ext_yz>
992 <sigma_ext_xz> 0.00000000 </sigma_ext_xz>
993
994 <sigma_xx> -0.40325920 </sigma_xx>
995 <sigma_yy> -1.11692760 </sigma_yy>
996 <sigma_zz> -1.39116835 </sigma_zz>
997 <sigma_xy> -0.00000015 </sigma_xy>
998 <sigma_yz> 0.00001865 </sigma_yz>
999 <sigma_xz> -0.00002306 </sigma_xz>
1000 </stress_tensor>
1001 total_electronic_charge: 16.00000000
1002 </iteration>
1003 <timing name="iteration" min="0.002" max="0.002"/>
1004 <iteration count="4">
1005 <ekin> 5.34839478 </ekin>
1006 <econf> 0.00000000 </econf>
1007 <eps> -5.48137994 </eps>
1008 <enl> 4.77521759 </enl>
1009 <ecoul> -15.60249275 </ecoul>
1010 <exc> -4.41268567 </exc>
1011 <esr> 0.07326517 </esr>
1012 <eself> 17.02153730 </eself>
1013 <ets> 0.00000000 </ets>
1014 <eexf> 0.00000000 </eexf>
1015 <etotal> -15.37294599 </etotal>
1016 <epv> 0.00000000 </epv>
1017 <eefield> 0.00000000 </eefield>
1018 <enthalpy> -15.37294599 </enthalpy>
1019 <atomset>
1020 <unit_cell
1021 a=" 16.00000000 0.00000000 0.00000000"
1022 b=" 0.00000000 16.00000000 0.00000000"
1023 c=" 0.00000000 0.00000000 16.00000000" />
1024 <atom name="Si1" species="silicon">
1025 <position> 3.70000710 -0.00000000 -0.00000002 </position>
1026 <velocity> 0.00000067 -0.00000000 -0.00000000 </velocity>
1027 <force> 0.00282791 -0.00000003 -0.00000756 </force>
1028 </atom>
1029 <atom name="Si2" species="silicon">
1030 <position> -0.00000000 2.20004262 0.00000002 </position>
1031 <velocity> -0.00000000 0.00000400 0.00000000 </velocity>
1032 <force> -0.00000028 0.01702190 0.00000967 </force>
1033 </atom>
1034 <atom name="Si3" species="silicon">
1035 <position> -3.70000710 -0.00000000 -0.00000002 </position>
1036 <velocity> -0.00000066 -0.00000000 -0.00000000 </velocity>
1037 <force> -0.00282646 -0.00000005 -0.00000879 </force>
1038 </atom>
1039 <atom name="Si4" species="silicon">
1040 <position> -0.00000000 -2.20004262 0.00000002 </position>
1041 <velocity> -0.00000000 -0.00000400 0.00000000 </velocity>
1042 <force> -0.00000027 -0.01702182 0.00000754 </force>
1043 </atom>
1044 </atomset>
1045 <ekin_e> 0.00000000 </ekin_e>
1046 <ekin_ion> 0.00000084 </ekin_ion>
1047 <temp_ion> 0.04420103 </temp_ion>
1048 <eta_ion> 0.00000000 </eta_ion>
1049 <econst> -15.37294515 </econst>
1050 <ekin_ec> -15.37294515 </ekin_ec>
1051 <stress_tensor unit="GPa">
1052 <sigma_eks_xx> -0.40337818 </sigma_eks_xx>
1053 <sigma_eks_yy> -1.11696101 </sigma_eks_yy>
1054 <sigma_eks_zz> -1.39107579 </sigma_eks_zz>
1055 <sigma_eks_xy> -0.00000014 </sigma_eks_xy>
1056 <sigma_eks_yz> 0.00001831 </sigma_eks_yz>
1057 <sigma_eks_xz> -0.00002349 </sigma_eks_xz>
1058
1059 <sigma_kin_xx> 0.00000033 </sigma_kin_xx>
1060 <sigma_kin_yy> 0.00001174 </sigma_kin_yy>
1061 <sigma_kin_zz> 0.00000000 </sigma_kin_zz>
1062 <sigma_kin_xy> -0.00000000 </sigma_kin_xy>
1063 <sigma_kin_yz> 0.00000000 </sigma_kin_yz>
1064 <sigma_kin_xz> 0.00000000 </sigma_kin_xz>
1065
1066 <sigma_ext_xx> 0.00000000 </sigma_ext_xx>
1067 <sigma_ext_yy> 0.00000000 </sigma_ext_yy>
1068 <sigma_ext_zz> 0.00000000 </sigma_ext_zz>
1069 <sigma_ext_xy> 0.00000000 </sigma_ext_xy>
1070 <sigma_ext_yz> 0.00000000 </sigma_ext_yz>
1071 <sigma_ext_xz> 0.00000000 </sigma_ext_xz>
1072
1073 <sigma_xx> -0.40337786 </sigma_xx>
1074 <sigma_yy> -1.11694927 </sigma_yy>
1075 <sigma_zz> -1.39107579 </sigma_zz>
1076 <sigma_xy> -0.00000014 </sigma_xy>
1077 <sigma_yz> 0.00001831 </sigma_yz>
1078 <sigma_xz> -0.00002349 </sigma_xz>
1079 </stress_tensor>
1080 total_electronic_charge: 16.00000000
1081 </iteration>
1082 <timing name="iteration" min="0.010" max="0.010"/>
1083 <iteration count="5">
1084 <ekin> 5.34839213 </ekin>
1085 <econf> 0.00000000 </econf>
1086 <eps> -5.48137474 </eps>
1087 <enl> 4.77521902 </enl>
1088 <ecoul> -15.60249850 </ecoul>
1089 <exc> -4.41268455 </exc>
1090 <esr> 0.07326235 </esr>
1091 <eself> 17.02153730 </eself>
1092 <ets> 0.00000000 </ets>
1093 <eexf> 0.00000000 </eexf>
1094 <etotal> -15.37294664 </etotal>
1095 <epv> 0.00000000 </epv>
1096 <eefield> 0.00000000 </eefield>
1097 <enthalpy> -15.37294664 </enthalpy>
1098 <atomset>
1099 <unit_cell
1100 a=" 16.00000000 0.00000000 0.00000000"
1101 b=" 0.00000000 16.00000000 0.00000000"
1102 c=" 0.00000000 0.00000000 16.00000000" />
1103 <atom name="Si1" species="silicon">
1104 <position> 3.70001108 -0.00000000 -0.00000003 </position>
1105 <velocity> 0.00000089 -0.00000000 -0.00000000 </velocity>
1106 <force> 0.00281674 -0.00000003 -0.00000752 </force>
1107 </atom>
1108 <atom name="Si2" species="silicon">
1109 <position> -0.00000000 2.20006657 0.00000004 </position>
1110 <velocity> -0.00000000 0.00000532 0.00000000 </velocity>
1111 <force> -0.00000027 0.01699715 0.00000953 </force>
1112 </atom>
1113 <atom name="Si3" species="silicon">
1114 <position> -3.70001108 -0.00000000 -0.00000003 </position>
1115 <velocity> -0.00000089 -0.00000000 -0.00000000 </velocity>
1116 <force> -0.00281533 -0.00000005 -0.00000865 </force>
1117 </atom>
1118 <atom name="Si4" species="silicon">
1119 <position> -0.00000000 -2.20006657 0.00000003 </position>
1120 <velocity> -0.00000000 -0.00000532 0.00000000 </velocity>
1121 <force> -0.00000026 -0.01699708 0.00000746 </force>
1122 </atom>
1123 </atomset>
1124 <ekin_e> 0.00000000 </ekin_e>
1125 <ekin_ion> 0.00000149 </ekin_ion>
1126 <temp_ion> 0.07849411 </temp_ion>
1127 <eta_ion> 0.00000000 </eta_ion>
1128 <econst> -15.37294515 </econst>
1129 <ekin_ec> -15.37294515 </ekin_ec>
1130 <stress_tensor unit="GPa">
1131 <sigma_eks_xx> -0.40353719 </sigma_eks_xx>
1132 <sigma_eks_yy> -1.11700470 </sigma_eks_yy>
1133 <sigma_eks_zz> -1.39096418 </sigma_eks_zz>
1134 <sigma_eks_xy> -0.00000014 </sigma_eks_xy>
1135 <sigma_eks_yz> 0.00001786 </sigma_eks_yz>
1136 <sigma_eks_xz> -0.00002405 </sigma_eks_xz>
1137
1138 <sigma_kin_xx> 0.00000058 </sigma_kin_xx>
1139 <sigma_kin_yy> 0.00002085 </sigma_kin_yy>
1140 <sigma_kin_zz> 0.00000000 </sigma_kin_zz>
1141 <sigma_kin_xy> -0.00000000 </sigma_kin_xy>
1142 <sigma_kin_yz> 0.00000000 </sigma_kin_yz>
1143 <sigma_kin_xz> 0.00000000 </sigma_kin_xz>
1144
1145 <sigma_ext_xx> 0.00000000 </sigma_ext_xx>
1146 <sigma_ext_yy> 0.00000000 </sigma_ext_yy>
1147 <sigma_ext_zz> 0.00000000 </sigma_ext_zz>
1148 <sigma_ext_xy> 0.00000000 </sigma_ext_xy>
1149 <sigma_ext_yz> 0.00000000 </sigma_ext_yz>
1150 <sigma_ext_xz> 0.00000000 </sigma_ext_xz>
1151
1152 <sigma_xx> -0.40353661 </sigma_xx>
1153 <sigma_yy> -1.11698386 </sigma_yy>
1154 <sigma_zz> -1.39096418 </sigma_zz>
1155 <sigma_xy> -0.00000014 </sigma_xy>
1156 <sigma_yz> 0.00001786 </sigma_yz>
1157 <sigma_xz> -0.00002405 </sigma_xz>
1158 </stress_tensor>
1159 total_electronic_charge: 16.00000000
1160 </iteration>
1161 <timing name="iteration" min="0.002" max="0.002"/>
1162 <timing name="charge" min="0.004" max="0.012"/>
1163 <timing name="ekin_e" min="0.000" max="0.000"/>
1164 <timing name="md_update_wf" min="0.000" max="0.000"/>
1165 <timing name="riccati" min="0.001" max="0.001"/>
1166 <timing name="ekin" min="0.000" max="0.001"/>
1167 <timing name="exc" min="0.001" max="0.001"/>
1168 <timing name="hpsi" min="0.004" max="0.004"/>
1169 <timing name="nonlocal" min="0.002" max="0.002"/>
1170 <timing name="charge_compute" min="0.000" max="0.011"/>
1171 <timing name="charge_integral" min="0.000" max="0.011"/>
1172 <timing name="charge_rowsum" min="0.000" max="0.000"/>
1173 <timing name="charge_vft" min="0.001" max="0.001"/>
1174 [qbox] End of command stream
1175 <real_time> 15.469 </real_time>
1176 <end_time> 2017-08-24T14:41:48Z </end_time>
1177 </fpmd:simulation>
1178 """)
+0
-542
ase/test/qbox/test.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <fpmd:simulation xmlns:fpmd="http://www.quantum-simulation.org/ns/fpmd/fpmd-1.0">
2 <uuid> 5bd1acfc-88da-11e7-bb1d-fa163ec3a82b </uuid>
3
4 ============================
5 I qbox 1.63.8 I
6 I I
7 I I
8 I I
9 I I
10 I I
11 I I
12 I I
13 I I
14 I I
15 I I
16 I I
17 I http://qboxcode.org I
18 ============================
19
20
21 <release> 1.63.8 centos7 </release>
22 <user> wardlt </user>
23 <sysname> Linux </sysname>
24 <nodename> js-168-106.jetstream-cloud.org </nodename>
25 <start_time> 2017-08-24T14:41:48Z </start_time>
26 <mpi_processes count="24">
27 <process id="0"> js-168-106.jetstream-cloud.org </process>
28 <process id="1"> js-168-106.jetstream-cloud.org </process>
29 <process id="2"> js-168-106.jetstream-cloud.org </process>
30 <process id="3"> js-168-106.jetstream-cloud.org </process>
31 <process id="4"> js-168-106.jetstream-cloud.org </process>
32 <process id="5"> js-168-106.jetstream-cloud.org </process>
33 <process id="6"> js-168-106.jetstream-cloud.org </process>
34 <process id="7"> js-168-106.jetstream-cloud.org </process>
35 <process id="8"> js-168-106.jetstream-cloud.org </process>
36 <process id="9"> js-168-106.jetstream-cloud.org </process>
37 <process id="10"> js-168-106.jetstream-cloud.org </process>
38 <process id="11"> js-168-106.jetstream-cloud.org </process>
39 <process id="12"> js-168-106.jetstream-cloud.org </process>
40 <process id="13"> js-168-106.jetstream-cloud.org </process>
41 <process id="14"> js-168-106.jetstream-cloud.org </process>
42 <process id="15"> js-168-106.jetstream-cloud.org </process>
43 <process id="16"> js-168-106.jetstream-cloud.org </process>
44 <process id="17"> js-168-106.jetstream-cloud.org </process>
45 <process id="18"> js-168-106.jetstream-cloud.org </process>
46 <process id="19"> js-168-106.jetstream-cloud.org </process>
47 <process id="20"> js-168-106.jetstream-cloud.org </process>
48 <process id="21"> js-168-106.jetstream-cloud.org </process>
49 <process id="22"> js-168-106.jetstream-cloud.org </process>
50 <process id="23"> js-168-106.jetstream-cloud.org </process>
51 </mpi_processes>
52 [qbox] <cmd># Si4 CP dynamics</cmd>
53 [qbox] <cmd>load ../si4gs/test.xml</cmd>
54 LoadCmd: loading from ../si4gs/test.xml
55 XMLGFPreprocessor: reading from ../si4gs/test.xml size: 358009
56 XMLGFPreprocessor: read time: 0.00014
57 XMLGFPreprocessor: local read rate: 101.6 MB/s aggregate read rate: 2440 MB/s
58 XMLGFPreprocessor: tag fixing time: 8.607e-05
59 XMLGFPreprocessor: segment definition time: 0.001074
60 XMLGFPreprocessor: boundary adjustment time: 4.053e-06
61 XMLGFPreprocessor: transcoding time: 3.099e-06
62 XMLGFPreprocessor: data redistribution time: 0.001073
63 XMLGFPreprocessor: XML compacting time: 0.0005789
64 XMLGFPreprocessor: total time: 0.003368
65 xmlcontent.size(): 120537
66 Starting XML parsing
67
68 species silicon:
69 <species name="silicon">
70 <description>
71 Translated from UPF format by upf2qso
72 Generated using unknown code
73 Author: Von Barth-Car ( 1984)
74 Info: automatically converted from PWSCF format
75 0 The Pseudo was generated with a Non-Relativistic Calculation
76 0.00000000000E+00 Local Potential cutoff radius
77 nl pn l occ Rcut Rcut US E pseu
78 3S 0 0 2.00 0.00000000000 0.00000000000 0.00000000000
79 3P 0 1 2.00 0.00000000000 0.00000000000 0.00000000000
80 SLA PZ NOGX NOGC
81 </description>
82 <symbol>Si</symbol>
83 <atomic_number>14</atomic_number>
84 <mass>28.09</mass>
85 <norm_conserving_pseudopotential>
86 <valence_charge>4</valence_charge>
87 <lmax>2</lmax>
88 <llocal>2</llocal>
89 <nquad>0</nquad>
90 <rquad>0</rquad>
91 <mesh_spacing>0.01</mesh_spacing>
92 </norm_conserving_pseudopotential>
93 </species>
94 Kleinman-Bylander potential
95 rcps_ = 1.5
96 WavefunctionHandler::startElement: wavefunction nspin=1 nel=16 nempty=0
97 WavefunctionHandler::startElement: slater_determinant
98 kpoint=0 0 0 weight=1 size=8
99 WavefunctionHandler::endElement: slater_determinant
100 XML parsing done
101 SampleReader: read time: 0.03573 s
102 [qbox] <cmd>set wf_dyn MD</cmd>
103 [qbox] <cmd>set atoms_dyn MD</cmd>
104 [qbox] <cmd>set dt 4</cmd>
105 [qbox] <cmd>set stress ON</cmd>
106 [qbox] <cmd>run 5</cmd>
107 EnergyFunctional: np0v,np1v,np2v: 30 30 30
108 EnergyFunctional: vft->np012(): 27000
109 <wavefunction ecut="3" nspin="1" nel="16" nempty="0">
110 <cell a="16.000000 0.000000 0.000000"
111 b="0.000000 16.000000 0.000000"
112 c="0.000000 0.000000 16.000000"/>
113 reciprocal lattice vectors
114 0.392699 0.000000 0.000000
115 0.000000 0.392699 0.000000
116 0.000000 0.000000 0.392699
117 <refcell a="0.000000 0.000000 0.000000"
118 b="0.000000 0.000000 0.000000"
119 c="0.000000 0.000000 0.000000"/>
120 <grid nx="14" ny="14" nz="14"/>
121 kpoint: 0.000000 0.000000 0.000000 weight: 1.000000
122 <slater_determinant kpoint="0.000000 0.000000 0.000000" size="8">
123 sdcontext: 24x1
124 basis size: 511
125 c dimensions: 696x8 (29x8 blocks)
126 <density_matrix form="diagonal" size="8">
127 </density_matrix>
128 </slater_determinant>
129 </wavefunction>
130 total_electronic_charge: 16.00000000
131 <iteration count="1">
132 <ekin> 5.34839594 </ekin>
133 <econf> 0.00000000 </econf>
134 <eps> -5.48138503 </eps>
135 <enl> 4.77521434 </enl>
136 <ecoul> -15.60248424 </ecoul>
137 <exc> -4.41268616 </exc>
138 <esr> 0.07326880 </esr>
139 <eself> 17.02153730 </eself>
140 <ets> 0.00000000 </ets>
141 <eexf> 0.00000000 </eexf>
142 <etotal> -15.37294515 </etotal>
143 <epv> 0.00000000 </epv>
144 <eefield> 0.00000000 </eefield>
145 <enthalpy> -15.37294515 </enthalpy>
146 <atomset>
147 <unit_cell
148 a=" 16.00000000 0.00000000 0.00000000"
149 b=" 0.00000000 16.00000000 0.00000000"
150 c=" 0.00000000 0.00000000 16.00000000" />
151 <atom name="Si1" species="silicon">
152 <position> 3.70000044 -0.00000000 -0.00000000 </position>
153 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
154 <force> 0.00284439 -0.00000004 -0.00000759 </force>
155 </atom>
156 <atom name="Si2" species="silicon">
157 <position> -0.00000000 2.20000267 0.00000000 </position>
158 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
159 <force> -0.00000030 0.01705795 0.00000984 </force>
160 </atom>
161 <atom name="Si3" species="silicon">
162 <position> -3.70000044 -0.00000000 -0.00000000 </position>
163 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
164 <force> -0.00284289 -0.00000006 -0.00000896 </force>
165 </atom>
166 <atom name="Si4" species="silicon">
167 <position> -0.00000000 -2.20000267 0.00000000 </position>
168 <velocity> 0.00000000 0.00000000 0.00000000 </velocity>
169 <force> -0.00000029 -0.01705787 0.00000764 </force>
170 </atom>
171 </atomset>
172 <ekin_e> 0.00000000 </ekin_e>
173 <ekin_ion> 0.00000000 </ekin_ion>
174 <temp_ion> 0.00000000 </temp_ion>
175 <eta_ion> 0.00000000 </eta_ion>
176 <econst> -15.37294515 </econst>
177 <ekin_ec> -15.37294515 </ekin_ec>
178 <stress_tensor unit="GPa">
179 <sigma_eks_xx> -0.40316092 </sigma_eks_xx>
180 <sigma_eks_yy> -1.11691203 </sigma_eks_yy>
181 <sigma_eks_zz> -1.39125067 </sigma_eks_zz>
182 <sigma_eks_xy> -0.00000015 </sigma_eks_xy>
183 <sigma_eks_yz> 0.00001892 </sigma_eks_yz>
184 <sigma_eks_xz> -0.00002269 </sigma_eks_xz>
185
186 <sigma_kin_xx> 0.00000000 </sigma_kin_xx>
187 <sigma_kin_yy> 0.00000000 </sigma_kin_yy>
188 <sigma_kin_zz> 0.00000000 </sigma_kin_zz>
189 <sigma_kin_xy> 0.00000000 </sigma_kin_xy>
190 <sigma_kin_yz> 0.00000000 </sigma_kin_yz>
191 <sigma_kin_xz> 0.00000000 </sigma_kin_xz>
192
193 <sigma_ext_xx> 0.00000000 </sigma_ext_xx>
194 <sigma_ext_yy> 0.00000000 </sigma_ext_yy>
195 <sigma_ext_zz> 0.00000000 </sigma_ext_zz>
196 <sigma_ext_xy> 0.00000000 </sigma_ext_xy>
197 <sigma_ext_yz> 0.00000000 </sigma_ext_yz>
198 <sigma_ext_xz> 0.00000000 </sigma_ext_xz>
199
200 <sigma_xx> -0.40316092 </sigma_xx>
201 <sigma_yy> -1.11691203 </sigma_yy>
202 <sigma_zz> -1.39125067 </sigma_zz>
203 <sigma_xy> -0.00000015 </sigma_xy>
204 <sigma_yz> 0.00001892 </sigma_yz>
205 <sigma_xz> -0.00002269 </sigma_xz>
206 </stress_tensor>
207 total_electronic_charge: 16.00000000
208 </iteration>
209 <timing name="iteration" min="0.003" max="0.003"/>
210 <iteration count="2">
211 <ekin> 5.34839594 </ekin>
212 <econf> 0.00000000 </econf>
213 <eps> -5.48138456 </eps>
214 <enl> 4.77521478 </enl>
215 <ecoul> -15.60248525 </ecoul>
216 <exc> -4.41268616 </exc>
217 <esr> 0.07326840 </esr>
218 <eself> 17.02153730 </eself>
219 <ets> 0.00000000 </ets>
220 <eexf> 0.00000000 </eexf>
221 <etotal> -15.37294524 </etotal>
222 <epv> 0.00000000 </epv>
223 <eefield> 0.00000000 </eefield>
224 <enthalpy> -15.37294524 </enthalpy>
225 <atomset>
226 <unit_cell
227 a=" 16.00000000 0.00000000 0.00000000"
228 b=" 0.00000000 16.00000000 0.00000000"
229 c=" 0.00000000 0.00000000 16.00000000" />
230 <atom name="Si1" species="silicon">
231 <position> 3.70000178 -0.00000000 -0.00000000 </position>
232 <velocity> 0.00000022 -0.00000000 -0.00000000 </velocity>
233 <force> 0.00284244 -0.00000004 -0.00000759 </force>
234 </atom>
235 <atom name="Si2" species="silicon">
236 <position> -0.00000000 2.20001066 0.00000001 </position>
237 <velocity> -0.00000000 0.00000133 0.00000000 </velocity>
238 <force> -0.00000030 0.01705370 0.00000982 </force>
239 </atom>
240 <atom name="Si3" species="silicon">
241 <position> -3.70000178 -0.00000000 -0.00000001 </position>
242 <velocity> -0.00000022 -0.00000000 -0.00000000 </velocity>
243 <force> -0.00284094 -0.00000006 -0.00000895 </force>
244 </atom>
245 <atom name="Si4" species="silicon">
246 <position> -0.00000000 -2.20001066 0.00000000 </position>
247 <velocity> -0.00000000 -0.00000133 0.00000000 </velocity>
248 <force> -0.00000029 -0.01705361 0.00000763 </force>
249 </atom>
250 </atomset>
251 <ekin_e> 0.00000000 </ekin_e>
252 <ekin_ion> 0.00000009 </ekin_ion>
253 <temp_ion> 0.00491777 </temp_ion>
254 <eta_ion> 0.00000000 </eta_ion>
255 <econst> -15.37294515 </econst>
256 <ekin_ec> -15.37294515 </ekin_ec>
257 <stress_tensor unit="GPa">
258 <sigma_eks_xx> -0.40318581 </sigma_eks_xx>
259 <sigma_eks_yy> -1.11691708 </sigma_eks_yy>
260 <sigma_eks_zz> -1.39122938 </sigma_eks_zz>
261 <sigma_eks_xy> -0.00000015 </sigma_eks_xy>
262 <sigma_eks_yz> 0.00001885 </sigma_eks_yz>
263 <sigma_eks_xz> -0.00002278 </sigma_eks_xz>
264
265 <sigma_kin_xx> 0.00000004 </sigma_kin_xx>
266 <sigma_kin_yy> 0.00000131 </sigma_kin_yy>
267 <sigma_kin_zz> 0.00000000 </sigma_kin_zz>
268 <sigma_kin_xy> -0.00000000 </sigma_kin_xy>
269 <sigma_kin_yz> 0.00000000 </sigma_kin_yz>
270 <sigma_kin_xz> 0.00000000 </sigma_kin_xz>
271
272 <sigma_ext_xx> 0.00000000 </sigma_ext_xx>
273 <sigma_ext_yy> 0.00000000 </sigma_ext_yy>
274 <sigma_ext_zz> 0.00000000 </sigma_ext_zz>
275 <sigma_ext_xy> 0.00000000 </sigma_ext_xy>
276 <sigma_ext_yz> 0.00000000 </sigma_ext_yz>
277 <sigma_ext_xz> 0.00000000 </sigma_ext_xz>
278
279 <sigma_xx> -0.40318578 </sigma_xx>
280 <sigma_yy> -1.11691578 </sigma_yy>
281 <sigma_zz> -1.39122938 </sigma_zz>
282 <sigma_xy> -0.00000015 </sigma_xy>
283 <sigma_yz> 0.00001885 </sigma_yz>
284 <sigma_xz> -0.00002278 </sigma_xz>
285 </stress_tensor>
286 total_electronic_charge: 16.00000000
287 </iteration>
288 <timing name="iteration" min="0.002" max="0.002"/>
289 <iteration count="3">
290 <ekin> 5.34839575 </ekin>
291 <econf> 0.00000000 </econf>
292 <eps> -5.48138300 </eps>
293 <enl> 4.77521599 </enl>
294 <ecoul> -15.60248818 </ecoul>
295 <exc> -4.41268608 </exc>
296 <esr> 0.07326719 </esr>
297 <eself> 17.02153730 </eself>
298 <ets> 0.00000000 </ets>
299 <eexf> 0.00000000 </eexf>
300 <etotal> -15.37294552 </etotal>
301 <epv> 0.00000000 </epv>
302 <eefield> 0.00000000 </eefield>
303 <enthalpy> -15.37294552 </enthalpy>
304 <atomset>
305 <unit_cell
306 a=" 16.00000000 0.00000000 0.00000000"
307 b=" 0.00000000 16.00000000 0.00000000"
308 c=" 0.00000000 0.00000000 16.00000000" />
309 <atom name="Si1" species="silicon">
310 <position> 3.70000400 -0.00000000 -0.00000001 </position>
311 <velocity> 0.00000044 -0.00000000 -0.00000000 </velocity>
312 <force> 0.00283676 -0.00000004 -0.00000758 </force>
313 </atom>
314 <atom name="Si2" species="silicon">
315 <position> -0.00000000 2.20002398 0.00000001 </position>
316 <velocity> -0.00000000 0.00000266 0.00000000 </velocity>
317 <force> -0.00000029 0.01704131 0.00000976 </force>
318 </atom>
319 <atom name="Si3" species="silicon">
320 <position> -3.70000399 -0.00000000 -0.00000001 </position>
321 <velocity> -0.00000044 -0.00000000 -0.00000000 </velocity>
322 <force> -0.00283528 -0.00000006 -0.00000889 </force>
323 </atom>
324 <atom name="Si4" species="silicon">
325 <position> -0.00000000 -2.20002398 0.00000001 </position>
326 <velocity> -0.00000000 -0.00000266 0.00000000 </velocity>
327 <force> -0.00000028 -0.01704123 0.00000759 </force>
328 </atom>
329 </atomset>
330 <ekin_e> 0.00000000 </ekin_e>
331 <ekin_ion> 0.00000037 </ekin_ion>
332 <temp_ion> 0.01966104 </temp_ion>
333 <eta_ion> 0.00000000 </eta_ion>
334 <econst> -15.37294515 </econst>
335 <ekin_ec> -15.37294515 </ekin_ec>
336 <stress_tensor unit="GPa">
337 <sigma_eks_xx> -0.40325935 </sigma_eks_xx>
338 <sigma_eks_yy> -1.11693283 </sigma_eks_yy>
339 <sigma_eks_zz> -1.39116835 </sigma_eks_zz>
340 <sigma_eks_xy> -0.00000015 </sigma_eks_xy>
341 <sigma_eks_yz> 0.00001865 </sigma_eks_yz>
342 <sigma_eks_xz> -0.00002306 </sigma_eks_xz>
343
344 <sigma_kin_xx> 0.00000014 </sigma_kin_xx>
345 <sigma_kin_yy> 0.00000522 </sigma_kin_yy>
346 <sigma_kin_zz> 0.00000000 </sigma_kin_zz>
347 <sigma_kin_xy> -0.00000000 </sigma_kin_xy>
348 <sigma_kin_yz> 0.00000000 </sigma_kin_yz>
349 <sigma_kin_xz> 0.00000000 </sigma_kin_xz>
350
351 <sigma_ext_xx> 0.00000000 </sigma_ext_xx>
352 <sigma_ext_yy> 0.00000000 </sigma_ext_yy>
353 <sigma_ext_zz> 0.00000000 </sigma_ext_zz>
354 <sigma_ext_xy> 0.00000000 </sigma_ext_xy>
355 <sigma_ext_yz> 0.00000000 </sigma_ext_yz>
356 <sigma_ext_xz> 0.00000000 </sigma_ext_xz>
357
358 <sigma_xx> -0.40325920 </sigma_xx>
359 <sigma_yy> -1.11692760 </sigma_yy>
360 <sigma_zz> -1.39116835 </sigma_zz>
361 <sigma_xy> -0.00000015 </sigma_xy>
362 <sigma_yz> 0.00001865 </sigma_yz>
363 <sigma_xz> -0.00002306 </sigma_xz>
364 </stress_tensor>
365 total_electronic_charge: 16.00000000
366 </iteration>
367 <timing name="iteration" min="0.002" max="0.002"/>
368 <iteration count="4">
369 <ekin> 5.34839478 </ekin>
370 <econf> 0.00000000 </econf>
371 <eps> -5.48137994 </eps>
372 <enl> 4.77521759 </enl>
373 <ecoul> -15.60249275 </ecoul>
374 <exc> -4.41268567 </exc>
375 <esr> 0.07326517 </esr>
376 <eself> 17.02153730 </eself>
377 <ets> 0.00000000 </ets>
378 <eexf> 0.00000000 </eexf>
379 <etotal> -15.37294599 </etotal>
380 <epv> 0.00000000 </epv>
381 <eefield> 0.00000000 </eefield>
382 <enthalpy> -15.37294599 </enthalpy>
383 <atomset>
384 <unit_cell
385 a=" 16.00000000 0.00000000 0.00000000"
386 b=" 0.00000000 16.00000000 0.00000000"
387 c=" 0.00000000 0.00000000 16.00000000" />
388 <atom name="Si1" species="silicon">
389 <position> 3.70000710 -0.00000000 -0.00000002 </position>
390 <velocity> 0.00000067 -0.00000000 -0.00000000 </velocity>
391 <force> 0.00282791 -0.00000003 -0.00000756 </force>
392 </atom>
393 <atom name="Si2" species="silicon">
394 <position> -0.00000000 2.20004262 0.00000002 </position>
395 <velocity> -0.00000000 0.00000400 0.00000000 </velocity>
396 <force> -0.00000028 0.01702190 0.00000967 </force>
397 </atom>
398 <atom name="Si3" species="silicon">
399 <position> -3.70000710 -0.00000000 -0.00000002 </position>
400 <velocity> -0.00000066 -0.00000000 -0.00000000 </velocity>
401 <force> -0.00282646 -0.00000005 -0.00000879 </force>
402 </atom>
403 <atom name="Si4" species="silicon">
404 <position> -0.00000000 -2.20004262 0.00000002 </position>
405 <velocity> -0.00000000 -0.00000400 0.00000000 </velocity>
406 <force> -0.00000027 -0.01702182 0.00000754 </force>
407 </atom>
408 </atomset>
409 <ekin_e> 0.00000000 </ekin_e>
410 <ekin_ion> 0.00000084 </ekin_ion>
411 <temp_ion> 0.04420103 </temp_ion>
412 <eta_ion> 0.00000000 </eta_ion>
413 <econst> -15.37294515 </econst>
414 <ekin_ec> -15.37294515 </ekin_ec>
415 <stress_tensor unit="GPa">
416 <sigma_eks_xx> -0.40337818 </sigma_eks_xx>
417 <sigma_eks_yy> -1.11696101 </sigma_eks_yy>
418 <sigma_eks_zz> -1.39107579 </sigma_eks_zz>
419 <sigma_eks_xy> -0.00000014 </sigma_eks_xy>
420 <sigma_eks_yz> 0.00001831 </sigma_eks_yz>
421 <sigma_eks_xz> -0.00002349 </sigma_eks_xz>
422
423 <sigma_kin_xx> 0.00000033 </sigma_kin_xx>
424 <sigma_kin_yy> 0.00001174 </sigma_kin_yy>
425 <sigma_kin_zz> 0.00000000 </sigma_kin_zz>
426 <sigma_kin_xy> -0.00000000 </sigma_kin_xy>
427 <sigma_kin_yz> 0.00000000 </sigma_kin_yz>
428 <sigma_kin_xz> 0.00000000 </sigma_kin_xz>
429
430 <sigma_ext_xx> 0.00000000 </sigma_ext_xx>
431 <sigma_ext_yy> 0.00000000 </sigma_ext_yy>
432 <sigma_ext_zz> 0.00000000 </sigma_ext_zz>
433 <sigma_ext_xy> 0.00000000 </sigma_ext_xy>
434 <sigma_ext_yz> 0.00000000 </sigma_ext_yz>
435 <sigma_ext_xz> 0.00000000 </sigma_ext_xz>
436
437 <sigma_xx> -0.40337786 </sigma_xx>
438 <sigma_yy> -1.11694927 </sigma_yy>
439 <sigma_zz> -1.39107579 </sigma_zz>
440 <sigma_xy> -0.00000014 </sigma_xy>
441 <sigma_yz> 0.00001831 </sigma_yz>
442 <sigma_xz> -0.00002349 </sigma_xz>
443 </stress_tensor>
444 total_electronic_charge: 16.00000000
445 </iteration>
446 <timing name="iteration" min="0.010" max="0.010"/>
447 <iteration count="5">
448 <ekin> 5.34839213 </ekin>
449 <econf> 0.00000000 </econf>
450 <eps> -5.48137474 </eps>
451 <enl> 4.77521902 </enl>
452 <ecoul> -15.60249850 </ecoul>
453 <exc> -4.41268455 </exc>
454 <esr> 0.07326235 </esr>
455 <eself> 17.02153730 </eself>
456 <ets> 0.00000000 </ets>
457 <eexf> 0.00000000 </eexf>
458 <etotal> -15.37294664 </etotal>
459 <epv> 0.00000000 </epv>
460 <eefield> 0.00000000 </eefield>
461 <enthalpy> -15.37294664 </enthalpy>
462 <atomset>
463 <unit_cell
464 a=" 16.00000000 0.00000000 0.00000000"
465 b=" 0.00000000 16.00000000 0.00000000"
466 c=" 0.00000000 0.00000000 16.00000000" />
467 <atom name="Si1" species="silicon">
468 <position> 3.70001108 -0.00000000 -0.00000003 </position>
469 <velocity> 0.00000089 -0.00000000 -0.00000000 </velocity>
470 <force> 0.00281674 -0.00000003 -0.00000752 </force>
471 </atom>
472 <atom name="Si2" species="silicon">
473 <position> -0.00000000 2.20006657 0.00000004 </position>
474 <velocity> -0.00000000 0.00000532 0.00000000 </velocity>
475 <force> -0.00000027 0.01699715 0.00000953 </force>
476 </atom>
477 <atom name="Si3" species="silicon">
478 <position> -3.70001108 -0.00000000 -0.00000003 </position>
479 <velocity> -0.00000089 -0.00000000 -0.00000000 </velocity>
480 <force> -0.00281533 -0.00000005 -0.00000865 </force>
481 </atom>
482 <atom name="Si4" species="silicon">
483 <position> -0.00000000 -2.20006657 0.00000003 </position>
484 <velocity> -0.00000000 -0.00000532 0.00000000 </velocity>
485 <force> -0.00000026 -0.01699708 0.00000746 </force>
486 </atom>
487 </atomset>
488 <ekin_e> 0.00000000 </ekin_e>
489 <ekin_ion> 0.00000149 </ekin_ion>
490 <temp_ion> 0.07849411 </temp_ion>
491 <eta_ion> 0.00000000 </eta_ion>
492 <econst> -15.37294515 </econst>
493 <ekin_ec> -15.37294515 </ekin_ec>
494 <stress_tensor unit="GPa">
495 <sigma_eks_xx> -0.40353719 </sigma_eks_xx>
496 <sigma_eks_yy> -1.11700470 </sigma_eks_yy>
497 <sigma_eks_zz> -1.39096418 </sigma_eks_zz>
498 <sigma_eks_xy> -0.00000014 </sigma_eks_xy>
499 <sigma_eks_yz> 0.00001786 </sigma_eks_yz>
500 <sigma_eks_xz> -0.00002405 </sigma_eks_xz>
501
502 <sigma_kin_xx> 0.00000058 </sigma_kin_xx>
503 <sigma_kin_yy> 0.00002085 </sigma_kin_yy>
504 <sigma_kin_zz> 0.00000000 </sigma_kin_zz>
505 <sigma_kin_xy> -0.00000000 </sigma_kin_xy>
506 <sigma_kin_yz> 0.00000000 </sigma_kin_yz>
507 <sigma_kin_xz> 0.00000000 </sigma_kin_xz>
508
509 <sigma_ext_xx> 0.00000000 </sigma_ext_xx>
510 <sigma_ext_yy> 0.00000000 </sigma_ext_yy>
511 <sigma_ext_zz> 0.00000000 </sigma_ext_zz>
512 <sigma_ext_xy> 0.00000000 </sigma_ext_xy>
513 <sigma_ext_yz> 0.00000000 </sigma_ext_yz>
514 <sigma_ext_xz> 0.00000000 </sigma_ext_xz>
515
516 <sigma_xx> -0.40353661 </sigma_xx>
517 <sigma_yy> -1.11698386 </sigma_yy>
518 <sigma_zz> -1.39096418 </sigma_zz>
519 <sigma_xy> -0.00000014 </sigma_xy>
520 <sigma_yz> 0.00001786 </sigma_yz>
521 <sigma_xz> -0.00002405 </sigma_xz>
522 </stress_tensor>
523 total_electronic_charge: 16.00000000
524 </iteration>
525 <timing name="iteration" min="0.002" max="0.002"/>
526 <timing name="charge" min="0.004" max="0.012"/>
527 <timing name="ekin_e" min="0.000" max="0.000"/>
528 <timing name="md_update_wf" min="0.000" max="0.000"/>
529 <timing name="riccati" min="0.001" max="0.001"/>
530 <timing name="ekin" min="0.000" max="0.001"/>
531 <timing name="exc" min="0.001" max="0.001"/>
532 <timing name="hpsi" min="0.004" max="0.004"/>
533 <timing name="nonlocal" min="0.002" max="0.002"/>
534 <timing name="charge_compute" min="0.000" max="0.011"/>
535 <timing name="charge_integral" min="0.000" max="0.011"/>
536 <timing name="charge_rowsum" min="0.000" max="0.000"/>
537 <timing name="charge_vft" min="0.001" max="0.001"/>
538 [qbox] End of command stream
539 <real_time> 15.469 </real_time>
540 <end_time> 2017-08-24T14:41:48Z </end_time>
541 </fpmd:simulation>
11 print(s22)
22 for a in s22:
33 print(a)
4 assert a in s22
5
6 for name in s22.names:
7 assert s22.has(name)
8 assert not s22.has('hello')
0 """Example, in order to run you must place a pseudopotential 'Na.psf' in
1 the folder"""
2
3 from ase.units import Ry, eV, Ha
4 from ase.calculators.siesta import Siesta
5 from ase import Atoms
6 import numpy as np
7 import matplotlib.pyplot as plt
8
9 # Define the systems
10 Na8 = Atoms('Na8',
11 positions=[[-1.90503810, 1.56107288, 0.00000000],
12 [1.90503810, 1.56107288, 0.00000000],
13 [1.90503810, -1.56107288, 0.00000000],
14 [-1.90503810, -1.56107288, 0.00000000],
15 [0.00000000, 0.00000000, 2.08495836],
16 [0.00000000, 0.00000000, -2.08495836],
17 [0.00000000, 3.22798122, 2.08495836],
18 [0.00000000, 3.22798122, -2.08495836]],
19 cell=[20, 20, 20])
20
21 # enter siesta input
22 siesta = Siesta(
23 mesh_cutoff=150 * Ry,
24 basis_set='DZP',
25 pseudo_qualifier='',
26 energy_shift=(10 * 10**-3) * eV,
27 fdf_arguments={
28 'SCFMustConverge': False,
29 'COOP.Write': True,
30 'WriteDenchar': True,
31 'PAO.BasisType': 'split',
32 'DM.Tolerance': 1e-4,
33 'DM.MixingWeight': 0.01,
34 'MaxSCFIterations': 300,
35 'DM.NumberPulay': 4,
36 'XML.Write': True})
37
38
39 Na8.set_calculator(siesta)
40 e = Na8.get_potential_energy()
41 siesta.pyscf_tddft(label="siesta", jcutoff=7, iter_broadening=0.15/Ha,
42 xc_code='LDA,PZ', tol_loc=1e-6, tol_biloc=1e-7, freq = np.arange(0.0, 5.0, 0.05))
43
44 # plot polarizability
45 fig = plt.figure(1)
46 ax1 = fig.add_subplot(121)
47 ax2 = fig.add_subplot(122)
48 ax1.plot(siesta.results["freq range"], siesta.results["polarizability nonin"][:, 0, 0].imag)
49 ax2.plot(siesta.results["freq range"], siesta.results["polarizability inter"][:, 0, 0].imag)
50
51 ax1.set_xlabel(r"$\omega$ (eV)")
52 ax2.set_xlabel(r"$\omega$ (eV)")
53
54 ax1.set_ylabel(r"Im($P_{xx}$) (au)")
55 ax2.set_ylabel(r"Im($P_{xx}$) (au)")
56
57 ax1.set_title(r"Non interacting")
58 ax2.set_title(r"Interacting")
59
60 fig.tight_layout()
61
62 plt.show()
0 """Example, in order to run you must place a pseudopotential 'Na.psf' in
1 the folder"""
2
3 from ase.units import Ry, eV, Ha
4 from ase.calculators.siesta import Siesta
5 from ase import Atoms
6 import numpy as np
7 import matplotlib.pyplot as plt
8
9 # Define the systems
10 Na8 = Atoms('Na8',
11 positions=[[-1.90503810, 1.56107288, 0.00000000],
12 [1.90503810, 1.56107288, 0.00000000],
13 [1.90503810, -1.56107288, 0.00000000],
14 [-1.90503810, -1.56107288, 0.00000000],
15 [0.00000000, 0.00000000, 2.08495836],
16 [0.00000000, 0.00000000, -2.08495836],
17 [0.00000000, 3.22798122, 2.08495836],
18 [0.00000000, 3.22798122, -2.08495836]],
19 cell=[20, 20, 20])
20
21 # enter siesta input
22 siesta = Siesta(
23 mesh_cutoff=150 * Ry,
24 basis_set='DZP',
25 pseudo_qualifier='',
26 energy_shift=(10 * 10**-3) * eV,
27 fdf_arguments={
28 'SCFMustConverge': False,
29 'COOP.Write': True,
30 'WriteDenchar': True,
31 'PAO.BasisType': 'split',
32 'DM.Tolerance': 1e-4,
33 'DM.MixingWeight': 0.01,
34 'MaxSCFIterations': 300,
35 'DM.NumberPulay': 4,
36 'XML.Write': True})
37
38
39 Na8.set_calculator(siesta)
40 e = Na8.get_potential_energy()
41 tddft = siesta.pyscf_tddft_eels(label="siesta", jcutoff=7, iter_broadening=0.15/Ha,
42 xc_code='LDA,PZ', tol_loc=1e-6, tol_biloc=1e-7, freq = np.arange(0.0, 5.0, 0.05))
43
44 # plot polarizability
45 fig = plt.figure(1)
46 ax1 = fig.add_subplot(121)
47 ax2 = fig.add_subplot(122)
48 ax1.plot(siesta.results["freq range"], siesta.results["eel spectra nonin"].imag)
49 ax2.plot(siesta.results["freq range"], siesta.results["eel spectra inter"].imag)
50
51 ax1.set_xlabel(r"$\omega$ (eV)")
52 ax2.set_xlabel(r"$\omega$ (eV)")
53
54 ax1.set_ylabel(r"Im($P_{xx}$) (au)")
55 ax2.set_ylabel(r"Im($P_{xx}$) (au)")
56
57 ax1.set_title(r"Non interacting")
58 ax2.set_title(r"Interacting")
59
60 fig.tight_layout()
61
62 plt.show()
00 """Example, in order to run you must place a pseudopotential 'Na.psf' in
11 the folder"""
22
3 from ase.units import Ry, eV
3 from ase.units import Ry, eV, Ha
44 from ase.calculators.siesta import Siesta
55 from ase.calculators.siesta.siesta_raman import SiestaRaman
66 from ase import Atoms
3333 'MaxSCFIterations': 300,
3434 'DM.NumberPulay': 4})
3535
36 mbpt_inp = {'prod_basis_type': 'MIXED',
37 'solver_type': 1,
38 'gmres_eps': 0.001,
39 'gmres_itermax': 256,
40 'gmres_restart': 250,
41 'gmres_verbose': 20,
42 'xc_ord_lebedev': 14,
43 'xc_ord_gl': 48,
44 'nr': 512,
45 'akmx': 100,
46 'eigmin_local': 1e-06,
47 'eigmin_bilocal': 1e-08,
48 'freq_eps_win1': 0.15,
49 'd_omega_win1': 0.05,
50 'dt': 0.1,
51 'omega_max_win1': 5.0,
52 'ext_field_direction': 2,
53 'dr': np.array([0.3, 0.3, 0.3]),
54 'para_type': 'MATRIX',
55 'chi0_v_algorithm': 14,
56 'format_output': 'text',
57 'comp_dens_chng_and_polarizability': 1,
58 'store_dens_chng': 1,
59 'enh_given_volume_and_freq': 0,
60 'diag_hs': 0,
61 'do_tddft_tem': 0,
62 'do_tddft_iter': 1,
63 'plot_freq': 3.02,
64 'gwa_initialization': 'SIESTA_PB'}
65
66
6736 CO2.set_calculator(siesta)
6837
69 ram = SiestaRaman(CO2, siesta, mbpt_inp)
38 ram = SiestaRaman(CO2, siesta, label="siesta", jcutoff=7, iter_broadening=0.15/Ha,
39 xc_code='LDA,PZ', tol_loc=1e-6, tol_biloc=1e-7, freq = np.arange(0.0, 5.0, 0.05))
7040 ram.run()
7141 ram.summary(intensity_unit_ram='A^4 amu^-1')
7242
0 """Example, in order to run you must place a pseudopotential 'Na.psf' in
1 the folder"""
2
3 from ase.units import Ry, eV, Ha
4 from ase.calculators.siesta import Siesta
5 from ase.calculators.siesta.siesta_raman import SiestaRaman
6 from ase import Atoms
7 import numpy as np
8
9 # Define the systems
10 # example of Raman calculation for CO2 molecule,
11 # comparison with QE calculation can be done from
12 # https://github.com/maxhutch/quantum-espresso/blob/master/PHonon/examples/example15/README
13
14 CO2 = Atoms('CO2',
15 positions=[[-0.009026, -0.020241, 0.026760],
16 [1.167544, 0.012723, 0.071808],
17 [-1.185592, -0.053316, -0.017945]],
18 cell=[20, 20, 20])
19
20 # enter siesta input
21 siesta = Siesta(
22 mesh_cutoff=150 * Ry,
23 basis_set='DZP',
24 pseudo_qualifier='',
25 energy_shift=(10 * 10**-3) * eV,
26 fdf_arguments={
27 'SCFMustConverge': False,
28 'COOP.Write': True,
29 'WriteDenchar': True,
30 'PAO.BasisType': 'split',
31 'DM.Tolerance': 1e-4,
32 'DM.MixingWeight': 0.01,
33 'MaxSCFIterations': 300,
34 'DM.NumberPulay': 4,
35 'XML.Write': True,
36 'DM.UseSaveDM': True})
37
38 CO2.set_calculator(siesta)
39
40 ram = SiestaRaman(CO2, siesta, label="siesta", jcutoff=7, iter_broadening=0.15/Ha,
41 xc_code='LDA,PZ', tol_loc=1e-6, tol_biloc=1e-7, freq = np.arange(0.0, 5.0, 0.05))
42 ram.run()
43 ram.summary(intensity_unit_ram='A^4 amu^-1')
44
45 ram.write_spectra(start=200)
99 assert abs(h - h2).max() == 0
1010
1111 stm = STM(atoms, use_density=True)
12 c = stm.get_averaged_current(-1, 4.5)
13 x, y, I = stm.scan2(-1.0, 1.0)
14 stm.write('stm2.pckl')
15 x, y, I2 = STM('stm2.pckl').scan2(-1, 1)
16 assert abs(I - I2).max() == 0
17
18 stm = STM(atoms, use_density=True)
1219 c = stm.get_averaged_current(42, 4.5)
1320 x, y = stm.linescan(42, c, [0, 0], [2, 2])
1421 assert abs(x[-1] - 2 * 2**0.5) < 1e-13
1919 opt.run(0.001)
2020
2121 # HCP:
22 from ase.build import hcp0001
23 cu = hcp0001('Cu', (1, 1, 2), a=a / sqrt(2))
24 cu.cell[1,0] += 0.05
22 from ase.build import bulk
23 cu = bulk('Cu', 'hcp', a=a / sqrt(2))
24 cu.cell[1,0] -= 0.05
2525 cu *= (6, 6, 3)
2626
2727 cu.set_calculator(EMT())
2121 opt.run(5.0)
2222
2323 # HCP:
24 from ase.build import hcp0001
25 cu = hcp0001('Cu', (1, 1, 2), a=a / sqrt(2))
26 cu.cell[1, 0] += 0.05
24 from ase.build import bulk
25 cu = bulk('Cu', 'hcp', a=a / sqrt(2))
26 cu.cell[1,0] -= 0.05
2727 cu *= (6, 6, 3)
2828 cu.set_calculator(EMT())
2929 print(cu.get_forces())
1212 atoms = molecule('CH4')
1313 calc = Vasp()
1414
15 with must_raise(RuntimeError):
16 atoms.write('POSCAR')
17
1518 with must_raise(ValueError):
1619 atoms.set_calculator(calc)
1720 atoms.get_total_energy()
0 """
1
2 Check VASP input handling
3
4 """
5
6 from ase.calculators.vasp.create_input import _args_without_comment
7 from ase.calculators.vasp.create_input import _to_vasp_bool, _from_vasp_bool
8
9 from ase.calculators.vasp import Vasp
10 from ase.build import molecule
11 from ase.test import must_raise
12
13 # Molecules come with no unit cell
14
15 atoms = molecule('CH4')
16 calc = Vasp()
17
18 with must_raise(RuntimeError):
19 atoms.write('POSCAR')
20
21 with must_raise(ValueError):
22 atoms.set_calculator(calc)
23 atoms.get_total_energy()
24
25 # Comment splitting logic
26
27 clean_args = _args_without_comment(['a', 'b', '#', 'c'])
28 assert len(clean_args) == 2
29 clean_args = _args_without_comment(['a', 'b', '!', 'c', '#', 'd'])
30 assert len(clean_args) == 2
31 clean_args = _args_without_comment(['#', 'a', 'b', '!', 'c', '#', 'd'])
32 assert len(clean_args) == 0
33
34 # Boolean handling: input
35
36 for s in ('T', '.true.'):
37 assert(_from_vasp_bool(s) is True)
38 for s in ('f', '.False.'):
39 assert(_from_vasp_bool(s) is False)
40 with must_raise(ValueError):
41 _from_vasp_bool('yes')
42 with must_raise(AssertionError):
43 _from_vasp_bool(True)
44
45 # Boolean handling: output
46
47 for x in ('T', '.true.', True):
48 assert(_to_vasp_bool(x) == '.TRUE.')
49 for x in ('f', '.FALSE.', False):
50 assert(_to_vasp_bool(x) == '.FALSE.')
51
52 with must_raise(ValueError):
53 _to_vasp_bool('yes')
54 with must_raise(AssertionError):
55 _from_vasp_bool(1)
0 """
1 Run some tests to ensure that VASP calculator constructs correct POTCAR files
2
3 """
4
5 from os import remove
6 from os.path import isfile
7 from ase.atoms import Atoms
8 from ase.calculators.vasp import Vasp
9
10
11 def check_potcar(setups, filename='POTCAR'):
12 """Return true if labels in setups are found in POTCAR"""
13
14 pp = []
15 with open(filename, 'r') as f:
16 for line in f:
17 if 'TITEL' in line.split():
18 pp.append(line.split()[3])
19 for setup in setups:
20 assert setup in pp
21
22 # Write some POTCARs and check they are ok
23 potcar = 'POTCAR'
24 try:
25 atoms = Atoms('CaGdCs',
26 positions=[[0, 0, 1], [0, 0, 2], [0, 0, 3]], cell=[5, 5, 5])
27
28 calc = Vasp(xc='pbe')
29 calc.initialize(atoms)
30 calc.write_potcar()
31 check_potcar(('Ca_pv', 'Gd', 'Cs_sv'), filename=potcar)
32
33 calc = Vasp(xc='pbe', setups='recommended')
34 calc.initialize(atoms)
35 calc.write_potcar()
36 check_potcar(('Ca_sv', 'Gd_3', 'Cs_sv'), filename=potcar)
37
38 atoms = Atoms('CaInI',
39 positions=[[0, 0, 1], [0, 0, 2], [0, 0, 3]], cell=[5, 5, 5])
40 calc = Vasp(xc='pbe', setups={'base': 'gw'})
41 calc.initialize(atoms)
42 calc.write_potcar()
43 check_potcar(('Ca_sv_GW', 'In_d_GW', 'I_GW'), filename=potcar)
44
45 calc = Vasp(xc='pbe', setups={'base': 'gw', 'I': ''})
46 calc.initialize(atoms)
47 calc.write_potcar()
48 check_potcar(('Ca_sv_GW', 'In_d_GW', 'I'), filename=potcar)
49
50 calc = Vasp(xc='pbe', setups={'base': 'gw', 'Ca': '_sv', 2: 'I'})
51 calc.initialize(atoms)
52 calc.write_potcar()
53 check_potcar(('Ca_sv', 'In_d_GW', 'I'), filename=potcar)
54 finally:
55 if isfile(potcar):
56 remove(potcar)
0 from __future__ import print_function
1
2 from unittest.case import SkipTest
3
4 from ase import Atoms
5
6 try:
7 from IPython.display import HTML
8 from ase.visualize import x3d
9 except ImportError:
10 raise SkipTest('cannot import HTML from IPython.displacy')
11 else:
12 print('Testing x3d...')
13 a = 3.6
14 b = a / 2
15 atoms = Atoms('Cu4',
16 positions=[(0, 0, 0),
17 (0, b, b),
18 (b, 0, b),
19 (b, b, 0)],
20 cell=(a, a, a),
21 pbc=True)
22 my_obj = x3d.view_x3d(atoms)
23 assert isinstance(my_obj, HTML)
0 """Tests for XrDebye class"""
1 from __future__ import print_function
2
3 from ase.utils.xrdebye import XrDebye, wavelengths
4 from ase.cluster.cubic import FaceCenteredCubic
5 import numpy as np
6
7 tolerance = 1E-5
8 # previously calculated values
9 expected_get = 116850.37344
10 expected_xrd = np.array([18549.274677, 52303.116995, 38502.372027])
11 expected_saxs = np.array([372650934.006398, 280252013.563702,
12 488123.103628])
13
14 # test system -- cluster of 587 silver atoms
15 atoms = FaceCenteredCubic('Ag', [(1, 0, 0), (1, 1, 0), (1, 1, 1)],
16 [6, 8, 8], 4.09)
17 xrd = XrDebye(atoms=atoms, wavelength=wavelengths['CuKa1'], damping=0.04,
18 method='Iwasa', alpha=1.01, warn=True)
19 # test get()
20 obtained_get = xrd.get(s=0.09)
21 assert np.abs((obtained_get - expected_get) / expected_get) < tolerance
22
23 # test XRD
24 obtained_xrd = xrd.calc_pattern(x=np.array([15, 30, 50]), mode='XRD')
25 assert np.allclose(obtained_xrd, expected_xrd, rtol=tolerance)
26
27 # test SAXS
28 obtained_saxs = xrd.calc_pattern(x=np.array([0.021, 0.09, 0.53]),
29 mode='SAXS')
30 assert np.allclose(obtained_xrd, expected_xrd, rtol=tolerance)
453453 raise ValueError('Imaginary frequencies are present.')
454454 else:
455455 self.vib_energies = np.real(self.vib_energies) # clear +0.j
456 self.referencepressure = 101325. # Pa
456 self.referencepressure = 1.0e5 # Pa
457457
458458 def get_enthalpy(self, temperature, verbose=True):
459459 """Returns the enthalpy, in eV, in the ideal gas approximation
524524 temperature / units._hplanck**2)**(3.0 / 2)
525525 S_t *= units._k * temperature / self.referencepressure
526526 S_t = units.kB * (np.log(S_t) + 5.0 / 2.0)
527 write(fmt % ('S_trans (1 atm)', S_t, S_t * temperature))
527 write(fmt % ('S_trans (1 bar)', S_t, S_t * temperature))
528528 S += S_t
529529
530530 # Rotational entropy (term inside the log is in SI units).
559559
560560 # Pressure correction to translational entropy.
561561 S_p = - units.kB * np.log(pressure / self.referencepressure)
562 write(fmt % ('S (1 atm -> P)', S_p, S_p * temperature))
562 write(fmt % ('S (1 bar -> P)', S_p, S_p * temperature))
563563 S += S_p
564564
565565 write('-' * 49)
33 import pickle
44 import sys
55 import time
6 import string
67 from importlib import import_module
78 from math import sin, cos, radians, atan2, degrees
89 from contextlib import contextmanager
1213 except ImportError:
1314 from fractions import gcd
1415
16 try:
17 from pathlib import PurePath
18 except ImportError:
19 class PurePath:
20 pass
21
1522 import numpy as np
1623
1724 from ase.utils.formula import formula_hill, formula_metal
2128 'devnull', 'gcd', 'convert_string_to_fd', 'Lock',
2229 'opencew', 'OpenLock', 'rotate', 'irotate', 'givens',
2330 'hsv2rgb', 'hsv', 'pickleload', 'FileNotFoundError',
24 'formula_hill', 'formula_metal']
31 'formula_hill', 'formula_metal', 'PurePath']
2532
2633
2734 # Python 2+3 compatibility stuff:
147154
148155 class Lock:
149156 def __init__(self, name='lock', world=None):
150 self.name = name
157 self.name = str(name)
151158
152159 if world is None:
153160 from ase.parallel import world
184191
185192 def __exit__(self, type, value, tb):
186193 pass
194
195
196 def search_current_git_hash(arg, world=None):
197 """Search for .git directory and current git commit hash.
198
199 Parameters:
200
201 arg: str (directory path) or python module
202 .git directory is searched from the parent directory of
203 the given directory or module.
204 """
205 if world is None:
206 from ase.parallel import world
207 if world.rank != 0:
208 return None
209
210 # Check argument
211 if isinstance(arg, basestring):
212 # Directory path
213 dpath = arg
214 else:
215 # Assume arg is module
216 dpath = os.path.dirname(arg.__file__)
217 dpath = os.path.abspath(dpath)
218 dpath = os.path.dirname(dpath) # Go to the parent directory
219 git_dpath = os.path.join(dpath, '.git')
220 if not os.path.isdir(git_dpath):
221 # Replace this 'if' with a loop if you want to check
222 # further parent directories
223 return None
224 HEAD_file = os.path.join(git_dpath, 'HEAD')
225 if not os.path.isfile(HEAD_file):
226 return None
227 with open(HEAD_file, 'r') as f:
228 line = f.readline().strip()
229 if line.startswith('ref: '):
230 ref = line[5:]
231 ref_file = os.path.join(git_dpath, ref)
232 else:
233 # Assuming detached HEAD state
234 ref_file = HEAD_file
235 if not os.path.isfile(ref_file):
236 return None
237 with open(ref_file, 'r') as f:
238 line = f.readline().strip()
239 if all(c in string.hexdigits for c in line):
240 return line
241 return None
187242
188243
189244 def rotate(rotations, rotation=np.identity(3)):
381381
382382 def determine_step(self, stp):
383383 dr = stp - self.old_stp
384 if abs(pymax(self.pk) * dr) > self.maxstep:
385 dr /= abs((pymax(self.pk) * dr) / self.maxstep)
384 x = np.reshape(self.pk, (-1, 3))
385 steplengths = ((dr*x)**2).sum(1)**0.5
386 maxsteplength = pymax(steplengths)
387 if maxsteplength >= self.maxstep:
388 dr *= self.maxstep / maxsteplength
386389 stp = self.old_stp + dr
387390 return stp
388391
199199
200200
201201 ###CO : added rigid_units and rotation_factors
202 def run(self, x_start, dirn, a_max=None, a1=None, func_start=None,
203 func_old=None, func_prime_start=None,
204 rigid_units=None, rotation_factors=None):
202 def run(self, x_start, dirn, a_max=None, a_min=None, a1=None,
203 func_start=None, func_old=None, func_prime_start=None,
204 rigid_units=None, rotation_factors=None, maxstep=None):
205205
206206 """Perform a backtracking / quadratic-interpolation linesearch
207207 to find an appropriate step length with Armijo condition.
223223 Note that this does not have to be a unit vector, but the
224224 function will return a value scaled with respect to dirn.
225225 a_max: an upper bound on the maximum step length allowed. Default is 2.0.
226 a_min: a lower bound on the minimum step length allowed. Default is 1e-10.
227 A RuntimeError is raised if this bound is violated
228 during the line search.
226229 a1: the initial guess for an acceptable step length. If no value is
227230 given, this will be set automatically, using quadratic
228231 interpolation using func_old, or "rounded" to 1.0 if the
237240 guess for the step length if it is not provided)
238241 rigid_units, rotationfactors : see documentation of RumPath, if it is
239242 unclear what these parameters are, then leave them at None
240
243 maxstep: maximum allowed displacement in Angstrom. Default is 0.2.
241244
242245 Returns:
243246 A tuple: (step, func_val, no_update)
253256 RuntimeError for problems encountered during iteration
254257 """
255258
256 a1 = self.handle_args(x_start, dirn, a_max, a1, func_start, func_old,
257 func_prime_start)
259 a1 = self.handle_args(x_start, dirn, a_max, a_min, a1, func_start,
260 func_old, func_prime_start, maxstep)
258261
259262 # DEBUG
260263 logger.debug("a1(auto) = ", a1)
300303 # print("c1*a1*phi_prime_start = ", self.c1*a1*self.phi_prime_start,
301304 # " | phi_a1 - phi_0 = ", phi_a1 - self.func_start)
302305 logger.info("a1 = %.3f, suff_dec = %r", a1, suff_dec)
303 if a1 < 1e-10:
304 raise RuntimeError('a1 too small, giving up')
306 if a1 < self.a_min:
307 raise RuntimeError('a1 < a_min, giving up')
305308 if self.phi_prime_start > 0.0:
306309 raise RuntimeError("self.phi_prime_start > 0.0")
307310
335338
336339
337340
338 def handle_args(self, x_start, dirn, a_max, a1, func_start, func_old,
339 func_prime_start):
341 def handle_args(self, x_start, dirn, a_max, a_min, a1, func_start, func_old,
342 func_prime_start, maxstep):
340343
341344 """Verify passed parameters and set appropriate attributes accordingly.
342345
356359 """
357360
358361 self.a_max = a_max
362 self.a_min = a_min
359363 self.x_start = x_start
360364 self.dirn = dirn
361365 self.func_old = func_old
369373 logger.warning("a_max too small relative to tol. Reverting to "
370374 "default value a_max = 2.0 (twice the <ideal> step).")
371375 a_max = 2.0 # THIS ASSUMES NEWTON/BFGS TYPE BEHAVIOUR!
376
377 if self.a_min is None:
378 self.a_min = 1e-10
372379
373380 if func_start is None:
374381 logger.debug("Setting func_start")
397404 logger.debug("a1 is None or a1 < self.tol. Reverting to default value "
398405 "a1 = 1.0")
399406 a1 = 1.0
407 if a1 is None or a1 < self.a_min:
408 logger.debug("a1 is None or a1 < a_min. Reverting to default value "
409 "a1 = 1.0")
410 a1 = 1.0
411
412 if maxstep is None:
413 maxstep = 0.2
414 logger.debug("maxstep = %e", maxstep)
415
416 r = np.reshape(dirn, (-1, 3))
417 steplengths = ((a1*r)**2).sum(1)**0.5
418 maxsteplength = np.max(steplengths)
419 if maxsteplength >= maxstep:
420 a1 *= maxstep / maxsteplength
421 logger.debug("Rescaled a1 to fulfill maxstep criterion")
400422
401423 self.a_start = a1
402424
404426 self.phi_prime_start)
405427 logger.debug("func_start = %s, self.func_old = %s", self.func_start,
406428 self.func_old)
407 logger.debug("a1 = %e, a_max = %e", a1, a_max)
429 logger.debug("a1 = %e, a_max = %e, a_min = %e", a1, a_max, self.a_min)
408430
409431 return a1
0 #!/usr/bin/env python3
1
2 """Generate new release of ASE.
3
4 This script does not attempt to import ASE - then it would depend on
5 which ASE is installed and how - but assumes that it is run from the
6 ASE root directory."""
7
8 import os
9 import subprocess
10 import re
11 import argparse
12 from time import strftime
13
14 def runcmd(cmd, output=False, error_ok=False):
15 print('Executing:', cmd)
16 try:
17 if output:
18 txt = subprocess.check_output(cmd, shell=True)
19 return txt.decode('utf8')
20 else:
21 return subprocess.check_call(cmd, shell=True)
22 except subprocess.CalledProcessError as err:
23 if error_ok:
24 print('Failed: {}'.format(err))
25 print('Continuing...')
26 else:
27 raise
28
29
30 bash = runcmd
31
32
33 def py(cmd, output=False):
34 return runcmd('python3 {}'.format(cmd))
35
36 def py2(cmd, output=False):
37 return runcmd('python2 {}'.format(cmd))
38
39 def git(cmd, error_ok=False):
40 cmd = 'git {}'.format(cmd)
41 return runcmd(cmd, output=True, error_ok=error_ok)
42
43
44 cwd = os.getcwd()
45 versionfile = 'ase/__init__.py'
46
47
48 def get_version():
49 with open(versionfile) as fd:
50 return re.search(r"__version__ = '(\S+)'", fd.read()).group(1)
51
52
53 def main():
54 p = argparse.ArgumentParser(usage='Generate new release of ASE.',
55 epilog='Run from the root directory of ASE.')
56 p.add_argument('version', nargs='?',
57 help='new version number')
58 p.add_argument('--clean', action='store_true',
59 help='delete release branch and tag')
60 args = p.parse_args()
61
62 try:
63 current_version = get_version()
64 except Exception as err:
65 p.error('Cannot get version: {}. Are you in the root directory?'
66 .format(err))
67
68 print('Current version: {}'.format(current_version))
69
70 if not args.version:
71 p.print_help()
72 raise SystemExit
73
74 version = args.version
75
76 branchname = 'ase-{}'.format(version)
77 current_version = get_version()
78
79 if args.clean:
80 print('Cleaning {}'.format(version))
81 git('checkout master')
82 git('tag -d {}'.format(version), error_ok=True)
83 git('branch -D {}'.format(branchname), error_ok=True)
84 git('branch -D {}'.format('web-page'), error_ok=True)
85 return
86
87 print('New release: {}'.format(version))
88
89 txt = git('status')
90 branch = re.match('On branch (\S+)', txt).group(1)
91 print('Currently on branch {}'.format(repr(branch)))
92 if branch != 'master':
93 git('checkout master')
94
95
96 git('checkout -b {}'.format(branchname))
97
98 majormiddle, minor = version.rsplit('.', 1)
99 minor = int(minor)
100 nextminor = minor + 1
101 next_devel_version = '{}.{}b1'.format(majormiddle, nextminor)
102
103 def update_version(version):
104 print('Editing {}: version {}'.format(versionfile, version))
105 new_versionline = "__version__ = '{}'\n".format(version)
106 lines = []
107 ok = False
108 with open(versionfile) as fd:
109 for line in fd:
110 if line.startswith('__version__'):
111 ok = True
112 line = new_versionline
113 lines.append(line)
114 assert ok
115 with open(versionfile, 'w') as fd:
116 for line in lines:
117 fd.write(line)
118
119 update_version(version)
120
121 releasenotes = 'doc/releasenotes.rst'
122 lines = []
123
124 searchtxt = re.escape("""\
125 Git master branch
126 =================
127
128 :git:`master <>`.
129 """)
130
131 replacetxt = """\
132 Git master branch
133 =================
134
135 :git:`master <>`.
136
137 * No changes yet
138
139
140 {header}
141 {underline}
142
143 {date}: :git:`{version} <../{version}>`
144 """
145
146 date = strftime('%d %B %Y').lstrip('0')
147 header = 'Version {}'.format(version)
148 underline = '=' * len(header)
149 replacetxt = replacetxt.format(header=header, version=version,
150 underline=underline, date=date)
151
152 print('Editing {}'.format(releasenotes))
153 with open(releasenotes) as fd:
154 txt = fd.read()
155 txt, n = re.subn(searchtxt, replacetxt, txt, re.MULTILINE)
156 assert n == 1
157
158 with open(releasenotes, 'w') as fd:
159 fd.write(txt)
160
161 searchtxt = """\
162 News
163 ====
164 """
165
166 replacetxt = """\
167 News
168 ====
169
170 * :ref:`ASE version {version} <releasenotes>` released ({date}).
171 """
172
173 replacetxt = replacetxt.format(version=version, date=date)
174
175 frontpage = 'doc/index.rst'
176 lines = []
177 print('Editing {}'.format(frontpage))
178 with open(frontpage) as fd:
179 txt = fd.read()
180 txt, n = re.subn(searchtxt, replacetxt, txt)
181 assert n == 1
182 with open(frontpage, 'w') as fd:
183 fd.write(txt)
184
185 installdoc = 'doc/install.rst'
186 print('Editing {}'.format(installdoc))
187
188 with open(installdoc) as fd:
189 txt = fd.read()
190
191 txt, nsub = re.subn(r'ase-\d+\.\d+.\d+',
192 'ase-{}'.format(version), txt)
193 assert nsub > 0
194 txt, nsub = re.subn(r'git clone -b \d+\.\d+.\d+',
195 'git clone -b {}'.format(version), txt)
196 assert nsub == 1
197
198 with open(installdoc, 'w') as fd:
199 fd.write(txt)
200
201 sphinxconf = 'doc/conf.py'
202 print('Editing {}'.format(sphinxconf))
203 comment = '# This line auto-edited by newrelease script'
204 line1 = "ase_dev_version = '{}' {}\n".format(next_devel_version, comment)
205 line2 = "ase_stable_version = '{}' {}\n".format(version, comment)
206 lines = []
207 with open(sphinxconf) as fd:
208 for line in fd:
209 if re.match('ase_dev_version = ', line):
210 line = line1
211 if re.match('ase_stable_version = ', line):
212 line = line2
213 lines.append(line)
214 with open(sphinxconf, 'w') as fd:
215 fd.write(''.join(lines))
216
217 git('add {}'.format(' '.join([versionfile, sphinxconf, installdoc,
218 frontpage, releasenotes])))
219 git('commit -m "ASE version {}"'.format(version))
220 git('tag -s {0} -m "ase-{0}"'.format(version))
221
222 py('setup.py sdist > setup_sdist.log')
223 py2('setup.py bdist_wheel > setup_bdist_wheel2.log')
224 py('setup.py bdist_wheel > setup_bdist_wheel3.log')
225 bash('gpg --armor --yes --detach-sign dist/ase-{}.tar.gz'.format(version))
226 git('checkout -b web-page')
227 git('branch --set-upstream-to=origin/web-page')
228 git('checkout {}'.format(branchname))
229 update_version(next_devel_version)
230 git('add {}'.format(versionfile))
231 git('branch --set-upstream-to=master')
232 git('commit -m "bump version number to {}"'.format(next_devel_version))
233
234 print()
235 print('Automatic steps done.')
236 print()
237 print('Now is a good time to:')
238 print(' * check the diff')
239 print(' * run the tests')
240 print(' * verify the web-page build')
241 print()
242 print('Remaining steps')
243 print('===============')
244 print('git show {} # Inspect!'.format(version))
245 print('git checkout master')
246 print('git merge {}'.format(branchname))
247 print('twine upload '
248 'dist/ase-{v}.tar.gz '
249 'dist/ase-{v}-py2-none-any.whl '
250 'dist/ase-{v}-py3-none-any.whl '
251 'dist/ase-{v}.tar.gz.asc'.format(v=version))
252 print('git push --tags origin master # Assuming your remote is "origin"')
253 print('git checkout web-page')
254 print('git push --force origin web-page')
255
256 main()
0 """Definition of the XrDebye class.
1
2 This module defines the XrDebye class for calculation
3 of X-ray scattering properties from atomic cluster
4 using Debye formula.
5 Also contains routine for calculation of atomic form factors and
6 X-ray wavelength dict.
7 """
8
9 from __future__ import print_function
10 from math import exp, pi, sin, sqrt, cos, acos
11 import numpy as np
12
13
14 from ase.data import atomic_numbers
15
16 # Table (1) of
17 # D. WAASMAIER AND A. KIRFEL, Acta Cryst. (1995). A51, 416-431
18 waasmaier = {
19 # a1 b1 a2 b2 a3 b3 a4 b4 a5 b5 c
20 'C': [ 2.657506, 14.780758, 1.078079, 0.776775, 1.490909, 42.086843, -4.241070, -0.000294, 0.713791, 0.239535, 4.297983],
21 'N': [11.893780, 0.000158, 3.277479, 10.232723, 1.858092, 30.344690, 0.858927, 0.656065, 0.912985, 0.217287, -11.804902],
22 'O': [ 2.960427, 14.182259, 2.5088111, 5.936858, 0.637053, 0.112726, 0.722838, 34.958481, 1.142756, 0.390240, 0.027014],
23 'P': [ 1.950541, 0.908139, 4.146930, 27.044953, 1.494560, 0.071280, 1.522042, 67.520190, 5.729711, 1.981173, 0.155233],
24 'S': [ 6.372157, 1.514347, 5.154568, 22.092528, 1.473732, 0.061373, 1.635073, 55.445176, 1.209372, 0.646925, 0.154722],
25 'Cl': [ 1.446071, 0.052357, 6.870609, 1.193165, 6.151801, 18.343416, 1.750347, 46.398394, 0.634168, 0.401005, 0.146773],
26 'Ni': [13.521865, 4.077277, 6.947285, 0.286763, 3.866028, 14.622634, 2.135900, 71.966078, 4.284731, 0.004437, -2.762697],
27 'Cu': [14.014192, 3.738280, 4.784577, 0.003744, 5.056806, 13.034982, 1.457971, 72.554793, 6.932996, 0.265666, -3.774477],
28 'Pd': [ 6.121511, 0.062549, 4.784063, 0.784031, 16.631683, 8.751391, 4.318258, 34.489983, 13.246773, 0.784031, 0.883099],
29 'Ag': [ 6.073874, 0.055333, 17.155437, 7.896512, 4.173344, 28.443739, 0.852238, 110.376108, 17.988685, 0.716809, 0.756603],
30 'Pt': [31.273891, 1.316992, 18.445441, 8.797154, 17.063745, 0.124741, 5.555933, 40.177994, 1.575270, 1.316997, 4.050394],
31 'Au': [16.777389, 0.122737, 19.317156, 8.621570, 32.979682, 1.256902, 5.595453, 38.008821, 10.576854, 0.000601, -6.279078],
32 }
33
34 wavelengths = {
35 'CuKa1': 1.5405981,
36 'CuKa2': 1.54443,
37 'CuKb1': 1.39225,
38 'WLa1': 1.47642,
39 'WLa2': 1.48748
40 }
41
42
43 class XrDebye(object):
44 """
45 Class for calculation of XRD or SAXS patterns.
46 """
47 def __init__(self, atoms, wavelength, damping=0.04,
48 method='Iwasa', alpha=1.01, warn=True):
49 """
50 Initilize the calculation of X-ray diffraction patterns
51
52 Parameters:
53
54 atoms: ase.Atoms
55 atoms object for which calculation will be performed.
56
57 wavelength: float, Angstrom
58 X-ray wavelength in Angstrom. Used for XRD and to setup dumpings.
59
60 damping : float, Angstrom**2
61 thermal damping factor parameter (B-factor).
62
63 method: {'Iwasa'}
64 method of calculation (damping and atomic factors affected).
65
66 If set to 'Iwasa' than angular damping and q-dependence of
67 atomic factors are used.
68
69 For any other string there will be only thermal damping
70 and constant atomic factors (`f_a(q) = Z_a`).
71
72 alpha: float
73 parameter for angular damping of scattering intensity.
74 Close to 1.0 for unplorized beam.
75
76 warn: boolean
77 flag to show warning if atomic factor can't be calculated
78 """
79 self.wavelength = wavelength
80 self.damping = damping
81 self.mode = ''
82 self.method = method
83 self.alpha = alpha
84 self.warn = warn
85
86 self.twotheta_list = []
87 self.q_list = []
88 self.intensity_list = []
89
90 self.atoms = atoms
91 # TODO: setup atomic form factors if method != 'Iwasa'
92
93 def set_damping(self, damping):
94 """ set B-factor for thermal damping """
95 self.damping = damping
96
97 def get(self, s):
98 """Get the powder x-ray (XRD) scattering intensity
99 using the Debye-Formula at single point.
100
101 Parameters:
102
103 s: float, in inverse Angstrom
104 scattering vector value (`s = q / 2\pi`).
105
106 Returns:
107 Intensity at given scattering vector `s`.
108 """
109
110 pre = exp(-self.damping * s**2 / 2)
111
112 if self.method == 'Iwasa':
113 sinth = self.wavelength * s / 2.
114 positive = 1. - sinth**2
115 if positive < 0:
116 positive = 0
117 costh = sqrt(positive)
118 cos2th = cos(2. * acos(costh))
119 pre *= costh / (1. + self.alpha * cos2th**2)
120
121 f = {}
122 def atomic(symbol):
123 """
124 get atomic factor, using cache.
125 """
126 if symbol not in f:
127 if self.method == 'Iwasa':
128 f[symbol] = self.get_waasmaier(symbol, s)
129 else:
130 f[symbol] = atomic_numbers[symbol]
131 return f[symbol]
132
133 I = 0.
134 fa = [] # atomic factors list
135 for a in self.atoms:
136 fa.append(atomic(a.symbol))
137
138 pos = self.atoms.get_positions() # positions of atoms
139 fa = np.array(fa) # atomic factors array
140
141 for i in range(len(self.atoms)):
142 vr = pos - pos[i]
143 I += np.sum(fa[i] * fa * np.sinc(2 * s * np.sqrt(np.sum(vr * vr, axis=1))))
144
145 return pre * I
146
147 def get_waasmaier(self, symbol, s):
148 """Scattering factor for free atoms.
149
150 Parameters:
151
152 symbol: string
153 atom element symbol.
154
155 s: float, in inverse Angstrom
156 scattering vector value (`s = q / 2\pi`).
157
158 Returns:
159 Intensity at given scattering vector `s`.
160
161 Note:
162 for hydrogen will be returned zero value."""
163 if symbol == 'H':
164 # XXXX implement analytical H
165 return 0
166 elif symbol in waasmaier:
167 abc = waasmaier[symbol]
168 f = abc[10]
169 s2 = s * s
170 for i in range(5):
171 f += abc[2 * i] * exp(-abc[2 * i + 1] * s2)
172 return f
173 if self.warn:
174 print('<xrdebye::get_atomic> Element', symbol, 'not available')
175 return 0
176
177 def calc_pattern(self, x=None, mode='XRD'):
178 r"""
179 Calculate X-ray diffraction pattern or
180 small angle X-ray scattering pattern.
181
182 Parameters:
183
184 x: float array
185 points where intensity will be calculated.
186 XRD - 2theta values, in degrees;
187 SAXS - q values in 1/A
188 (`q = 2 \pi \cdot s = 4 \pi \sin( \theta) / \lambda`).
189 If ``x`` is ``None`` then default values will be used.
190
191 mode: {'XRD', 'SAXS'}
192 the mode of calculation: X-ray diffraction (XRD) or
193 small-angle scattering (SAXS).
194
195 Returns:
196 list of intensities calculated for values given in ``x``.
197 """
198 self.mode = mode.upper()
199 assert(mode in ['XRD', 'SAXS'])
200
201 result = []
202 if mode == 'XRD':
203 if x is None:
204 self.twotheta_list = np.linspace(15, 55, 100)
205 else:
206 self.twotheta_list = x
207 self.q_list = []
208 print('#2theta\tIntensity')
209 for twotheta in self.twotheta_list:
210 s = 2 * sin(twotheta * pi / 180 / 2.0) / self.wavelength
211 result.append(self.get(s))
212 print('%.3f\t%f' % (twotheta, result[-1]))
213 elif mode == 'SAXS':
214 if x is None:
215 self.twotheta_list = np.logspace(-3, -0.3, 100)
216 else:
217 self.q_list = x
218 self.twotheta_list = []
219 print('#q\tIntensity')
220 for q in self.q_list:
221 s = q / (2 * pi)
222 result.append(self.get(s))
223 print('%.4f\t%f' % (q, result[-1]))
224 self.intensity_list = np.array(result)
225 return self.intensity_list
226
227 def write_pattern(self, filename):
228 """ Save calculated data to file specified by ``filename`` string."""
229 f = open(filename, 'w')
230 f.write('# Wavelength = %f\n' % self.wavelength)
231 if self.mode == 'XRD':
232 x, y = self.twotheta_list, self.intensity_list
233 f.write('# 2theta \t Intesity\n')
234 elif self.mode == 'SAXS':
235 x, y = self.q_list, self.intensity_list
236 f = open(filename, 'w')
237 f.write('# q(1/A)\tIntesity\n')
238 else:
239 f.close()
240 raise Exception('No data available, call calc_pattern() first.')
241
242 for i in range(len(x)):
243 f.write(' %f\t%f\n' % (x[i], y[i]))
244
245 f.close()
246
247 def plot_pattern(self, filename=None, show=None, ax=None):
248 """ Plot XRD or SAXS depending on filled data
249
250 Uses Matplotlib to plot pattern. Use *show=True* to
251 show the figure and *filename='abc.png'* or
252 *filename='abc.eps'* to save the figure to a file.
253
254 Returns:
255 ``matplotlib.axes.Axes`` object."""
256
257 import matplotlib.pyplot as plt
258
259 if filename is None and show is None:
260 show = True
261
262 if ax is None:
263 plt.clf() # clear figure
264 ax = plt.gca()
265
266 if self.mode == 'XRD':
267 x, y = np.array(self.twotheta_list), np.array(self.intensity_list)
268 ax.plot(x, y / np.max(y), '.-')
269 ax.set_xlabel('2$\\theta$')
270 ax.set_ylabel('Intensity')
271 elif self.mode == 'SAXS':
272 x, y = np.array(self.q_list), np.array(self.intensity_list)
273 ax.loglog(x, y / np.max(y), '.-')
274 ax.set_xlabel('q, 1/Angstr.')
275 ax.set_ylabel('Intensity')
276 else:
277 raise Exception('No data available, call calc_pattern() first')
278
279 if show:
280 plt.show()
281 if filename is not None:
282 fig = ax.get_figure()
283 fig.savefig(filename)
284
285 return ax
11
22 """Infrared intensities"""
33
4 import pickle
54 from math import sqrt
65 from sys import stdout
76
109 import ase.units as units
1110 from ase.parallel import parprint, paropen
1211 from ase.vibrations import Vibrations
13 from ase.utils import basestring
12 from ase.utils import basestring, pickleload
1413
1514
1615 class Infrared(Vibrations):
170169
171170 # Get "static" dipole moment and forces
172171 name = '%s.eq.pckl' % self.name
173 [forces_zero, dipole_zero] = pickle.load(open(name, 'rb'))
172 [forces_zero, dipole_zero] = pickleload(open(name, 'rb'))
174173 self.dipole_zero = (sum(dipole_zero**2)**0.5) / units.Debye
175174 self.force_zero = max([sum((forces_zero[j])**2)**0.5
176175 for j in self.indices])
182181 for a in self.indices:
183182 for i in 'xyz':
184183 name = '%s.%d%s' % (self.name, a, i)
185 [fminus, dminus] = pickle.load(open(name + '-.pckl', 'rb'))
186 [fplus, dplus] = pickle.load(open(name + '+.pckl', 'rb'))
184 [fminus, dminus] = pickleload(
185 open(name + '-.pckl', 'rb'))
186 [fplus, dplus] = pickleload(
187 open(name + '+.pckl', 'rb'))
187188 if self.nfree == 4:
188 [fminusminus, dminusminus] = pickle.load(
189 [fminusminus, dminusminus] = pickleload(
189190 open(name + '--.pckl', 'rb'))
190 [fplusplus, dplusplus] = pickle.load(
191 [fplusplus, dplusplus] = pickleload(
191192 open(name + '++.pckl', 'rb'))
192193 if self.method == 'frederiksen':
193194 fminus[a] += -fminus.sum(0)
145145 if self.ir:
146146 dipole = self.calc.get_dipole_moment(self.atoms)
147147 if self.ram:
148 freq, pol = self.get_polarizability()
148 freq, noninPol, pol = self.get_polarizability()
149149 if rank == 0:
150150 if self.ir and self.ram:
151 pickle.dump([forces, dipole, freq, pol], fd, protocol=2)
151 pickle.dump([forces, dipole, freq, noninPol, pol], fd, protocol=2)
152152 sys.stdout.write(
153153 'Writing %s, dipole moment = (%.6f %.6f %.6f)\n' %
154154 (filename, dipole[0], dipole[1], dipole[2]))
247247 s = units._hbar * 1e10 / sqrt(units._e * units._amu)
248248 self.hnu = s * omega2.astype(complex)**0.5
249249
250 def get_energies(self, method='standard', direction='central'):
250 def get_energies(self, method='standard', direction='central', **kw):
251251 """Get vibration energies in eV."""
252252
253253 if (self.H is None or method.lower() != self.method or
254254 direction.lower() != self.direction):
255 self.read(method, direction)
255 self.read(method, direction, **kw)
256256 return self.hnu
257257
258258 def get_frequencies(self, method='standard', direction='central'):
3939 view_sage_jmol(atoms)
4040 return
4141 elif vwr in ('ngl', 'nglview'):
42 from ase.visualize.nglview import view_ngl
42 from ase.visualize.ngl import view_ngl
4343 return view_ngl(atoms)
4444 elif vwr == 'x3d':
4545 from ase.visualize.x3d import view_x3d
0 # coding: utf-8
1
2 from ase import Atoms
3
4
5 class NGLDisplay:
6 """Structure display class
7
8 Provides basic structure/trajectory display
9 in the notebook and optional gui which can be used to enhance its
10 usability. It is also possible to extend the functionality of the
11 particular instance of the viewer by adding further widgets
12 manipulating the structure.
13 """
14 def __init__(self, atoms, xsize=500, ysize=500):
15 import nglview
16 import nglview.color
17
18 from ipywidgets import Dropdown, FloatSlider, IntSlider, HBox, VBox
19 self.atoms = atoms
20 if isinstance(atoms[0], Atoms):
21 # Assume this is a trajectory or struct list
22 self.view = nglview.show_asetraj(atoms)
23 self.frm = IntSlider(value=0, min=0, max=len(atoms) - 1)
24 self.frm.observe(self._update_frame)
25 self.struct = atoms[0]
26 else:
27 # Assume this is just a single structure
28 self.view = nglview.show_ase(atoms)
29 self.struct = atoms
30 self.frm = None
31
32 self.colors = {}
33 self.view._remote_call('setSize', target='Widget',
34 args=['%dpx' % (xsize,), '%dpx' % (ysize,)])
35 self.view.add_unitcell()
36 self.view.add_spacefill()
37 self.view.remove_ball_and_stick()
38 self.view.camera = 'orthographic'
39 self.view.parameters = { "clipDist": 0 }
40
41 self.view.center()
42
43 self.asel = Dropdown(options=['All'] +
44 list(set(self.struct.get_chemical_symbols())),
45 value='All', description='Show')
46
47 self.csel = Dropdown(options=nglview.color.COLOR_SCHEMES,
48 value=' ', description='Color scheme')
49
50 self.rad = FloatSlider(value=0.8, min=0.0, max=1.5, step=0.01,
51 description='Ball size')
52
53 self.asel.observe(self._select_atom)
54 self.csel.observe(self._update_repr)
55 self.rad.observe(self._update_repr)
56
57 self.view.update_spacefill(radiusType='covalent',
58 scale=0.8,
59 color_scheme=self.csel.value,
60 color_scale='rainbow')
61
62 wdg = [self.asel, self.csel, self.rad]
63 if self.frm:
64 wdg.append(self.frm)
65
66 self.gui = HBox([self.view, VBox(wdg)])
67 # Make useful shortcuts for the user of the class
68 self.gui.view = self.view
69 self.gui.control_box = self.gui.children[1]
70 self.gui.custom_colors = self.custom_colors
71
72 def _update_repr(self, chg=None):
73 self.view.update_spacefill(radiusType='covalent',
74 scale=self.rad.value,
75 color_scheme=self.csel.value,
76 color_scale='rainbow')
77
78 def _update_frame(self, chg=None):
79 self.view.frame = self.frm.value
80 return
81
82 def _select_atom(self, chg=None):
83 sel = self.asel.value
84 self.view.remove_spacefill()
85 for e in set(self.struct.get_chemical_symbols()):
86 if (sel == 'All' or e == sel):
87 if e in self.colors:
88 self.view.add_spacefill(selection='#' + e,
89 color=self.colors[e])
90 else:
91 self.view.add_spacefill(selection='#' + e)
92 self._update_repr()
93
94 def custom_colors(self, clr=None):
95 """
96 Define custom colors for some atoms. Pass a dictionary of the form
97 {'Fe':'red', 'Au':'yellow'} to the function.
98 To reset the map to default call the method without parameters.
99 """
100 if clr:
101 self.colors = clr
102 else:
103 self.colors = {}
104 self._select_atom()
105
106
107 def view_ngl(atoms, w=500, h=500):
108 """
109 Returns the nglviewer + some control widgets in the VBox ipywidget.
110 The viewer supports any Atoms objectand any sequence of Atoms objects.
111 The returned object has two shortcuts members:
112
113 .view:
114 nglviewer ipywidget for direct interaction
115 .control_box:
116 VBox ipywidget containing view control widgets
117 """
118 return NGLDisplay(atoms, w, h).gui
+0
-103
ase/visualize/nglview.py less more
0 # coding: utf-8
1
2 from ase import Atoms
3
4
5 class NGLDisplay:
6 """Structure display class
7
8 Provides basic structure/trajectory display
9 in the notebook and optional gui which can be used to enhance its
10 usability. It is also possible to extend the functionality of the
11 particular instance of the viewer by adding further widgets
12 manipulating the structure.
13 """
14 def __init__(self, atoms, xsize=500, ysize=500):
15 import nglview
16 from ipywidgets import Dropdown, FloatSlider, IntSlider, HBox, VBox
17 self.atoms = atoms
18 if isinstance(atoms[0], Atoms):
19 # Assume this is a trajectory or struct list
20 self.view = nglview.show_asetraj(atoms)
21 self.frm = IntSlider(value=0, min=0, max=len(atoms) - 1)
22 self.frm.observe(self._update_frame)
23 self.struct = atoms[0]
24 else:
25 # Assume this is just a single structure
26 self.view = nglview.show_ase(atoms)
27 self.struct = atoms
28 self.frm = None
29
30 self.colors = {}
31 self.view._remote_call('setSize', target='Widget',
32 args=['%dpx' % (xsize,), '%dpx' % (ysize,)])
33 self.view.add_unitcell()
34 self.view.add_spacefill()
35 self.view.camera = 'orthographic'
36 self.view.update_spacefill(radiusType='covalent', scale=0.7)
37 self.view.center()
38
39 self.asel = Dropdown(options=['All'] +
40 list(set(self.struct.get_chemical_symbols())),
41 value='All', description='Show')
42
43 self.rad = FloatSlider(value=0.8, min=0.0, max=1.5, step=0.01,
44 description='Ball size')
45
46 self.asel.observe(self._select_atom)
47 self.rad.observe(self._update_repr)
48
49 wdg = [self.asel, self.rad]
50 if self.frm:
51 wdg.append(self.frm)
52
53 self.gui = HBox([self.view, VBox(wdg)])
54 # Make useful shortcuts for the user of the class
55 self.gui.view = self.view
56 self.gui.control_box = self.gui.children[1]
57 self.gui.custom_colors = self.custom_colors
58
59 def _update_repr(self, chg=None):
60 self.view.update_spacefill(radiusType='covalent', scale=self.rad.value)
61
62 def _update_frame(self, chg=None):
63 self.view.frame = self.frm.value
64 return
65
66 def _select_atom(self, chg=None):
67 sel = self.asel.value
68 self.view.remove_spacefill()
69 for e in set(self.struct.get_chemical_symbols()):
70 if (sel == 'All' or e == sel):
71 if e in self.colors:
72 self.view.add_spacefill(selection='#' + e,
73 color=self.colors[e])
74 else:
75 self.view.add_spacefill(selection='#' + e)
76 self._update_repr()
77
78 def custom_colors(self, clr=None):
79 """
80 Define custom colors for some atoms. Pass a dictionary of the form
81 {'Fe':'red', 'Au':'yellow'} to the function.
82 To reset the map to default call the method without parameters.
83 """
84 if clr:
85 self.colors = clr
86 else:
87 self.colors = {}
88 self._select_atom()
89
90
91 def view_ngl(atoms, w=500, h=500):
92 """
93 Returns the nglviewer + some control widgets in the VBox ipywidget.
94 The viewer supports any Atoms objectand any sequence of Atoms objects.
95 The returned object has two shortcuts members:
96
97 .view:
98 nglviewer ipywidget for direct interaction
99 .control_box:
100 VBox ipywidget containing view control widgets
101 """
102 return NGLDisplay(atoms, w, h).gui
00 """Inline viewer for jupyter notebook using X3D."""
11
2 from tempfile import NamedTemporaryFile
2 try:
3 from StringIO import StringIO
4 except ImportError:
5 from io import StringIO
36 from IPython.display import HTML
4
57
68 def view_x3d(atoms):
79 """View atoms inline in a jupyter notbook. This command
8 should only be used within a jupyter/ipython notebook."""
9 with NamedTemporaryFile('r+', suffix='.html') as ntf:
10 atoms.write(ntf.name, format='html')
11 ntf.seek(0)
12 html_atoms = ntf.read()
13 return HTML(html_atoms)
10 should only be used within a jupyter/ipython notebook.
11
12 Args:
13 atoms - ase.Atoms, atoms to be rendered"""
14
15 output = StringIO()
16 atoms.write(output, format='html')
17 data = output.getvalue()
18 output.close()
19 return HTML(data)
+0
-103
ase/xrdebye.py less more
0 from __future__ import print_function
1 from math import exp, pi, sin, sqrt, cos, acos
2 import numpy as np
3
4 from ase.data import atomic_numbers
5
6 # Table (1) of
7 # D. WAASMAIER AND A. KIRFEL, Acta Cryst. (1995). A51, 416-431
8 waasmaier = {
9 # a1 b1 a2 b2 a3 b3 a4 b4 a5 b5 c
10 'C' : [2.657506, 14.780758, 1.078079, 0.776775, 1.490909, 42.086843,
11 -4.241070, -0.000294, 0.713791, 0.239535, 4.297983],
12 'S' : [6.372157, 1.514347, 5.154568, 22.092528, 1.473732, 0.061373,
13 1.635073, 55.445176, 1.209372, 0.646925, 0.154722],
14 'Pd': [6.121511, 0.062549, 4.784063, 0.784031, 16.631683, 8.751391, 4.318258, 34.489983, 13.246773, 0.784031, 0.883099],
15 'Ag': [6.073874, 0.055333, 17.155437, 7.896512, 4.173344, 28.443739, 0.852238, 110.376108, 17.988685, 0.716809, 0.756603],
16 'Au': [16.777389, 0.122737, 19.317156, 8.621570, 32.979682, 1.256902, 5.595453, 38.008821, 10.576854, 0.000601, -6.279078],
17 'P' : [1.950541, 0.908139, 4.146930, 27.044953, 1.494560, 0.071280, 1.522042, 67.520190, 5.729711, 1.981173, 0.155233],
18 'Cl': [1.446071, 0.052357, 6.870609, 1.193165, 6.151801, 18.343416, 1.750347, 46.398394, 0.634168, 0.401005, 0.146773],
19 }
20
21 class XrDebye:
22 def __init__(self, wavelength, alpha=1.01, damping=0.04, warn=True,
23 method='Iwasa'):
24 """
25 Obtain powder x-ray spectra.
26
27 wavelength in Angstrom
28 damping in Angstrom**2
29 """
30 self.wavelength = wavelength
31 self.damping = damping
32 self.alpha = alpha
33 self.warn = warn
34 self.method = method
35
36 def set_damping(self, damping):
37 self.damping = damping
38
39 def get(self, atoms, s):
40 """Get the powder x-ray (XRD) pattern using the Debye-Formula.
41
42 After: T. Iwasa and K. Nobusada, J. Phys. Chem. C 111 (2007) 45
43 s is assumed to be in 1/Angstrom
44 """
45
46 sinth = self.wavelength * s / 2.
47 costh = sqrt(1. - sinth**2)
48 cos2th = cos(2. * acos(costh))
49 pre = exp(- self.damping * s**2 / 2)
50
51 if self.method == 'Iwasa':
52 pre *= costh / (1. + self.alpha * cos2th**2)
53
54 f = {}
55 def atomic(symbol):
56 if symbol not in f:
57 if self.method == 'Iwasa':
58 f[symbol] = self.get_waasmaier(symbol, s)
59 else:
60 f[symbol] = atomic_numbers[symbol]
61 return f[symbol]
62
63 def sinc(x):
64 if x < 1.e-6:
65 x2 = x * x
66 return 1 - x2 / 6. + x2 * x2 / 120.
67 else:
68 return sin(x) / x
69
70 I = 0.
71 for a in atoms:
72 fa = atomic(a.symbol)
73 # print a.symbol, fa
74 for b in atoms:
75 fb = atomic(b.symbol)
76
77 if a == b:
78 twopisr = 0.
79 else:
80 vrij = a.position - b.position
81 rij = np.sqrt(np.dot(vrij, vrij))
82 twopisr = 2 * pi * s * rij
83
84 I += fa * fb * sinc(twopisr)
85
86 return pre * I
87
88 def get_waasmaier(self, symbol, s):
89 """Scattering factor for free atoms."""
90 if symbol == 'H':
91 # XXXX implement analytical H
92 return 0
93 elif symbol in waasmaier:
94 abc = waasmaier[symbol]
95 f = abc[10]
96 s2 = s*s
97 for i in range(5):
98 f += abc[2 * i] * exp(-abc[2 * i + 1] * s2)
99 return f
100 if self.warn:
101 print('<xrdebye::get_atomic> Element', symbol, 'not available')
102 return 0
8181 dimer
8282 atom
8383 transport/transport
84 calculators/qmmm
4545 >>> from ase import Atoms
4646 >>> OH = Atoms('OH')
4747 >>> OH[0].charge = -1
48 >>> OH.get_charges()
48 >>> OH.get_initial_charges()
4949 array([-1., 0.])
5050
5151 Another example:
3131 transparent=False,
3232 display=False,
3333 run_povray=True)
34
34
3535 import os
3636
3737 for i in range(2):
3838 error = os.system('pdflatex -interaction=nonstopmode general_surface ' +
3939 '> /dev/null')
40 assert error == 0, 'pdflatex failed'
40 if error:
41 with open('general_surface.pdf', 'w') as fd:
42 fd.write('pdflatex not found\n')
43 break
4144 os.remove('general_surface.aux')
4245 os.remove('general_surface.log')
4346
4545
4646 The calculators can be divided in four groups:
4747
48 1) Asap_, GPAW_ and Hotbit_ have their own native ASE interfaces.
49
50 2) ABINIT, AMBER, CP2K, CASTEP, DFTB+, ELK, EXCITING, FHI-aims, FLEUR, GAUSSIAN,
51 Gromacs, Jacapo, LAMMPS, MOPAC, NWChem, Octopus, Quantum ESPRESSO, SIESTA,
48 1) Asap_, GPAW_, and Hotbit_ have their own native ASE interfaces.
49
50 2) ABINIT, AMBER, CP2K, CASTEP, deMon2k, DFTB+, ELK, EXCITING, FHI-aims, FLEUR, GAUSSIAN,
51 Gromacs, Jacapo, LAMMPS, MOPAC, NWChem, Octopus, ONETEP, Quantum ESPRESSO, SIESTA,
5252 TURBOMOLE and VASP, have Python wrappers in the ASE package, but the actual
5353 FORTRAN/C/C++ codes are not part of ASE.
5454
5757
5858 4) Calculators that wrap others, included in the ASE package:
5959 :class:`ase.calculators.checkpoint.CheckpointCalculator`,
60 the :class:`ase.calculators.loggingcalc.LoggingCalculator` and
61 the :ref:`Grimme-D3 <grimme>` potential.
62
63
64 =================================== ===========================================
65 name description
66 =================================== ===========================================
67 Asap_ Highly efficient EMT code
68 GPAW_ Real-space/plane-wave/LCAO PAW code
69 Hotbit_ DFT based tight binding
70 :mod:`~ase.calculators.abinit` Plane-wave pseudopotential code
71 :mod:`~ase.calculators.amber` Classical molecular dynamics code
72 :mod:`~ase.calculators.castep` Plane-wave pseudopotential code
73 :mod:`~ase.calculators.cp2k` DFT and classical potentials
74 :mod:`~ase.calculators.dftb` DFT based tight binding
75 :mod:`~ase.calculators.dmol` Atomic orbital DFT code
76 :mod:`~ase.calculators.eam` Embedded Atom Method
77 elk Full Potential LAPW code
78 :mod:`~ase.calculators.espresso` Plane-wave pseudopotential code
79 :mod:`~ase.calculators.exciting` Full Potential LAPW code
80 :mod:`~ase.calculators.aims` Numeric atomic orbital, full potential code
81 :mod:`~ase.calculators.fleur` Full Potential LAPW code
82 gaussian Gaussian based electronic structure code
83 :mod:`~ase.calculators.gromacs` Classical molecular dynamics code
84 :mod:`~ase.calculators.gulp` Interatomic potential code
85 :mod:`~ase.calculators.jacapo` Plane-wave ultra-soft pseudopotential code
86 :mod:`~ase.calculators.lammps` Classical molecular dynamics code
87 mopac ...
88 :mod:`~ase.calculators.nwchem` Gaussian based electronic structure code
89 :mod:`~ase.calculators.octopus` Real-space pseudopotential code
90 :mod:`~ase.calculators.siesta` LCAO pseudopotential code
91 :mod:`~ase.calculators.turbomole` Fast atom orbital code
92 :mod:`~ase.calculators.vasp` Plane-wave PAW code
93 :mod:`~ase.calculators.emt` Effective Medium Theory calculator
94 lj Lennard-Jones potential
95 morse Morse potential
96 :mod:`~ase.calculators.checkpoint` Checkpoint calculator
97 :mod:`~ase.calculators.loggingcalc` Logging calculator
98 :mod:`~ase.calculators.dftd3` DFT-D3 dispersion correction calculator
99 =================================== ===========================================
60 the :class:`ase.calculators.loggingcalc.LoggingCalculator`,
61 the :ref:`Grimme-D3 <grimme>` potential, and the qmmm calculators
62 :class:`~ase.calculators.qmmm.EIQMMM`, and :class:`~ase.calculators.qmmm.SimpleQMMM`.
63
64
65 ========================================= ===========================================
66 name description
67 ========================================= ===========================================
68 Asap_ Highly efficient EMT code
69 GPAW_ Real-space/plane-wave/LCAO PAW code
70 Hotbit_ DFT based tight binding
71 :mod:`~ase.calculators.abinit` Plane-wave pseudopotential code
72 :mod:`~ase.calculators.amber` Classical molecular dynamics code
73 :mod:`~ase.calculators.castep` Plane-wave pseudopotential code
74 :mod:`~ase.calculators.cp2k` DFT and classical potentials
75 :mod:`~ase.calculators.demon` Gaussian based DFT code
76 :mod:`~ase.calculators.dftb` DFT based tight binding
77 :mod:`~ase.calculators.dmol` Atomic orbital DFT code
78 :mod:`~ase.calculators.eam` Embedded Atom Method
79 elk Full Potential LAPW code
80 :mod:`~ase.calculators.espresso` Plane-wave pseudopotential code
81 :mod:`~ase.calculators.exciting` Full Potential LAPW code
82 :mod:`~ase.calculators.aims` Numeric atomic orbital, full potential code
83 :mod:`~ase.calculators.fleur` Full Potential LAPW code
84 gaussian Gaussian based electronic structure code
85 :mod:`~ase.calculators.gromacs` Classical molecular dynamics code
86 :mod:`~ase.calculators.gulp` Interatomic potential code
87 :mod:`~ase.calculators.jacapo` Plane-wave ultra-soft pseudopotential code
88 :mod:`~ase.calculators.lammps` Classical molecular dynamics code
89 :mod:`~ase.calculators.mopac` ...
90 :mod:`~ase.calculators.nwchem` Gaussian based electronic structure code
91 :mod:`~ase.calculators.octopus` Real-space pseudopotential code
92 :mod:`~ase.calculators.onetep` Linear-scaling pseudopotential code
93 :mod:`~ase.calculators.siesta` LCAO pseudopotential code
94 :mod:`~ase.calculators.turbomole` Fast atom orbital code
95 :mod:`~ase.calculators.vasp` Plane-wave PAW code
96 :mod:`~ase.calculators.emt` Effective Medium Theory calculator
97 lj Lennard-Jones potential
98 morse Morse potential
99 :mod:`~ase.calculators.checkpoint` Checkpoint calculator
100 :mod:`~ase.calculators.loggingcalc` Logging calculator
101 :mod:`~ase.calculators.dftd3` DFT-D3 dispersion correction calculator
102 :class:`~ase.calculators.qmmm.EIQMMM` Explicit Interaction QM/MM
103 :class:`~ase.calculators.qmmm.SimpleQMMM` Subtractive (ONIOM style) QM/MM
104 ========================================= ===========================================
100105
101106 .. index:: D3, Grimme
102107 .. _grimme:
118123 .. _Asap: http://wiki.fysik.dtu.dk/asap
119124 .. _GPAW: http://wiki.fysik.dtu.dk/gpaw
120125 .. _Hotbit: https://github.com/pekkosk/hotbit
121
122126
123127 Calculator keywords
124128 ===================
198202 amber
199203 castep
200204 cp2k
205 crystal
206 demon
201207 dftb
202208 dmol
203209 espresso
209215 jacapo
210216 lammps
211217 lammpsrun
218 mopac
212219 nwchem
213220 octopus
221 onetep
214222 siesta
215223 turbomole
216224 vasp
0 .. module:: ase.calculators.crystal
1
2 =========
3 CRYSTAL14
4 =========
5
6 Introduction
7 ============
8
9 The CRYSTAL_ simulation package is a Hartree-Fock and density
10 functional theory code using Gaussian localized basis functions.
11 CRYSTAL_ can handle systems periodic in 0 (molecules, 0D), 1 (polymers, 1D),
12 2 (slabs, 2D), and 3 dimensions (crystals, 3D).
13 This interface makes possible to use CRYSTAL_ as a calculator
14 in ASE.
15
16 .. _CRYSTAL: http://www.crystal.unito.it/
17
18
19 Environment variables
20 =====================
21
22 Set environment variables in your configuration file (what is the name
23 of the command to be run). It is mandatory to set the input file as
24 "INPUT" and the standard output as "OUTPUT".
25
26 - bash::
27
28 $ export ASE_CRYSTAL_COMMAND="/bin/CRY14/crystal < INPUT > OUTPUT 2>&1" (an example)
29
30 - csh/tcsh::
31
32 $ setenv ASE_CRYSTAL_COMMAND "/my_disk/my_name/bin/crystal < INPUT > OUTPUT 2>&1" (an example)
33
34
35 CRYSTAL Calculator (a FileIOCalculator)
36 =======================================
37
38 The calculator calls the CRYSTAL_ code only
39 to perform single point and gradient calculations.
40 The file 'fort.34' contains the input geometry and
41 the 'fort.20' contains the wave function in a binary
42 format.
43
44 Below follows a list with a selection of parameters.
45
46 ============== ========= =============== ============================
47 keyword type default value description
48 ============== ========= =============== ============================
49 ``restart`` ``bool`` None Restart old calculation
50 ``xc`` various 'HF' Hamiltonian. HF, MP2 or DFT
51 methods available
52 ``spinpol`` ``bool`` False Spin polarization
53 ``guess`` ``bool`` True Read wf from fort.20 file
54 when present
55 ``basis`` ``str`` 'custom' Read basis set from
56 basis file
57 ``kpts`` various None or (1,1,1) **k**-point sampling if
58 calculation is periodic
59 ``isp`` ``int`` 1 Density of the Gilat net
60 with respect to Monkhorst-
61 Pack
62 ``smearing`` ``float`` None Smearing. Only Fermi-Dirac
63 available
64 ``otherkeys`` ``list`` [] All other CRYSTAL keywords
65 ============== ========= =============== ============================
66
67 For parameters not set in ``otherkeys`` CRYSTAL_ will set the default value.
68 See the official `CRYSTAL manual`_ for more details.
69
70 .. _CRYSTAL manual: http://www.crystal.unito.it/Manuals/crystal14.pdf
71
72
73 Exchange-correlation functionals
74 ================================
75
76 The ``xc`` parameter is used to define the method used for the
77 calculation. Available options are Hartree-Fock ('HF'), second order
78 perturbation theory ('MP2') and the density-functional theory where ``xc``
79 defines the exchange and correlation functional. In the latter case
80 a single string defines a standalone functional (see `CRYSTAL manual`_),
81 a tuple of strings set the first string as EXCHANGE and the second
82 string as 'CORRELAT' (see `CRYSTAL manual`_ for more details).
83
84 .. code-block:: python
85
86 calc = CRYSTAL(xc=('PBE','LYP'))
87
88
89 Setups
90 ======
91
92 The CRYSTAL_ simulation package has few built-in basis sets, which
93 can be set in the calculation using the ``basis`` parameter, e. g.:
94
95 .. code-block:: python
96
97 calc = CRYSTAL(xc='PBE', basis='sto-3g')
98
99 The default is to read from an external basis set. A library of
100 basis sets in CRYSTAL_ format can be found on the
101 website `CRYSTAL basis sets`_.
102
103 .. _CRYSTAL basis sets: http://www.crystal.unito.it/basis-sets.php
104
105 In this case a file named 'basis' must be present in the working directory
106 and must contain the basis sets for all the atom species.
107
108 .. note::
109
110 The CRYSTAL_ simulation package allows to set up to three different
111 all electron basis sets and/or two valence electron basis sets for
112 the same atomic species (see `CRYSTAL manual`_ page 21 for more details).
113
114 The number to be added to the atomic number reported in the 'basis'
115 file must be specified as an ``Atoms()`` class tag:
116
117 >>> geom[0].tag = 100
118
119 In this case '100' will be summed to the atomic number of the first atom
120 in the 'fort.34' geometry file (e. g. '6', Carbon, becomes '106').
121
122
123 Spin-polarized calculation
124 ==========================
125
126 If the atoms object has non-zero magnetic moments, a spin-polarized
127 calculation will be performed by default.
128 It is also possible to manually tell the calculator to perform a
129 spin-polarized calculation through the parameter ``spinpol``:
130
131 .. code-block:: python
132
133 calc = CRYSTAL(xc='PBE', spinpol=True)
134
135
136 Brillouin-zone sampling
137 =======================
138
139 Brillouin-zone sampling is controlled by ``kpts``. This parameter
140 can be set to a sequence of three int values, e.g. (2, 2, 3),
141 which define a regular Monkhorst-Pack grid. If it is not defined a
142 ``gamma`` calculation will be performed.
143 For 2D calculations ``kpts[2]`` will be to set to one, for 1D ones
144 also ``kpts[1]`` will be set to unity.
145 For molecular calculations (0D) any definition of the ``kpts``
146 parameter will be ignored.
147
148 The ``isp`` parameter can be used to define the relative
149 density of the auxiliary Gilat net (see `CRYSTAL manual`_):
150
151 .. code-block:: python
152
153 calc = CRYSTAL(xc='PBE', kpts=(2, 2, 2), isp=2)
154
155 In this example the resulting Gilat net would be (4, 4, 4).
156
157
158 Reading an external wave function
159 =================================
160
161 The calculator reads by default the wave function stored in
162 the 'fort.20' file if present (``guess=True``).
163 If this parameter is set to False the code will calculate the
164 wave function from scratch at any step, slowing down the perfromances.
165
166
167 Code related keywords
168 =====================
169
170 The CRYSTAL_ simulation package allows for many other keywords.
171 Most of them can be specified through the ``otherkeys`` parameter.
172
173 .. code-block:: python
174
175 calc = CRYSTAL(xc='PBE', otherkeys=['scfdir', 'anderson',
176 ['maxcycles', '500'],
177 ['toldee', '6'],
178 ['tolinteg', '7 7 7 7 14'],
179 ['fmixing', '90']])
0 .. module:: ase.calculators.demon
1
2 Demon
3 =====
4
5 http://www.demon-software.com/public_html/index.html
6
7 .. autoclass:: Demon
1414 GPAW to allow seamless calculation of dispersion-corrected DFT energies,
1515 forces, and stresses.
1616
17 .. _DFTD3: http://www.thch.uni-bonn.de/tc/index.php?section=downloads&subsection=DFT-D3
17 .. _DFTD3: https://www.chemie.uni-bonn.de/pctc/mulliken-center/software/dft-d3/
1818
1919 This is a list of all supported keywords and settings:
2020
33 LAMMPS Calculators
44 ==================
55
6 LAMMPS_ (Large-scale Atomic/Molecular Massively Parallel Simulator) is
6 LAMMPS_link_ (Large-scale Atomic/Molecular Massively Parallel Simulator) is
77 a classical molecular dynamics code.
88
99 There are two calculators that interface to the LAMMPS molecular
2121 further commands can be sent to this object and executed until it is
2222 explicitly closed. Any additional variables calculated by LAMMPS can
2323 also be extracted. Note however, any mistakes in the code sent to the
24 LAMMPS routine will cause python to terminate.
25
26 ASE is licensed as LGPL and LAMMPS is GPL which 'prohibits' them from
27 being linked together in a distribution such as ASE. As a result, LAMMPSlib is
28 not distributed with the ASE project but is available separately at
29 lammpslib_. Further explanation of the licensing is constained in
30 :ref:`license info`.
24 LAMMPS routine will cause python to terminate. Further information on the
25 python interface of LAMMPS can be found at lammpspy_link_. Note that it can be
26 very benefitial to compile lammps with C++ exceptions. Otherwise there will be
27 no error messages upon crashes.
3128
3229 It should not matter which code you use, but if you want access to
3330 more of LAMMPS internal variables or to perform a more complicated
3835 Both of these interfaces are still experimental code and any
3936 problems should be reported to the ASE developers mailing list.
4037
41 .. _LAMMPS: http://lammps.sandia.gov
42 .. _lammpslib: https://svn.fysik.dtu.dk/projects/ase-extra/trunk/ase/calculators
38 .. autoclass:: ase.calculators.lammpsrun.LAMMPS
39
40 .. autoclass:: ase.calculators.lammpslib.LAMMPSlib
41
42 .. _LAMMPS_link: http://lammps.sandia.gov
43 .. _lammpslib_link: https://svn.fysik.dtu.dk/projects/ase-extra/trunk/ase/calculators
44 .. _lammpspy_link: http://lammps.sandia.gov/doc/Section_python.html
0 .. module:: ase.calculators.mopac
1
2 Mopac
3 =====
4
5 http://openmopac.net/
6
7 .. autoclass:: MOPAC
5757 xc='B3LYP',
5858 basis='6-31+G*')
5959
60 If you need to request more memory, it is typically not sufficient to do so
61 only through your queuing system. You need to also let NWChem know about the
62 additional available memory, with NWChem's `memory` keyword which in turn is
63 added through ASE's `raw` keyword (which puts raw text lines in the NWChem
64 input file). An example is below; see the official NWChem documentation for
65 the proper use of the `memory` keyword.
66
67 .. code-block:: python
68 :emphasize-lines: 2
69
70 calc = NWChem(label='calc/nwchem',
71 raw='memory 2000 MB')
72
6073
6174 Parameters
6275 ==========
6376
6477 The list of possible parameters and their defaults is shown below.
78 See the NWChem documentation for full explanations of these different options.
6579
6680 =============== ======== ======================== ============================
6781 keyword type default value description
7791 NWChem centers the
7892 coordinates by default.
7993 ``convergence`` ``dict`` Convergence criteria.
80 ``basis`` ``str`` ``'3-21G'`` Basic set.
94 ``basis`` ``str`` ``'3-21G'`` Basis set.
8195 ``print`` ``str`` ``None`` Flags within the DFT block
8296 steering the output details.
8397 ``basispar`` ``None``
8498 ``ecp`` ``None``
8599 ``so`` ``None``
86 ``spinorbit`` ``None``
87 ``odft`` ``None``
100 ``spinorbit`` ``None`` Use spin-orbit DFT module.
101 ``odft`` ``None`` Use open-shell (spin-polarized)
102 DFT.
88103 ``raw`` ``''`` Raw text outside DFT block
89104 control string.
90105 =============== ======== ======================== ============================
0 .. module:: ase.calculators.onetep
1
2 ======
3 ONETEP
4 ======
5
6 Introduction
7 ============
8
9 ONETEP_ is a fully-featured density-functional package combining linear scaling
10 with system size, systematic plane-wave accuracy, and excellent parallel
11 scaling. It uses a set of atom-centered local orbitals (denoted NGWFs) which
12 are optimised in situ to enable high accuracy calculations with a minimal number
13 of orbitals.
14
15 This interface makes it possible to use ONETEP as a calculator in ASE.
16 You need to have a copy of the ONETEP code (and an appropriate license) to use
17 this interface.
18
19 Additionally you will need pseudopotential or PAW dataset files for the
20 combination of atom types of your system.
21
22 .. _ONETEP: http://www.onetep.org
23
24
25 Environment variables
26 =====================
27
28 The environment variable :envvar:`ASE_ONETEP_COMMAND` must hold the command
29 to invoke the ONETEP calculation. The variable must be a string with a link
30 to the ONETEP binary, and any other settings required for the parallel
31 execution
32 Example:
33
34 You can this environment variable in your shell configuration file:
35
36 .. highlight:: bash
37
38 ::
39
40 $ export ASE_ONETEP_COMMAND="export OMP_NUM_THREADS=4; mpirun -n 6 /storage/nanosim/ONETEP/devel/bin/onetep.csc PREFIX.dat >> PREFIX.out 2> PREFIX.err"
41
42
43 .. highlight:: python
44
45 Or within python itself:
46
47 >>> environ["ASE_ONETEP_COMMAND"]="export OMP_NUM_THREADS=4; mpirun -n 6 /storage/nanosim/ONETEP/devel/bin/onetep.csc PREFIX.dat >> PREFIX.out 2> PREFIX.err"
48
49
50 ONETEP Calculator
51 =================
52
53 This is implemented as a FileIOCalculator: most parameters from the ONETEP
54 keyword list: http://www.onetep.org/Main/Keywords can be specified using
55 the calculator's `set` routine.
56
57 ==================== ========= ============= =====================================
58 keyword type default value description
59 ==================== ========= ============= =====================================
60 ``label`` ``str`` None Name of input and output files
61 ``cutoff_energy`` ``str`` ``1000 eV`` Energy cutoff of psinc grid
62 ``ngwf_radius`` ``str`` ``12.0 bohr`` Cutoff Radius of NGWF
63 ``kernel_cutoff`` ``str`` ``1000 bohr`` Cutoff Radius for density kernel
64 ==================== ========= ============= =====================================
65
66
67 Example
68 =======
69
70 Here is an example of setting up a calculation on a graphene sheet: ::
71
72 # Set up a graphene lattice with a 9x9 supercell
73 from ase.lattice.hexagonal import *
74 from ase.visualize import view
75 index1=9
76 index2=9
77 alat = 2.45
78 clat = 19.2857142857
79 gra = Graphene(symbol = 'C',latticeconstant={'a':alat,'c':clat},size=(index1,index2,1))
80
81 # Set up a ONETEP calculation using PBE functional and ensemble DFT
82 from ase.calculators.onetep import Onetep
83 from os.path import isfile, dirname, abspath, join
84 from os import environ
85 environ["ASE_ONETEP_COMMAND"]="export OMP_NUM_THREADS=4;
86 mpirun -n 6 /storage/nanosim/ONETEP/devel/bin/onetep.csc PREFIX.dat >> PREFIX.out 2> PREFIX.err"
87 calc = Onetep(label='gra')
88 pseudos='/path/to/pseudos'
89 calc.set_pseudos([('C', join(pseudos, 'C.PBE-paw.abinit'))])
90 calc.set(paw=True,xc='PBE', cutoff_energy='500 eV',ngwf_radius=8,edft='T')
91
92 # Run the calculation
93 gra.get_potential_energy()
94
95 .. highlight:: python
96
97 Here is an example of setting up a calculation on a water molecule: ::
98
99 # Set up water molecule in box with 6 ang padding.
100 from ase.build import molecule
101 wat = molecule('H2O')
102 wat.center(6)
103
104 # Set up a ONETEP geometry optimisation calculation using the PBE functional
105 from ase.calculators.onetep import Onetep
106 from os.path import isfile, dirname, abspath, join
107 from os import environ
108 environ["ASE_ONETEP_COMMAND"]="export OMP_NUM_THREADS=8; mpirun -n 2 /home/theory/phspvr/ONETEP/devel/bin/onetep.csc PREFIX.dat >> PREFIX.out 2> PREFIX.err"
109 calc = Onetep(label='water')
110 prefix='/home/theory/phspvr/JTH_PBE'
111 calc.set_pseudos([('H', join(prefix, 'H.PBE-paw.abinit')), ('O', join(prefix, 'O.PBE-paw.abinit'))])
112 calc.set(task='GeometryOptimization',paw=True,xc='PBE',cutoff_energy='600 eV')
113 wat.set_calculator(calc)
114 wat.get_forces()
115
116 .. highlight:: python
22 QMMM
33 ====
44
5 .. seealso::
5 There are two QM/MM calculators native to ASE:
66
7 The :ref:`qmmm` tutorial.
8
9
10 Simple QMMM calculations
11 ------------------------
12
13 .. autoclass:: SimpleQMMM
14
15 This type of QMMM can combine any pair of ASE calculators::
16
17 from ase.calculators.qmmm import SimpleQMMM
18 atoms = ...
19 atoms.calc = SimpleQMMM([0, 1, 2],
20 QMCalculator(...),
21 MMCalculator(...))
22
23 where ``[0, 1, 2]`` would select the first three atoms for the QM-part.
7 ========================= ===================
8 Explicit Interaction QMMM :class:`EIQMMM`
9 Simple, subtrative QMMM :class:`SimpleQMMM`
10 ========================= ===================
2411
2512
2613 Explicit Interaction QMMM
2714 -------------------------
15
16 In Explicit Interaction QMMM, the QM and MM regions
17 are explicitly coupled with an electrostatic interaction term.
18 This requires that the electrostatic potential from the classical charges of the
19 MM subsystem is fed into the QM calculator. This is built into GPAW_. More info
20 `In this paper <https://doi.org/10.1021/acs.jctc.7b00621>`__, which should be cited if
21 the method is used.
22
23 .. _GPAW: http://wiki.fysik.dtu.dk/gpaw
24
25 .. seealso::
26
27 The :ref:`qmmm` tutorial, on how to use the Explicit Interaction QMMM calculator
2828
2929 .. autoclass:: EIQMMM
3030
4848 default is this one:
4949
5050 .. autoclass:: Embedding
51
52 Simple, subtractive QMMM calculations
53 -------------------------------------
54
55 This QM/MM calculator is similar to the original ONIOM model, doing
56 simple, subtractive QM/MM between any two calculators.
57
58 .. autoclass:: SimpleQMMM
59
60 This type of QMMM can combine any pair of ASE calculators::
61
62 from ase.calculators.qmmm import SimpleQMMM
63 atoms = ...
64 atoms.calc = SimpleQMMM([0, 1, 2],
65 QMCalculator(...),
66 MMCalculator(...))
67
68 where ``[0, 1, 2]`` would select the first three atoms for the QM-part.
211211 a broken file will result in an error(False) or the whether the calculator
212212 will simply continue without the restart file.
213213
214 TDDFT Calculations
215 ==================
216
217 It is possible to run Time Dependent Density Functional Theory (TDDFT) using the
218 `PYSCF-NAO <https://github.com/cfm-mpc/pyscf/tree/nao/pyscf/lib/nao>`_ code together
219 with the SIESTA code. This code allows to run TDDFT up to
220 thousand atoms with small computational ressources. Visit the
221 `github <https://github.com/cfm-mpc/pyscf/tree/nao>`_ webpage for
222 further informations about PYSCF-NAO.
223
224 Example of code to calculate polarizability of Na8 cluster,::
225
226 from ase.units import Ry, eV, Ha
227 from ase.calculators.siesta import Siesta
228 from ase import Atoms
229 import numpy as np
230 import matplotlib.pyplot as plt
231
232 # Define the systems
233 Na8 = Atoms('Na8',
234 positions=[[-1.90503810, 1.56107288, 0.00000000],
235 [1.90503810, 1.56107288, 0.00000000],
236 [1.90503810, -1.56107288, 0.00000000],
237 [-1.90503810, -1.56107288, 0.00000000],
238 [0.00000000, 0.00000000, 2.08495836],
239 [0.00000000, 0.00000000, -2.08495836],
240 [0.00000000, 3.22798122, 2.08495836],
241 [0.00000000, 3.22798122, -2.08495836]],
242 cell=[20, 20, 20])
243
244 # Siesta input
245 siesta = Siesta(
246 mesh_cutoff=150 * Ry,
247 basis_set='DZP',
248 pseudo_qualifier='',
249 energy_shift=(10 * 10**-3) * eV,
250 fdf_arguments={
251 'SCFMustConverge': False,
252 'COOP.Write': True,
253 'WriteDenchar': True,
254 'PAO.BasisType': 'split',
255 'DM.Tolerance': 1e-4,
256 'DM.MixingWeight': 0.01,
257 'MaxSCFIterations': 300,
258 'DM.NumberPulay': 4,
259 'XML.Write': True})
260
261 Na8.set_calculator(siesta)
262 e = Na8.get_potential_energy()
263 freq, pol = siesta.get_polarizability_pyscf_inter(label="siesta",
264 jcutoff=7,
265 iter_broadening=0.15/Ha,
266 xc_code='LDA,PZ',
267 tol_loc=1e-6,
268 tol_biloc=1e-7,
269 freq = np.arange(0.0, 5.0, 0.05))
270 # plot polarizability
271 plt.plot(freq, pol[:, 0, 0].imag)
272 plt.show()
273
274 Remark:
275 -------
276
277 The PYSCF-NAO code is still under active development and to have access to
278 it with ASE you will need to use this PYSCF `fork <https://github.com/cfm-mpc/pyscf>`_
279 and use the branch nao. To summarize::
280
281 git clone https://github.com/cfm-mpc/pyscf
282 git fetch
283 git checkout nao
284
285 Then you can follow the instruction of the `README <https://github.com/cfm-mpc/pyscf/blob/nao/pyscf/lib/nao/README.md>`_.
286 The installation is relatively easy, go to the lib directory::
287
288 cd pyscf/pyscf/lib
289 cp cmake_arch_config/cmake.arch.inc-your-config cmake.arch.inc
290 mkdir build
291 cd build
292 cmake ..
293 make
294
295 Then you need to add the pyscf directory to your PYTHONPATH
296
297 .. code-block:: none
298
299 export PYTHONPATH=/PATH-TO-PYSCF/pyscf:$PYTHONPATH
300
301
302
303 Raman Calculations with SIESTA and PYSCF-NAO
304 ============================================
305
306 It is possible to calulate the Raman spectra with SIESTA, PYSCF-NAO anf the
307 vibration module from ASE. Example with CO2,::
308
309 from ase.units import Ry, eV, Ha
310 from ase.calculators.siesta import Siesta
311 from ase.calculators.siesta.siesta_raman import SiestaRaman
312 from ase import Atoms
313 import numpy as np
314
315 # Define the systems
316 # example of Raman calculation for CO2 molecule,
317 # comparison with QE calculation can be done from
318 # https://github.com/maxhutch/quantum-espresso/blob/master/PHonon/examples/example15/README
319
320 CO2 = Atoms('CO2',
321 positions=[[-0.009026, -0.020241, 0.026760],
322 [1.167544, 0.012723, 0.071808],
323 [-1.185592, -0.053316, -0.017945]],
324 cell=[20, 20, 20])
325
326 # enter siesta input
327 # To perform good vibrational calculations it is strongly advised
328 # to relax correctly the molecule geometry before to actually run the
329 # calculations. Then to use a large mesh_cutoff and to have the option
330 # PAO.SoftDefault turned on
331 siesta = Siesta(
332 mesh_cutoff=450 * Ry,
333 basis_set='DZP',
334 xc="GGA",
335 pseudo_qualifier='gga',
336 energy_shift=(10 * 10**-3) * eV,
337 fdf_arguments={
338 'SCFMustConverge': False,
339 'COOP.Write': True,
340 'WriteDenchar': True,
341 'PAO.BasisType': 'split',
342 "PAO.SoftDefault": True,
343 'DM.Tolerance': 1e-4,
344 'DM.MixingWeight': 0.01,
345 'MaxSCFIterations': 300,
346 'DM.NumberPulay': 4,
347 'XML.Write': True,
348 'DM.UseSaveDM': True})
349
350 CO2.set_calculator(siesta)
351
352 ram = SiestaRaman(CO2, siesta, nfree=4, label="siesta", jcutoff=7, iter_broadening=0.15/Ha,
353 xc_code='LDA,PZ', tol_loc=1e-6, tol_biloc=1e-7, freq = np.arange(0.0, 5.0, 0.05))
354
355 ram.run()
356 ram.summary(intensity_unit_ram='A^4 amu^-1')
357 ram.write_spectra(start=200, intensity_unit_ram='A^4 amu^-1')
358
214359
215360 Further Examples
216361 ================
217362 See also ``ase/test/calculators/siesta/test_scripts`` for further examples
218363 on how the calculator can be used.
364
365
366 Siesta Calculator Class
367 =======================
368
369 .. autoclass:: ase.calculators.siesta.base_siesta.BaseSiesta
155155
156156 For many elements, VASP is distributed with a choice of
157157 pseudopotential setups. These may be hard/soft variants of the
158 pseudopotential or include additional valence electrons. While the
159 Vasp calculator will default to the pseudopotential folders with the
160 same name as the element, alternative setups may be selected
161 with the `setups` dictionary.
162
163 To use an alternative setup for all instances of an element, simply
164 provide the characters which need to be added, e.g.
158 pseudopotential or include additional valence electrons.
159 Three base setups are provided:
160
161 minimal (default):
162 If a PAW folder exists with the same name as the element,
163 this will be used. For the other elements, the PAW setup
164 with the least electrons has been chosen.
165 recommended:
166 corresponds to the `table of recommended PAW setups <https://cms.mpi.univie.ac.at/vasp/vasp/Recommended_PAW_potentials_DFT_calculations_using_vasp_5_2.html>`_ supplied by the VASP developers.
167 gw:
168 corresponds to the `table of recommended setups for GW <https://cms.mpi.univie.ac.at/vasp/vasp/Recommended_GW_PAW_potentials_vasp_5_2.html>`_ supplied by the VASP developers.
169
170 Where elements are missing from the default sets, the Vasp Calculator
171 will attempt to use a setup folder with the same name as the element.
172 A default setup may be selected with the ``setups`` keyword:
173
174 .. code-block:: python
175
176 from ase.calculators.vasp import Vasp
177 calc = Vasp(setups='recommended')
178
179 To use an alternative setup for all instances of an element, use the
180 dictionary form of ``setups`` to provide the characters which need
181 to be added to the element name, e.g.
165182
166183 .. code-block:: python
167184
168185 calc = Vasp(xc='PBE', setups={'Li': '_sv'})
169186
170187 will use the ``Li_sv`` all-electron pseudopotential for all Li atoms.
188
171189 To apply special setups to individual atoms, identify them by their
172190 zero-indexed number in the atom list and use the full setup name. For
173191 example,
174192
175193 .. code-block:: python
176194
177 calc= Vasp(xc='PBE', setups={3: 'Ga_d'})
195 calc = Vasp(xc='PBE', setups={3: 'Ga_d'})
178196
179197 will treat the Ga atom in position 3 (i.e. the fourth atom) of the
180198 atoms object as special, with an additional 10 d-block valence
181199 electrons, while other Ga atoms use the default 3-electron setup and
182200 other elements use their own default setups. The positional index may
183201 be quoted as a string (e.g. ``{'3': 'Ga_d'}``).
202
203 These approaches may be combined by using the 'base' key to access a
204 default set, e.g.
205
206 .. code-block:: python
207
208 calc = Vasp(xc='PBE', setups={'base': 'recommended', 'Li': '', 4: 'H.5'})
184209
185210 Spin-polarized calculation
186211 ==========================
0 .. module:: ase.cluster
0 .. module:: ase.cluster
11
22 ==========================
33 Nanoparticles and clusters
44 ==========================
55
6
7 There are modules for creating nanoparticles (clusters) with a given crystal structure by specifying either the number of layers in different directions, or by making a Wulff construction.
6 There are modules for creating nanoparticles (clusters) with a given crystal
7 structure by specifying either the number of layers in different directions,
8 or by making a Wulff construction.
89
910 Examples
1011 ========
1213 Layer specification
1314 -------------------
1415
15 This example sets up a nanoparticle of copper in the FCC crystal structure, by specifying 6 layers in the (100) directions, 9 in the (110) directions and 5 in the (111) directions::
16 This example sets up a nanoparticle of copper in the FCC crystal structure,
17 by specifying 6 layers in the (100) directions, 9 in the (110) directions and
18 5 in the (111) directions::
1619
1720 import ase
1821 from ase.cluster.cubic import FaceCenteredCubic
4548 lc = 3.61000
4649 size = 1000 # Number of atoms
4750 atoms = wulff_construction('Cu', surfaces, esurf,
48 size, 'fcc',
49 rounding='above', latticeconstant=lc)
51 size, 'fcc',
52 rounding='above', latticeconstant=lc)
5053
5154 Note that the Wulff construction currently only work with cubic
5255 lattices.
9194
9295 .. |truncated| image:: truncated.png
9396
94
97
9598
9699 The functions for creating nanoparticles take the following
97100 arguments:
131134 from ase.cluster import wulff_construction
132135
133136 .. autofunction:: ase.cluster.wulff_construction
134
135
136
137
138
139
00 # creates: ase-db.txt, ase-db-long.txt, known-keys.csv
1 from __future__ import print_function
2
13 import subprocess
24
35 import ase.db
00 # creates: cubic.svg, fcc.svg, bcc.svg, tetragonal.svg, orthorhombic.svg
11 # creates: hexagonal.svg, monoclinic.svg
2 from math import pi, sin, cos
3
42 import numpy as np
53 import matplotlib.pyplot as plt
64
75 from ase.dft.kpoints import (get_special_points, special_paths,
86 parse_path_string)
9
10
11 def bz_vertices(cell):
12 from scipy.spatial import Voronoi
13 icell = np.linalg.inv(cell)
14 I = np.indices((3, 3, 3)).reshape((3, 27)) - 1
15 G = np.dot(icell, I).T
16 vor = Voronoi(G)
17 bz1 = []
18 for vertices, points in zip(vor.ridge_vertices, vor.ridge_points):
19 if -1 not in vertices and 13 in points:
20 normal = G[points].sum(0)
21 normal /= (normal**2).sum()**0.5
22 bz1.append((vor.vertices[vertices], normal))
23 return bz1
24
25
26 def plot(cell, paths, elev=None, scale=1):
27 import matplotlib.pyplot as plt
28 from mpl_toolkits.mplot3d import Axes3D
29 Axes3D # silence pyflakes
30
31 fig = plt.figure(figsize=(5, 5))
32 ax = fig.gca(projection='3d')
33
34 azim = pi / 5
35 elev = elev or pi / 6
36 x = sin(azim)
37 y = cos(azim)
38 view = [x * cos(elev), y * cos(elev), sin(elev)]
39
40 bz1 = bz_vertices(cell)
41
42 for points, normal in bz1:
43 if np.dot(normal, view) < 0:
44 ls = ':'
45 else:
46 ls = '-'
47 x, y, z = np.concatenate([points, points[:1]]).T
48 ax.plot(x, y, z, c='k', ls=ls)
49
50 txt = ''
51 for names, points in paths:
52 x, y, z = np.array(points).T
53 ax.plot(x, y, z, c='b', ls='-')
54
55 for name, point in zip(names, points):
56 x, y, z = point
57 if name == 'G':
58 name = '\\Gamma'
59 elif len(name) > 1:
60 name = name[0] + '_' + name[1]
61 ax.text(x, y, z, '$' + name + '$',
62 ha='center', va='bottom', color='r')
63 txt += '`' + name + '`-'
64
65 txt = txt[:-1] + '|'
66
67 print(txt[:-1])
68
69 ax.set_axis_off()
70 ax.autoscale_view(tight=True)
71 s = np.array(paths[0][1]).max() / 0.5 * 0.45 * scale
72 ax.set_xlim(-s, s)
73 ax.set_ylim(-s, s)
74 ax.set_zlim(-s, s)
75 ax.set_aspect('equal')
76
77 ax.view_init(azim=azim / pi * 180, elev=elev / pi * 180)
7 from ase.dft.bz import bz3d_plot
788
799
8010 for X, cell in [
9828
9929 if X == 'bcc':
10030 scale = 0.6
101 elev = pi / 13
31 elev = 0.24
32 # pi / 13
10233 else:
10334 scale = 1
10435 elev = None
10536
106 plot(cell, paths, elev, scale)
37 bz3d_plot(cell=cell, paths=paths, elev=elev, scale=scale)
10738 plt.savefig(X + '.svg')
3737 formatted files.
3838
3939 For the CIF format, STAR extensions as save frames, global blocks,
40 nested loops and multi-data values are not supported. Furthermore,
41 ASE currently assumes the ``loop_`` identifier, and the following
42 loop variable names to be on separate lines.
40 nested loops and multi-data values are not supported.
4341
4442 .. note::
4543
102100
103101 .. image:: io3.png
104102
105 Note that in general the XYZ-format does not contain information about the unic cell, however, ASE uses the extended XYZ-format which stores the unitcell:
103 Note that in general the XYZ-format does not contain information about the unit cell, however, ASE uses the extended XYZ-format which stores the unitcell:
106104
107105 >>> from ase.io import read, write
108106 >>> write('slab.xyz', slab)
114112 [ 0. , 0. , 18.168]])
115113 >>> a.get_pbc()
116114 array([ True, True, False], dtype=bool)
115
116 Another way to include the unit cell is to write the cell vectors at the end of the file as ``VEC<N> <x> <y> <z>`` (used for example in the ADF software).
117
118 >>> write('slab.xyz', vec_cell=True)
117119
118120 Use ASE's native format for writing all information:
119121
22 Building neighbor-lists
33 =======================
44
5 The :class:`ase.calculators.emt.EMT` potential and the GPAW_ DFT calculator
6 both make use of ASE's built-in neighbor-list class:
5 A neighbor list is a collision detector for spheres: Given
6 a number of spheres of different radius located at different points,
7 it calculates the pairs of spheres that overlap.
8
9 ASE provides two implementations of neighbor lists. The newer
10 linearly-scaling function
11 :func:`ase.neighborlist.neighbor_list` and
12 the older quadratically-scaling class
13 :class:`ase.neighborlist.NeighborList`. The latter will likely
14 use the former as a backend in the future for linear scaling.
15
16 For flexibility, both implementations provide a “primitive”
17 interface which accepts arrays as arguments rather than the
18 more complex :class:`ase.atoms.Atoms` objects.
19
20
21 .. autofunction:: ase.neighborlist.neighbor_list
22
23 .. autofunction:: ase.neighborlist.primitive_neighbor_list
724
825 .. autoclass:: ase.neighborlist.NeighborList
926 :members:
1027
28 .. autoclass:: PrimitiveNeighborList
1129
1230 .. _GPAW: http://wiki.fysik.dtu.dk/gpaw
101101
102102 .. autoclass:: Phonons
103103 :members:
104
105
106
1515 energies = []
1616 log_calc = LoggingCalculator(EMT())
1717
18 for precon, label in [(None, 'None'), (Exp(A=3, use_pyamg=False), 'Exp(A=3)')]:
18 for precon, label in [(None, 'None'), (Exp(A=3, mu=1.0), 'Exp(A=3)')]:
1919 log_calc.label = label
2020 atoms = a0.copy()
2121 atoms.set_calculator(log_calc)
44 ==============================
55
66 This module contains utility functions and classes.
7
8 .. toctree::
9
10 xrdebye
711
812 .. autofunction:: ase.utils.opencew
913 .. autofunction:: ase.utils.gcd
66 Vibrational modes
77 =================
88
9 You can calculate the vibrational modes of a an
9 You can calculate the vibrational modes of an
1010 :class:`~ase.Atoms` object in the harmonic approximation using
1111 the :class:`Vibrations`.
1212
00 # creates: mlab_options.txt
11 import subprocess
2 subprocess.check_call('python -m ase.visualize.mlab -h > mlab_options.txt',
2 subprocess.check_call('python3 -m ase.visualize.mlab -h > mlab_options.txt',
33 shell=True)
9696 .. _NGL: https://github.com/arose/ngl
9797 .. _ipywidgets: https://github.com/jupyter-widgets/ipywidgets
9898
99 .. autoclass:: ase.visualize.nglview.NGLDisplay
99 .. autoclass:: ase.visualize.ngl.NGLDisplay
100100 :inherited-members:
101101
102 .. autofunction:: ase.visualize.nglview.view_ngl
103 .. automethod:: ase.visualize.nglview.NGLDisplay.custom_colors
102 .. autofunction:: ase.visualize.ngl.view_ngl
103 .. automethod:: ase.visualize.ngl.NGLDisplay.custom_colors
104104
105105
106106 .. module:: ase.visualize.mlab
0 # creates: saxs.png, xrd.png
1
2 from ase.utils.xrdebye import XrDebye
3 from ase.cluster.cubic import FaceCenteredCubic
4 import numpy as np
5
6 # create nanoparticle with approx. 2 nm diameter
7 atoms = FaceCenteredCubic('Ag', [(1, 0, 0), (1, 1, 0), (1, 1, 1)],
8 [6, 8, 8], 4.09)
9 # setup for desired wavelength
10 xrd = XrDebye(atoms=atoms, wavelength=0.50523)
11 # calculate and plot diffraction pattern
12 xrd.calc_pattern(x=np.arange(15, 30, 0.1), mode='XRD')
13 xrd.plot_pattern('xrd.png')
14 # calculate and plot samll-angle scattering
15 xrd.calc_pattern(x=np.logspace(-2, -0.3, 50), mode='SAXS')
16 xrd.plot_pattern('saxs.png')
0 .. module:: ase.utils.xrdebye
1
2 ===========================
3 X-ray scattering simulation
4 ===========================
5
6
7 The module for simulation of X-ray scattering properties from the atomic
8 level. The approach works only for finite systems, so that periodic boundary
9 conditions and cell shape are ignored.
10
11 Theory
12 ======
13
14 The scattering can be calculated using Debye formula [Debye1915]_ :
15
16 .. math::
17
18 I(q) = \sum_{a, b} f_a(q) \cdot f_b(q) \cdot
19 \frac{\sin(q \cdot r_{ab})}{q \cdot r_{ab}}
20
21 where:
22
23 - `a` and `b` -- atom indexes;
24 - `f_a(q)` -- `a`-th atomic scattering factor;
25 - `r_{ab}` -- distance between atoms `a` and `b`;
26 - `q` is a scattering vector length defined using scattering angle
27 (`\theta`) and wavelength (`\lambda`) as
28 `q = 4\pi \cdot \sin(\theta)/\lambda`.
29
30 The thermal vibration of atoms can be accounted by introduction of damping
31 exponent factor (Debye-Waller factor) written as `\exp(-B \cdot q^2 / 2)`.
32 The angular dependency of geometrical and polarization factors are expressed
33 as [Iwasa2007]_ `\cos(\theta)/(1 + \alpha \cos^2(2\theta))`, where `\alpha
34 \approx 1` if incident beam is not polarized.
35
36
37 Units
38 -----
39
40 The following measurement units are used:
41
42 - scattering vector `q` -- inverse Angstrom (1/Å),
43 - thermal damping parameter `B` -- squared Angstrom (Å\ :sup:`2`).
44
45
46 Example
47 =======
48
49 The considered system is a nanoparticle of silver which is built using
50 ``FaceCenteredCubic`` function (see :mod:`ase.cluster`) with parameters
51 selected to produce approximately 2 nm sized particle::
52
53 from ase.cluster.cubic import FaceCenteredCubic
54 import numpy as np
55
56 surfaces = [(1, 0, 0), (1, 1, 0), (1, 1, 1)]
57 atoms = FaceCenteredCubic('Ag', [(1, 0, 0), (1, 1, 0), (1, 1, 1)],
58 [6, 8, 8], 4.09)
59
60 Next, we need to specify the wavelength of the X-ray source::
61
62 xrd = XrDebye(atoms=atoms, wavelength=0.50523)
63
64 The X-ray diffraction pattern on the `2\theta` angles ranged from 15 to 30
65 degrees can be simulated as follows::
66
67 xrd.calc_pattern(x=np.arange(15, 30, 0.1), mode='XRD')
68 xrd.plot_pattern('xrd.png')
69
70 The resulted X-ray diffraction pattern shows (220) and (311) peaks at 20 and
71 ~24 degrees respectively.
72
73 .. image:: xrd.png
74
75 The small-angle scattering curve can be simulated too. Assuming that
76 scattering vector is ranged from `10^{-2}=0.01` to `10^{-0.3}\approx 0.5` 1/Å
77 the following code should be run: ::
78
79 xrd.calc_pattern(x=np.logspace(-2, -0.3, 50), mode='SAXS')
80 xrd.plot_pattern('saxs.png')
81
82 The resulted SAXS pattern:
83
84 .. image:: saxs.png
85
86
87 Further details
88 ===============
89
90 The module contains wavelengths dictionary with X-ray wavelengths for copper
91 and wolfram anodes::
92
93 from ase.utils.xrdebye import wavelengths
94 print('Cu Kalpha1 wavelength: %f Angstr.' % wavelengths['CuKa1'])
95
96
97 The dependence of atomic form-factors from scattering vector is calculated
98 based on coefficients given in ``waasmaier`` dictionary according
99 [Waasmaier1995]_ if method of calculations is set to 'Iwasa'. In other case,
100 the atomic factor is equal to atomic number and angular damping factor is
101 omitted.
102
103
104 XrDebye class members
105 ---------------------
106
107 .. autoclass:: XrDebye
108 :members:
109
110
111 References
112 ==========
113
114 .. [Debye1915] P. Debye Ann. Phys. **351**, 809–823 (1915)
115 .. [Iwasa2007] T. Iwasa, K. Nobusada J. Phys. Chem. C, **111**, 45-49 (2007) http://dx.doi.org/10.1021/jp063532w
116 .. [Waasmaier1995] D. Waasmaier, A. Kirfel Acta Cryst. **A51**, 416-431 (1995)
1717 info Print information about files or system
1818 test Test ASE
1919 gui ASE's :ref:`graphical user interface <ase-gui>`
20 convert Convert between file formats (see :mod:`ase.io`)
21 reciprocal Show the reciprocal space
2022 find Find files with atoms in
2123 db Manipulate and query :ref:`ASE database <ase-db>`
2224 run Run calculation with one of ASE's calculators
2729 band-structure Plot band-structure
2830 completion Add tab-completion for Bash
2931 ============== =================================================
32
33 .. note::
34
35 The ase CLI interface is not quite stable. Use with care in scripts!
3036
3137
3238 Python -m tricks
3939 html_static_path = ['static']
4040 html_last_updated_fmt = '%a, %d %b %Y %H:%M:%S'
4141
42 ase_dev_version = '3.15.1b1' # This line auto-edited by newrelease script
43 ase_stable_version = '3.15.0' # This line auto-edited by newrelease script
42 ase_dev_version = '3.16.1b1' # This line auto-edited by newrelease script
43 ase_stable_version = '3.16.0' # This line auto-edited by newrelease script
4444
4545 html_context = {
4646 'current_version': __version__,
5959 ('index', 'ASE.tex', 'ASE', 'ASE-developers', 'howto', not True)]
6060
6161 intersphinx_mapping = {'gpaw': ('https://wiki.fysik.dtu.dk/gpaw', None),
62 'python': ('https://docs.python.org/2.7', None)}
62 'python': ('https://docs.python.org/3.6', None)}
6363
6464 # Avoid GUI windows during doctest:
6565 doctest_global_setup = """
0 easyblock = 'PythonPackage'
1
2 name = 'ASE'
3 version = '3.15.0'
4 versionsuffix = '-Python-%(pyver)s'
5
6 homepage = 'http://wiki.fysik.dtu.dk/ase'
7 description = """ASE is a python package providing an open source Atomic Simulation Environment
8 in the Python scripting language."""
9
10 toolchain = {'name': 'foss', 'version': '2016b'}
11
12 source_urls = [PYPI_LOWER_SOURCE]
13 sources = [SOURCELOWER_TAR_GZ]
14 checksums = ['5e22d961b1311ef4ba2d83527f7cc7448abac8cf9bddd1593bee548459263fe8']
15
16 dependencies = [
17 ('Python', '2.7.12'),
18 ('matplotlib', '1.5.3', '-Python-%(pyver)s'),
19 ]
20
21 sanity_check_paths = {
22 'files': ['bin/ase'],
23 'dirs': [],
24 }
25
26 moduleclass = 'chem'
0 easyblock = 'PythonPackage'
1
2 name = 'ASE'
3 version = '3.15.0'
4 versionsuffix = '-Python-%(pyver)s'
5
6 homepage = 'http://wiki.fysik.dtu.dk/ase'
7 description = """ASE is a python package providing an open source Atomic Simulation Environment
8 in the Python scripting language."""
9
10 toolchain = {'name': 'foss', 'version': '2016b'}
11
12 source_urls = [PYPI_LOWER_SOURCE]
13 sources = [SOURCELOWER_TAR_GZ]
14 checksums = ['5e22d961b1311ef4ba2d83527f7cc7448abac8cf9bddd1593bee548459263fe8']
15
16 dependencies = [
17 ('Python', '3.5.2'),
18 ('matplotlib', '1.5.3', '-Python-%(pyver)s'),
19 ]
20
21 sanity_check_paths = {
22 'files': ['bin/ase'],
23 'dirs': [],
24 }
25
26 moduleclass = 'chem'
0 easyblock = 'PythonPackage'
1
2 name = 'ASE'
3 version = '3.15.0'
4 versionsuffix = '-Python-%(pyver)s'
5
6 homepage = 'http://wiki.fysik.dtu.dk/ase'
7 description = """ASE is a python package providing an open source Atomic Simulation Environment
8 in the Python scripting language."""
9
10 toolchain = {'name': 'foss', 'version': '2017b'}
11
12 source_urls = [PYPI_LOWER_SOURCE]
13 sources = [SOURCELOWER_TAR_GZ]
14 checksums = ['5e22d961b1311ef4ba2d83527f7cc7448abac8cf9bddd1593bee548459263fe8']
15
16 dependencies = [
17 ('Python', '3.6.2'),
18 ('matplotlib', '2.1.0', '-Python-%(pyver)s'),
19 ]
20
21 sanity_check_paths = {
22 'files': ['bin/ase'],
23 'dirs': [],
24 }
25
26 moduleclass = 'chem'
77 license <license info>`.
88
99 .. _Python: http://www.python.org
10
11 ASE provides interfaces to different codes through :mod:`Calculators
12 <ase.calculators>` which are used together with the central
13 :mod:`Atoms <ase.atoms>` object and the many available algorithms in
14 ASE.
1015
1116 >>> # Example: structure optimization of hydrogen molecule
1217 >>> from ase import Atoms
2934
3035 Supported :mod:`Calculators <ase.calculators>`:
3136
32 |abinit| |Asap| |Atomistica| |CASTEP| |CP2K| |deMon| |dftb|
37 |abinit| |Asap| |Atomistica| |CASTEP| |CP2K| |CRYSTAL| |deMon| |dftb|
3338 |elk| |exciting| |EMT|
3439 |fhi-aims| |fleur| |gpaw| |gromacs|
3540 |hotbit| |jacapo| |jdftx| |lammps| |nwchem|
3641 |octopus| |onetep| |q_espresso| |siesta| |turbomole| |vasp|
3742 :mod:`~ase.calculators.amber`
3843 :mod:`DMol³ <ase.calculators.dmol>`
39 Gaussian_
44 Gaussian_
4045 :mod:`Grimme DFT-D3 <ase.calculators.dftd3>`
4146 :mod:`~ase.calculators.gulp`
4247 Mopac_
4348 :mod:`~ase.calculators.tip3p`
49 :mod:`~ase.calculators.qmmm`
50
51
52 `Reference publication on ASE <https://doi.org/10.1088/1361-648X/aa680e>`__
53
4454
4555 Please go through this check-list to figure out if you need to convert your
4656 old ASE trajectory files to the modern file-format:
5565
5666 News
5767 ====
68
69 * :ref:`ASE version 3.16.0 <releasenotes>` released (21 March 2018).
5870
5971 * :ref:`ASE version 3.15.0 <releasenotes>` released (28 September 2017).
6072
164176 .. |CP2K| image:: static/cp2k.png
165177 :target: ase/calculators/cp2k.html
166178 :align: middle
179 .. |CRYSTAL| image:: static/crystal.png
180 :target: ase/calculators/crystal.html
181 :align: middle
167182 .. |deMon| image:: static/demon.png
168 :target: http://www.demon-software.com/public_html/index.html
183 :target: ase/calculators/demon.html
169184 :align: middle
170185 .. |elk| image:: static/elk.png
171186 :target: http://elk.sourceforge.net/
189204 :target: http://wiki.fysik.dtu.dk/gpaw
190205 :align: middle
191206 .. |gromacs| image:: static/gromacs.png
192 :target: http://www.gromacs.org/
207 :target: ase/calculators/gromacs.html
193208 :align: middle
194209 .. |hotbit| image:: static/hotbit.png
195 :target: https://trac.cc.jyu.fi/projects/hotbit
210 :target: https://github.com/pekkosk/hotbit
196211 :align: middle
197212 .. |jacapo| image:: static/jacapo.png
198213 :target: ase/calculators/jacapo.html
199214 :align: middle
200215 .. |jdftx| image:: static/jdftx.png
201 :target: http://sourceforge.net/p/jdftx/wiki/ASE%20Interface
216 :target: http://jdftx.org/ASE.html
202217 :align: middle
203218 .. |lammps| image:: static/lammps.png
204219 :target: ase/calculators/lammps.html
210225 :target: ase/calculators/octopus.html
211226 :align: middle
212227 .. |onetep| image:: static/onetep.png
213 :target: http://www.onetep.org/
228 :target: ase/calculators/onetep.html
214229 :align: middle
215230 .. |q_espresso| image:: static/espresso.png
216231 :target: ase/calculators/espresso.html
228243
229244
230245 .. _Gaussian: http://www.gaussian.com/
231 .. _Mopac: http://openmopac.net/
246 .. _Mopac: ase/calculators/mopac.html
232247 .. _Sphinx: http://sphinx.pocoo.org
233248 .. _Asap: http://wiki.fysik.dtu.dk/asap
234249 .. _CAMd: http://www.camd.dtu.dk
77 ============
88
99 * Python_ 2.7, 3.4-3.6
10 * NumPy_ (base N-dimensional array package)
10 * NumPy_ 1.9 or newer (base N-dimensional array package)
1111
1212 Optional:
1313
101101 :Tar-file:
102102
103103 You can get the source as a `tar-file <http://xkcd.com/1168/>`__ for the
104 latest stable release (ase-3.15.0.tar.gz_) or the latest
104 latest stable release (ase-3.16.0.tar.gz_) or the latest
105105 development snapshot (`<snapshot.tar.gz>`_).
106106
107107 Unpack and make a soft link::
108108
109 $ tar -xf ase-3.15.0.tar.gz
110 $ ln -s ase-3.15.0 ase
109 $ tar -xf ase-3.16.0.tar.gz
110 $ ln -s ase-3.16.0 ase
111111
112112 Here is a `list of tarballs <https://pypi.org/simple/ase/>`__.
113113
116116 Alternatively, you can get the source for the latest stable release from
117117 https://gitlab.com/ase/ase like this::
118118
119 $ git clone -b 3.15.0 https://gitlab.com/ase/ase.git
119 $ git clone -b 3.16.0 https://gitlab.com/ase/ase.git
120120
121121 or if you want the development version::
122122
147147 dates of older releases can be found there.
148148
149149
150 .. _ase-3.15.0.tar.gz: https://pypi.org/packages/source/a/ase/ase-3.15.0.tar.gz
150 .. _ase-3.16.0.tar.gz: https://pypi.org/packages/source/a/ase/ase-3.16.0.tar.gz
151151
152152
153153 Environment variables
99
1010 :git:`master <>`.
1111
12 * No changes yet
12 * No changes yet
13
14
15 Version 3.16.0
16 ==============
17
18 21 March 2018: :git:`3.16.0 <../3.16.0>`
19
20 * New linear-scaling neighbor list
21 available as a function :meth:`~ase.neighborlist.neighbor_list`.
22
23 * Castep calculator: option for automatic detection of pseudopotential files from a given directory (castep_pp_path); support for GBRV pseudopotential library; updated outfile parsing to comply with CASTEP 18.1.
24
25 * New LAMMPS calculator LAMMPSlib utilizing the Python bindings provided by LAMMPS instead of file I/O. Very basic calculator but can serve as base class for more sophisticated ones.
26
27 * Support for µSTEM xtl data format.
28
29 * New scanning tunnelling spectroscopy (STS) mode for
30 :class:`~ase.dft.stm.STM` simulations.
31
32 * New method, :meth:`~ase.Atoms.get_angles`, for calculating multiple angles.
33
34 * New ``ase reciprocal`` :ref:`command <cli>` for showing the
35 1. Brilluin zone, **k**-points and special points.
36
37 * New ``ase convert`` :ref:`command <cli>` for converting between file formats.
38
39 * Improved XRD/SAXS module: :mod:`ase.utils.xrdebye`.
40
41 * New cell editor for the GUI.
42
43 * Improved "quick info" dialog in the GUI. The dialog now lists results
44 cached by the calculator.
45
46 * The "add atoms" dialog now offers a load file dialog as was the case before the tkinter port. It also provides a chooser for the G2 dataset.
47
48 * Interface for the :mod:`CRYSTAL <ase.calculators.crystal` code has been
49 added.
50
51 * The :func:`ase.dft.bandgap.bandgap` function used with ``direct=True``
52 will now also consider spin-flip transitions. To get the spin-preserving
53 direct gap (the old behavior), use::
54
55 min(bandgap(..., spin=s, direct=True) for s in [0, 1])
56
57 * Bug fixed in the :meth:`ase.phonons.Phonons.symmetrize` method when using an
58 even number of repeats.
59
1360
1461 Version 3.15.0
1562 ==============
Binary diff not shown
Binary diff not shown
113113 sampled_energies = np.array(sampled_energies)
114114
115115 if len(sampled_points) > 0 and len(sampled_energies) >= len(sampled_points[0]):
116 weights = np.linalg.lstsq(sampled_points, sampled_energies)[0]
116 weights = np.linalg.lstsq(sampled_points, sampled_energies, rcond=-1)[0]
117117 else:
118118 weights = None
119119
3434 Run the algorithm
3535 =================
3636
37 With the database properly initiated we are ready to start the GA. Below is a short example with a few procreation operators that works on slabs, the ``RankFitnessPopulation`` described earlier. A full generation of new candidates are evaluated before they are added to the population, this is more efficient when using a fast method for evaluation. :download:`ga_convex_run.py`
37 With the database properly initiated we are ready to start the GA. Below is a short example with a few procreation operators that works on slabs, and the ``RankFitnessPopulation`` described earlier. A full generation of new candidates are evaluated before they are added to the population, this is more efficient when using a fast method for evaluation. :download:`ga_convex_run.py`
3838
3939 .. literalinclude:: ga_convex_run.py
4040
5151 .. _customization:
5252
5353 Customization of the algorithm
54 ==============================
54 ------------------------------
5555
5656 So far we have a working algorithm but it is quite naive, let us make some extensions for increasing efficiency.
5757
5858 Exact duplicate identification
59 ------------------------------
59 ==============================
6060
6161 Evaluating identical candidates is a risk when they are created by the operators, so in order not to waste computational resources it is important to implement a check for whether an identical calculation has been performed.
6262
8282 .. _symmetry:
8383
8484 Symmetric duplicate identification
85 ----------------------------------
85 ==================================
8686
8787 Having identical or very similar in the population will limit the diversity and cause premature convergence of the GA. We will try to prevent that by detecting if two structures are not identical in positions but instead symmetrically identical. For this we need a metric with which to characterize a structure, a symmetry tolerant fingerprint. There are many ways to achieve this and we will use a very simple average number of nearest neighbors, defined as:
8888
8989 .. math:: \text{NN}_\text{avg} = [\frac{\#\text{Cu-Cu}}{N_{\text{Cu}}} , \frac{\#\text{Cu-Pt}}{N_{\text{Cu}}}, \frac{\#\text{Pt-Cu}}{N_{\text{Pt}}}, \frac{\#\text{Pt-Pt}}{N_{\text{Pt}}}]
9090
91 where :math:`\#\text{Cu-Cu}` is the number of Cu - Cu nearest neighbors and :math:`N_\text{Cu}` is the total number of Cu atoms in the slab. This check can be performed at two points; either just after candidate creation before evaluation or after evaluation before potential inclusion into the population. The latter method is well suited for situations where the evaluation will induce a change in the candidate e.g. by structural relaxation. We will use the former method here.
91 where :math:`\#\text{Cu-Cu}` is the number of Cu - Cu nearest neighbors and :math:`N_\text{Cu}` is the total number of Cu atoms in the slab. This check can be performed at two points; either just after candidate creation before evaluation or after evaluation before potential inclusion into the population. We will use the latter method here and add a comparator to the population.
9292
9393 The nearest neighbor average is put in ``candidate.info['key_value_pairs']`` as a string rounded off to two decimal points. *Note* this accuracy is fitting for this size slab, but need testing for other systems.
9494
9797 from ase.ga.utilities import get_nnmat_string
9898
9999 ...
100
101 # The population instance is changed to
102 pop = RankFitnessPopulation(data_connection=db,
103 population_size=pop_size,
104 variable_function=get_comp,
105 comparator=StringComparator('nnmat_string'))
100106
101107 # Evaluating the starting population is changed to
102108 while db.get_number_of_unrelaxed_candidates() > 0:
109115
110116 ...
111117
112 # The line with dup = ... is replaced by
118 # If a candidate is not an exact duplicate the nnmat should be calculated
119 # and added to the key_value_pairs
120 set_raw_score(offspring, -get_mixing_energy(offspring))
113121 nnmat_string = get_nnmat_string(offspring, 2, True)
114 dup = (db.is_duplicate(atoms_string=offspring.info['key_value_pairs']['atoms_string']) or
115 db.is_duplicate(formula=offspring.get_chemical_formula(),
116 nnmat_string=nnmat_string))
117
118 ...
119
120 # If the offspring is not a duplicate we must add the nnmat_string to
121 # the key_value_pairs
122 set_raw_score(offspring, -get_mixing_energy(offspring))
123122 offspring.info['key_value_pairs']['nnmat_string'] = nnmat_string
123 offspring.info['key_value_pairs']['atoms_string'] = atoms_string
124124 new_generation.append(offspring)
125
126
127125
128126
129127 Problem specific mutation operators
130 -----------------------------------
128 ===================================
131129
132130 Sometimes it is necessary to introduce operators that force the GA to investigate certain areas of the phase space. The :class:`ase.ga.slab_operators.SymmetrySlabPermutation` permutes the atoms in the slab to yield a more symmetric offspring. *Note* this requires `spglib <https://atztogo.github.io/spglib/>`_ to be installed. Try it by::
133131
7373 # Negative mixing energy means more stable than the pure slabs
7474 # The optimization always progress towards larger raw score,
7575 # so we take the negative mixing energy as the raw score
76 print('Evaluating initial candidates')
7677 while db.get_number_of_unrelaxed_candidates() > 0:
7778 a = db.get_an_unrelaxed_candidate()
7879 set_raw_score(a, -get_mixing_energy(a))
8081 pop.update()
8182
8283 # Below is the iterative part of the algorithm
83 for _ in range(num_gens):
84 gen_num = db.get_generation_number()
85 for i in range(num_gens):
86 print('Creating and evaluating generation {0}'.format(gen_num + i))
8487 new_generation = []
8588 for _ in range(pop_size):
8689 # Select parents for a new candidate
2323 c = np.array([config.cell[2, 2] for config in configs])
2424
2525 functions = np.array([a**0, a, c, a**2, a * c, c**2])
26 p = np.linalg.lstsq(functions.T, energies)[0]
26 p = np.linalg.lstsq(functions.T, energies, rcond=-1)[0]
2727
2828 p0 = p[0]
2929 p1 = p[1:3]
33 ASE for QM/MM Simulations
44 =========================
55
6 QM/MM Simulations couple two (or more) descriptions to get total energy
7 and forces for the entire system in an efficiant manner. The method paper
8 on our implementation is currently being written.
9 General background can be found
10 `here <https://link.springer.com/article/10.1007/s00214-006-0143-z/>`__,
11 `here <http://onlinelibrary.wiley.com/doi/10.1002/anie.200802019/abstract>`__,
12 and
13 `here <https://www.elsevier.com/books/combining-quantum-mechanics-and-molecular-mechanics-some-recent-progresses-in-qm-mm-methods/sabin/978-0-12-380898-1>`__ .
6 QM/MM Simulations couple two (or, in principle, more) descriptions to get total energy
7 and forces for the entire system in an efficiant manner.
8 ASE has a native Explicit Interaction calculator, :class:`~ase.calculators.qmmm.EIQMMM`, that uses an electrostatic embedding
9 model to couple the subsystems explicitly. See
10 `the method paper for more info. <https://doi.org/10.1021/acs.jctc.7b00621>`__,
11
1412 Examples of what this code has been used for can be seen
1513 `here <http://pubs.acs.org/doi/abs/10.1021/jz500850s>`__,
1614 and `here <http://pubs.acs.org/doi/abs/10.1021/acs.inorgchem.6b01840>`__.
7371
7472
7573 The following script will calculate the QM/MM single point energy of the
76 water dimer from the :ref:`s22`, using LDA and TIP3P.
74 water dimer from the :ref:`s22`, using LDA and TIP3P, for illustration purposes.
7775
7876 .. literalinclude:: water_dimer.py
7977
6767 platforms=['unix'],
6868 packages=find_packages(),
6969 install_requires=['numpy', 'scipy', 'matplotlib', 'flask'],
70 extras_require={'docs': ['sphinx', 'sphinx_rtd_theme', 'pillow']},
7071 package_data=package_data,
7172 entry_points={'console_scripts': ['ase=ase.cli.main:main',
7273 'ase-db=ase.cli.main:old',