python-ase-3.6.0.2515/ 0000755 0001754 0001754 00000000000 11757245036 013212 5 ustar askhl askhl python-ase-3.6.0.2515/setup.py 0000755 0001754 0001754 00000005434 11721701551 014723 0 ustar askhl askhl #!/usr/bin/env python
# Copyright (C) 2007 CAMP
# Please see the accompanying LICENSE file for further information.
from distutils.core import setup
from glob import glob
from os.path import join
import os
import sys
long_description = """\
ASE is a python package providing an open source Atomic Simulation
Environment in the python scripting language."""
if sys.version_info < (2, 3, 0, 'final', 0):
raise SystemExit, 'Python 2.3 or later is required!'
packages = ['ase',
'ase.cluster',
'ase.cluster.data',
'ase.io',
'ase.md',
'ase.dft',
'ase.gui',
'ase.gui.languages',
'ase.data',
'ase.test',
'ase.test.abinit',
'ase.test.castep',
'ase.test.cmr',
'ase.test.elk',
'ase.test.fio',
'ase.test.fleur',
'ase.test.jacapo',
'ase.test.nwchem',
'ase.test.vasp',
'ase.tasks',
'ase.utils',
'ase.lattice',
'ase.lattice.spacegroup',
'ase.examples',
'ase.optimize',
'ase.optimize.test',
'ase.visualize',
'ase.visualize.vtk',
'ase.transport',
'ase.calculators',
'ase.calculators.jacapo']
package_dir={'ase': 'ase'}
package_data={'ase': ['lattice/spacegroup/spacegroup.dat',
'gui/po/ag.pot',
'gui/po/makefile',
'gui/po/??_??/LC_MESSAGES/ag.po']}
# Compile makes sense only when building
if 'build' in sys.argv or 'build_ext' in sys.argv or 'install' in sys.argv:
msgfmt = 'msgfmt'
# Compile translation files (requires gettext)
status = os.system(msgfmt + ' -V')
if status == 0:
for pofile in glob('ase/gui/po/??_??/LC_MESSAGES/ag.po'):
mofile = os.path.join(os.path.split(pofile)[0], 'ag.mo')
os.system(msgfmt + ' -cv %s --output-file=%s' % (pofile, mofile))
package_data['ase'].append('gui/po/??_??/LC_MESSAGES/ag.mo')
# Get the current version number:
execfile('ase/svnversion_io.py') # write ase/svnversion.py and get svnversion
execfile('ase/version.py') # get version_base
if svnversion:
version = version_base + '.' + svnversion
else:
version = version_base
setup(name = 'python-ase',
version=version,
description='Atomic Simulation Environment',
url='https://wiki.fysik.dtu.dk/ase',
maintainer='CAMd',
maintainer_email='camd@fysik.dtu.dk',
license='LGPLv2.1+',
platforms=['linux'],
packages=packages,
package_dir=package_dir,
package_data=package_data,
scripts=['tools/ag', 'tools/ase', 'tools/ASE2ase.py', 'tools/testase.py'],
long_description=long_description)
python-ase-3.6.0.2515/LICENSE 0000644 0001754 0001754 00000001140 11364026230 014176 0 ustar askhl askhl ASE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
ASE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ASE. If not, see .
python-ase-3.6.0.2515/tools/ 0000755 0001754 0001754 00000000000 11757245033 014347 5 ustar askhl askhl python-ase-3.6.0.2515/tools/trajectoryinfo 0000755 0001754 0001754 00000000763 11531205172 017333 0 ustar askhl askhl #!/usr/bin/env python
from ase.io.trajectory import print_trajectory_info
from ase.io.bundletrajectory import print_bundletrajectory_info
import sys
import os
if len(sys.argv) <= 1:
print >>sys.stderr, "Usage: trajectoryinfo file.traj [file2.traj ...]"
sys.exit(1)
for f in sys.argv[1:]:
if os.path.isfile(f):
print_trajectory_info(f)
elif os.path.isdir(f):
print_bundletrajectory_info(f)
else:
print "ERROR: %s is neither a file nor a directory!" % (f,)
python-ase-3.6.0.2515/tools/sphinx.py 0000644 0001754 0001754 00000005276 11566720374 016250 0 ustar askhl askhl #!/usr/bin/python
import os
import sys
import time
import glob
import trace
import tempfile
tmpdir = tempfile.mkdtemp(prefix='ase-')
os.chdir(tmpdir)
def build(email):
if os.system('svn checkout ' +
'https://svn.fysik.dtu.dk/projects/ase/trunk ase') != 0:
raise RuntimeError('Checkout of ASE failed!')
os.chdir('ase')
if os.system('python setup.py install --home=.') != 0:
raise RuntimeError('Installation failed!')
sys.path.insert(0, 'lib/python')
from ase.test import test
from ase.version import version
# Run test-suite:
stream = open('test-results.txt', 'w')
results = test(verbosity=2, dir='ase/test', display=False, stream=stream)
stream.close()
if len(results.failures) > 0 or len(results.errors) > 0:
address = email
subject = 'ASE test-suite failed!'
os.system('mail -s "%s" %s < %s' %
(subject, address, 'test-results.txt'))
raise RuntimeError('Testsuite failed!')
# Generate tar-file:
assert os.system('python setup.py sdist') == 0
if os.system('epydoc --docformat restructuredtext --parse-only ' +
'--name ASE ' +
'--url http://wiki.fysik.dtu.dk/ase ' +
'--show-imports --no-frames -v ase &> epydoc.out') != 0:
raise RuntimeError('Epydoc failed!')
epydoc_errors = open('epydoc.out').read()
if ' Warning:' in epydoc_errors:
sys.stderr.write(epydoc_errors)
os.chdir('doc')
os.mkdir('_build')
if os.system('PYTHONPATH=%s/ase sphinx-build . _build' % tmpdir) != 0:
raise RuntimeError('Sphinx failed!')
os.system('cd _build; cp _static/searchtools.js .; ' +
'sed -i s/snapshot.tar/%s.tar/ download.html' % version)
if 1:
if os.system('PYTHONPATH=%s/ase ' % tmpdir +
'sphinx-build -b latex . _build 2> error') != 0:
raise RuntimeError('Sphinx failed!')
os.system(
'grep -v "WARNING: unusable reference target found" error 1>&2')
os.chdir('_build')
#os.system('cd ../..; ln -s doc/_static')
if os.system('make ase-manual.pdf 2>&1') != 0:
raise RuntimeError('pdflatex failed!')
else:
os.chdir('_build')
assert os.system('mv ../../html epydoc;' +
'mv ../../dist/python-ase-%s.tar.gz .' % version) == 0
tarfiledir = None
if len(sys.argv) == 3:
tarfiledir = sys.argv[2]
try:
os.remove(tarfiledir + '/ase-webpages.tar.gz')
except OSError:
pass
build(sys.argv[1])
if tarfiledir is not None:
os.system('cd ..; tar czf %s/ase-webpages.tar.gz _build' % tarfiledir)
os.system('cd; rm -r ' + tmpdir)
python-ase-3.6.0.2515/tools/ASE2ase.py 0000755 0001754 0001754 00000005437 11410147616 016112 0 ustar askhl askhl #!/usr/bin/env python
import sys
def convert(filename):
lines = open(filename).readlines()
t1 = ''.join(lines)
first = True
for i in range(len(lines)):
line = lines[i]
if line.startswith('from ASE'):
if first:
lines[i] = 'from ase.all import *\n'
first = False
else:
lines[i] = ''
t = ''.join(lines)
for old, new in [('GetCartesianPositions', 'get_positions'),
('SetCartesianPositions', 'set_positions'),
('GetPotentialEnergy', 'get_potential_energy'),
('SetCalculator', 'set_calculator'),
('GetScaledPositions', 'get_scaled_positions'),
('SetScaledPositions', 'set_scaled_positions'),
('SetUnitCell', 'set_cell'),
('GetUnitCell', 'get_cell'),
('GetBoundaryConditions', 'get_pbc'),
('GetCartesianForces', 'get_forces'),
('GetCartesianVelocities', 'get_velocities'),
('SetCartesianVelocities', 'set_velocities'),
('GetCartesianMomenta', 'get_momenta'),
('SetCartesianMomenta', 'set_momenta'),
('ListOfAtoms', 'Atoms'),
('periodic', 'pbc'),
('pbcity', 'periodicity'),
('.Converge(', '.run('),
('Repeat', 'repeat'),
('Numeric', 'numpy'),
('numpyal', 'Numerical'),
('GetAtomicNumber()', 'number'),
('GetChemicalSymbol()', 'symbol'),
('GetCartesianPosition()', 'position'),
('GetTag()', 'tag'),
('GetCharge()', 'charge'),
('GetMass()', 'mass'),
('GetCartesianMomentum()', 'momentum'),
('GetMagneticMoment()', 'magmom'),
]:
t = t.replace(old, new)
t2 = ''
while 1:
i = t.find('.')
i2 = t.find('def ')
if 0 <= i < i2:
n = 1
elif i2 != -1:
n = 4
i = i2
else:
break
t2 += t[:i + n]
t = t[i + n:]
if t[0].isupper() and t[1].islower():
j = t.find('(')
if j != -1 and t[2: j].isalpha():
for k in range(j):
if t[k].isupper() and k > 0:
t2 += '_'
t2 += t[k].lower()
t = t[j:]
t2 += t
if t2 != t1:
print filename, len(t1) - len(t2)
open(filename + '.bak', 'w').write(t1)
open(filename, 'w').write(t2)
for filename in sys.argv[1:]:
convert(filename)
python-ase-3.6.0.2515/tools/pep8.py 0000755 0001754 0001754 00000136644 11566675500 015622 0 ustar askhl askhl #!/usr/bin/python
# pep8.py - Check Python source code formatting, according to PEP 8
# Copyright (C) 2006 Johann C. Rocholl
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Copied from:
#
# https://github.com/jcrocholl/pep8/blob/
# 8d2d68790b6931833277cd671dfb8158962fac0c/pep8.py
#
# on May 10, 2011.
"""
Check Python source code formatting, according to PEP 8:
http://www.python.org/dev/peps/pep-0008/
For usage and a list of options, try this:
$ python pep8.py -h
This program and its regression test suite live here:
http://github.com/jcrocholl/pep8
Groups of errors and warnings:
E errors
W warnings
100 indentation
200 whitespace
300 blank lines
400 imports
500 line length
600 deprecation
700 statements
You can add checks to this program by writing plugins. Each plugin is
a simple function that is called for each line of source code, either
physical or logical.
Physical line:
- Raw line of text from the input file.
Logical line:
- Multi-line statements converted to a single line.
- Stripped left and right.
- Contents of strings replaced with 'xxx' of same length.
- Comments removed.
The check function requests physical or logical lines by the name of
the first argument:
def maximum_line_length(physical_line)
def extraneous_whitespace(logical_line)
def blank_lines(logical_line, blank_lines, indent_level, line_number)
The last example above demonstrates how check plugins can request
additional information with extra arguments. All attributes of the
Checker object are available. Some examples:
lines: a list of the raw lines from the input file
tokens: the tokens that contribute to this logical line
line_number: line number in the input file
blank_lines: blank lines before this one
indent_char: first indentation character in this file (' ' or '\t')
indent_level: indentation (with tabs expanded to multiples of 8)
previous_indent_level: indentation on previous line
previous_logical: previous logical line
The docstring of each check function shall be the relevant part of
text from PEP 8. It is printed if the user enables --show-pep8.
Several docstrings contain examples directly from the PEP 8 document.
Okay: spam(ham[1], {eggs: 2})
E201: spam( ham[1], {eggs: 2})
These examples are verified automatically when pep8.py is run with the
--doctest option. You can add examples for your own check functions.
The format is simple: "Okay" or error/warning code followed by colon
and space, the rest of the line is example source code. If you put 'r'
before the docstring, you can use \n for newline, \t for tab and \s
for space.
"""
__version__ = '0.5.1dev'
import os
import sys
import re
import time
import inspect
import keyword
import tokenize
from optparse import OptionParser
from fnmatch import fnmatch
try:
frozenset
except NameError:
from sets import ImmutableSet as frozenset
DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git'
DEFAULT_IGNORE = 'E24'
MAX_LINE_LENGTH = 79
INDENT_REGEX = re.compile(r'([ \t]*)')
RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*(,)')
SELFTEST_REGEX = re.compile(r'(Okay|[EW]\d{3}):\s(.*)')
ERRORCODE_REGEX = re.compile(r'[EW]\d{3}')
DOCSTRING_REGEX = re.compile(r'u?r?["\']')
WHITESPACE_AROUND_OPERATOR_REGEX = \
re.compile('([^\w\s]*)\s*(\t| )\s*([^\w\s]*)')
EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]')
WHITESPACE_AROUND_NAMED_PARAMETER_REGEX = \
re.compile(r'[()]|\s=[^=]|[^=!<>]=\s')
WHITESPACE = ' \t'
BINARY_OPERATORS = frozenset(['**=', '*=', '+=', '-=', '!=', '<>',
'%=', '^=', '&=', '|=', '==', '/=', '//=', '<=', '>=', '<<=', '>>=',
'%', '^', '&', '|', '=', '/', '//', '<', '>', '<<'])
UNARY_OPERATORS = frozenset(['>>', '**', '*', '+', '-'])
OPERATORS = BINARY_OPERATORS | UNARY_OPERATORS
SKIP_TOKENS = frozenset([tokenize.COMMENT, tokenize.NL, tokenize.INDENT,
tokenize.DEDENT, tokenize.NEWLINE])
E225NOT_KEYWORDS = (frozenset(keyword.kwlist + ['print']) -
frozenset(['False', 'None', 'True']))
BENCHMARK_KEYS = ('directories', 'files', 'logical lines', 'physical lines')
options = None
args = None
##############################################################################
# Plugins (check functions) for physical lines
##############################################################################
def tabs_or_spaces(physical_line, indent_char):
r"""
Never mix tabs and spaces.
The most popular way of indenting Python is with spaces only. The
second-most popular way is with tabs only. Code indented with a mixture
of tabs and spaces should be converted to using spaces exclusively. When
invoking the Python command line interpreter with the -t option, it issues
warnings about code that illegally mixes tabs and spaces. When using -tt
these warnings become errors. These options are highly recommended!
Okay: if a == 0:\n a = 1\n b = 1
E101: if a == 0:\n a = 1\n\tb = 1
"""
indent = INDENT_REGEX.match(physical_line).group(1)
for offset, char in enumerate(indent):
if char != indent_char:
return offset, "E101 indentation contains mixed spaces and tabs"
def tabs_obsolete(physical_line):
r"""
For new projects, spaces-only are strongly recommended over tabs. Most
editors have features that make this easy to do.
Okay: if True:\n return
W191: if True:\n\treturn
"""
indent = INDENT_REGEX.match(physical_line).group(1)
if indent.count('\t'):
return indent.index('\t'), "W191 indentation contains tabs"
def trailing_whitespace(physical_line):
r"""
JCR: Trailing whitespace is superfluous.
FBM: Except when it occurs as part of a blank line (i.e. the line is
nothing but whitespace). According to Python docs[1] a line with only
whitespace is considered a blank line, and is to be ignored. However,
matching a blank line to its indentation level avoids mistakenly
terminating a multi-line statement (e.g. class declaration) when
pasting code into the standard Python interpreter.
[1] http://docs.python.org/reference/lexical_analysis.html#blank-lines
The warning returned varies on whether the line itself is blank, for easier
filtering for those who want to indent their blank lines.
Okay: spam(1)
W291: spam(1)\s
W293: class Foo(object):\n \n bang = 12
"""
physical_line = physical_line.rstrip('\n') # chr(10), newline
physical_line = physical_line.rstrip('\r') # chr(13), carriage return
physical_line = physical_line.rstrip('\x0c') # chr(12), form feed, ^L
stripped = physical_line.rstrip()
if physical_line != stripped:
if stripped:
return len(stripped), "W291 trailing whitespace"
else:
return 0, "W293 blank line contains whitespace"
def trailing_blank_lines(physical_line, lines, line_number):
r"""
JCR: Trailing blank lines are superfluous.
Okay: spam(1)
W391: spam(1)\n
"""
if physical_line.strip() == '' and line_number == len(lines):
return 0, "W391 blank line at end of file"
def missing_newline(physical_line):
"""
JCR: The last line should have a newline.
"""
if physical_line.rstrip() == physical_line:
return len(physical_line), "W292 no newline at end of file"
def maximum_line_length(physical_line):
"""
Limit all lines to a maximum of 79 characters.
There are still many devices around that are limited to 80 character
lines; plus, limiting windows to 80 characters makes it possible to have
several windows side-by-side. The default wrapping on such devices looks
ugly. Therefore, please limit all lines to a maximum of 79 characters.
For flowing long blocks of text (docstrings or comments), limiting the
length to 72 characters is recommended.
"""
line = physical_line.rstrip()
length = len(line)
if length > MAX_LINE_LENGTH:
try:
# The line could contain multi-byte characters
if not hasattr(line, 'decode'): # Python 3
line = line.encode('latin-1')
length = len(line.decode('utf-8'))
except UnicodeDecodeError:
pass
if length > MAX_LINE_LENGTH:
return MAX_LINE_LENGTH, "E501 line too long (%d characters)" % length
##############################################################################
# Plugins (check functions) for logical lines
##############################################################################
def blank_lines(logical_line, blank_lines, indent_level, line_number,
previous_logical, previous_indent_level,
blank_lines_before_comment):
r"""
Separate top-level function and class definitions with two blank lines.
Method definitions inside a class are separated by a single blank line.
Extra blank lines may be used (sparingly) to separate groups of related
functions. Blank lines may be omitted between a bunch of related
one-liners (e.g. a set of dummy implementations).
Use blank lines in functions, sparingly, to indicate logical sections.
Okay: def a():\n pass\n\n\ndef b():\n pass
Okay: def a():\n pass\n\n\n# Foo\n# Bar\n\ndef b():\n pass
E301: class Foo:\n b = 0\n def bar():\n pass
E302: def a():\n pass\n\ndef b(n):\n pass
E303: def a():\n pass\n\n\n\ndef b(n):\n pass
E303: def a():\n\n\n\n pass
E304: @decorator\n\ndef a():\n pass
"""
if line_number == 1:
return # Don't expect blank lines before the first line
max_blank_lines = max(blank_lines, blank_lines_before_comment)
if previous_logical.startswith('@'):
if max_blank_lines:
return 0, "E304 blank lines found after function decorator"
elif max_blank_lines > 2 or (indent_level and max_blank_lines == 2):
return 0, "E303 too many blank lines (%d)" % max_blank_lines
elif (logical_line.startswith('def ') or
logical_line.startswith('class ') or
logical_line.startswith('@')):
if indent_level:
if not (max_blank_lines or previous_indent_level < indent_level or
DOCSTRING_REGEX.match(previous_logical)):
return 0, "E301 expected 1 blank line, found 0"
elif max_blank_lines != 2:
return 0, "E302 expected 2 blank lines, found %d" % max_blank_lines
def extraneous_whitespace(logical_line):
"""
Avoid extraneous whitespace in the following situations:
- Immediately inside parentheses, brackets or braces.
- Immediately before a comma, semicolon, or colon.
Okay: spam(ham[1], {eggs: 2})
E201: spam( ham[1], {eggs: 2})
E201: spam(ham[ 1], {eggs: 2})
E201: spam(ham[1], { eggs: 2})
E202: spam(ham[1], {eggs: 2} )
E202: spam(ham[1 ], {eggs: 2})
E202: spam(ham[1], {eggs: 2 })
E203: if x == 4: print x, y; x, y = y , x
E203: if x == 4: print x, y ; x, y = y, x
E203: if x == 4 : print x, y; x, y = y, x
"""
line = logical_line
for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line):
text = match.group()
char = text.strip()
found = match.start()
if text == char + ' ' and char in '([{':
return found + 1, "E201 whitespace after '%s'" % char
if text == ' ' + char and line[found - 1] != ',':
if char in '}])':
return found, "E202 whitespace before '%s'" % char
if char in ',;:':
return found, "E203 whitespace before '%s'" % char
def missing_whitespace(logical_line):
"""
JCR: Each comma, semicolon or colon should be followed by whitespace.
Okay: [a, b]
Okay: (3,)
Okay: a[1:4]
Okay: a[:4]
Okay: a[1:]
Okay: a[1:4:2]
E231: ['a','b']
E231: foo(bar,baz)
"""
line = logical_line
for index in range(len(line) - 1):
char = line[index]
if char in ',;:' and line[index + 1] not in WHITESPACE:
before = line[:index]
if char == ':' and before.count('[') > before.count(']'):
continue # Slice syntax, no space required
if char == ',' and line[index + 1] == ')':
continue # Allow tuple with only one element: (3,)
return index, "E231 missing whitespace after '%s'" % char
def indentation(logical_line, previous_logical, indent_char,
indent_level, previous_indent_level):
r"""
Use 4 spaces per indentation level.
For really old code that you don't want to mess up, you can continue to
use 8-space tabs.
Okay: a = 1
Okay: if a == 0:\n a = 1
E111: a = 1
Okay: for item in items:\n pass
E112: for item in items:\npass
Okay: a = 1\nb = 2
E113: a = 1\n b = 2
"""
if indent_char == ' ' and indent_level % 4:
return 0, "E111 indentation is not a multiple of four"
indent_expect = previous_logical.endswith(':')
if indent_expect and indent_level <= previous_indent_level:
return 0, "E112 expected an indented block"
if indent_level > previous_indent_level and not indent_expect:
return 0, "E113 unexpected indentation"
def whitespace_before_parameters(logical_line, tokens):
"""
Avoid extraneous whitespace in the following situations:
- Immediately before the open parenthesis that starts the argument
list of a function call.
- Immediately before the open parenthesis that starts an indexing or
slicing.
Okay: spam(1)
E211: spam (1)
Okay: dict['key'] = list[index]
E211: dict ['key'] = list[index]
E211: dict['key'] = list [index]
"""
prev_type = tokens[0][0]
prev_text = tokens[0][1]
prev_end = tokens[0][3]
for index in range(1, len(tokens)):
token_type, text, start, end, line = tokens[index]
if (token_type == tokenize.OP and
text in '([' and
start != prev_end and
(prev_type == tokenize.NAME or prev_text in '}])') and
# Syntax "class A (B):" is allowed, but avoid it
(index < 2 or tokens[index - 2][1] != 'class') and
# Allow "return (a.foo for a in range(5))"
(not keyword.iskeyword(prev_text))):
return prev_end, "E211 whitespace before '%s'" % text
prev_type = token_type
prev_text = text
prev_end = end
def whitespace_around_operator(logical_line):
"""
Avoid extraneous whitespace in the following situations:
- More than one space around an assignment (or other) operator to
align it with another.
Okay: a = 12 + 3
E221: a = 4 + 5
E222: a = 4 + 5
E223: a = 4\t+ 5
E224: a = 4 +\t5
"""
for match in WHITESPACE_AROUND_OPERATOR_REGEX.finditer(logical_line):
before, whitespace, after = match.groups()
tab = whitespace == '\t'
offset = match.start(2)
if before in OPERATORS:
return offset, (tab and "E224 tab after operator" or
"E222 multiple spaces after operator")
elif after in OPERATORS:
return offset, (tab and "E223 tab before operator" or
"E221 multiple spaces before operator")
def missing_whitespace_around_operator(logical_line, tokens):
r"""
- Always surround these binary operators with a single space on
either side: assignment (=), augmented assignment (+=, -= etc.),
comparisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not),
Booleans (and, or, not).
- Use spaces around arithmetic operators.
Okay: i = i + 1
Okay: submitted += 1
Okay: x = x * 2 - 1
Okay: hypot2 = x * x + y * y
Okay: c = (a + b) * (a - b)
Okay: foo(bar, key='word', *args, **kwargs)
Okay: baz(**kwargs)
Okay: negative = -1
Okay: spam(-1)
Okay: alpha[:-i]
Okay: if not -5 < x < +5:\n pass
Okay: lambda *args, **kw: (args, kw)
E225: i=i+1
E225: submitted +=1
E225: x = x*2 - 1
E225: hypot2 = x*x + y*y
E225: c = (a+b) * (a-b)
E225: c = alpha -4
E225: z = x **y
"""
parens = 0
need_space = False
prev_type = tokenize.OP
prev_text = prev_end = None
for token_type, text, start, end, line in tokens:
if token_type in (tokenize.NL, tokenize.NEWLINE, tokenize.ERRORTOKEN):
# ERRORTOKEN is triggered by backticks in Python 3000
continue
if text in ('(', 'lambda'):
parens += 1
elif text == ')':
parens -= 1
if need_space:
if start != prev_end:
need_space = False
elif text == '>' and prev_text == '<':
# Tolerate the "<>" operator, even if running Python 3
pass
else:
return prev_end, "E225 missing whitespace around operator"
elif token_type == tokenize.OP and prev_end is not None:
if text == '=' and parens:
# Allow keyword args or defaults: foo(bar=None).
pass
elif text in BINARY_OPERATORS:
need_space = True
elif text in UNARY_OPERATORS:
# Allow unary operators: -123, -x, +1.
# Allow argument unpacking: foo(*args, **kwargs).
if prev_type == tokenize.OP:
if prev_text in '}])':
need_space = True
elif prev_type == tokenize.NAME:
if prev_text not in E225NOT_KEYWORDS:
need_space = True
else:
need_space = True
if need_space and start == prev_end:
return prev_end, "E225 missing whitespace around operator"
prev_type = token_type
prev_text = text
prev_end = end
def whitespace_around_comma(logical_line):
"""
Avoid extraneous whitespace in the following situations:
- More than one space around an assignment (or other) operator to
align it with another.
JCR: This should also be applied around comma etc.
Note: these checks are disabled by default
Okay: a = (1, 2)
E241: a = (1, 2)
E242: a = (1,\t2)
"""
line = logical_line
for separator in ',;:':
found = line.find(separator + ' ')
if found > -1:
return found + 1, "E241 multiple spaces after '%s'" % separator
found = line.find(separator + '\t')
if found > -1:
return found + 1, "E242 tab after '%s'" % separator
def whitespace_around_named_parameter_equals(logical_line):
"""
Don't use spaces around the '=' sign when used to indicate a
keyword argument or a default parameter value.
Okay: def complex(real, imag=0.0):
Okay: return magic(r=real, i=imag)
Okay: boolean(a == b)
Okay: boolean(a != b)
Okay: boolean(a <= b)
Okay: boolean(a >= b)
E251: def complex(real, imag = 0.0):
E251: return magic(r = real, i = imag)
"""
parens = 0
for match in WHITESPACE_AROUND_NAMED_PARAMETER_REGEX.finditer(
logical_line):
text = match.group()
if parens and len(text) == 3:
issue = "E251 no spaces around keyword / parameter equals"
return match.start(), issue
if text == '(':
parens += 1
elif text == ')':
parens -= 1
def whitespace_before_inline_comment(logical_line, tokens):
"""
Separate inline comments by at least two spaces.
An inline comment is a comment on the same line as a statement. Inline
comments should be separated by at least two spaces from the statement.
They should start with a # and a single space.
Okay: x = x + 1 # Increment x
Okay: x = x + 1 # Increment x
E261: x = x + 1 # Increment x
E262: x = x + 1 #Increment x
E262: x = x + 1 # Increment x
"""
prev_end = (0, 0)
for token_type, text, start, end, line in tokens:
if token_type == tokenize.NL:
continue
if token_type == tokenize.COMMENT:
if not line[:start[1]].strip():
continue
if prev_end[0] == start[0] and start[1] < prev_end[1] + 2:
return (prev_end,
"E261 at least two spaces before inline comment")
if (len(text) > 1 and text.startswith('# ')
or not text.startswith('# ')):
return start, "E262 inline comment should start with '# '"
else:
prev_end = end
def imports_on_separate_lines(logical_line):
r"""
Imports should usually be on separate lines.
Okay: import os\nimport sys
E401: import sys, os
Okay: from subprocess import Popen, PIPE
Okay: from myclas import MyClass
Okay: from foo.bar.yourclass import YourClass
Okay: import myclass
Okay: import foo.bar.yourclass
"""
line = logical_line
if line.startswith('import '):
found = line.find(',')
if found > -1:
return found, "E401 multiple imports on one line"
def compound_statements(logical_line):
r"""
Compound statements (multiple statements on the same line) are
generally discouraged.
While sometimes it's okay to put an if/for/while with a small body
on the same line, never do this for multi-clause statements. Also
avoid folding such long lines!
Okay: if foo == 'blah':\n do_blah_thing()
Okay: do_one()
Okay: do_two()
Okay: do_three()
E701: if foo == 'blah': do_blah_thing()
E701: for x in lst: total += x
E701: while t < 10: t = delay()
E701: if foo == 'blah': do_blah_thing()
E701: else: do_non_blah_thing()
E701: try: something()
E701: finally: cleanup()
E701: if foo == 'blah': one(); two(); three()
E702: do_one(); do_two(); do_three()
"""
line = logical_line
found = line.find(':')
if -1 < found < len(line) - 1:
before = line[:found]
if (before.count('{') <= before.count('}') and # {'a': 1} (dict)
before.count('[') <= before.count(']') and # [1:2] (slice)
not re.search(r'\blambda\b', before)): # lambda x: x
return found, "E701 multiple statements on one line (colon)"
found = line.find(';')
if -1 < found:
return found, "E702 multiple statements on one line (semicolon)"
def python_3000_has_key(logical_line):
"""
The {}.has_key() method will be removed in the future version of
Python. Use the 'in' operation instead, like:
d = {"a": 1, "b": 2}
if "b" in d:
print d["b"]
"""
pos = logical_line.find('.has_key(')
if pos > -1:
return pos, "W601 .has_key() is deprecated, use 'in'"
def python_3000_raise_comma(logical_line):
"""
When raising an exception, use "raise ValueError('message')"
instead of the older form "raise ValueError, 'message'".
The paren-using form is preferred because when the exception arguments
are long or include string formatting, you don't need to use line
continuation characters thanks to the containing parentheses. The older
form will be removed in Python 3000.
"""
match = RAISE_COMMA_REGEX.match(logical_line)
if match:
return match.start(1), "W602 deprecated form of raising exception"
def python_3000_not_equal(logical_line):
"""
!= can also be written <>, but this is an obsolete usage kept for
backwards compatibility only. New code should always use !=.
The older syntax is removed in Python 3000.
"""
pos = logical_line.find('<>')
if pos > -1:
return pos, "W603 '<>' is deprecated, use '!='"
def python_3000_backticks(logical_line):
"""
Backticks are removed in Python 3000.
Use repr() instead.
"""
pos = logical_line.find('`')
if pos > -1:
return pos, "W604 backticks are deprecated, use 'repr()'"
def python_3000_print(logical_line):
"""
Use Python 3 compatible print statement.
Okay: print('hello %s' % you)
E802: print 'hello', you
"""
if logical_line.lstrip().startswith('print '):
start = logical_line.find('print')
return start, 'E802 not Python 3 compatible, use print(...)'
def single_quoted_strings(logical_line, tokens):
"""
Use single quoted strings instead of double quoted, unless the
string contains a single quote.
Okay: s = 'abc'
E801: s = "abc"
Okay: s = "don't"
"""
for type, text, start, stop, line in tokens:
if (type == tokenize.STRING and
not text.startswith('"""') and
text[0] == '"' and
"'" not in text):
if len(text) > 30:
text = text[:28] + ' ..."'
return start, 'E801 double quoted string: %s' % text
##############################################################################
# Helper functions
##############################################################################
if '' == ''.encode():
# Python 2: implicit encoding.
def readlines(filename):
return open(filename).readlines()
else:
# Python 3: decode to latin-1.
# This function is lazy, it does not read the encoding declaration.
# XXX: use tokenize.detect_encoding()
def readlines(filename):
return open(filename, encoding='latin-1').readlines()
def expand_indent(line):
"""
Return the amount of indentation.
Tabs are expanded to the next multiple of 8.
>>> expand_indent(' ')
4
>>> expand_indent('\\t')
8
>>> expand_indent(' \\t')
8
>>> expand_indent(' \\t')
8
>>> expand_indent(' \\t')
16
"""
result = 0
for char in line:
if char == '\t':
result = result // 8 * 8 + 8
elif char == ' ':
result += 1
else:
break
return result
def mute_string(text):
"""
Replace contents with 'xxx' to prevent syntax matching.
>>> mute_string('"abc"')
'"xxx"'
>>> mute_string("'''abc'''")
"'''xxx'''"
>>> mute_string("r'abc'")
"r'xxx'"
"""
start = 1
end = len(text) - 1
# String modifiers (e.g. u or r)
if text.endswith('"'):
start += text.index('"')
elif text.endswith("'"):
start += text.index("'")
# Triple quotes
if text.endswith('"""') or text.endswith("'''"):
start += 2
end -= 2
return text[:start] + 'x' * (end - start) + text[end:]
def message(text):
"""Print a message."""
# print >> sys.stderr, options.prog + ': ' + text
# print >> sys.stderr, text
print(text)
##############################################################################
# Framework to run all checks
##############################################################################
def find_checks(argument_name):
"""
Find all globally visible functions where the first argument name
starts with argument_name.
"""
checks = []
for name, function in globals().items():
if not inspect.isfunction(function):
continue
args = inspect.getargspec(function)[0]
if args and args[0].startswith(argument_name):
codes = ERRORCODE_REGEX.findall(inspect.getdoc(function) or '')
for code in codes or ['']:
if not code or not ignore_code(code):
checks.append((name, function, args))
break
checks.sort()
return checks
class Checker(object):
"""
Load a Python source file, tokenize it, check coding style.
"""
def __init__(self, filename, lines=None):
self.filename = filename
if filename is None:
self.filename = 'stdin'
self.lines = lines or []
elif lines is None:
self.lines = readlines(filename)
else:
self.lines = lines
options.counters['physical lines'] += len(self.lines)
def readline(self):
"""
Get the next line from the input buffer.
"""
self.line_number += 1
if self.line_number > len(self.lines):
return ''
return self.lines[self.line_number - 1]
def readline_check_physical(self):
"""
Check and return the next physical line. This method can be
used to feed tokenize.generate_tokens.
"""
line = self.readline()
if line:
self.check_physical(line)
return line
def run_check(self, check, argument_names):
"""
Run a check plugin.
"""
arguments = []
for name in argument_names:
arguments.append(getattr(self, name))
return check(*arguments)
def check_physical(self, line):
"""
Run all physical checks on a raw input line.
"""
self.physical_line = line
if self.indent_char is None and len(line) and line[0] in ' \t':
self.indent_char = line[0]
for name, check, argument_names in options.physical_checks:
result = self.run_check(check, argument_names)
if result is not None:
offset, text = result
self.report_error(self.line_number, offset, text, check)
def build_tokens_line(self):
"""
Build a logical line from tokens.
"""
self.mapping = []
logical = []
length = 0
previous = None
for token in self.tokens:
token_type, text = token[0:2]
if token_type in SKIP_TOKENS:
continue
if token_type == tokenize.STRING:
text = mute_string(text)
if previous:
end_line, end = previous[3]
start_line, start = token[2]
if end_line != start_line: # different row
prev_text = self.lines[end_line - 1][end - 1]
if prev_text == ',' or (prev_text not in '{[('
and text not in '}])'):
logical.append(' ')
length += 1
elif end != start: # different column
fill = self.lines[end_line - 1][end:start]
logical.append(fill)
length += len(fill)
self.mapping.append((length, token))
logical.append(text)
length += len(text)
previous = token
self.logical_line = ''.join(logical)
assert self.logical_line.lstrip() == self.logical_line
assert self.logical_line.rstrip() == self.logical_line
def check_logical(self):
"""
Build a line from tokens and run all logical checks on it.
"""
options.counters['logical lines'] += 1
self.build_tokens_line()
first_line = self.lines[self.mapping[0][1][2][0] - 1]
indent = first_line[:self.mapping[0][1][2][1]]
self.previous_indent_level = self.indent_level
self.indent_level = expand_indent(indent)
if options.verbose >= 2:
print(self.logical_line[:80].rstrip())
for name, check, argument_names in options.logical_checks:
if options.verbose >= 4:
print(' ' + name)
result = self.run_check(check, argument_names)
if result is not None:
offset, text = result
if isinstance(offset, tuple):
original_number, original_offset = offset
else:
for token_offset, token in self.mapping:
if offset >= token_offset:
original_number = token[2][0]
original_offset = (token[2][1]
+ offset - token_offset)
self.report_error(original_number, original_offset,
text, check)
self.previous_logical = self.logical_line
def check_all(self, expected=None, line_offset=0):
"""
Run all checks on the input file.
"""
self.expected = expected or ()
self.line_offset = line_offset
self.line_number = 0
self.file_errors = 0
self.indent_char = None
self.indent_level = 0
self.previous_logical = ''
self.blank_lines = 0
self.blank_lines_before_comment = 0
self.tokens = []
parens = 0
for token in tokenize.generate_tokens(self.readline_check_physical):
if options.verbose >= 3:
if token[2][0] == token[3][0]:
pos = '[%s:%s]' % (token[2][1] or '', token[3][1])
else:
pos = 'l.%s' % token[3][0]
print('l.%s\t%s\t%s\t%r' %
(token[2][0], pos, tokenize.tok_name[token[0]], token[1]))
self.tokens.append(token)
token_type, text = token[0:2]
if token_type == tokenize.OP and text in '([{':
parens += 1
if token_type == tokenize.OP and text in '}])':
parens -= 1
if token_type == tokenize.NEWLINE and not parens:
self.check_logical()
self.blank_lines = 0
self.blank_lines_before_comment = 0
self.tokens = []
if token_type == tokenize.NL and not parens:
if len(self.tokens) <= 1:
# The physical line contains only this token.
self.blank_lines += 1
self.tokens = []
if token_type == tokenize.COMMENT:
source_line = token[4]
token_start = token[2][1]
if source_line[:token_start].strip() == '':
self.blank_lines_before_comment = max(self.blank_lines,
self.blank_lines_before_comment)
self.blank_lines = 0
if text.endswith('\n') and not parens:
# The comment also ends a physical line. This works around
# Python < 2.6 behaviour, which does not generate NL after
# a comment which is on a line by itself.
self.tokens = []
return self.file_errors
def report_error(self, line_number, offset, text, check):
"""
Report an error, according to options.
"""
code = text[:4]
if ignore_code(code):
return
if options.quiet == 1 and not self.file_errors:
message(self.filename)
if code in options.counters:
options.counters[code] += 1
else:
options.counters[code] = 1
options.messages[code] = text[5:]
if options.quiet or code in self.expected:
# Don't care about expected errors or warnings
return
self.file_errors += 1
if options.counters[code] == 1 or options.repeat:
message("%s:%s:%d: %s" %
(self.filename, self.line_offset + line_number,
offset + 1, text))
if options.show_source:
line = self.lines[line_number - 1]
message(line.rstrip())
message(' ' * offset + '^')
if options.show_pep8:
message(check.__doc__.lstrip('\n').rstrip())
def input_file(filename):
"""
Run all checks on a Python source file.
"""
if options.verbose:
message('checking ' + filename)
errors = Checker(filename).check_all()
def input_dir(dirname, runner=None):
"""
Check all Python source files in this directory and all subdirectories.
"""
dirname = dirname.rstrip('/')
if excluded(dirname):
return
if runner is None:
runner = input_file
for root, dirs, files in os.walk(dirname):
if options.verbose:
message('directory ' + root)
options.counters['directories'] += 1
dirs.sort()
for subdir in dirs:
if excluded(subdir):
dirs.remove(subdir)
files.sort()
for filename in files:
if filename_match(filename) and not excluded(filename):
options.counters['files'] += 1
runner(os.path.join(root, filename))
def excluded(filename):
"""
Check if options.exclude contains a pattern that matches filename.
"""
basename = os.path.basename(filename)
for pattern in options.exclude:
if fnmatch(basename, pattern):
# print basename, 'excluded because it matches', pattern
return True
def filename_match(filename):
"""
Check if options.filename contains a pattern that matches filename.
If options.filename is unspecified, this always returns True.
"""
if not options.filename:
return True
for pattern in options.filename:
if fnmatch(filename, pattern):
return True
def ignore_code(code):
"""
Check if options.ignore contains a prefix of the error code.
If options.select contains a prefix of the error code, do not ignore it.
"""
for select in options.select:
if code.startswith(select):
return False
for ignore in options.ignore:
if code.startswith(ignore):
return True
def reset_counters():
for key in list(options.counters.keys()):
if key not in BENCHMARK_KEYS:
del options.counters[key]
options.messages = {}
def get_error_statistics():
"""Get error statistics."""
return get_statistics("E")
def get_warning_statistics():
"""Get warning statistics."""
return get_statistics("W")
def get_statistics(prefix=''):
"""
Get statistics for message codes that start with the prefix.
prefix='' matches all errors and warnings
prefix='E' matches all errors
prefix='W' matches all warnings
prefix='E4' matches all errors that have to do with imports
"""
stats = []
keys = list(options.messages.keys())
keys.sort()
for key in keys:
if key.startswith(prefix):
stats.append('%-7s %s %s' %
(options.counters[key], key, options.messages[key]))
return stats
def get_count(prefix=''):
"""Return the total count of errors and warnings."""
keys = list(options.messages.keys())
count = 0
for key in keys:
if key.startswith(prefix):
count += options.counters[key]
return count
def print_statistics(prefix=''):
"""Print overall statistics (number of errors and warnings)."""
for line in get_statistics(prefix):
print(line)
def print_benchmark(elapsed):
"""
Print benchmark numbers.
"""
print('%-7.2f %s' % (elapsed, 'seconds elapsed'))
for key in BENCHMARK_KEYS:
print('%-7d %s per second (%d total)' % (
options.counters[key] / elapsed, key,
options.counters[key]))
def run_tests(filename):
"""
Run all the tests from a file.
A test file can provide many tests. Each test starts with a declaration.
This declaration is a single line starting with '#:'.
It declares codes of expected failures, separated by spaces or 'Okay'
if no failure is expected.
If the file does not contain such declaration, it should pass all tests.
If the declaration is empty, following lines are not checked, until next
declaration.
Examples:
* Only E224 and W701 are expected: #: E224 W701
* Following example is conform: #: Okay
* Don't check these lines: #:
"""
lines = readlines(filename) + ['#:\n']
line_offset = 0
codes = ['Okay']
testcase = []
for index, line in enumerate(lines):
if not line.startswith('#:'):
if codes:
# Collect the lines of the test case
testcase.append(line)
continue
if codes and index > 0:
label = '%s:%s:1' % (filename, line_offset + 1)
codes = [c for c in codes if c != 'Okay']
# Run the checker
errors = Checker(filename, testcase).check_all(codes, line_offset)
# Check if the expected errors were found
for code in codes:
if not options.counters.get(code):
errors += 1
message('%s: error %s not found' % (label, code))
if options.verbose and not errors:
message('%s: passed (%s)' % (label, ' '.join(codes)))
# Keep showing errors for multiple tests
reset_counters()
# output the real line numbers
line_offset = index
# configure the expected errors
codes = line.split()[1:]
# empty the test case buffer
del testcase[:]
def selftest():
"""
Test all check functions with test cases in docstrings.
"""
count_passed = 0
count_failed = 0
checks = options.physical_checks + options.logical_checks
for name, check, argument_names in checks:
for line in check.__doc__.splitlines():
line = line.lstrip()
match = SELFTEST_REGEX.match(line)
if match is None:
continue
code, source = match.groups()
checker = Checker(None)
for part in source.split(r'\n'):
part = part.replace(r'\t', '\t')
part = part.replace(r'\s', ' ')
checker.lines.append(part + '\n')
options.quiet = 2
checker.check_all()
error = None
if code == 'Okay':
if len(options.counters) > len(BENCHMARK_KEYS):
codes = [key for key in options.counters.keys()
if key not in BENCHMARK_KEYS]
error = "incorrectly found %s" % ', '.join(codes)
elif not options.counters.get(code):
error = "failed to find %s" % code
# Reset the counters
reset_counters()
if not error:
count_passed += 1
else:
count_failed += 1
if len(checker.lines) == 1:
print("pep8.py: %s: %s" %
(error, checker.lines[0].rstrip()))
else:
print("pep8.py: %s:" % error)
for line in checker.lines:
print(line.rstrip())
if options.verbose:
print("%d passed and %d failed." % (count_passed, count_failed))
if count_failed:
print("Test failed.")
else:
print("Test passed.")
def process_options(arglist=None):
"""
Process options passed either via arglist or via command line args.
"""
global options, args
parser = OptionParser(version=__version__,
usage="%prog [options] input ...")
parser.add_option('-v', '--verbose', default=0, action='count',
help="print status messages, or debug with -vv")
parser.add_option('-q', '--quiet', default=0, action='count',
help="report only file names, or nothing with -qq")
parser.add_option('-r', '--repeat', action='store_true',
help="show all occurrences of the same error")
parser.add_option('--exclude', metavar='patterns', default=DEFAULT_EXCLUDE,
help="exclude files or directories which match these "
"comma separated patterns (default: %s)" %
DEFAULT_EXCLUDE)
parser.add_option('--filename', metavar='patterns', default='*.py',
help="when parsing directories, only check filenames "
"matching these comma separated patterns (default: "
"*.py)")
parser.add_option('--select', metavar='errors', default='',
help="select errors and warnings (e.g. E,W6)")
parser.add_option('--ignore', metavar='errors', default='',
help="skip errors and warnings (e.g. E4,W)")
parser.add_option('--show-source', action='store_true',
help="show source code for each error")
parser.add_option('--show-pep8', action='store_true',
help="show text of PEP 8 for each error")
parser.add_option('--statistics', action='store_true',
help="count errors and warnings")
parser.add_option('--count', action='store_true',
help="print total number of errors and warnings "
"to standard error and set exit code to 1 if "
"total is not null")
parser.add_option('--benchmark', action='store_true',
help="measure processing speed")
parser.add_option('--testsuite', metavar='dir',
help="run regression tests from dir")
parser.add_option('--doctest', action='store_true',
help="run doctest on myself")
options, args = parser.parse_args(arglist)
if options.testsuite:
args.append(options.testsuite)
if not args and not options.doctest:
parser.error('input not specified')
options.prog = os.path.basename(sys.argv[0])
options.exclude = options.exclude.split(',')
for index in range(len(options.exclude)):
options.exclude[index] = options.exclude[index].rstrip('/')
if options.filename:
options.filename = options.filename.split(',')
if options.select:
options.select = options.select.split(',')
else:
options.select = []
if options.ignore:
options.ignore = options.ignore.split(',')
elif options.select:
# Ignore all checks which are not explicitly selected
options.ignore = ['']
elif options.testsuite or options.doctest:
# For doctest and testsuite, all checks are required
options.ignore = []
else:
# The default choice: ignore controversial checks
options.ignore = DEFAULT_IGNORE.split(',')
options.physical_checks = find_checks('physical_line')
options.logical_checks = find_checks('logical_line')
options.counters = dict.fromkeys(BENCHMARK_KEYS, 0)
options.messages = {}
return options, args
def _main():
"""
Parse options and run checks on Python source.
"""
options, args = process_options()
if options.doctest:
import doctest
doctest.testmod(verbose=options.verbose)
selftest()
if options.testsuite:
runner = run_tests
else:
runner = input_file
start_time = time.time()
for path in args:
if os.path.isdir(path):
input_dir(path, runner=runner)
elif not excluded(path):
options.counters['files'] += 1
runner(path)
elapsed = time.time() - start_time
if options.statistics:
print_statistics()
if options.benchmark:
print_benchmark(elapsed)
count = get_count()
if count:
if options.count:
sys.stderr.write(str(count) + '\n')
sys.exit(1)
if __name__ == '__main__':
_main()
python-ase-3.6.0.2515/tools/ag 0000755 0001754 0001754 00000000073 11410145374 014655 0 ustar askhl askhl #!/usr/bin/env python
from ase.gui.ag import main
main()
python-ase-3.6.0.2515/tools/ase 0000755 0001754 0001754 00000000077 11647035022 015042 0 ustar askhl askhl #!/usr/bin/env python
from ase.tasks.main import main
main()
python-ase-3.6.0.2515/tools/testase.py 0000755 0001754 0001754 00000000226 11026166242 016365 0 ustar askhl askhl #!/usr/bin/env python
from sys import argv
display = (len(argv) != 2 or argv[1] != '--no-display')
from ase.test import test
test(2, display=display)
python-ase-3.6.0.2515/MANIFEST.in 0000644 0001754 0001754 00000000220 11716703044 014733 0 ustar askhl askhl include ase/lattice/spacegroup/spacegroup.dat
include ase/gui/po/ag.pot
include ase/gui/po/makefile
include ase/gui/po/??_??/LC_MESSAGES/ag.po
python-ase-3.6.0.2515/tutorials/ 0000755 0001754 0001754 00000000000 11757245034 015236 5 ustar askhl askhl python-ase-3.6.0.2515/tutorials/N2Ru-Dissociation2.py 0000644 0001754 0001754 00000001347 11410127017 021075 0 ustar askhl askhl import numpy as np
from ase.io import read
from ase.constraints import FixAtoms
from ase.calculators.emt import EMT
from ase.neb import NEB
from ase.optimize import QuasiNewton
initial = read('N2.traj')
final = read('2N.traj')
configs = [initial.copy() for i in range(8)] + [final]
constraint = FixAtoms(mask=[atom.symbol != 'N' for atom in initial])
for config in configs:
config.set_calculator(EMT())
config.set_constraint(constraint)
band = NEB(configs)
band.interpolate()
# Create a quickmin object:
relax = QuasiNewton(band)
relax.run(steps=20)
e0 = initial.get_potential_energy()
for config in configs:
d = config[-2].position - config[-1].position
print np.linalg.norm(d), config.get_potential_energy() - e0
python-ase-3.6.0.2515/tutorials/N2Ru-Dissociation2-ANEB.py 0000644 0001754 0001754 00000002607 11004120066 021574 0 ustar askhl askhl from ase import *
# XXX This cannot be converted to ase 3, since we lack ANEB
raise NotImplementedError
#from ASE.Calculators.PairPotential import PairPotential
#from ASE.Filters.Subset import Subset
#from ASE.Dynamics.AdaptiveNudgedElasticBand import AdaptiveNudgedElasticBand
#from ASE.IO.NetCDF import ReadNetCDF
import os
# check that N2.nc and 2N.nc exists otherwise run
# N2Ru-Dissociation1.py
if not (os.path.exists('N2.nc') and os.path.exists('N2.nc')):
os.system('python N2Ru-Dissociation1.py')
initial = read('N2.traj')
final = read('2N.traj')
configs = [initial.copy() for i in range(4)] + [final]
constraint = FixAtoms(mask=[atom.symbol != 'N' for atom in initial])
for config in configs:
config.set_calculator(EMT())
config.set_constraint(constraint)
band = NEB(configs)
band.interpolate()
# Create a quickmin object:
relax = QuasiNewton(band)
#configs0 = [initial]
#for i in range(3):
# configs0.append(initial.Copy())
#configs0.append(final)
#
#configs = []
#for config in configs0:
# config.SetCalculator(PairPotential())
# configs.append(Subset(config, indices=[-2, -1]))
# setup the Adaptive Nudged Elastic Band dynamics
aneb = AdaptiveNudgedElasticBand(configs,prefix='aneb',linear_interpolation=True,maxlevels=1)
aneb.Converge()
# test the anebfit tool
os.system('anebfit aneb')
os.system('xmgrace aneb_-1.agr&')
# clean up
# os.system('rm aneb*conf*')
python-ase-3.6.0.2515/tutorials/N2Ru-Association.py 0000644 0001754 0001754 00000002250 11004141010 020615 0 ustar askhl askhl from ase import *
#from math import sqrt
#from ASE.Calculators.PairPotential import PairPotential
#from ASE.Filters.Subset import Subset
#from ASE.Filters.FixBondLength import FixBondLength
#from ASE.Dynamics.MDMin import MDMin
#from ASE.Trajectories.NetCDFTrajectory import NetCDFTrajectory
#from ASE.IO.NetCDF import ReadNetCDF
slab = read('2N.traj')
slab.set_calculator(EMT())
constraint = FixBondLength(-2, -1)
#mask=[atom.symbol != 'N' for atom in slab])
#molecule = Subset(slab, indices=[-2, -1])
# Create a trajectory for the dissociation path:
path = PickleTrajectory('association.traj', slab)
# Put the initial state in the trajectory:
path.write()
# From now on, we relax the molecule under the constraint of fixed
# bond length:
#fixed = FixBondLength(molecule, 0, 1)
#relax = MDMin(fixed, dt=0.08, fmax=0.05)
relax = QuasiNewton(slab)
d = linalg.norm(slab[-2].position - slab[-1].position)
#d = fixed.GetBondLength()
delta = 0.1
e0 = slab.get_potential_energy()
print d, 0.0
while d > 1.10:
d -= delta
fixed.SetBondLength(d, fix='first')
# XXX
raise NotImplementedError
relax.run(fmax=.05)
path.write()
print d, slab.GetPotentialEnergy() - e0
python-ase-3.6.0.2515/tutorials/N2Ru-Dissociation1.py 0000644 0001754 0001754 00000002466 11410127017 021077 0 ustar askhl askhl from ase import Atoms
from ase.calculators.emt import EMT
from ase.constraints import FixAtoms
from ase.optimize import QuasiNewton
from ase.io import write
# Find the initial and final states for the reaction.
# Set up a (3 x 3) two layer slab of Ru:
a = 2.70
c = 1.59 * a
sqrt3 = 3. ** .5
bulk = Atoms('2Cu', [(0., 0., 0.), (1./3, 1./3, -0.5*c)],
tags=(1, 1),
pbc=(1, 1, 0))
bulk.set_cell([(a, 0, 0),
(a / 2, sqrt3 * a / 2, 0),
(0, 0, 1)])
slab = bulk.repeat((4, 4, 1))
# Initial state.
# Add the molecule:
x = a / 2.
y = a * 3. ** .5 / 6.
z = 1.8
d = 1.10 # N2 bond length
# Molecular state parallel to the surface:
slab += Atoms('2N', [(x, y, z), (x + sqrt3 * d / 2, y + d / 2, z)])
# Use the EMT calculator for the forces and energies:
slab.set_calculator(EMT())
# We don't want to worry about the Cu degrees of freedom:
mask = [atom.symbol == 'Cu' for atom in slab]
slab.set_constraint(FixAtoms(mask=mask))
relax = QuasiNewton(slab)
relax.run(fmax=0.05)
print 'initial state:', slab.get_potential_energy()
write('N2.traj', slab)
# Now the final state.
# Move the second N atom to a neighboring hollow site:
slab[-1].set_position((x + a, y, z))
relax.run()
print 'final state: ', slab.get_potential_energy()
write('2N.traj', slab)
python-ase-3.6.0.2515/tutorials/N2Ru-relax.py 0000644 0001754 0001754 00000001741 11410127017 017474 0 ustar askhl askhl from ase import Atoms
from ase.calculators.emt import EMT
from ase.optimize import QuasiNewton
from ase.constraints import FixAtoms
a = 2.70
c = 1.59 * a
h = 1.85
d = 1.10
slab = Atoms('2Cu', [(0., 0., 0.), (1/3., 1/3., -0.5*c)],
tags=(0, 1),
pbc=(1, 1, 0))
slab.set_cell([(a, 0, 0),
(a / 2, 3**0.5 * a / 2, 0),
(0, 0, 1)])
slab = slab.repeat((4, 4, 1))
slab.set_calculator(EMT())
mask = [a.tag == 1 for a in slab]
slab.set_constraint(FixAtoms(mask=mask))
dyn = QuasiNewton(slab)
dyn.run(fmax=0.05)
e_slab = slab.get_potential_energy()
x = slab.positions[0, 2] / (c / 2) * 100
print 'Relaxation of the top layer: %f %%' % x
molecule = Atoms('2N', positions=[(0., 0., h),
(0., 0., h + d)])
molecule.set_calculator(EMT())
e_N2 = molecule.get_potential_energy()
slab.extend(molecule)
dyn = QuasiNewton(slab)
dyn.run(fmax=0.05)
print 'Adsorption energy:', e_slab + e_N2 - slab.get_potential_energy()
python-ase-3.6.0.2515/README.txt 0000755 0001754 0001754 00000000110 11166435455 014703 0 ustar askhl askhl ==========
Python ASE
==========
Webpage: http://wiki.fysik.dtu.dk/ase
python-ase-3.6.0.2515/ase/ 0000755 0001754 0001754 00000000000 11757245036 013762 5 ustar askhl askhl python-ase-3.6.0.2515/ase/tasks/ 0000755 0001754 0001754 00000000000 11757245036 015107 5 ustar askhl askhl python-ase-3.6.0.2515/ase/tasks/task.py 0000644 0001754 0001754 00000031261 11721212447 016415 0 ustar askhl askhl import sys
import optparse
import traceback
from time import time
import numpy as np
from ase.parallel import world
from ase.visualize import view
from ase.io import read, write
from ase.io import string2index
from ase.constraints import FixAtoms
from ase.optimize.lbfgs import LBFGS
from ase.utils import opencew, devnull, prnt
from ase.tasks.io import read_json, write_json
from ase.data import chemical_symbols, atomic_numbers
from ase.tasks.calcfactory import calculator_factory
class Task:
taskname = 'generic-task'
def __init__(self, calcfactory='emt',
tag=None, magmoms=None, gui=False,
write_summary=False, use_lock_files=False,
write_to_file=None, slice=slice(None),
logfile='-'):
"""Generic task object.
This task will do a single of the energy and forces for the
configurations that subcalsses define in their build_system()
methods.
calcfactory: CalculatorFactory object or str
A calculator factory or the name of a calculator.
For the meaning of the other arguments, see the add_options()
and parse_args() methods."""
self.set_calculator_factory(calcfactory)
self.tag = tag
self.magmoms = magmoms
self.gui = gui
self.write_summary = write_summary
self.use_lock_files = use_lock_files
self.write_to_file = write_to_file
self.slice = slice
if world.rank == 0:
if logfile is None:
logfile = devnull
elif isinstance(logfile, str):
if logfile == '-':
logfile = sys.stdout
else:
logfile = open(logfile, 'w')
else:
logfile = devnull
self.logfile = logfile
self.write_funcs = [write_json]
self.read_func = read_json
self.data = {} # data read from json files
self.results = {} # results from analysis of json files
self.summary_header = [('name', ''), ('E', 'eV')]
self.interactive_python_session = False
self.contains = None
self.modify = None
def set_calculator_factory(self, calcfactory):
if isinstance(calcfactory, str):
calcfactory = calculator_factory(calcfactory)
self.calcfactory = calcfactory
def log(self, *args, **kwargs):
prnt(file=self.logfile, *args, **kwargs)
def get_filename(self, name=None, ext=''):
filename = self.taskname + '-' + self.calcfactory.name.lower()
if self.tag:
filename += '-' + self.tag
if name:
filename = name + '-' + filename
return filename + ext
def expand(self, names):
"""Expand ranges like H-Li to H, He, Li."""
if isinstance(names, str):
names = [names]
newnames = []
for name in names:
if name.count('-') == 1:
s1, s2 = name.split('-')
Z1 = atomic_numbers.get(s1)
Z2 = atomic_numbers.get(s2)
if Z1 is None or Z2 is None:
newnames.append(name)
else:
newnames.extend(chemical_symbols[Z1:Z2 + 1])
else:
newnames.append(name)
return newnames
def exclude(self, names):
newnames = []
for name in names:
atoms = self.create_system(name)
if (self.contains is None or
self.contains in atoms.get_chemical_symbols()):
newnames.append(name)
return newnames
def run(self, names):
"""Run task far all names.
The task will be one of these four:
* Open ASE's GUI
* Write configuration to file
* Write summary
* Do the actual calculation
"""
names = self.expand(names)
names = names[self.slice]
names = self.exclude(names)
if self.gui:
for name in names:
view(self.create_system(name))
return
if self.write_to_file:
if self.write_to_file[0] == '.':
for name in names:
filename = self.get_filename(name, self.write_to_file)
write(filename, self.create_system(name))
else:
assert len(names) == 1
write(self.write_to_file, self.create_system(names[0]))
return
if self.write_summary:
self.read(names)
self.analyse()
self.summarize(names)
return
atoms = None
for name in names:
if self.use_lock_files:
lockfilename = self.get_filename(name, '.json')
fd = opencew(lockfilename)
if fd is None:
self.log('Skipping', name)
continue
fd.close()
atoms = self.run_single(name)
return atoms
def run_single(self, name):
try:
atoms = self.create_system(name)
except Exception:
self.log(name, 'FAILED')
traceback.print_exc(file=self.logfile)
return
atoms.calc = self.calcfactory(self.get_filename(name), atoms)
tstart = time()
try:
data = self.calculate(name, atoms)
except KeyboardInterrupt:
raise
except Exception:
self.log(name, 'FAILED')
traceback.print_exc(file=self.logfile)
return
tstop = time()
data['time'] = tstop - tstart
for write in self.write_funcs:
filenamebase = self.get_filename(name)
write(filenamebase, atoms, data)
return atoms
def create_system(self, name):
if '.' in name:
system = read(name)
else:
system = self.build_system(name)
if self.magmoms is not None:
system.set_initial_magnetic_moments(
np.tile(self.magmoms, len(system) // len(self.magmoms)))
if self.modify:
exec self.modify
return system
def calculate(self, name, atoms):
e = atoms.get_potential_energy()
f = atoms.get_forces()
return {'energy': e, 'forces': f}
def read(self, names):
self.data = {}
for name in names:
filenamebase = self.get_filename(name)
try:
data = self.read_func(filenamebase)
except (IOError, SyntaxError, ValueError):
continue
self.data[name] = data
def analyse(self):
for name, data in self.data.items():
self.results[name] = [data['energy']]
def summarize(self, names):
self.log(' '.join('%10s' % x[0] for x in self.summary_header))
self.log(' '.join('%10s' % x[1] for x in self.summary_header))
for name in names:
data = self.results.get(name, [])
s = '%10s' % name
for x in data:
if x is None:
s += ' '
else:
s += '%11.3f' % x
self.log(s)
def create_parser(self):
calcname = self.calcfactory.name
parser = optparse.OptionParser(
usage='%prog [options] system(s)',
description='Run %s calculation.' % calcname)
self.add_options(parser)
return parser
def add_options(self, parser):
general = optparse.OptionGroup(parser, 'General')
general.add_option('-t', '--tag',
help='String tag added to filenames.')
general.add_option('-M', '--magnetic-moment',
metavar='M1,M2,...',
help='Magnetic moment(s). ' +
'Use "-M 1" or "-M 2.3,-2.3".')
general.add_option('-G', '--gui', action='store_true',
help="Pop up ASE's GUI.")
general.add_option('-s', '--write-summary', action='store_true',
help='Write summary.')
general.add_option('--slice', metavar='start:stop:step',
help='Select subset of calculations using ' +
'Python slice syntax. ' +
'Use "::2" to do every second calculation and ' +
'":-5" to do the last five.')
general.add_option('-w', '--write-to-file', metavar='FILENAME',
help='Write configuration to file.')
general.add_option('-i', '--interactive-python-session',
action='store_true',
help='Run calculation inside interactive Python ' +
'session. A possible $PYTHONSTARTUP script ' +
'will be imported and the "atoms" variable ' +
'refers to the Atoms object.')
general.add_option('-l', '--use-lock-files', action='store_true',
help='Skip calculations where the json ' +
'lock-file or result file already exists.')
general.add_option('--contains', metavar='ELEMENT',
help='Run only systems containing specific ' +
'element.')
general.add_option('--modify', metavar='...',
help='Modify system with Python statement. ' +
'Example: "system.positions[-1,2]+=0.1". ' +
'Warning: no spaces allowed!')
parser.add_option_group(general)
def parse_args(self, args=None):
if args is None:
args = sys.argv[1:]
parser = self.create_parser()
self.calcfactory.add_options(parser)
opts, args = parser.parse_args(args)
if len(args) == 0:
parser.error('incorrect number of arguments')
self.parse(opts, args)
self.calcfactory.parse(opts, args)
return args
def parse(self, opts, args):
if opts.tag:
self.tag = opts.tag
if opts.magnetic_moment:
self.magmoms = np.array(
[float(m) for m in opts.magnetic_moment.split(',')])
self.gui = opts.gui
self.write_summary = opts.write_summary
self.write_to_file = opts.write_to_file
self.use_lock_files = opts.use_lock_files
self.interactive_python_session = opts.interactive_python_session
self.contains = opts.contains
self.modify = opts.modify
if opts.slice:
self.slice = string2index(opts.slice)
class OptimizeTask(Task):
taskname = 'opt'
def __init__(self, fmax=None, constrain_tags=[], **kwargs):
self.fmax = fmax
self.constrain_tags = constrain_tags
Task.__init__(self, **kwargs)
self.summary_header.append(('E-E0', 'eV'))
def optimize(self, name, atoms):
mask = [t in self.constrain_tags for t in atoms.get_tags()]
if mask:
constrain = FixAtoms(mask=mask)
atoms.constraints = [constrain]
optimizer = LBFGS(atoms, trajectory=self.get_filename(name, '.traj'),
logfile=None)
optimizer.run(self.fmax)
def calculate(self, name, atoms):
data = Task.calculate(self, name, atoms)
if self.fmax is not None:
self.optimize(name, atoms)
data['minimum energy'] = atoms.get_potential_energy()
data['minimum forces'] = atoms.get_forces()
return data
def analyse(self):
Task.analyse(self)
for name, data in self.data.items():
if 'minimum energy' in data:
self.results[name].append(data['energy'] -
data['minimum energy'])
else:
self.results[name].append(None)
def add_options(self, parser):
Task.add_options(self, parser)
optimize = optparse.OptionGroup(parser, 'Optimize')
optimize.add_option('-R', '--relax', type='float', metavar='FMAX',
help='Relax internal coordinates using L-BFGS '
'algorithm.')
optimize.add_option('--constrain-tags', type='str',
metavar='T1,T2,...',
help='Constrain atoms with tags T1, T2, ...')
parser.add_option_group(optimize)
def parse(self, opts, args):
Task.parse(self, opts, args)
self.fmax = opts.relax
if opts.constrain_tags:
self.constrain_tags = [int(t)
for t in opts.constrain_tags.split(',')]
python-ase-3.6.0.2515/ase/tasks/__init__.py 0000644 0001754 0001754 00000000000 11647035022 017174 0 ustar askhl askhl python-ase-3.6.0.2515/ase/tasks/bulk.py 0000644 0001754 0001754 00000012505 11672645356 016426 0 ustar askhl askhl import optparse
import numpy as np
from ase.lattice import bulk
from ase.tasks.task import OptimizeTask
from ase.data import chemical_symbols, reference_states
from ase.utils.eos import EquationOfState
from ase.io.trajectory import PickleTrajectory
import ase.units as units
class BulkTask(OptimizeTask):
taskname = 'bulk'
def __init__(self, crystal_structure=None, lattice_constant=None,
c_over_a=None, cubic=False, orthorhombic=False, fit=None,
**kwargs):
"""Bulk task."""
self.crystal_structure = crystal_structure
self.lattice_constant = lattice_constant
self.c_over_a = c_over_a
self.cubic = cubic
self.orthorhombic = orthorhombic
self.fit = fit
self.repeat = None
OptimizeTask.__init__(self, **kwargs)
self.summary_header += [('V0', 'Ang^3'),
('B', 'GPa')]
def expand(self, names):
"""Expand fcc, bcc, hcp and diamond.
The name fcc will be expanded to all the elements with the fcc
stucture and so on."""
names = OptimizeTask.expand(self, names)
newnames = []
for name in names:
if name in ['fcc', 'bcc', 'hcp', 'diamond']:
for Z in range(1, 95):
x = reference_states[Z]
if x is not None and x['symmetry'] == name:
newnames.append(chemical_symbols[Z])
else:
newnames.append(name)
return newnames
def build_system(self, name):
atoms = bulk(name, crystalstructure=self.crystal_structure,
a=self.lattice_constant, covera=self.c_over_a,
orthorhombic=self.orthorhombic, cubic=self.cubic)
M = {'Fe': 2.3, 'Co': 1.2, 'Ni': 0.6}.get(name)
if M is not None:
atoms.set_initial_magnetic_moments([M] * len(atoms))
if self.repeat is not None:
r = self.repeat.split(',')
if len(r) == 1:
r = 3 * r
atoms = atoms.repeat([int(c) for c in r])
return atoms
def fit_volume(self, name, atoms):
N, x = self.fit
cell0 = atoms.get_cell()
strains = np.linspace(1 - x, 1 + x, N)
energies = []
traj = PickleTrajectory(self.get_filename(name, '-fit.traj'), 'w')
for s in strains:
atoms.set_cell(cell0 * s, scale_atoms=True)
energies.append(atoms.get_potential_energy())
traj.write(atoms)
traj.close()
assert N % 2 == 1
data = {'energy': energies[N // 2],
'strains': strains,
'energies': energies}
return data
def calculate(self, name, atoms):
#????
if self.fit:
return self.fit_volume(name, atoms)
else:
return OptimizeTask.calculate(self, name, atoms)
def analyse(self):
OptimizeTask.analyse(self)
for name, data in self.data.items():
if 'strains' in data:
atoms = self.create_system(name)
volumes = data['strains']**3 * atoms.get_volume()
energies = data['energies']
eos = EquationOfState(volumes, energies)
try:
v, e, B = eos.fit()
except ValueError:
self.results[name].extend([None, None])
else:
self.results[name][1:] = [energies[2] - e, v,
B * 1e24 / units.kJ]
else:
self.results[name].extend([None, None])
def add_options(self, parser):
OptimizeTask.add_options(self, parser)
bulk = optparse.OptionGroup(parser, 'Bulk')
bulk.add_option('-F', '--fit', metavar='N,x',
help='Find optimal volume and bulk modulus ' +
'using N points and variations of the lattice ' +
'constants from -x % to +x %.')
bulk.add_option('-x', '--crystal-structure',
help='Crystal structure.',
choices=['sc', 'fcc', 'bcc', 'diamond', 'hcp',
'rocksalt', 'zincblende'])
bulk.add_option('-a', '--lattice-constant', type='float',
help='Lattice constant in Angstrom.')
bulk.add_option('--c-over-a', type='float',
help='c/a ratio.')
bulk.add_option('-O', '--orthorhombic', action='store_true',
help='Use orthorhombic unit cell.')
bulk.add_option('-C', '--cubic', action='store_true',
help='Use cubic unit cell.')
bulk.add_option('-r', '--repeat',
help='Repeat unit cell. Use "-r 2" or "-r 2,3,1".')
parser.add_option_group(bulk)
def parse(self, opts, args):
OptimizeTask.parse(self, opts, args)
if opts.fit:
points, strain = opts.fit.split(',')
self.fit = (int(points), float(strain) * 0.01)
self.crystal_structure = opts.crystal_structure
self.lattice_constant = opts.lattice_constant
self.c_over_a = opts.c_over_a
self.orthorhombic = opts.orthorhombic
self.cubic = opts.cubic
self.repeat = opts.repeat
python-ase-3.6.0.2515/ase/tasks/calcfactory.py 0000644 0001754 0001754 00000012534 11656523010 017745 0 ustar askhl askhl import optparse
from math import sqrt, pi
import numpy as np
from ase.dft.kpoints import monkhorst_pack
def str2dict(s, namespace={}):
"""Convert comma-separated key=vale string to dictionary.
Example:
>>> str2dict('a=1.2,b=True,c=abc,d=1,2,3')
{'a': 1.2, 'c': 'abc', 'b': True, 'd': (1, 2, 3)}
"""
dct = {}
s = (s + ',').split('=')
for i in range(len(s) - 1):
key = s[i]
m = s[i + 1].rfind(',')
value = s[i + 1][:m]
try:
value = eval(value, namespace)
except (NameError, SyntaxError):
pass
dct[key] = value
s[i + 1] = s[i + 1][m + 1:]
return dct
class CalculatorFactory:
def __init__(self, Class, name, label='label',
kpts=None, kptdensity=3.0,
**kwargs):
"""Calculator factory object.
Used to create calculators with specific parameters."""
self.Class = Class
self.name = name
self.label = label
self.kpts = kpts
self.kptdensity = kptdensity
self.kwargs = kwargs
def calculate_kpts(self, atoms):
"""Estimate an appropriate number of k-points."""
if self.kpts is not None:
# Number of k-points was explicitely set:
return self.kpts
# Use kptdensity to make a good estimate:
recipcell = atoms.get_reciprocal_cell()
kpts = []
for i in range(3):
if atoms.pbc[i]:
k = 2 * pi * sqrt((recipcell[i]**2).sum()) * self.kptdensity
kpts.append(max(1, 2 * int(round(k / 2))))
else:
kpts.append(1)
return kpts
def __call__(self, name, atoms):
"""Create calculator.
Put name in the filename of all created files."""
kpts = self.calculate_kpts(atoms)
if kpts != 'no k-points':
self.kwargs['kpts'] = kpts
if self.label is not None:
self.kwargs[self.label] = name
return self.Class(**self.kwargs)
def add_options(self, parser):
calc = optparse.OptionGroup(parser, 'Calculator')
calc.add_option('-k', '--monkhorst-pack',
metavar='K1,K2,K3',
help='Monkhorst-Pack sampling of BZ. Example: ' +
'"4,4,4": 4x4x4 k-points, "4,4,4g": same set of ' +
'k-points shifted to include the Gamma point.')
calc.add_option('--k-point-density', type='float', default=3.0,
help='Density of k-points in Angstrom.')
calc.add_option('-p', '--parameters', metavar='key=value,...',
help='Comma-separated key=value pairs of ' +
'calculator specific parameters.')
parser.add_option_group(calc)
def parse(self, opts, args):
mp = opts.monkhorst_pack
if mp is not None:
if mp[-1].lower() == 'g':
kpts = np.array([int(k) for k in mp[:-1].split(',')])
shift = 0.5 * ((kpts + 1) % 2) / kpts
self.kpts = monkhorst_pack(kpts) + shift
else:
self.kpts = [int(k) for k in mp.split(',')]
self.kptdensity = opts.k_point_density
if opts.parameters:
self.kwargs.update(str2dict(opts.parameters))
# Recognized names of calculators sorted alphabetically:
calcnames = ['abinit', 'aims', 'asap', 'castep', 'dftb', 'elk', 'emt',
'exciting', 'fleur', 'gpaw', 'hotbit', 'jacapo',
'lammps', 'lj', 'morse',
'nwchem', 'siesta', 'turbomole', 'vasp']
classnames = {'asap': 'EMT',
'elk': 'ELK',
'emt': 'EMT',
'fleur': 'FLEUR',
'jacapo': 'Jacapo',
'lammps': 'LAMMPS',
'lj': 'LennardJones',
'morse': 'MorsePotential',
'nwchem': 'NWchem',
'vasp': 'Vasp'}
def calculator_factory(name, **kwargs):
"""Create an ASE calculator factory."""
if name == 'asap':
from asap3 import EMT
return CalculatorFactory(EMT, 'Asap', None, 'no k-points', **kwargs)
if name == 'elk':
from ase.calculators.elk import ELK
return CalculatorFactory(ELK, 'ELK', 'dir', **kwargs)
if name == 'fleur':
from ase.calculators.fleur import FLEUR
return CalculatorFactory(FLEUR, 'FLEUR', 'workdir', **kwargs)
if name == 'gpaw':
from gpaw.factory import GPAWFactory
return GPAWFactory(**kwargs)
if name == 'hotbit':
from hotbit import Calculator
return CalculatorFactory(Calculator, 'Hotbit', 'txt', 'no k-points',
**kwargs)
if name == 'jacapo':
from ase.calculators.jacapo import Jacapo
return CalculatorFactory(Jacapo, 'Jacapo', 'nc', **kwargs)
if name == 'vasp':
from ase.calculators.vasp import Vasp
return CalculatorFactory(Vasp, 'Vasp', None, **kwargs)
classname = classnames.get(name, name.title())
module = __import__('ase.calculators.' + name, {}, None, [classname])
Class = getattr(module, classname)
if name in ['emt', 'lammps', 'lj', 'morse']:
kpts = 'no k-points'
else:
kpts = None
if name in ['emt', 'lj', 'morse']:
label = None
else:
label = 'label'
return CalculatorFactory(Class, classname, label, kpts, **kwargs)
python-ase-3.6.0.2515/ase/tasks/molecule.py 0000644 0001754 0001754 00000021244 11720704647 017267 0 ustar askhl askhl from math import sqrt
import optparse
import numpy as np
from ase.atoms import Atoms, string2symbols
from ase.structure import molecule
from ase.tasks.task import OptimizeTask
from ase.data import covalent_radii, atomic_numbers
from ase.data import ground_state_magnetic_moments
from ase.utils.eos import EquationOfState
from ase.io.trajectory import PickleTrajectory
import ase.units as units
class MoleculeTask(OptimizeTask):
taskname = 'molecule'
def __init__(self, vacuum=3.0, cell=None, atomize=False,
bond_length=None, fit=None,
**kwargs):
"""Molecule task.
This task can calculate bond lengths and vibration frequencies
of dimer molecules."""
self.vacuum = vacuum
self.unit_cell = cell
self.atomize = atomize
self.bond_length = bond_length
self.fit = fit
OptimizeTask.__init__(self, **kwargs)
self.summary_header += [('d0', 'Ang'),
('hnu', 'meV'),
('Ea', 'eV'),
('Ea0', 'eV')]
def run(self, names1):
names = []
atoms = set()
for name in names1:
if name.lower() == 'g2':
from ase.data.g2 import molecule_names
names.extend(molecule_names)
from ase.data.g2 import atom_names
if self.atomize:
atoms.update(atom_names)
elif name.lower() == 'g2-1':
from ase.data.g2_1 import molecule_names
names.extend(molecule_names)
from ase.data.g2_1 import atom_names
if self.atomize:
atoms.update(atom_names)
else:
names.append(name)
if self.atomize:
atoms.update(self.build_system(name).get_chemical_symbols())
if self.atomize:
names.extend(atoms)
return OptimizeTask.run(self, names)
def build_system(self, name):
try:
# Known molecule or atom?
atoms = molecule(name)
if len(atoms) == 2 and self.bond_length is not None:
atoms.set_distance(0, 1, self.bond_length)
except NotImplementedError:
symbols = string2symbols(name)
if len(symbols) == 1:
magmom = ground_state_magnetic_moments[atomic_numbers[symbols[0]]]
atoms = Atoms(name, magmoms=[magmom])
elif len(symbols) == 2:
# Dimer
if self.bond_length is None:
b = (covalent_radii[atomic_numbers[symbols[0]]] +
covalent_radii[atomic_numbers[symbols[1]]])
else:
b = self.bond_length
atoms = Atoms(name, positions=[(0, 0, 0),
(b, 0, 0)])
else:
raise ValueError('Unknown molecule: ' + name)
if self.unit_cell is None:
atoms.center(vacuum=self.vacuum)
else:
atoms.cell = self.unit_cell
atoms.center()
return atoms
def fit_bond_length(self, name, atoms):
N, x = self.fit
assert N % 2 == 1
d0 = atoms.get_distance(0, 1)
distances = np.linspace(d0 * (1 - x), d0 * (1 + x), N)
energies = []
traj = PickleTrajectory(self.get_filename(name, '-fit.traj'), 'w')
for d in distances:
atoms.set_distance(0, 1, d)
energies.append(atoms.get_potential_energy())
self.check_occupation_numbers(atoms)
traj.write(atoms)
traj.close()
data = {'energy': energies[N // 2],
'distances': distances,
'energies': energies}
return data
def calculate(self, name, atoms):
if self.fit and len(atoms) == 2:
return self.fit_bond_length(name, atoms)
else:
data = OptimizeTask.calculate(self, name, atoms)
self.check_occupation_numbers(atoms)
return data
def analyse(self):
OptimizeTask.analyse(self)
for name, data in self.data.items():
if 'distances' in data:
distances = data['distances']
energies = data['energies']
fit0 = np.poly1d(np.polyfit(1 / distances, energies, 3))
fit1 = np.polyder(fit0, 1)
fit2 = np.polyder(fit1, 1)
dmin = None
for t in np.roots(fit1):
if t > 0 and fit2(t) > 0:
dmin = 1 / t
break
if dmin is None:
raise ValueError('No minimum!')
if abs(dmin) < min(distances) or abs(dmin) > max(distances):
raise ValueError('Fit outside of range! ' + \
str(abs(dmin)) + ' not in ' + \
str(distances))
emin = fit0(t)
k = fit2(t) * t**4
m1, m2 = self.create_system(name).get_masses()
m = m1 * m2 / (m1 + m2)
hnu = units._hbar * 1e10 * sqrt(k / units._e / units._amu / m)
data['minimum energy'] = emin
self.results[name][1:] = [energies[2] - emin, dmin, 1000 * hnu]
else:
self.results[name].extend([None, None])
for name, data in self.data.items():
atoms = self.create_system(name)
if len(atoms) == 1:
self.results[name].extend([None, None])
continue
eatoms = 0.0
for symbol in atoms.get_chemical_symbols():
if symbol in self.data and symbol != name:
eatoms += self.data[symbol]['energy']
else:
eatoms = None
break
ea = None
ea0 = None
if eatoms is not None:
ea = eatoms - data['energy']
if 'minimum energy' in data:
ea0 = eatoms - data['minimum energy']
self.results[name].extend([ea, ea0])
def add_options(self, parser):
OptimizeTask.add_options(self, parser)
mol = optparse.OptionGroup(parser, 'Molecule')
mol.add_option('-v', '--vacuum', type='float', default=3.0,
help='Amount of vacuum to add around isolated systems '
'(in Angstrom).')
mol.add_option('--unit-cell',
help='Unit cell. Examples: "10.0" or "9,10,11" ' +
'(in Angstrom).')
mol.add_option('--bond-length', type='float',
help='Bond length of dimer in Angstrom.')
mol.add_option('-F', '--fit', metavar='N,x',
help='Find optimal bondlength and vibration ' +
'frequency using N points and displacements from ' +
'-x % to +x %.')
mol.add_option('--atomize', action='store_true',
help='Calculate Atomization energies.')
parser.add_option_group(mol)
def parse(self, opts, args):
OptimizeTask.parse(self, opts, args)
self.vacuum = opts.vacuum
self.bond_length = opts.bond_length
self.atomize = opts.atomize
if opts.fit:
points, strain = opts.fit.split(',')
self.fit = (int(points), float(strain) * 0.01)
if opts.unit_cell:
if ',' in opts.unit_cell:
self.unit_cell = [float(x) for x in opts.unit_cell.split(',')]
else:
self.unit_cell = [float(opts.unit_cell)] * 3
def check_occupation_numbers(self, config):
"""Check that occupation numbers are integers and sum
to desired magnetic moment. """
if config.pbc.any():
return
calc = config.get_calculator()
try:
mref = abs(config.get_initial_magnetic_moments().sum())
nspins = calc.get_number_of_spins()
mcalc = 0.0
for s in range(nspins):
f = calc.get_occupation_numbers(spin=s)
if abs((f.round() - f).sum()) > 0.0001:
raise RuntimeError('Fractional occupation numbers?! ' + \
str(f) + ' for spin ' + str(s))
mcalc += abs(f).sum() * (-1)**s
mcalc = abs(mcalc)
if mref > 0.0:
if abs(mcalc - mref) > 0.0001:
raise RuntimeError('Incorrect magnetic moment?! ' + \
str(mcalc) + ' vs ' + str(mref))
except AttributeError:
pass
python-ase-3.6.0.2515/ase/tasks/main.py 0000644 0001754 0001754 00000005423 11647743006 016407 0 ustar askhl askhl import os
import sys
import tempfile
import textwrap
import traceback
from ase.tasks.task import Task
from ase.tasks.bulk import BulkTask
from ase.tasks.molecule import MoleculeTask
from ase.tasks.calcfactory import calcnames
usage = """\
Usage: ase [calculator] [task] [options] system(s)
%s
task: 'molecule', 'bulk' or the name of Python script that instantiates
a Task object. Default value is 'molecule'.
systems: chemical formulas or filenames of files containing the atomic
structure.
Try "ase molecule --help" or "ase bulk --help".
"""
def run(args=sys.argv[1:], calcname='emt'):
if isinstance(args, str):
args = args.split(' ')
argsoriginal = args[:]
if len(args) > 0 and args[0] in calcnames:
calcname = args.pop(0)
taskname = 'molecule'
if (len(args) > 0 and
(args[0] in ['molecule', 'bulk'] or args[0].endswith('.py'))):
taskname = args.pop(0)
if len(args) == 0:
sys.stderr.write(
usage % textwrap.fill(', '.join(calcnames[:-1]) +
' or ' + calcnames[-1] +
'. Default value is emt.',
initial_indent='calculator: ',
subsequent_indent=' ' * 12))
return
if taskname.endswith('.py'):
locals = {}
execfile(taskname, locals, locals)
tasks = [task for task in locals.values() if isinstance(task, Task)]
assert len(tasks) == 1
task = tasks[0]
elif taskname == 'bulk':
task = BulkTask()
else:
task = MoleculeTask()
task.set_calculator_factory(calcname)
args = task.parse_args(args)
if task.interactive_python_session:
if '-i' in argsoriginal:
argsoriginal.remove('-i')
if '--interactive-python-session' in argsoriginal:
argsoriginal.remove('--interactive-python-session')
file = tempfile.NamedTemporaryFile()
file.write('import os\n')
file.write('if "PYTHONSTARTUP" in os.environ:\n')
file.write(' execfile(os.environ["PYTHONSTARTUP"])\n')
file.write('from ase.tasks.main import run\n')
file.write('atoms, task = run(%r, %r)\n' % (argsoriginal, calcname))
file.flush()
os.system('python -i %s' % file.name)
return
atoms = task.run(args)
return atoms, task
def main():
try:
run()
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
traceback.print_exc()
sys.stderr.write("""
An exception occurred! Please report the issue to
ase-developer@listserv.fysik.dtu.dk - thanks! Please also report this
if it was a user error, so that a better error message can be provided
next time.""")
raise
python-ase-3.6.0.2515/ase/tasks/io.py 0000644 0001754 0001754 00000002573 11647035022 016065 0 ustar askhl askhl import numpy as np
from ase.parallel import world
try:
import json
except ImportError:
json = None
if json is None:
def dumps(obj):
if isinstance(obj, str):
return '"' + obj + '"'
if isinstance(obj, (int, float)):
return repr(obj)
if isinstance(obj, dict):
return '{' + ','.join(dumps(key) + ':' + dumps(value)
for key, value in obj.items()) + '}'
return '[' + ','.join(dumps(value) for value in obj) + ']'
loads = eval
else:
class NDArrayEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.ndarray):
return obj.tolist()
return json.JSONEncoder.default(self, obj)
dumps = NDArrayEncoder().encode
loads = json.loads
def numpyfy(obj):
if isinstance(obj, dict):
return dict((key, numpyfy(value)) for key, value in obj.items())
if isinstance(obj, list):
try:
obj = np.array(obj)
except ValueError:
obj = [numpyfy(value) for value in obj]
return obj
def write_json(name, atoms, results):
if world.rank == 0:
fd = open(name + '.json', 'w')
fd.write(dumps(results))
fd.close()
def read_json(name):
fd = open(name + '.json', 'r')
results = loads(fd.read())
fd.close()
return numpyfy(results)
python-ase-3.6.0.2515/ase/quaternions.py 0000644 0001754 0001754 00000007466 11672655157 016726 0 ustar askhl askhl import numpy as np
from ase.atoms import Atoms
class Quaternions(Atoms):
def __init__(self, *args, **kwargs):
quaternions = None
if 'quaternions' in kwargs:
quaternions = np.array(kwargs['quaternions'])
del kwargs['quaternions']
Atoms.__init__(self, *args, **kwargs)
if quaternions is not None:
self.set_array('quaternions', quaternions, shape=(4,))
# set default shapes
self.set_shapes(np.array([[5, 3, 1]] * len(self)))
def set_shapes(self, shapes):
self.set_array('shapes', shapes, shape=(3,))
def set_quaternions (self, quaternions):
self.set_array('quaternions', quaternions, quaternion=(4,))
def get_shapes(self):
return self.get_array('shapes')
def get_quaternions(self):
return self.get_array('quaternions')
class Quaternion:
def __init__(self, qin=[1, 0, 0, 0]):
assert(len(qin) == 4)
self.q = np.array(qin)
def __str__(self):
return self.q.__str__()
def __mult__(self, other):
sw, sx, sy, sz = self.q[0], self.q[1], self.q[2], self.q[3]
ow, ox, oy, oz = other.q[0], other.q[1], other.q[2], other.q[3]
return Quaternion([sw*ow - sx*ox - sy*oy - sz*oz,
sw*ox + sx*ow + sy*oz - sz*oy,
sw*oy + sy*ow + sz*ox - sx*oz,
sw*oz + sz*ow + sx*oy - sy*ox])
def conjugate(self):
return Quaternion(-self.q * np.array([-1., 1., 1., 1.]))
def rotate(self, vector):
"""Apply the rotation matrix to a vector."""
qw, qx, qy, qz = self.q[0], self.q[1], self.q[2], self.q[3]
x, y, z = vector[0], vector[1], vector[2]
ww = qw * qw
xx = qx * qx
yy = qy * qy
zz = qz * qz
wx = qw * qx
wy = qw * qy
wz = qw * qz
xy = qx * qy
xz = qx * qz
yz = qy * qz
return np.array([
(ww + xx - yy - zz) * x + 2 * ((xy - wz) * y + (xz + wy) * z),
(ww - xx + yy - zz) * y + 2 * ((xy + wz) * x + (yz - wx) * z),
(ww - xx - yy + zz) * z + 2 * ((xz - wy) * x + (yz + wx) * y)
])
def rotation_matrix(self):
qw, qx, qy, qz = self.q[0], self.q[1], self.q[2], self.q[3]
ww = qw * qw
xx = qx * qx
yy = qy * qy
zz = qz * qz
wx = qw * qx
wy = qw * qy
wz = qw * qz
xy = qx * qy
xz = qx * qz
yz = qy * qz
return np.array([[ww + xx - yy - zz , 2 * (xy + wz), 2 * (xz - wy)],
[2*(xy - wz), ww - xx + yy - zz, 2*(yz + wx)],
[2*(xz + wy), 2*(yz - wx), ww - xx - yy + zz]
])
def rotate_byq(self, q, vector):
"""Apply the rotation matrix to a vector."""
qw, qx, qy, qz = q[0], q[1], q[2], q[3]
x, y, z = vector[0], vector[1], vector[2]
ww = qw * qw
xx = qx * qx
yy = qy * qy
zz = qz * qz
wx = qw * qx
wy = qw * qy
wz = qw * qz
xy = qx * qy
xz = qx * qz
yz = qy * qz
return np.array([
(ww + xx - yy - zz) * x + 2 * ((xy - wz) * y + (xz + wy) * z),
(ww - xx + yy - zz) * y + 2 * ((xy + wz) * x + (yz - wx) * z),
(ww - xx - yy + zz) * z + 2 * ((xz - wy) * x + (yz + wx) * y)
])
def from_matrix(self, matrix):
"""Build quaternion from rotation matrix."""
m = np.array(matrix)
assert m.shape == (3, 3)
qw = np.sqrt(1 + m[0, 0] + m[1, 1] + m[2, 2]) / 2.
qx = (m[2, 1] - m[1, 2]) / (4 * qw)
qy = (m[0, 2] - m[2, 0]) / (4 *qw)
qz = (m[1, 0] - m[0, 1]) / (4 *qw)
self.q = np.array([qw, qx, qy, qz])
return self
python-ase-3.6.0.2515/ase/gui/ 0000755 0001754 0001754 00000000000 11757245036 014546 5 ustar askhl askhl python-ase-3.6.0.2515/ase/gui/status.py 0000644 0001754 0001754 00000006755 11711330540 016441 0 ustar askhl askhl # -*- coding: utf-8 -*-
from math import sqrt, pi, acos
import gtk
import numpy as np
from ase.data import chemical_symbols as symbols
from ase.data import atomic_names as names
from ase.gui.widgets import pack
from gettext import gettext as _
def formula(Z):
hist = {}
for z in Z:
if z in hist:
hist[z] += 1
else:
hist[z] = 1
text = ''
Z = hist.keys()
Z.sort()
for z in Z:
text += symbols[z]
n = hist[z]
if n > 1:
text += '%d' % n
return text
class Status:
def __init__(self, vbox):
self.eventbox = gtk.EventBox()
self.label = gtk.Label()
self.eventbox.add(self.label)
self.label.show()
if gtk.pygtk_version < (2, 12):
self.set_tip(self.eventbox, _('Tip for status box ...'))
else:
self.eventbox.set_tooltip_text(_('Tip for status box ...'))
pack(vbox, self.eventbox)
self.ordered_indices = []
def status(self):
# use where here: XXX
indices = np.arange(self.images.natoms)[self.images.selected]
ordered_indices = self.images.selected_ordered
n = len(indices)
self.nselected = n
if n == 0:
self.label.set_text('')
return
Z = self.images.Z[indices]
R = self.R[indices]
if n == 1:
tag = self.images.T[self.frame,indices][0]
mom = self.images.M[self.frame][indices]
text = (u' #%d %s (%s): %.3f Ã…, %.3f Ã…, %.3f Ã… ' %
((indices[0], names[Z[0]], symbols[Z[0]]) + tuple(R[0])))
# TRANSLATORS: mom refers to magnetic moment
text += _(' tag=%(tag)s mom=%(mom)1.2f') % dict(tag=tag, mom=mom)
elif n == 2:
D = R[0] - R[1]
d = sqrt(np.dot(D, D))
text = u' %s-%s: %.3f Ã…' % (symbols[Z[0]], symbols[Z[1]], d)
elif n == 3:
d = []
for c in range(3):
D = R[c] - R[(c + 1) % 3]
d.append(np.dot(D, D))
a = []
for c in range(3):
t1 = 0.5 * (d[c] + d[(c + 1) % 3] - d[(c + 2) % 3])
t2 = sqrt(d[c] * d[(c + 1) % 3])
try:
t3 = acos(t1 / t2)
except ValueError:
if t1 > 0:
t3 = 0
else:
t3 = pi
a.append(t3 * 180 / pi)
text = (u' %s-%s-%s: %.1f°, %.1f°, %.1f°' %
tuple([symbols[z] for z in Z] + a))
elif len(ordered_indices) == 4:
R = self.R[ordered_indices]
Z = self.images.Z[ordered_indices]
a = R[1]-R[0]
b = R[2]-R[1]
c = R[3]-R[2]
bxa = np.cross(b,a)
bxa /= np.sqrt(np.vdot(bxa,bxa))
cxb = np.cross(c,b)
cxb /= np.sqrt(np.vdot(cxb,cxb))
angle = np.vdot(bxa,cxb)
if angle < -1: angle = -1
if angle > 1: angle = 1
angle = np.arccos(angle)
if (np.vdot(bxa,c)) > 0: angle = 2*np.pi-angle
angle = angle*180.0/np.pi
text = (u'%s %s->%s->%s->%s: %.1f°'
% tuple([_('dihedral')] + [symbols[z] for z in Z]+[angle]))
else:
text = ' ' + formula(Z)
self.label.set_markup(text)
if __name__ == '__main__':
import os
os.system('python gui.py')
python-ase-3.6.0.2515/ase/gui/simulation.py 0000644 0001754 0001754 00000012672 11706276516 017315 0 ustar askhl askhl "Base class for simulation windows"
import gtk
from gettext import gettext as _
from ase.gui.widgets import oops, pack, help
from ase import Atoms
from ase.constraints import FixAtoms
class Simulation(gtk.Window):
def __init__(self, gui):
gtk.Window.__init__(self)
self.gui = gui
def packtext(self, vbox, text, label=None):
"Pack an text frame into the window."
pack(vbox, gtk.Label(""))
txtframe = gtk.Frame(label)
txtlbl = gtk.Label(text)
txtframe.add(txtlbl)
txtlbl.show()
pack(vbox, txtframe)
pack(vbox, gtk.Label(""))
def packimageselection(self, outerbox, txt1=_(" (rerun simulation)"),
txt2=_(" (continue simulation)")):
"Make the frame for selecting starting config if more than one."
self.startframe = gtk.Frame(_("Select starting configuration:"))
pack(outerbox, [self.startframe])
vbox = gtk.VBox()
self.startframe.add(vbox)
vbox.show()
self.numconfig_format = _("There are currently %i "
"configurations loaded.")
self.numconfig_label = gtk.Label("")
pack(vbox, [self.numconfig_label])
lbl = gtk.Label(_("Choose which one to use as the "
"initial configuration"))
pack(vbox, [lbl])
self.start_radio_first = gtk.RadioButton(
None, _("The first configuration %s.") % txt1)
pack(vbox, [self.start_radio_first])
self.start_radio_nth = gtk.RadioButton(self.start_radio_first,
_("Configuration number "))
self.start_nth_adj = gtk.Adjustment(0, 0, 1, 1)
self.start_nth_spin = gtk.SpinButton(self.start_nth_adj, 0, 0)
self.start_nth_spin.set_sensitive(False)
pack(vbox, [self.start_radio_nth, self.start_nth_spin])
self.start_radio_last = gtk.RadioButton(self.start_radio_first,
_("The last configuration %s.") % txt2)
self.start_radio_last.set_active(True)
pack(vbox, self.start_radio_last)
self.start_radio_nth.connect("toggled", self.start_radio_nth_toggled)
self.setupimageselection()
def start_radio_nth_toggled(self, widget):
self.start_nth_spin.set_sensitive(self.start_radio_nth.get_active())
def setupimageselection(self):
"Decide if the start image selection frame should be shown."
n = self.gui.images.nimages
if n <= 1:
self.startframe.hide()
else:
self.startframe.show()
if self.start_nth_adj.value >= n:
self.start_nth_adj.value = n-1
self.start_nth_adj.upper = n-1
self.numconfig_label.set_text(self.numconfig_format % (n,))
def getimagenumber(self):
"Get the image number selected in the start image frame."
nmax = self.gui.images.nimages
if nmax <= 1:
return 0
elif self.start_radio_first.get_active():
return 0
elif self.start_radio_nth.get_active():
return self.start_nth_adj.value
else:
assert self.start_radio_last.get_active()
return nmax-1
def makebutbox(self, vbox, helptext=None):
self.buttons = gtk.HButtonBox()
runbut = gtk.Button(_("Run"))
runbut.connect('clicked', self.run)
closebut = gtk.Button(stock=gtk.STOCK_CLOSE)
closebut.connect('clicked', lambda x: self.destroy())
for w in (runbut, closebut):
self.buttons.pack_start(w, 0, 0)
w.show()
if helptext:
helpbut = [help(helptext)]
else:
helpbut = []
pack(vbox, helpbut + [self.buttons], end=True, bottom=True)
def setup_atoms(self):
self.atoms = self.get_atoms()
if self.atoms is None:
return False
try:
self.calculator = self.gui.simulation['calc']
except KeyError:
oops(_("No calculator: Use Calculate/Set Calculator on the menu."))
return False
self.atoms.set_calculator(self.calculator())
return True
def get_atoms(self):
"Make an atoms object from the active image"
images = self.gui.images
if images.natoms < 1:
oops(_("No atoms present"))
return None
n = self.getimagenumber()
natoms = len(images.P[n]) / images.repeat.prod()
constraint = None
if not images.dynamic.all():
constraint = FixAtoms(mask=1-images.dynamic)
return Atoms(positions=images.P[n,:natoms],
symbols=images.Z[:natoms],
cell=images.A[n],
magmoms=images.M[n,:natoms],
tags=images.T[n,:natoms],
pbc=images.pbc,
constraint=constraint)
def begin(self, **kwargs):
if self.gui.simulation.has_key('progress'):
self.gui.simulation['progress'].begin(**kwargs)
def end(self):
if self.gui.simulation.has_key('progress'):
self.gui.simulation['progress'].end()
def prepare_store_atoms(self):
"Informs the gui that the next configuration should be the first."
self.gui.prepare_new_atoms()
self.count_steps = 0
def store_atoms(self):
"Observes the minimization and stores the atoms in the gui."
self.gui.append_atoms(self.atoms)
self.count_steps += 1
python-ase-3.6.0.2515/ase/gui/colors.py 0000644 0001754 0001754 00000061012 11715550644 016417 0 ustar askhl askhl # encoding: utf-8
"""colors.py - select how to color the atoms in the GUI."""
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack, cancel_apply_ok, oops, help
import ase
from ase.data.colors import jmol_colors
import numpy as np
import colorsys
named_colors = ('Green', 'Yellow', 'Blue', 'Red', 'Orange', 'Cyan',
'Magenta', 'Black', 'White', 'Grey', 'Violet', 'Brown',
'Navy')
class ColorWindow(gtk.Window):
"A window for selecting how to color the atoms."
def __init__(self, gui):
gtk.Window.__init__(self)
self.gui = gui
self.colormode = gui.colormode
self.actual_colordata = None
self.set_title(_("Colors"))
vbox = gtk.VBox()
self.add(vbox)
vbox.show()
# The main layout consists of two columns, the leftmost split in an upper and lower part.
self.maintable = gtk.Table(2,2)
pack(vbox, self.maintable)
self.methodbox = gtk.VBox()
self.methodbox.show()
self.maintable.attach(self.methodbox, 0, 1, 0, 1)
self.scalebox = gtk.VBox()
self.scalebox.show()
self.maintable.attach(self.scalebox, 0, 1, 1, 2)
self.colorbox = gtk.Frame()
self.colorbox.show()
self.maintable.attach(self.colorbox, 1, 2, 0, 2, gtk.EXPAND)
# Upper left: Choose how the atoms are colored.
lbl = gtk.Label(_("Choose how the atoms are colored:"))
pack(self.methodbox, [lbl])
self.radio_jmol = gtk.RadioButton(None, _('By atomic number, default "jmol" colors'))
self.radio_atno = gtk.RadioButton(self.radio_jmol,
_('By atomic number, user specified'))
self.radio_tag = gtk.RadioButton(self.radio_jmol, _('By tag'))
self.radio_force = gtk.RadioButton(self.radio_jmol, _('By force'))
self.radio_velocity = gtk.RadioButton(self.radio_jmol, _('By velocity'))
self.radio_manual = gtk.RadioButton(self.radio_jmol, _('Manually specified'))
self.radio_same = gtk.RadioButton(self.radio_jmol, _('All the same color'))
self.force_box = gtk.VBox()
self.velocity_box = gtk.VBox()
for widget in (self.radio_jmol, self.radio_atno, self.radio_tag,
self.radio_force, self.force_box, self.radio_velocity,
self.velocity_box, self.radio_manual, self.radio_same):
pack(self.methodbox, [widget])
if isinstance(widget, gtk.RadioButton):
widget.connect('toggled', self.method_radio_changed)
# Now fill in the box for additional information in case the force is used.
self.force_label = gtk.Label(_("This should not be displayed!"))
pack(self.force_box, [self.force_label])
self.force_min = gtk.Adjustment(0.0, 0.0, 100.0, 0.05)
self.force_max = gtk.Adjustment(0.0, 0.0, 100.0, 0.05)
self.force_steps = gtk.Adjustment(10, 2, 500, 1)
force_apply = gtk.Button(_('Update'))
force_apply.connect('clicked', self.set_force_colors)
pack(self.force_box, [gtk.Label(_('Min: ')),
gtk.SpinButton(self.force_min, 10.0, 2),
gtk.Label(_(' Max: ')),
gtk.SpinButton(self.force_max, 10.0, 2),
gtk.Label(_(' Steps: ')),
gtk.SpinButton(self.force_steps, 1, 0),
gtk.Label(' '),
force_apply])
self.force_box.hide()
# Now fill in the box for additional information in case the velocity is used.
self.velocity_label = gtk.Label("This should not be displayed!")
pack(self.velocity_box, [self.velocity_label])
self.velocity_min = gtk.Adjustment(0.0, 0.0, 10.0, 0.005)
self.velocity_max = gtk.Adjustment(0.0, 0.0, 10.0, 0.005)
self.velocity_steps = gtk.Adjustment(10, 2, 500, 1)
velocity_apply = gtk.Button(_('Update'))
velocity_apply.connect('clicked', self.set_velocity_colors)
pack(self.velocity_box, [gtk.Label(_('Min: ')),
gtk.SpinButton(self.velocity_min, 10.0, 3),
gtk.Label(_(' Max: ')),
gtk.SpinButton(self.velocity_max, 10.0, 3),
gtk.Label(_(' Steps: ')),
gtk.SpinButton(self.velocity_steps, 1, 0),
gtk.Label(' '),
velocity_apply])
self.velocity_box.hide()
# Lower left: Create a color scale
pack(self.scalebox, gtk.Label(""))
lbl = gtk.Label(_('Create a color scale:'))
pack(self.scalebox, [lbl])
color_scales = (
_('Black - white'),
_('Black - red - yellow - white'),
_('Black - green - white'),
_('Black - blue - cyan'),
_('Hue'),
_('Named colors')
)
self.scaletype_created = None
self.scaletype = gtk.combo_box_new_text()
for s in color_scales:
self.scaletype.append_text(s)
self.createscale = gtk.Button(_("Create"))
pack(self.scalebox, [self.scaletype, self.createscale])
self.createscale.connect('clicked', self.create_color_scale)
# The actually colors are specified in a box possibly with scrollbars
self.colorwin = gtk.ScrolledWindow()
self.colorwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
self.colorwin.show()
self.colorbox.add(self.colorwin)
self.colorwin.add_with_viewport(gtk.VBox()) # Dummy contents
buts = cancel_apply_ok(cancel=lambda widget: self.destroy(),
apply=self.apply,
ok=self.ok)
pack(vbox, [buts], end=True, bottom=True)
# Make the initial setup of the colors
self.color_errors = {}
self.init_colors_from_gui()
self.show()
gui.register_vulnerable(self)
def notify_atoms_changed(self):
"Called by gui object when the atoms have changed."
self.destroy()
def init_colors_from_gui(self):
cm = self.gui.colormode
# Disallow methods if corresponding data is not available
if not self.gui.images.T.any():
self.radio_tag.set_sensitive(False)
if self.radio_tag.get_active() or cm == 'tag':
self.radio_jmol.set_active(True)
return
else:
self.radio_tag.set_sensitive(True)
if np.isnan(self.gui.images.F).any() or not self.gui.images.F.any():
self.radio_force.set_sensitive(False)
if self.radio_force.get_active() or cm == 'force':
self.radio_jmol.set_active(True)
return
else:
self.radio_force.set_sensitive(True)
if np.isnan(self.gui.images.V).any() or not self.gui.images.V.any():
self.radio_velocity.set_sensitive(False)
if self.radio_velocity.get_active() or cm == 'velocity':
self.radio_jmol.set_active(True)
return
else:
self.radio_velocity.set_sensitive(True)
self.radio_manual.set_sensitive(self.gui.images.natoms <= 1000)
# Now check what the current color mode is
if cm == 'jmol':
self.radio_jmol.set_active(True)
self.set_jmol_colors()
elif cm == 'Z':
self.radio_atno.set_active(True)
elif cm == 'tag':
self.radio_tag.set_active(True)
elif cm == 'force':
self.radio_force.set_active(True)
elif cm == 'velocity':
self.radio_velocity.set_active(True)
elif cm == 'manual':
self.radio_manual.set_active(True)
elif cm == 'same':
self.radio_same.set_active(True)
def method_radio_changed(self, widget=None):
"Called when a radio button is changed."
self.scaletype_created = None
self.scaletype.set_active(-1)
if not widget.get_active():
# Ignore most events when a button is turned off.
if widget is self.radio_force:
self.force_box.hide()
if widget is self.radio_velocity:
self.velocity_box.hide()
return
if widget is self.radio_jmol:
self.set_jmol_colors()
elif widget is self.radio_atno:
self.set_atno_colors()
elif widget is self.radio_tag:
self.set_tag_colors()
elif widget is self.radio_force:
self.show_force_stuff()
self.set_force_colors()
elif widget is self.radio_velocity:
self.show_velocity_stuff()
self.set_velocity_colors()
elif widget is self.radio_manual:
self.set_manual_colors()
elif widget is self.radio_same:
self.set_same_color()
else:
raise RuntimeError('Unknown widget in method_radio_changed')
def make_jmol_colors(self):
"Set the colors to the default jmol colors"
self.colordata_z = []
hasfound = {}
for z in self.gui.images.Z:
if z not in hasfound:
hasfound[z] = True
self.colordata_z.append([z, jmol_colors[z]])
def set_jmol_colors(self):
"We use the immutable jmol colors."
self.make_jmol_colors()
self.set_atno_colors()
for entry in self.color_entries:
entry.set_sensitive(False)
self.colormode = 'jmol'
def set_atno_colors(self):
"We use user-specified per-element colors."
if not hasattr(self, 'colordata_z'):
# No initial colors. Use jmol colors
self.make_jmol_colors()
self.actual_colordata = self.colordata_z
self.color_labels = ["%i (%s):" % (z, ase.data.chemical_symbols[z])
for z, col in self.colordata_z]
self.make_colorwin()
self.colormode = "atno"
def set_tag_colors(self):
"We use per-tag colors."
# Find which tags are in use
tags = self.gui.images.T
existingtags = []
for t in range(tags.min(), tags.max()+1):
if t in tags:
existingtags.append(t)
if not hasattr(self, 'colordata_tags') or len(self.colordata_tags) != len(existingtags):
colors = self.get_named_colors(len(existingtags))
self.colordata_tags = [[x, y] for x, y in
zip(existingtags, colors)]
self.actual_colordata = self.colordata_tags
self.color_labels = [str(x)+':' for x, y in self.colordata_tags]
self.make_colorwin()
self.colormode = 'tags'
def set_same_color(self):
"All atoms have the same color"
if not hasattr(self, 'colordata_same'):
try:
self.colordata_same = self.actual_colordata[0:1]
except AttributeError:
self.colordata_same = self.get_named_colors(1)
self.actual_colordata = self.colordata_same
self.actual_colordata[0][0] = 0
self.color_labels = ['all:']
self.make_colorwin()
self.colormode = 'same'
def set_force_colors(self, *args):
"Use the forces as basis for the colors."
borders = np.linspace(self.force_min.value,
self.force_max.value,
self.force_steps.value,
endpoint=False)
if self.scaletype_created is None:
colors = self.new_color_scale([[0, [1,1,1]],
[1, [0,0,1]]], len(borders))
elif (not hasattr(self, 'colordata_force') or
len(self.colordata_force) != len(borders)):
colors = self.get_color_scale(len(borders), self.scaletype_created)
else:
colors = [y for x, y in self.colordata_force]
self.colordata_force = [[x, y] for x, y in zip(borders, colors)]
self.actual_colordata = self.colordata_force
self.color_labels = ["%.2f:" % x for x, y in self.colordata_force]
self.make_colorwin()
self.colormode = 'force'
fmin = self.force_min.value
fmax = self.force_max.value
factor = self.force_steps.value / (fmax -fmin)
self.colormode_force_data = (fmin, factor)
def set_velocity_colors(self, *args):
"Use the velocities as basis for the colors."
borders = np.linspace(self.velocity_min.value,
self.velocity_max.value,
self.velocity_steps.value,
endpoint=False)
if self.scaletype_created is None:
colors = self.new_color_scale([[0, [1,1,1]],
[1, [1,0,0]]], len(borders))
elif (not hasattr(self, 'colordata_velocity') or
len(self.colordata_velocity) != len(borders)):
colors = self.get_color_scale(len(borders), self.scaletype_created)
else:
colors = [y for x, y in self.colordata_velocity]
self.colordata_velocity = [[x, y] for x, y in zip(borders, colors)]
self.actual_colordata = self.colordata_velocity
self.color_labels = ["%.2f:" % x for x, y in self.colordata_velocity]
self.make_colorwin()
self.colormode = 'velocity'
vmin = self.velocity_min.value
vmax = self.velocity_max.value
factor = self.velocity_steps.value / (vmax -vmin)
self.colormode_velocity_data = (vmin, factor)
def set_manual_colors(self):
"Set colors of all atoms from the last selection."
# We cannot directly make np.arrays of the colors, as they may
# be sequences of the same length, causing creation of a 2D
# array of characters/numbers instead of a 1D array of
# objects.
colors = np.array([None] * self.gui.images.natoms)
if self.colormode in ['atno', 'jmol', 'tags']:
maxval = max([x for x, y in self.actual_colordata])
oldcolors = np.array([None] * (maxval+1))
for x, y in self.actual_colordata:
oldcolors[x] = y
if self.colormode == 'tags':
colors[:] = oldcolors[self.gui.images.T[self.gui.frame]]
else:
colors[:] = oldcolors[self.gui.images.Z]
elif self.colormode == 'force':
oldcolors = np.array([None] * len(self.actual_colordata))
oldcolors[:] = [y for x, y in self.actual_colordata]
F = self.gui.images.F[self.gui.frame]
F = np.sqrt((F * F).sum(axis=-1))
nF = (F - self.colormode_force_data[0]) * self.colormode_force_data[1]
nF = np.clip(nF.astype(int), 0, len(oldcolors)-1)
colors[:] = oldcolors[nF]
elif self.colormode == 'velocity':
oldcolors = np.array([None] * len(self.actual_colordata))
oldcolors[:] = [y for x, y in self.actual_colordata]
V = self.gui.images.V[self.gui.frame]
V = np.sqrt((V * V).sum(axis=-1))
nV = (V - self.colormode_velocity_data[0]) * self.colormode_velocity_data[1]
nV = np.clip(nV.astype(int), 0, len(oldcolors)-1)
colors[:] = oldcolors[nV]
elif self.colormode == 'same':
oldcolor = self.actual_colordata[0][1]
if len(colors) == len(oldcolor):
# Direct assignment would be e.g. one letter per atom. :-(
colors[:] = [oldcolor] * len(colors)
else:
colors[:] = oldcolor
elif self.colormode == 'manual':
if self.actual_colordata is None: # import colors from gui, if they don't exist already
colors = [y for x,y in self.gui.colordata]
self.color_labels = ["%d:" % i for i in range(len(colors))]
self.actual_colordata = [[i, x] for i, x in enumerate(colors)]
self.make_colorwin()
self.colormode = 'manual'
def show_force_stuff(self):
"Show and update widgets needed for selecting the force scale."
self.force_box.show()
F = np.sqrt(((self.gui.images.F*self.gui.images.dynamic[:,np.newaxis])**2).sum(axis=-1))
fmax = F.max()
nimages = self.gui.images.nimages
assert len(F) == nimages
if nimages > 1:
fmax_frame = self.gui.images.F[self.gui.frame].max()
txt = _("Max force: %.2f (this frame), %.2f (all frames)") % (fmax_frame, fmax)
else:
txt = _("Max force: %.2f.") % (fmax,)
self.force_label.set_text(txt)
if self.force_max.value == 0.0:
self.force_max.value = fmax
def show_velocity_stuff(self):
"Show and update widgets needed for selecting the velocity scale."
self.velocity_box.show()
V = np.sqrt((self.gui.images.V * self.gui.images.V).sum(axis=-1))
vmax = V.max()
nimages = self.gui.images.nimages
assert len(V) == nimages
if nimages > 1:
vmax_frame = self.gui.images.V[self.gui.frame].max()
txt = _("Max velocity: %.2f (this frame), %.2f (all frames)") % (vmax_frame, vmax)
else:
txt = _("Max velocity: %.2f.") % (vmax,)
self.velocity_label.set_text(txt)
if self.velocity_max.value == 0.0:
self.velocity_max.value = vmax
def make_colorwin(self):
"""Make the list of editable color entries.
Uses self.actual_colordata and self.color_labels. Produces self.color_entries.
"""
assert len(self.actual_colordata) == len(self.color_labels)
self.color_entries = []
old = self.colorwin.get_child()
self.colorwin.remove(old)
del old
table = gtk.Table(len(self.actual_colordata)+1, 4)
self.colorwin.add_with_viewport(table)
table.show()
self.color_display = []
for i in range(len(self.actual_colordata)):
lbl = gtk.Label(self.color_labels[i])
entry = gtk.Entry(max=20)
val = self.actual_colordata[i][1]
error = False
if not isinstance(val, str):
assert len(val) == 3
intval = tuple(np.round(65535*np.array(val)).astype(int))
val = "%.3f, %.3f, %.3f" % tuple(val)
clr = gtk.gdk.Color(*intval)
else:
try:
clr = gtk.gdk.color_parse(val)
except ValueError:
error = True
entry.set_text(val)
blob = gtk.EventBox()
space = gtk.Label
space = gtk.Label(" ")
space.show()
blob.add(space)
if error:
space.set_text(_("ERROR"))
else:
blob.modify_bg(gtk.STATE_NORMAL, clr)
table.attach(lbl, 0, 1, i, i+1, yoptions=0)
table.attach(entry, 1, 2, i, i+1, yoptions=0)
table.attach(blob, 2, 3, i, i+1, yoptions=0)
lbl.show()
entry.show()
blob.show()
entry.connect('activate', self.entry_changed, i)
self.color_display.append(blob)
self.color_entries.append(entry)
def entry_changed(self, widget, index):
"""The user has changed a color."""
txt = widget.get_text()
txtfields = txt.split(',')
if len(txtfields) == 3:
self.actual_colordata[index][1] = [float(x) for x in txtfields]
val = tuple([int(65535*float(x)) for x in txtfields])
clr = gtk.gdk.Color(*val)
else:
self.actual_colordata[index][1] = txt
try:
clr = gtk.gdk.color_parse(txt)
except ValueError:
# Cannot parse the color
displ = self.color_display[index]
displ.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('white'))
displ.get_child().set_text(_("ERR"))
self.color_errors[index] = (self.color_labels[index], txt)
return
self.color_display[index].get_child().set_text(" ") # Clear error message
self.color_errors.pop(index, None)
self.color_display[index].modify_bg(gtk.STATE_NORMAL, clr)
def create_color_scale(self, *args):
if self.radio_jmol.get_active():
self.radio_atno.set_active(1)
n = len(self.color_entries)
s = self.scaletype.get_active()
scale = self.get_color_scale(n, s)
self.scaletype_created = s
for i in range(n):
if isinstance(scale[i], str):
self.color_entries[i].set_text(scale[i])
else:
s = "%.3f, %.3f, %.3f" % tuple(scale[i])
self.color_entries[i].set_text(s)
self.color_entries[i].activate()
def get_color_scale(self, n, s):
if s == 0:
# Black - White
scale = self.new_color_scale([[0, [0,0,0]],
[1, [1,1,1]]], n)
elif s == 1:
# Black - Red - Yellow - White (STM colors)
scale = self.new_color_scale([[0, [0,0,0]],
[0.33, [1,0,0]],
[0.67, [1,1,0]],
[1, [1,1,1]]], n)
elif s == 2:
# Black - Green - White
scale = self.new_color_scale([[0, [0,0,0]],
[0.5, [0,0.9,0]],
[0.75, [0.2,1.0,0.2]],
[1, [1,1,1]]], n)
elif s == 3:
# Black - Blue - Cyan
scale = self.new_color_scale([[0, [0,0,0]],
[0.5, [0,0,1]],
[1, [0,1,1]]], n)
elif s == 4:
# Hues
hues = np.linspace(0.0, 1.0, n, endpoint=False)
scale = ["%.3f, %.3f, %.3f" % colorsys.hls_to_rgb(h, 0.5, 1)
for h in hues]
elif s == 5:
# Named colors
scale = self.get_named_colors(n)
else:
scale = None
return scale
def new_color_scale(self, fixpoints, n):
"Create a homogeneous color scale."
x = np.array([a[0] for a in fixpoints], float)
y = np.array([a[1] for a in fixpoints], float)
assert y.shape[1] == 3
res = []
for a in np.linspace(0.0, 1.0, n, endpoint=True):
n = x.searchsorted(a)
if n == 0:
v = y[0] # Before the start
elif n == len(x):
v = x[-1] # After the end
else:
x0 = x[n-1]
x1 = x[n]
y0 = y[n-1]
y1 = y[n]
v = y0 + (y1 - y0) / (x1 - x0) * (a - x0)
res.append(v)
return res
def get_named_colors(self, n):
if n <= len(named_colors):
return named_colors[:n]
else:
return named_colors + ('Black',) * (n - len(named_colors))
def apply(self, *args):
#if self.colormode in ['atno', 'jmol', 'tags']:
# Color atoms according to an integer value number
if self.color_errors:
oops(_("Incorrect color specification"),
"%s: %s" % self.color_errors.values()[0])
return False
colordata = self.actual_colordata
if self.colormode == 'force':
# Use integers instead for border values
colordata = [[i, x[1]] for i, x in enumerate(self.actual_colordata)]
self.gui.colormode_force_data = self.colormode_force_data
if self.colormode == 'velocity':
# Use integers instead for border values
colordata = [[i, x[1]] for i, x in enumerate(self.actual_colordata)]
self.gui.colormode_velocity_data = self.colormode_velocity_data
maxval = max([x for x, y in colordata])
self.gui.colors = [None] * (maxval + 1)
new = self.gui.drawing_area.window.new_gc
alloc = self.gui.colormap.alloc_color
for z, val in colordata:
if isinstance(val, str):
self.gui.colors[z] = new(alloc(val))
else:
clr = tuple([int(65535*x) for x in val])
assert len(clr) == 3
self.gui.colors[z] = new(alloc(*clr))
self.gui.colormode = self.colormode
self.gui.colordata = self.actual_colordata
self.gui.draw()
return True
def cancel(self, *args):
self.destroy()
def ok(self, *args):
if self.apply():
self.destroy()
python-ase-3.6.0.2515/ase/gui/minimize.py 0000644 0001754 0001754 00000012547 11706276516 016753 0 ustar askhl askhl # encoding: utf-8
"Module for performing energy minimization."
import gtk
from gettext import gettext as _
from ase.gui.simulation import Simulation
from ase.gui.widgets import oops, pack, AseGuiCancelException
import ase
import numpy as np
class MinimizeMixin:
minimizers = ('BFGS', 'BFGSLineSearch', 'LBFGS', 'LBFGSLineSearch', 'MDMin', 'FIRE')
def make_minimize_gui(self, box):
self.algo = gtk.combo_box_new_text()
for m in self.minimizers:
self.algo.append_text(m)
self.algo.set_active(0)
self.algo.connect('changed', self.min_algo_specific)
pack(box, [gtk.Label(_("Algorithm: ")), self.algo])
self.fmax = gtk.Adjustment(0.05, 0.00, 10.0, 0.01)
self.fmax_spin = gtk.SpinButton(self.fmax, 0, 3)
lbl = gtk.Label()
lbl.set_markup(_("Convergence criterion: Fmax = "))
pack(box, [lbl, self.fmax_spin])
self.steps = gtk.Adjustment(100, 1, 1000000, 1)
self.steps_spin = gtk.SpinButton(self.steps, 0, 0)
pack(box, [gtk.Label(_("Max. number of steps: ")), self.steps_spin])
# Special stuff for MDMin
lbl = gtk.Label(_("Pseudo time step: "))
self.mdmin_dt = gtk.Adjustment(0.05, 0.0, 10.0, 0.01)
spin = gtk.SpinButton(self.mdmin_dt, 0, 3)
self.mdmin_widgets = [lbl, spin]
pack(box, self.mdmin_widgets)
self.min_algo_specific()
def min_algo_specific(self, *args):
"SHow or hide algorithm-specific widgets."
minimizer = self.minimizers[self.algo.get_active()]
for w in self.mdmin_widgets:
if minimizer == 'MDMin':
w.show()
else:
w.hide()
class Minimize(Simulation, MinimizeMixin):
"Window for performing energy minimization."
def __init__(self, gui):
Simulation.__init__(self, gui)
self.set_title(_("Energy minimization"))
vbox = gtk.VBox()
self.packtext(vbox,
_("Minimize the energy with respect to the positions."))
self.packimageselection(vbox)
pack(vbox, gtk.Label(""))
self.make_minimize_gui(vbox)
pack(vbox, gtk.Label(""))
self.status_label = gtk.Label("")
pack(vbox, [self.status_label])
self.makebutbox(vbox)
vbox.show()
self.add(vbox)
self.show()
self.gui.register_vulnerable(self)
def run(self, *args):
"User has pressed [Run]: run the minimization."
if not self.setup_atoms():
return
fmax = self.fmax.value
steps = self.steps.value
mininame = self.minimizers[self.algo.get_active()]
self.begin(mode="min", algo=mininame, fmax=fmax, steps=steps)
algo = getattr(ase.optimize, mininame)
try:
logger_func = self.gui.simulation['progress'].get_logger_stream
except (KeyError, AttributeError):
logger = None
else:
logger = logger_func() # Don't catch errors in the function.
# Display status message
self.status_label.set_text(_("Running ..."))
self.status_label.modify_fg(gtk.STATE_NORMAL,
gtk.gdk.color_parse('#AA0000'))
while gtk.events_pending():
gtk.main_iteration()
self.prepare_store_atoms()
if mininame == "MDMin":
minimizer = algo(self.atoms, logfile=logger,
dt=self.mdmin_dt.value)
else:
minimizer = algo(self.atoms, logfile=logger)
minimizer.attach(self.store_atoms)
try:
minimizer.run(fmax=fmax, steps=steps)
except AseGuiCancelException:
# Update display to reflect cancellation of simulation.
self.status_label.set_text(_("Minimization CANCELLED after "
"%i steps.")
% (self.count_steps,))
self.status_label.modify_fg(gtk.STATE_NORMAL,
gtk.gdk.color_parse('#AA4000'))
except MemoryError:
self.status_label.set_text(_("Out of memory, consider using "
"LBFGS instead"))
self.status_label.modify_fg(gtk.STATE_NORMAL,
gtk.gdk.color_parse('#AA4000'))
else:
# Update display to reflect succesful end of simulation.
self.status_label.set_text(_("Minimization completed in %i steps.")
% (self.count_steps,))
self.status_label.modify_fg(gtk.STATE_NORMAL,
gtk.gdk.color_parse('#007700'))
self.end()
if self.count_steps:
# Notify other windows that atoms have changed.
# This also notifies this window!
self.gui.notify_vulnerable()
# Open movie window and energy graph
if self.gui.images.nimages > 1:
self.gui.movie()
assert not np.isnan(self.gui.images.E[0])
if not self.gui.plot_graphs_newatoms():
expr = 'i, e - E[-1]'
self.gui.plot_graphs(expr=expr)
def notify_atoms_changed(self):
"When atoms have changed, check for the number of images."
self.setupimageselection()
python-ase-3.6.0.2515/ase/gui/constraints.py 0000644 0001754 0001754 00000002757 11706276516 017503 0 ustar askhl askhl #!/usr/bin/env python
from math import sqrt
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack, Help
class Constraints(gtk.Window):
def __init__(self, gui):
gtk.Window.__init__(self)
self.set_title(_('Constraints'))
vbox = gtk.VBox()
b = pack(vbox, [gtk.Button(_('Constrain')),
gtk.Label(_(' selected atoms'))])[0]
b.connect('clicked', self.selected)
b = pack(vbox, [gtk.Button(_('Constrain')),
gtk.Label(_(' immobile atoms:'))])[0]
b.connect('clicked', self.immobile)
b = pack(vbox, [gtk.Button(_('Unconstrain')),
gtk.Label(_(' selected atoms:'))])[0]
b.connect('clicked', self.unconstrain)
b = pack(vbox, gtk.Button(_('Clear constraints')))
b.connect('clicked', self.clear)
close = pack(vbox, gtk.Button(_('Close')))
close.connect('clicked', lambda widget: self.destroy())
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
def selected(self, button):
self.gui.images.dynamic[self.gui.images.selected] = False
self.gui.draw()
def unconstrain(self, button):
self.gui.images.dynamic[self.gui.images.selected] = True
self.gui.draw()
def immobile(self, button):
self.gui.images.set_dynamic()
self.gui.draw()
def clear(self, button):
self.gui.images.dynamic[:] = True
self.gui.draw()
python-ase-3.6.0.2515/ase/gui/bulk_modulus.py 0000644 0001754 0001754 00000002024 11207220276 017610 0 ustar askhl askhl # -*- coding: utf-8 -*-
from math import sqrt
import numpy as np
from ase.units import kJ
from ase.utils.eos import EquationOfState
def BulkModulus(images):
v = np.array([abs(np.linalg.det(A)) for A in images.A])
#import matplotlib.pyplot as plt
import pylab as plt
plt.ion()
EquationOfState(v, images.E).plot()
"""
fit = np.poly1d(np.polyfit(v**-(1.0 / 3), images.E, 3))
fit1 = np.polyder(fit, 1)
fit2 = np.polyder(fit1, 1)
for t in np.roots(fit1):
if t > 0 and fit2(t) > 0:
break
v0 = t**-3
e0 = fit(t)
B = t**5 * fit2(t) / 9 / kJ * 1.0e24 # Gpa
import pylab
import matplotlib
#matplotlib.use('GTK')
pylab.ion()
x = 3.95
pylab.figure(figsize=(x * 2.5**0.5, x))
pylab.plot(v, images.E, 'o')
x = np.linspace(min(v), max(v), 100)
pylab.plot(x, fit(x**-(1.0 / 3)), '-r')
pylab.xlabel(u'volume [Ã…^3]')
pylab.ylabel(u'energy [eV]')
pylab.title(u'E: %.3f eV, V: %.3f Ã…^3, B: %.3f GPa' % (e0, v0, B))
pylab.show()
"""
python-ase-3.6.0.2515/ase/gui/__init__.py 0000644 0001754 0001754 00000000000 10761014616 016635 0 ustar askhl askhl python-ase-3.6.0.2515/ase/gui/execute.py 0000644 0001754 0001754 00000032563 11706276516 016574 0 ustar askhl askhl #!/usr/bin/env python
import __future__
import gtk
from gettext import gettext as _
import os.path
import numpy as np
import sys
from ase.gui.widgets import pack, Help
from ase.data.colors import jmol_colors
from ase.atoms import Atoms
class Execute(gtk.Window):
""" The Execute class provides an expert-user window for modification
and evaluation of system properties with a simple one-line command structure.
There are two types of commands, one set only applies to the global image and
one set applies to all atoms. If the command line contains any of the atom
commands, then it is executed separately for all atoms and for all images.
Otherwise it is executed only once per image.
Please do not mix global and atom commands."""
terminal_help_txt=_("""
Global commands work on all frames or only on the current frame
- Assignment of a global variable may not reference a local one
- use 'Current frame' switch to switch off application to all frames
e:\t\ttotal energy of one frame
fmax:\tmaximal force in one frame
A:\tunit cell
E:\t\ttotal energy array of all frames
F:\t\tall forces in one frame
M:\tall magnetic moments
R:\t\tall atomic positions
S:\tall selected atoms (boolean array)
D:\tall dynamic atoms (boolean array)
examples: frame = 1, A[0][1] += 4, e-E[-1]
Atom commands work on each atom (or a selection) individually
- these can use global commands on the RHS of an equation
- use 'selected atoms only' to restrict application of command
x,y,z:\tatomic coordinates
r,g,b:\tatom display color, range is [0..1]
rad:\tatomic radius for display
s:\t\tatom is selected
d:\t\tatom is movable
f:\t\tforce
Z:\tatomic number
m:\tmagnetic moment
examples: x -= A[0][0], s = z > 5, Z = 6
Special commands and objects:
sa,cf:\t(un)restrict to selected atoms/current frame
frame:\tframe number
center:\tcenters the system in its existing unit cell
del S:\tdelete selection
CM:\tcenter of mass
ans[-i]:\tith last calculated result
exec file: executes commands listed in file
cov[Z]:(read only): covalent radius of atomic number Z
gui:\tadvanced: ag window python object
img:\tadvanced: ag images object
""")
def __init__(self, gui):
gtk.Window.__init__(self)
self.gui = gui
self.set_title(_('Expert user mode'))
vbox = gtk.VBox()
vbox.set_border_width(5)
self.sw = gtk.ScrolledWindow()
self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.textview = gtk.TextView()
self.textbuffer = self.textview.get_buffer()
self.textview.set_editable(False)
self.textview.set_cursor_visible(False)
self.sw.add(self.textview)
pack(vbox, self.sw, expand=True, padding = 5)
self.sw.set_size_request(540, 150)
self.textview.show()
self.add_text(_('Welcome to the ASE Expert user mode'))
self.cmd = gtk.Entry(60)
self.cmd.connect('activate', self.execute)
self.cmd.connect('key-press-event', self.update_command_buffer)
pack(vbox, [gtk.Label('>>>'),self.cmd])
self.cmd_buffer = getattr(gui,'expert_mode_buffer',[''])
self.cmd_position = len(self.cmd_buffer)-1
self.selected = gtk.CheckButton(_('Only selected atoms (sa) '))
self.selected.connect('toggled',self.selected_changed)
self.images_only = gtk.CheckButton(_('Only current frame (cf) '))
self.images_only.connect('toggled',self.images_changed)
pack(vbox, [self.selected, self.images_only])
save_button = gtk.Button(stock=gtk.STOCK_SAVE)
save_button.connect('clicked',self.save_output)
help_button = gtk.Button(stock=gtk.STOCK_HELP)
help_button.connect('clicked',self.terminal_help,"")
stop_button = gtk.Button(stock=gtk.STOCK_STOP)
stop_button.connect('clicked',self.stop_execution)
self.stop = False
pack(vbox, [gtk.Label(_('Global: Use A, D, E, M, N, R, S, n, frame;'
' Atoms: Use a, f, m, s, x, y, z, Z ')),
stop_button, help_button, save_button], end = True)
self.add(vbox)
vbox.show()
self.show()
# set color mode to manual when opening this window for rgb manipulation
self.colors = self.gui.get_colors()
rgb_data = self.gui.get_colors(rgb = True)
self.rgb_data = [] # ensure proper format of rgb_data
for i, rgb in enumerate(rgb_data):
self.rgb_data += [[i, rgb]]
self.gui.colordata = self.rgb_data
self.gui.colors = list(self.colors)
self.gui.colormode = 'manual'
self.cmd.grab_focus()
def execute(self, widget=None, cmd = None):
global_commands = ['A','Col','D','e','E','F','frame','M','n','N','R','S'] # explicitly 'implemented' commands for use on whole system or entire single frame
index_commands = ['a','b','d','f','g','m','r','rad','s','x','y','z','Z'] # commands for use on all (possibly selected) atoms
new = self.gui.drawing_area.window.new_gc
alloc = self.gui.colormap.alloc_color
self.stop = False
if cmd is None:
cmd = self.cmd.get_text().strip()
if len(cmd) == 0:
return
self.add_text('>>> '+cmd)
self.cmd_buffer[-1] = cmd
self.cmd_buffer += ['']
setattr(self.gui,'expert_mode_buffer', self.cmd_buffer)
self.cmd_position = len(self.cmd_buffer)-1
self.cmd.set_text('')
else:
self.add_text('--> '+cmd)
gui = self.gui
img = gui.images
frame = gui.frame
N = img.nimages
n = img.natoms
S = img.selected
D = img.dynamic[:, np.newaxis]
E = img.E
if self.selected.get_active():
indices = np.where(S)[0]
else:
indices = range(n)
ans = getattr(gui,'expert_mode_answers',[])
loop_images = range(N)
if self.images_only.get_active():
loop_images = [self.gui.frame]
# split off the first valid command in cmd to determine whether
# it is global or index based, this includes things such as 4*z and z*4
index_based = False
first_command = cmd.split()[0]
special = ['=',',','+','-','/','*',';','.','[',']','(',')',
'{','}','0','1','2','3','4','5','6','7','8','9']
while first_command[0] in special and len(first_command)>1:
first_command = first_command[1:]
for c in special:
if c in first_command:
first_command = first_command[:first_command.find(c)]
for c in index_commands:
if c == first_command:
index_based = True
name = os.path.expanduser('~/.ase/'+cmd)
# check various special commands:
if os.path.exists(name): # run script from default directory
self.run_script(name)
elif cmd == 'del S': # delete selection
gui.delete_selected_atoms()
elif cmd == 'sa': # selected atoms only
self.selected.set_active(not self.selected.get_active())
elif cmd == 'cf': # current frame only
self.images_only.set_active(not self.images_only.get_active())
elif cmd == 'center': # center system
img.center()
elif cmd == 'CM': # calculate center of mass
for i in loop_images:
if self.stop:
break
atoms = Atoms(positions=img.P[i][indices],
numbers=img.Z[indices])
self.add_text(repr(atoms.get_center_of_mass()))
ans += [atoms.get_center_of_mass()]
elif first_command == 'exec': # execute script
name = cmd.split()[1]
if '~' in name:
name = os.path.expanduser(name)
if os.path.exists(name):
self.run_script(name)
else:
self.add_text(_('*** WARNING: file does not exist - %s') % name)
else:
code = compile(cmd + '\n', 'execute.py', 'single',
__future__.CO_FUTURE_DIVISION)
if index_based and len(indices) == 0 and self.selected.get_active():
self.add_text(_("*** WARNING: No atoms selected to work with"))
for i in loop_images:
if self.stop:
break
R = img.P[i][indices]
A = img.A[i]
F = img.F[i][indices]
e = img.E[i]
M = img.M[i][indices]
Col = []
cov = img.covalent_radii
for j in indices:
Col += [gui.colordata[j]]
if len(indices) > 0:
fmax = max(((F * D[indices])**2).sum(1)**.5)
else:
fmax = None
frame = gui.frame
if not index_based:
try:
self.add_text(repr(eval(cmd)))
ans += [eval(cmd)]
except:
exec code
gui.set_frame(frame)
if gui.movie_window is not None:
gui.movie_window.frame_number.value = frame
img.selected = S
img.A[i] = A
img.P[i][indices] = R
img.M[i][indices] = M
else:
for n,a in enumerate(indices):
if self.stop:
break
x, y, z = R[n]
r, g, b = Col[n][1]
d = D[a]
f = np.vdot(F[n]*d,F[n]*d)**0.5
s = S[a]
Z = img.Z[a]
Zold = Z
m = M[n]
rad = img.r[a]
try:
self.add_text(repr(eval(cmd)))
ans += [eval(cmd)]
except:
exec code
S[a] = s
img.P[i][a] = x, y, z
img.Z[a] = Z
img.r[a] = rad
img.dynamic[a] = d
if Z != Zold:
img.r[a] = cov[Z] * 0.89
r,g,b = jmol_colors[Z]
gui.colordata[a] = [a,[r,g,b]]
color = tuple([int(65535*x) for x in [r,g,b]])
gui.colors[a] = new(alloc(*color))
img.M[i][a] = m
setattr(self.gui,'expert_mode_answers', ans)
gui.set_frame(frame,init=True)
def add_text(self,val):
text_end = self.textbuffer.get_end_iter()
self.textbuffer.insert(text_end,val+'\n');
if self.sw.get_vscrollbar() is not None:
scroll = self.sw.get_vscrollbar().get_adjustment()
scroll.set_value(scroll.get_upper())
def selected_changed(self, *args):
if self.selected.get_active():
self.add_text(_('*** Only working on selected atoms'))
else:
self.add_text(_('*** Working on all atoms'))
def images_changed(self, *args):
if self.images_only.get_active():
self.add_text(_('*** Only working on current image'))
else:
self.add_text(_('*** Working on all images'))
def update_command_buffer(self, entry, event, *args):
arrow = {gtk.keysyms.Up: -1, gtk.keysyms.Down: 1}.get(event.keyval, None)
if arrow is not None:
self.cmd_position += arrow
self.cmd_position = max(self.cmd_position,0)
self.cmd_position = min(self.cmd_position,len(self.cmd_buffer)-1)
cmd = self.cmd_buffer[self.cmd_position]
self.cmd.set_text(cmd)
return True
else:
return False
def save_output(self, *args):
chooser = gtk.FileChooserDialog(
_('Save Terminal text ...'), None, gtk.FILE_CHOOSER_ACTION_SAVE,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
save = chooser.run()
if save == gtk.RESPONSE_OK or save == gtk.RESPONSE_SAVE:
filename = chooser.get_filename()
text = self.textbuffer.get_text(self.textbuffer.get_start_iter(),
self.textbuffer.get_end_iter())
fd = open(filename,'w')
fd.write(text)
fd.close()
chooser.destroy()
def run_script(self, name):
commands = open(name,'r').readlines()
for c_parse in commands:
c = c_parse.strip()
if '#' in c:
c = c[:c.find('#')].strip()
if len(c) > 0:
self.execute(cmd = c.strip())
def terminal_help(self,*args):
Help(self.terminal_help_txt)
def stop_execution(self, *args):
self.stop = True
python = execute
python-ase-3.6.0.2515/ase/gui/calculator.py 0000644 0001754 0001754 00000235111 11711330540 017235 0 ustar askhl askhl # encoding: utf-8
"calculator.py - module for choosing a calculator."
import gtk
from gettext import gettext as _
import os
import numpy as np
from copy import copy
from ase.gui.setupwindow import SetupWindow
from ase.gui.progress import DefaultProgressIndicator, GpawProgressIndicator
from ase.gui.widgets import pack, oops, cancel_apply_ok
from ase import Atoms
from ase.data import chemical_symbols
import ase
# Asap and GPAW may be imported if selected.
introtext = _("""\
To make most calculations on the atoms, a Calculator object must first
be associated with it. ASE supports a number of calculators, supporting
different elements, and implementing different physical models for the
interatomic interactions.\
""")
# Informational text about the calculators
lj_info_txt = _("""\
The Lennard-Jones pair potential is one of the simplest
possible models for interatomic interactions, mostly
suitable for noble gasses and model systems.
Interactions are described by an interaction length and an
interaction strength.\
""")
emt_info_txt = _("""\
The EMT potential is a many-body potential, giving a
good description of the late transition metals crystalling
in the FCC crystal structure. The elements described by the
main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and
Au, the Al potential is however not suitable for materials
science application, as the stacking fault energy is wrong.
A number of parameter sets are provided.
Default parameters:
The default EMT parameters, as published in K. W. Jacobsen,
P. Stoltze and J. K. Nørskov, Surf. Sci. 366, 394 (1996).
Alternative Cu, Ag and Au:
An alternative set of parameters for Cu, Ag and Au,
reoptimized to experimental data including the stacking
fault energies by Torben Rasmussen (partly unpublished).
Ruthenium:
Parameters for Ruthenium, as published in J. Gavnholt and
J. Schiøtz, Phys. Rev. B 77, 035404 (2008).
Metallic glasses:
Parameters for MgCu and CuZr metallic glasses. MgCu
parameters are in N. P. Bailey, J. Schiøtz and
K. W. Jacobsen, Phys. Rev. B 69, 144205 (2004).
CuZr in A. Paduraru, A. Kenoufi, N. P. Bailey and
J. Schiøtz, Adv. Eng. Mater. 9, 505 (2007).
""")
aseemt_info_txt = _("""\
The EMT potential is a many-body potential, giving a
good description of the late transition metals crystalling
in the FCC crystal structure. The elements described by the
main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and
Au. In addition, this implementation allows for the use of
H, N, O and C adatoms, although the description of these is
most likely not very good.
This is the ASE implementation of EMT. For large
simulations the ASAP implementation is more suitable; this
implementation is mainly to make EMT available when ASAP is
not installed.
""")
brenner_info_txt = _("""\
The Brenner potential is a reactive bond-order potential for
carbon and hydrocarbons. As a bond-order potential, it takes
into account that carbon orbitals can hybridize in different
ways, and that carbon can form single, double and triple
bonds. That the potential is reactive means that it can
handle gradual changes in the bond order as chemical bonds
are formed or broken.
The Brenner potential is implemented in Asap, based on a
C implentation published at http://www.rahul.net/pcm/brenner/ .
The potential is documented here:
Donald W Brenner, Olga A Shenderova, Judith A Harrison,
Steven J Stuart, Boris Ni and Susan B Sinnott:
"A second-generation reactive empirical bond order (REBO)
potential energy expression for hydrocarbons",
J. Phys.: Condens. Matter 14 (2002) 783-802.
doi: 10.1088/0953-8984/14/4/312
""")
gpaw_info_txt = _("""\
GPAW implements Density Functional Theory using a
Grid-based real-space representation of the wave
functions, and the Projector Augmented Wave
method for handling the core regions.
""")
aims_info_txt = _("""\
FHI-aims is an external package implementing density
functional theory and quantum chemical methods using
all-electron methods and a numeric local orbital basis set.
For full details, see http://www.fhi-berlin.mpg.de/aims/
or Comp. Phys. Comm. v180 2175 (2009). The ASE
documentation contains information on the keywords and
functionalities available within this interface.
""")
aims_pbc_warning_text = _("""\
WARNING:
Your system seems to have more than zero but less than
three periodic dimensions. Please check that this is
really what you want to compute. Assuming full
3D periodicity for this calculator.""")
vasp_info_txt = _("""\
VASP is an external package implementing density
functional functional theory using pseudopotentials
or the projector-augmented wave method together
with a plane wave basis set. For full details, see
http://cms.mpi.univie.ac.at/vasp/vasp/
""")
emt_parameters = (
(_("Default (Al, Ni, Cu, Pd, Ag, Pt, Au)"), None),
(_("Alternative Cu, Ag and Au"), "EMTRasmussenParameters"),
(_("Ruthenium"), "EMThcpParameters"),
(_("CuMg and CuZr metallic glass"), "EMTMetalGlassParameters")
)
class SetCalculator(SetupWindow):
"Window for selecting a calculator."
# List the names of the radio button attributes
radios = ("none", "lj", "emt", "aseemt", "brenner", "gpaw", "aims", "vasp")
# List the names of the parameter dictionaries
paramdicts = ("lj_parameters","gpaw_parameters","aims_parameters",)
# The name used to store parameters on the gui object
classname = "SetCalculator"
def __init__(self, gui):
SetupWindow.__init__(self)
self.set_title(_("Select calculator"))
vbox = gtk.VBox()
# Intoductory text
self.packtext(vbox, introtext)
pack(vbox, [gtk.Label(_("Calculator:"))])
# No calculator (the default)
self.none_radio = gtk.RadioButton(None, _("None"))
pack(vbox, [self.none_radio])
# Lennard-Jones
self.lj_radio = gtk.RadioButton(self.none_radio,
_("Lennard-Jones (ASAP)"))
self.lj_setup = gtk.Button(_("Setup"))
self.lj_info = InfoButton(lj_info_txt)
self.lj_setup.connect("clicked", self.lj_setup_window)
self.pack_line(vbox, self.lj_radio, self.lj_setup, self.lj_info)
# EMT
self.emt_radio = gtk.RadioButton(
self.none_radio, _("EMT - Effective Medium Theory (ASAP)"))
self.emt_setup = gtk.combo_box_new_text()
self.emt_param_info = {}
for p in emt_parameters:
self.emt_setup.append_text(p[0])
self.emt_param_info[p[0]] = p[1]
self.emt_setup.set_active(0)
self.emt_info = InfoButton(emt_info_txt)
self.pack_line(vbox, self.emt_radio, self.emt_setup, self.emt_info)
# EMT (ASE implementation)
self.aseemt_radio = gtk.RadioButton(
self.none_radio, _("EMT - Effective Medium Theory (ASE)"))
self.aseemt_info = InfoButton(aseemt_info_txt)
self.pack_line(vbox, self.aseemt_radio, None, self.aseemt_info)
# Brenner potential
self.brenner_radio = gtk.RadioButton(
self.none_radio, _("Brenner Potential (ASAP)"))
self.brenner_info = InfoButton(brenner_info_txt)
self.pack_line(vbox, self.brenner_radio, None, self.brenner_info)
# GPAW
self.gpaw_radio = gtk.RadioButton(self.none_radio,
_("Density Functional Theory (GPAW)")
)
self.gpaw_setup = gtk.Button(_("Setup"))
self.gpaw_info = InfoButton(gpaw_info_txt)
self.gpaw_setup.connect("clicked", self.gpaw_setup_window)
self.pack_line(vbox, self.gpaw_radio, self.gpaw_setup, self.gpaw_info)
# FHI-aims
self.aims_radio = gtk.RadioButton(self.none_radio,
_("Density Functional Theory "
"(FHI-aims)"))
self.aims_setup = gtk.Button(_("Setup"))
self.aims_info = InfoButton(aims_info_txt)
self.aims_setup.connect("clicked", self.aims_setup_window)
self.pack_line(vbox, self.aims_radio, self.aims_setup, self.aims_info)
# VASP
self.vasp_radio = gtk.RadioButton(self.none_radio,
_("Density Functional Theory "
"(VASP)"))
self.vasp_setup = gtk.Button(_("Setup"))
self.vasp_info = InfoButton(vasp_info_txt)
self.vasp_setup.connect("clicked", self.vasp_setup_window)
self.pack_line(vbox, self.vasp_radio, self.vasp_setup, self.vasp_info)
# Buttons etc.
pack(vbox, gtk.Label(""))
buts = cancel_apply_ok(cancel=lambda widget: self.destroy(),
apply=self.apply,
ok=self.ok)
pack(vbox, [buts], end=True, bottom=True)
self.check = gtk.CheckButton(_("Check that the calculator is "
"reasonable."))
self.check.set_active(True)
fr = gtk.Frame()
fr.add(self.check)
fr.show_all()
pack(vbox, [fr], end=True, bottom=True)
# Finalize setup
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
self.load_state()
def pack_line(self, box, radio, setup, info):
hbox = gtk.HBox()
hbox.pack_start(radio, 0, 0)
hbox.pack_start(gtk.Label(" "), 0, 0)
hbox.pack_end(info, 0, 0)
if setup is not None:
radio.connect("toggled", self.radio_toggled, setup)
setup.set_sensitive(False)
hbox.pack_end(setup, 0, 0)
hbox.show_all()
box.pack_start(hbox, 0, 0)
def radio_toggled(self, radio, button):
button.set_sensitive(radio.get_active())
def lj_setup_window(self, widget):
if not self.get_atoms():
return
lj_param = getattr(self, "lj_parameters", None)
LJ_Window(self, lj_param, "lj_parameters")
# When control is retuned, self.lj_parameters has been set.
def gpaw_setup_window(self, widget):
if not self.get_atoms():
return
gpaw_param = getattr(self, "gpaw_parameters", None)
GPAW_Window(self, gpaw_param, "gpaw_parameters")
# When control is retuned, self.gpaw_parameters has been set.
def aims_setup_window(self, widget):
if not self.get_atoms():
return
aims_param = getattr(self, "aims_parameters", None)
AIMS_Window(self, aims_param, "aims_parameters")
# When control is retuned, self.aims_parameters has been set.
def vasp_setup_window(self, widget):
if not self.get_atoms():
return
vasp_param = getattr(self, "vasp_parameters", None)
VASP_Window(self, vasp_param, "vasp_parameters")
# When control is retuned, self.vasp_parameters has been set.
def get_atoms(self):
"Make an atoms object from the active frame"
images = self.gui.images
frame = self.gui.frame
if images.natoms < 1:
oops(_("No atoms present"))
return False
self.atoms = Atoms(positions=images.P[frame],
symbols=images.Z,
cell=images.A[frame],
pbc=images.pbc,
magmoms=images.M[frame])
if not images.dynamic.all():
from ase.constraints import FixAtoms
self.atoms.set_constraint(FixAtoms(mask=1-images.dynamic))
return True
def apply(self, *widget):
if self.do_apply():
self.save_state()
return True
else:
return False
def do_apply(self):
nochk = not self.check.get_active()
self.gui.simulation["progress"] = DefaultProgressIndicator()
if self.none_radio.get_active():
self.gui.simulation['calc'] = None
return True
elif self.lj_radio.get_active():
if nochk or self.lj_check():
self.choose_lj()
return True
elif self.emt_radio.get_active():
if nochk or self.emt_check():
self.choose_emt()
return True
elif self.aseemt_radio.get_active():
if nochk or self.aseemt_check():
self.choose_aseemt()
return True
elif self.brenner_radio.get_active():
if nochk or self.brenner_check():
self.choose_brenner()
return True
elif self.gpaw_radio.get_active():
if nochk or self.gpaw_check():
self.choose_gpaw()
return True
elif self.aims_radio.get_active():
if nochk or self.aims_check():
self.choose_aims()
return True
elif self.vasp_radio.get_active():
if nochk or self.vasp_check():
self.choose_vasp()
return True
return False
def ok(self, *widget):
if self.apply():
self.destroy()
def save_state(self):
state = {}
for r in self.radios:
radiobutton = getattr(self, r+"_radio")
if radiobutton.get_active():
state["radio"] = r
state["emtsetup"] = self.emt_setup.get_active()
state["check"] = self.check.get_active()
for p in self.paramdicts:
if hasattr(self, p):
state[p] = getattr(self, p)
self.gui.module_state[self.classname] = state
def load_state(self):
try:
state = self.gui.module_state[self.classname]
except KeyError:
return
r = state["radio"]
radiobutton = getattr(self, r + "_radio")
radiobutton.set_active(True)
self.emt_setup.set_active(state["emtsetup"])
self.check.set_active(state["check"])
for p in self.paramdicts:
if state.has_key(p):
setattr(self, p, state[p])
def lj_check(self):
try:
import asap3
except ImportError:
oops(_("ASAP is not installed. (Failed to import asap3)"))
return False
if not hasattr(self, "lj_parameters"):
oops(_("You must set up the Lennard-Jones parameters"))
return False
try:
self.atoms.set_calculator(asap3.LennardJones(**self.lj_parameters))
except (asap3.AsapError, TypeError, ValueError), e:
oops(_("Could not create useful Lennard-Jones calculator."),
str(e))
return False
return True
def choose_lj(self):
# Define a function on the fly!
import asap3
def lj_factory(p=self.lj_parameters, lj=asap3.LennardJones):
return lj(**p)
self.gui.simulation["calc"] = lj_factory
def emt_get(self):
import asap3
provider_name = self.emt_setup.get_active_text()
provider = self.emt_param_info[provider_name]
if provider is not None:
provider = getattr(asap3, provider)
return (asap3.EMT, provider, asap3)
def emt_check(self):
if not self.get_atoms():
return False
try:
emt, provider, asap3 = self.emt_get()
except ImportError:
oops(_("ASAP is not installed. (Failed to import asap3)"))
return False
try:
if provider is not None:
self.atoms.set_calculator(emt(provider()))
else:
self.atoms.set_calculator(emt())
except (asap3.AsapError, TypeError, ValueError), e:
oops(_("Could not attach EMT calculator to the atoms."),
str(e))
return False
return True
def choose_emt(self):
emt, provider, asap3 = self.emt_get()
if provider is None:
emt_factory = emt
else:
def emt_factory(emt=emt, prov=provider):
return emt(prov())
self.gui.simulation["calc"] = emt_factory
def aseemt_check(self):
return self.element_check("ASE EMT", ['H', 'Al', 'Cu', 'Ag', 'Au',
'Ni', 'Pd', 'Pt', 'C', 'N', 'O'])
def choose_aseemt(self):
self.gui.simulation["calc"] = ase.EMT
ase.EMT.disabled = False # In case Asap has been imported.
def brenner_check(self):
try:
import asap3
except ImportError:
oops(_("ASAP is not installed. (Failed to import asap3)"))
return False
return self.element_check("Brenner potential", ['H', 'C', 'Si'])
def choose_brenner(self):
import asap3
self.gui.simulation["calc"] = asap3.BrennerPotential
def choose_aseemt(self):
self.gui.simulation["calc"] = ase.EMT
ase.EMT.disabled = False # In case Asap has been imported.
def gpaw_check(self):
try:
import gpaw
except ImportError:
oops(_("GPAW is not installed. (Failed to import gpaw)"))
return False
if not hasattr(self, "gpaw_parameters"):
oops(_("You must set up the GPAW parameters"))
return False
return True
def choose_gpaw(self):
# This reuses the same GPAW object.
try:
import gpaw
except ImportError:
oops(_("GPAW is not installed. (Failed to import gpaw)"))
return False
p = self.gpaw_parameters
use = ["xc", "kpts", "mode"]
if p["use_h"]:
use.append("h")
else:
use.append("gpts")
if p["mode"] == "lcao":
use.append("basis")
gpaw_param = {}
for s in use:
gpaw_param[s] = p[s]
if p["use mixer"]:
mx = getattr(gpaw, p["mixer"])
mx_args = {}
mx_arg_n = ["beta", "nmaxold", "weight"]
if p["mixer"] == "MixerDiff":
mx_arg_n.extend(["beta_m", "nmaxold_m", "weight_m"])
for s in mx_arg_n:
mx_args[s] = p[s]
gpaw_param["mixer"] = mx(**mx_args)
progress = GpawProgressIndicator()
self.gui.simulation["progress"] = progress
gpaw_param["txt"] = progress.get_gpaw_stream()
gpaw_calc = gpaw.GPAW(**gpaw_param)
def gpaw_factory(calc = gpaw_calc):
return calc
self.gui.simulation["calc"] = gpaw_factory
def aims_check(self):
if not hasattr(self, "aims_parameters"):
oops(_("You must set up the FHI-aims parameters"))
return False
return True
def choose_aims(self):
param = self.aims_parameters
from ase.calculators.aims import Aims
calc_aims = Aims(**param)
def aims_factory(calc = calc_aims):
return calc
self.gui.simulation["calc"] = aims_factory
def vasp_check(self):
if not hasattr(self, "vasp_parameters"):
oops(_("You must set up the VASP parameters"))
return False
return True
def choose_vasp(self):
param = self.vasp_parameters
from ase.calculators.vasp import Vasp
calc_vasp = Vasp(**param)
def vasp_factory(calc = calc_vasp):
return calc
self.gui.simulation["calc"] = vasp_factory
def element_check(self, name, elements):
"Check that all atoms are allowed"
elements = [ase.data.atomic_numbers[s] for s in elements]
elements_dict = {}
for e in elements:
elements_dict[e] = True
if not self.get_atoms():
return False
try:
for e in self.atoms.get_atomic_numbers():
elements_dict[e]
except KeyError:
oops(_("Element %(sym)s not allowed by the '%(name)s' calculator")
% dict(sym=ase.data.chemical_symbols[e], name=name))
return False
return True
class InfoButton(gtk.Button):
def __init__(self, txt):
gtk.Button.__init__(self, _("Info"))
self.txt = txt
self.connect('clicked', self.run)
def run(self, widget):
dialog = gtk.MessageDialog(flags=gtk.DIALOG_MODAL,
type=gtk.MESSAGE_INFO,
buttons=gtk.BUTTONS_CLOSE)
dialog.set_markup(self.txt)
dialog.connect('response', lambda x, y: dialog.destroy())
dialog.show()
class LJ_Window(gtk.Window):
def __init__(self, owner, param, attrname):
gtk.Window.__init__(self)
self.set_title(_("Lennard-Jones parameters"))
self.owner = owner
self.attrname = attrname
atoms = owner.atoms
atnos = atoms.get_atomic_numbers()
found = {}
for z in atnos:
found[z] = True
self.present = found.keys()
self.present.sort() # Sorted list of atomic numbers
nelem = len(self.present)
vbox = gtk.VBox()
label = gtk.Label(_("Specify the Lennard-Jones parameters here"))
pack(vbox, [label])
pack(vbox, gtk.Label(""))
pack(vbox, [gtk.Label(_("Epsilon (eV):"))])
tbl, self.epsilon_adj = self.makematrix(self.present)
pack(vbox, [tbl])
pack(vbox, gtk.Label(""))
pack(vbox, [gtk.Label(_("Sigma (Ã…):"))])
tbl, self.sigma_adj = self.makematrix(self.present)
pack(vbox, [tbl])
# TRANSLATORS: Shift roughly means adjust (about a potential)
self.modif = gtk.CheckButton(_("Shift to make smooth at cutoff"))
self.modif.set_active(True)
pack(vbox, gtk.Label(""))
pack(vbox, self.modif)
pack(vbox, gtk.Label(""))
butbox = gtk.HButtonBox()
cancel_but = gtk.Button(stock=gtk.STOCK_CANCEL)
cancel_but.connect('clicked', lambda widget: self.destroy())
ok_but = gtk.Button(stock=gtk.STOCK_OK)
ok_but.connect('clicked', self.ok)
butbox.pack_start(cancel_but, 0, 0)
butbox.pack_start(ok_but, 0, 0)
butbox.show_all()
pack(vbox, [butbox], end=True, bottom=True)
vbox.show()
self.add(vbox)
# Now, set the parameters
if param and param['elements'] == self.present:
self.set_param(self.epsilon_adj, param["epsilon"], nelem)
self.set_param(self.sigma_adj, param["sigma"], nelem)
self.modif.set_active(param["modified"])
self.show()
self.grab_add() # Lock all other windows
def makematrix(self, present):
nelem = len(present)
adjdict = {}
tbl = gtk.Table(2+nelem, 2+nelem)
for i in range(nelem):
s = chemical_symbols[present[i]]
tbl.attach(gtk.Label(" " + str(present[i])), 0, 1, i, i+1)
tbl.attach(gtk.Label(" "+s+" "), 1, 2, i, i+1)
tbl.attach(gtk.Label(str(present[i])), i+2, i+3, 1+nelem, 2+nelem)
tbl.attach(gtk.Label(s), i+2, i+3, nelem, 1+nelem)
for j in range(i+1):
adj = gtk.Adjustment(1.0, 0.0, 100.0, 0.1)
spin = gtk.SpinButton(adj, 0.1, 3)
tbl.attach(spin, 2+j, 3+j, i, i+1)
adjdict[(i,j)] = adj
tbl.show_all()
return tbl, adjdict
def set_param(self, adj, params, n):
for i in range(n):
for j in range(n):
if j <= i:
adj[(i,j)].value = params[i,j]
def get_param(self, adj, params, n):
for i in range(n):
for j in range(n):
if j <= i:
params[i,j] = params[j,i] = adj[(i,j)].value
def destroy(self):
self.grab_remove()
gtk.Window.destroy(self)
def ok(self, *args):
params = {}
params["elements"] = copy(self.present)
n = len(self.present)
eps = np.zeros((n,n))
self.get_param(self.epsilon_adj, eps, n)
sigma = np.zeros((n,n))
self.get_param(self.sigma_adj, sigma, n)
params["epsilon"] = eps
params["sigma"] = sigma
params["modified"] = self.modif.get_active()
setattr(self.owner, self.attrname, params)
self.destroy()
class GPAW_Window(gtk.Window):
gpaw_xc_list = ['LDA', 'PBE', 'RPBE', 'revPBE']
gpaw_xc_default = 'PBE'
def __init__(self, owner, param, attrname):
gtk.Window.__init__(self)
self.set_title(_("GPAW parameters"))
self.owner = owner
self.attrname = attrname
atoms = owner.atoms
self.ucell = atoms.get_cell()
self.size = tuple([self.ucell[i,i] for i in range(3)])
self.pbc = atoms.get_pbc()
self.orthogonal = self.isorthogonal(self.ucell)
self.natoms = len(atoms)
vbox = gtk.VBox()
#label = gtk.Label("Specify the GPAW parameters here")
#pack(vbox, [label])
# Print some info
txt = _("%i atoms.\n") % (self.natoms,)
if self.orthogonal:
txt += _("Orthogonal unit cell: %.2f x %.2f x %.2f Ã….") % self.size
else:
txt += _("Non-orthogonal unit cell:\n")
txt += str(self.ucell)
pack(vbox, [gtk.Label(txt)])
# XC potential
self.xc = gtk.combo_box_new_text()
for i, x in enumerate(self.gpaw_xc_list):
self.xc.append_text(x)
if x == self.gpaw_xc_default:
self.xc.set_active(i)
pack(vbox, [gtk.Label(_("Exchange-correlation functional: ")),
self.xc])
# Grid spacing
self.radio_h = gtk.RadioButton(None, _("Grid spacing"))
self.h = gtk.Adjustment(0.18, 0.0, 1.0, 0.01)
self.h_spin = gtk.SpinButton(self.h, 0, 2)
pack(vbox, [self.radio_h, gtk.Label(" h = "), self.h_spin,
gtk.Label(_("Ã…"))])
self.radio_gpts = gtk.RadioButton(self.radio_h, _("Grid points"))
self.gpts = []
self.gpts_spin = []
for i in range(3):
g = gtk.Adjustment(4, 4, 1000, 4)
s = gtk.SpinButton(g, 0, 0)
self.gpts.append(g)
self.gpts_spin.append(s)
self.gpts_hlabel = gtk.Label("")
self.gpts_hlabel_format = _("heff = (%.3f, %.3f, %.3f) Ã…")
pack(vbox, [self.radio_gpts, gtk.Label(" gpts = ("), self.gpts_spin[0],
gtk.Label(", "), self.gpts_spin[1], gtk.Label(", "),
self.gpts_spin[2], gtk.Label(") "), self.gpts_hlabel])
self.radio_h.connect("toggled", self.radio_grid_toggled)
self.radio_gpts.connect("toggled", self.radio_grid_toggled)
self.radio_grid_toggled(None)
for g in self.gpts:
g.connect("value-changed", self.gpts_changed)
self.h.connect("value-changed", self.h_changed)
# K-points
self.kpts = []
self.kpts_spin = []
for i in range(3):
if self.pbc[i] and self.orthogonal:
default = np.ceil(20.0 / self.size[i])
else:
default = 1
g = gtk.Adjustment(default, 1, 100, 1)
s = gtk.SpinButton(g, 0, 0)
self.kpts.append(g)
self.kpts_spin.append(s)
if not self.pbc[i]:
s.set_sensitive(False)
g.connect("value-changed", self.k_changed)
pack(vbox, [gtk.Label(_("k-points k = (")), self.kpts_spin[0],
gtk.Label(", "), self.kpts_spin[1], gtk.Label(", "),
self.kpts_spin[2], gtk.Label(")")])
self.kpts_label = gtk.Label("")
self.kpts_label_format = _("k-points x size: (%.1f, %.1f, %.1f) Ã…")
pack(vbox, [self.kpts_label])
self.k_changed()
# Spin polarized
self.spinpol = gtk.CheckButton(_("Spin polarized"))
pack(vbox, [self.spinpol])
pack(vbox, gtk.Label(""))
# Mode and basis functions
self.mode = gtk.combo_box_new_text()
self.mode.append_text(_("FD - Finite Difference (grid) mode"))
self.mode.append_text(_("LCAO - Linear Combination of Atomic "
"Orbitals"))
self.mode.set_active(0)
pack(vbox, [gtk.Label(_("Mode: ")), self.mode])
self.basis = gtk.combo_box_new_text()
self.basis.append_text(_("sz - Single Zeta"))
self.basis.append_text(_("szp - Single Zeta polarized"))
self.basis.append_text(_("dzp - Double Zeta polarized"))
self.basis.set_active(2) # dzp
pack(vbox, [gtk.Label(_("Basis functions: ")), self.basis])
pack(vbox, gtk.Label(""))
self.mode.connect("changed", self.mode_changed)
self.mode_changed()
# Mixer
self.use_mixer = gtk.CheckButton(_("Non-standard mixer parameters"))
pack(vbox, [self.use_mixer])
self.radio_mixer = gtk.RadioButton(None, "Mixer ")
self.radio_mixersum = gtk.RadioButton(self.radio_mixer, "MixerSum ")
self.radio_mixerdiff = gtk.RadioButton(self.radio_mixer, "MixerDiff")
pack(vbox, [self.radio_mixer, self.radio_mixersum,
self.radio_mixerdiff])
self.beta_adj = gtk.Adjustment(0.25, 0.0, 1.0, 0.05)
self.beta_spin = gtk.SpinButton(self.beta_adj, 0, 2)
self.nmaxold_adj = gtk.Adjustment(3, 1, 10, 1)
self.nmaxold_spin = gtk.SpinButton(self.nmaxold_adj, 0, 0)
self.weight_adj = gtk.Adjustment(50, 1, 500, 1)
self.weight_spin = gtk.SpinButton(self.weight_adj, 0, 0)
pack(vbox, [gtk.Label("beta = "), self.beta_spin,
gtk.Label(" nmaxold = "), self.nmaxold_spin,
gtk.Label(" weight = "), self.weight_spin])
self.beta_m_adj = gtk.Adjustment(0.70, 0.0, 1.0, 0.05)
self.beta_m_spin = gtk.SpinButton(self.beta_m_adj, 0, 2)
self.nmaxold_m_adj = gtk.Adjustment(2, 1, 10, 1)
self.nmaxold_m_spin = gtk.SpinButton(self.nmaxold_m_adj, 0, 0)
self.weight_m_adj = gtk.Adjustment(10, 1, 500, 1)
self.weight_m_spin = gtk.SpinButton(self.weight_m_adj, 0, 0)
pack(vbox, [gtk.Label("beta_m = "), self.beta_m_spin,
gtk.Label(" nmaxold_m = "), self.nmaxold_m_spin,
gtk.Label(" weight_m = "), self.weight_m_spin])
for but in (self.spinpol, self.use_mixer, self.radio_mixer,
self.radio_mixersum, self.radio_mixerdiff):
but.connect("clicked", self.mixer_changed)
self.mixer_changed()
# Eigensolver
# Poisson-solver
vbox.show()
self.add(vbox)
# Buttons at the bottom
pack(vbox, gtk.Label(""))
butbox = gtk.HButtonBox()
cancel_but = gtk.Button(stock=gtk.STOCK_CANCEL)
cancel_but.connect('clicked', lambda widget: self.destroy())
ok_but = gtk.Button(stock=gtk.STOCK_OK)
ok_but.connect('clicked', self.ok)
butbox.pack_start(cancel_but, 0, 0)
butbox.pack_start(ok_but, 0, 0)
butbox.show_all()
pack(vbox, [butbox], end=True, bottom=True)
# Set stored parameters
if param:
self.xc.set_active(param["xc#"])
if param["use_h"]:
self.radio_h.set_active(True)
else:
self.radio_gpts.set_active(True)
for i in range(3):
self.gpts[i].value = param["gpts"][i]
self.kpts[i].value = param["kpts"][i]
self.spinpol.set_active(param["spinpol"])
self.mode.set_active(param["mode#"])
self.basis.set_active(param["basis#"])
self.use_mixer.set_active(param["use mixer"])
getattr(self, "radio_" + param["mixer"].lower()).set_active(True)
for t in ("beta", "nmaxold", "weight", "beta_m", "nmaxold_m",
"weight_m"):
getattr(self, t+"_adj").value = param[t]
self.show()
self.grab_add() # Lock all other windows
def radio_grid_toggled(self, widget):
hmode = self.radio_h.get_active()
self.h_spin.set_sensitive(hmode)
for s in self.gpts_spin:
s.set_sensitive(not hmode)
self.gpts_changed()
def gpts_changed(self, *args):
if self.radio_gpts.get_active():
g = np.array([int(g.value) for g in self.gpts])
size = np.array([self.ucell[i,i] for i in range(3)])
txt = self.gpts_hlabel_format % tuple(size / g)
self.gpts_hlabel.set_markup(txt)
else:
self.gpts_hlabel.set_markup("")
def h_changed(self, *args):
h = self.h.value
for i in range(3):
g = 4 * round(self.ucell[i,i] / (4*h))
self.gpts[i].value = g
def k_changed(self, *args):
size = [self.kpts[i].value * np.sqrt(np.vdot(self.ucell[i],
self.ucell[i]))
for i in range(3)]
self.kpts_label.set_text(self.kpts_label_format % tuple(size))
def mode_changed(self, *args):
self.basis.set_sensitive(self.mode.get_active() == 1)
def mixer_changed(self, *args):
radios = (self.radio_mixer, self.radio_mixersum, self.radio_mixerdiff)
spin1 = (self.beta_spin, self.nmaxold_spin, self.weight_spin)
spin2 = (self.beta_m_spin, self.nmaxold_m_spin, self.weight_m_spin)
if self.use_mixer.get_active():
# Mixer parameters can be specified.
if self.spinpol.get_active():
self.radio_mixer.set_sensitive(False)
self.radio_mixersum.set_sensitive(True)
self.radio_mixerdiff.set_sensitive(True)
if self.radio_mixer.get_active():
self.radio_mixersum.set_active(True)
else:
self.radio_mixer.set_sensitive(True)
self.radio_mixersum.set_sensitive(False)
self.radio_mixerdiff.set_sensitive(False)
self.radio_mixer.set_active(True)
if self.radio_mixerdiff.get_active():
active = spin1 + spin2
passive = ()
else:
active = spin1
passive = spin2
for widget in active:
widget.set_sensitive(True)
for widget in passive:
widget.set_sensitive(False)
else:
# No mixer parameters
for widget in radios + spin1 + spin2:
widget.set_sensitive(False)
def isorthogonal(self, matrix):
ortho = True
for i in range(3):
for j in range(3):
if i != j and matrix[i][j] != 0.0:
ortho = False
return ortho
def ok(self, *args):
param = {}
param["xc"] = self.xc.get_active_text()
param["xc#"] = self.xc.get_active()
param["use_h"] = self.radio_h.get_active()
param["h"] = self.h.value
param["gpts"] = [int(g.value) for g in self.gpts]
param["kpts"] = [int(k.value) for k in self.kpts]
param["spinpol"] = self.spinpol.get_active()
param["mode"] = self.mode.get_active_text().split()[0].lower()
param["mode#"] = self.mode.get_active()
param["basis"] = self.basis.get_active_text().split()[0].lower()
param["basis#"] = self.basis.get_active()
param["use mixer"] = self.use_mixer.get_active()
if self.radio_mixer.get_active():
m = "Mixer"
elif self.radio_mixersum.get_active():
m = "MixerSum"
else:
assert self.radio_mixerdiff.get_active()
m = "MixerDiff"
param["mixer"] = m
for t in ("beta", "nmaxold", "weight", "beta_m", "nmaxold_m",
"weight_m"):
param[t] = getattr(self, t+"_adj").value
setattr(self.owner, self.attrname, param)
self.destroy()
class AIMS_Window(gtk.Window):
aims_xc_cluster = ['pw-lda','pz-lda','pbe','pbesol','rpbe','revpbe',
'blyp','am05','b3lyp','hse03','hse06','pbe0','pbesol0',
'hf','mp2']
aims_xc_periodic = ['pw-lda','pz-lda','pbe','pbesol','rpbe','revpbe',
'blyp','am05']
aims_xc_default = 'pbe'
aims_relativity_list = ['none','atomic_zora','zora']
aims_keyword_gui_list = ['xc','vdw_correction_hirshfeld','k_grid','spin','charge','relativistic',
'sc_accuracy_etot','sc_accuracy_eev','sc_accuracy_rho','sc_accuracy_forces',
'compute_forces','run_command','species_dir','default_initial_moment']
def __init__(self, owner, param, attrname):
self.owner = owner
self.attrname = attrname
atoms = owner.atoms
self.periodic = atoms.get_pbc().all()
if not self.periodic and atoms.get_pbc().any():
aims_periodic_warning = True
self.periodic = True
else:
aims_periodic_warning = False
from ase.calculators.aims import float_keys,exp_keys,string_keys,int_keys,bool_keys,list_keys,input_keys
self.aims_keyword_list =float_keys+exp_keys+string_keys+int_keys+bool_keys+list_keys+input_keys
self.expert_keywords = []
natoms = len(atoms)
gtk.Window.__init__(self)
self.set_title(_("FHI-aims parameters"))
vbox = gtk.VBox()
vbox.set_border_width(5)
# Print some info
txt = _("%i atoms.\n") % (natoms)
if self.periodic:
self.ucell = atoms.get_cell()
txt += _("Periodic geometry, unit cell is:\n")
for i in range(3):
txt += "(%8.3f %8.3f %8.3f)\n" % (self.ucell[i][0], self.ucell[i][1], self.ucell[i][2])
self.xc_list = self.aims_xc_periodic
else:
txt += _("Non-periodic geometry.\n")
self.xc_list = self.aims_xc_cluster
pack(vbox, [gtk.Label(txt)])
# XC functional & dispersion correction
self.xc = gtk.combo_box_new_text()
self.xc_setup = False
self.TS = gtk.CheckButton(_("Hirshfeld-based dispersion correction"))
pack(vbox, [gtk.Label(_("Exchange-correlation functional: ")),self.xc])
pack(vbox, [self.TS])
pack(vbox, [gtk.Label("")])
# k-grid?
if self.periodic:
self.kpts = []
self.kpts_spin = []
for i in range(3):
default = np.ceil(20.0 / np.sqrt(np.vdot(self.ucell[i],self.ucell[i])))
g = gtk.Adjustment(default, 1, 100, 1)
s = gtk.SpinButton(g, 0, 0)
self.kpts.append(g)
self.kpts_spin.append(s)
g.connect("value-changed", self.k_changed)
pack(vbox, [gtk.Label(_("k-points k = (")), self.kpts_spin[0],
gtk.Label(", "), self.kpts_spin[1], gtk.Label(", "),
self.kpts_spin[2], gtk.Label(")")])
self.kpts_label = gtk.Label("")
self.kpts_label_format = _("k-points x size: (%.1f, %.1f, %.1f) Ã…")
pack(vbox, [self.kpts_label])
self.k_changed()
pack(vbox, gtk.Label(""))
# Spin polarized, charge, relativity
self.spinpol = gtk.CheckButton(_("Spin / initial moment "))
self.spinpol.connect('toggled',self.spinpol_changed)
self.moment = gtk.Adjustment(0,-100,100,0.1)
self.moment_spin = gtk.SpinButton(self.moment, 0, 0)
self.moment_spin.set_digits(2)
self.moment_spin.set_sensitive(False)
self.charge = gtk.Adjustment(0,-100,100,0.1)
self.charge_spin = gtk.SpinButton(self.charge, 0, 0)
self.charge_spin.set_digits(2)
self.relativity_type = gtk.combo_box_new_text()
for i, x in enumerate(self.aims_relativity_list):
self.relativity_type.append_text(x)
self.relativity_type.connect('changed',self.relativity_changed)
self.relativity_threshold = gtk.Entry(max=8)
self.relativity_threshold.set_text('1.00e-12')
self.relativity_threshold.set_sensitive(False)
pack(vbox, [self.spinpol,
self.moment_spin,
gtk.Label(_(" Charge")),
self.charge_spin,
gtk.Label(_(" Relativity")),
self.relativity_type,
gtk.Label(_(" Threshold")),
self.relativity_threshold])
pack(vbox, gtk.Label(""))
# self-consistency criteria
pack(vbox,[gtk.Label(_("Self-consistency convergence:"))])
self.sc_tot_energy = gtk.Adjustment(1e-6, 1e-6, 1e0, 1e-6)
self.sc_tot_energy_spin = gtk.SpinButton(self.sc_tot_energy, 0, 0)
self.sc_tot_energy_spin.set_digits(6)
self.sc_tot_energy_spin.set_numeric(True)
self.sc_sum_eigenvalue = gtk.Adjustment(1e-3, 1e-6, 1e0, 1e-6)
self.sc_sum_eigenvalue_spin = gtk.SpinButton(self.sc_sum_eigenvalue, 0, 0)
self.sc_sum_eigenvalue_spin.set_digits(6)
self.sc_sum_eigenvalue_spin.set_numeric(True)
self.sc_density = gtk.Adjustment(1e-4, 1e-6, 1e0, 1e-6)
self.sc_density_spin = gtk.SpinButton(self.sc_density, 0, 0)
self.sc_density_spin.set_digits(6)
self.sc_density_spin.set_numeric(True)
self.compute_forces = gtk.CheckButton(_("Compute forces"))
self.compute_forces.set_active(True)
self.compute_forces.connect("toggled", self.compute_forces_toggled,"")
self.sc_forces = gtk.Adjustment(1e-4, 1e-6, 1e0, 1e-6)
self.sc_forces_spin = gtk.SpinButton(self.sc_forces, 0, 0)
self.sc_forces_spin.set_numeric(True)
self.sc_forces_spin.set_digits(6)
# XXX: use gtk table for layout. Spaces will not work well otherwise
# (depend on fonts, widget style, ...)
# TRANSLATORS: Don't care too much about these, just get approximately
# the same string lengths
pack(vbox, [gtk.Label(_("Energy: ")),
self.sc_tot_energy_spin,
gtk.Label(_(" eV Sum of eigenvalues: ")),
self.sc_sum_eigenvalue_spin,
gtk.Label(_(" eV"))])
pack(vbox, [gtk.Label(_("Electron density: ")),
self.sc_density_spin,
gtk.Label(_(" Force convergence: ")),
self.sc_forces_spin,
gtk.Label(_(" eV/Ang "))])
pack(vbox, [self.compute_forces])
pack(vbox, gtk.Label(""))
swin = gtk.ScrolledWindow()
swin.set_border_width(0)
swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.expert_keyword_set = gtk.Entry(max = 55)
self.expert_keyword_add = gtk.Button(stock = gtk.STOCK_ADD)
self.expert_keyword_add.connect("clicked", self.expert_keyword_import)
self.expert_keyword_set.connect("activate", self.expert_keyword_import)
pack(vbox,[gtk.Label(_("Additional keywords: ")),
self.expert_keyword_set,
self.expert_keyword_add])
self.expert_vbox = gtk.VBox()
vbox.pack_start(swin, True, True, 0)
swin.add_with_viewport(self.expert_vbox)
self.expert_vbox.get_parent().set_shadow_type(gtk.SHADOW_NONE)
self.expert_vbox.get_parent().set_size_request(-1, 100)
swin.show()
self.expert_vbox.show()
pack(vbox, gtk.Label(""))
# run command and species defaults:
pack(vbox, gtk.Label(_('FHI-aims execution command: ')))
self.run_command = pack(vbox, gtk.Entry(max=0))
pack(vbox, gtk.Label(_('Directory for species defaults: ')))
self.species_defaults = pack(vbox, gtk.Entry(max=0))
# set defaults from previous instance of the calculator, if applicable:
if param is not None:
self.set_param(param)
else:
self.set_defaults()
# Buttons at the bottom
pack(vbox, gtk.Label(""))
butbox = gtk.HButtonBox()
default_but = gtk.Button(_("Set Defaults"))
default_but.connect("clicked",self.set_defaults)
import_control_but = gtk.Button(_("Import control.in"))
import_control_but.connect("clicked",self.import_control)
export_control_but = gtk.Button(_("Export control.in"))
export_control_but.connect("clicked", self.export_control)
cancel_but = gtk.Button(stock=gtk.STOCK_CANCEL)
cancel_but.connect('clicked', lambda widget: self.destroy())
ok_but = gtk.Button(stock=gtk.STOCK_OK)
ok_but.connect('clicked', self.ok)
butbox.pack_start(default_but, 0, 0)
butbox.pack_start(import_control_but, 0, 0)
butbox.pack_start(export_control_but, 0, 0)
butbox.pack_start(cancel_but, 0, 0)
butbox.pack_start(ok_but, 0, 0)
butbox.show_all()
pack(vbox, [butbox], end=True, bottom=True)
self.expert_vbox.show()
vbox.show()
self.add(vbox)
self.show()
self.grab_add()
if aims_periodic_warning:
oops(aims_pbc_warning_text)
def set_defaults(self, *args):
atoms = self.owner.atoms.copy()
if not self.xc_setup:
self.xc_setup = True
for i, x in enumerate(self.xc_list):
self.xc.append_text(x)
for i, x in enumerate(self.xc_list):
if x == self.aims_xc_default:
self.xc.set_active(i)
self.TS.set_active(False)
if self.periodic:
self.ucell = atoms.get_cell()
for i in range(3):
default = np.ceil(20.0 / np.sqrt(np.vdot(self.ucell[i],self.ucell[i])))
self.kpts_spin[i].set_value(default)
self.spinpol.set_active(False)
self.moment.set_value(0)
self.moment_spin.set_sensitive(False)
self.charge.set_value(0)
aims_relativity_default = 'none'
for a in atoms:
if a.number > 20:
aims_relativity_default = 'atomic_zora'
for i, x in enumerate(self.aims_relativity_list):
if x == aims_relativity_default:
self.relativity_type.set_active(i)
self.sc_tot_energy.set_value(1e-6)
self.sc_sum_eigenvalue.set_value(1e-3)
self.sc_density.set_value(1e-4)
self.sc_forces.set_value(1e-4)
for key in self.expert_keywords:
key[0].destroy()
key[1].destroy()
key[2].destroy()
key[3] = False
for child in self.expert_vbox.children():
self.expert_vbox.remove(child)
if os.environ.has_key('AIMS_COMMAND'):
text = os.environ['AIMS_COMMAND']
else:
text = ""
self.run_command.set_text(text)
if os.environ.has_key('AIMS_SPECIES_DIR'):
text = os.environ['AIMS_SPECIES_DIR']
else:
text = ""
self.species_defaults.set_text(text)
def set_attributes(self, *args):
param = {}
param["xc"] = self.xc.get_active_text()
if self.periodic:
param["k_grid"] = (int(self.kpts[0].value),
int(self.kpts[1].value),
int(self.kpts[2].value))
if self.spinpol.get_active():
param["spin"] = "collinear"
param["default_initial_moment"] = self.moment.get_value()
else:
param["spin"] = "none"
param["default_initial_moment"] = None
param["vdw_correction_hirshfeld"] = self.TS.get_active()
param["charge"] = self.charge.value
param["relativistic"] = self.relativity_type.get_active_text()
if param["relativistic"] == 'atomic_zora':
param["relativistic"] += " scalar "
if param["relativistic"] == 'zora':
param["relativistic"] += " scalar "+self.relativity_threshold.get_text()
param["sc_accuracy_etot"] = self.sc_tot_energy.value
param["sc_accuracy_eev"] = self.sc_sum_eigenvalue.value
param["sc_accuracy_rho"] = self.sc_density.value
param["compute_forces"] = self.compute_forces.get_active()
param["sc_accuracy_forces"] = self.sc_forces.value
param["run_command"] = self.run_command.get_text()
param["species_dir"] = self.species_defaults.get_text()
from ase.calculators.aims import float_keys,exp_keys,string_keys,int_keys,bool_keys,list_keys,input_keys
for option in self.expert_keywords:
if option[3]: # set type of parameter according to which list it is in
key = option[0].get_text().strip()
val = option[1].get_text().strip()
if key == 'output':
if param.has_key('output'):
param[key] += [val]
else:
param[key] = [val]
elif key in float_keys or key in exp_keys:
param[key] = float(val)
elif key in list_keys or key in string_keys or key in input_keys:
param[key] = val
elif key in int_keys:
param[key] = int(val)
elif key in bool_keys:
param[key] = bool(val)
setattr(self.owner, self.attrname, param)
def set_param(self, param):
if param["xc"] is not None:
for i, x in enumerate(self.xc_list):
if x == param["xc"]:
self.xc.set_active(i)
if isinstance(param["vdw_correction_hirshfeld"],bool):
self.TS.set_active(param["vdw_correction_hirshfeld"])
if self.periodic and param["k_grid"] is not None:
self.kpts[0].value = int(param["k_grid"][0])
self.kpts[1].value = int(param["k_grid"][1])
self.kpts[2].value = int(param["k_grid"][2])
if param["spin"] is not None:
self.spinpol.set_active(param["spin"] == "collinear")
self.moment_spin.set_sensitive(param["spin"] == "collinear")
if param["default_initial_moment"] is not None:
self.moment.value = param["default_initial_moment"]
if param["charge"] is not None:
self.charge.value = param["charge"]
if param["relativistic"] is not None:
if isinstance(param["relativistic"],(tuple,list)):
rel = param["relativistic"]
else:
rel = param["relativistic"].split()
for i, x in enumerate(self.aims_relativity_list):
if x == rel[0]:
self.relativity_type.set_active(i)
if x == 'zora':
self.relativity_threshold.set_text(rel[2])
self.relativity_threshold.set_sensitive(True)
if param["sc_accuracy_etot"] is not None:
self.sc_tot_energy.value = param["sc_accuracy_etot"]
if param["sc_accuracy_eev"] is not None:
self.sc_sum_eigenvalue.value = param["sc_accuracy_eev"]
if param["sc_accuracy_rho"] is not None:
self.sc_density.value = param["sc_accuracy_rho"]
if param["compute_forces"] is not None:
if param["compute_forces"]:
if param["sc_accuracy_forces"] is not None:
self.sc_forces.value = param["sc_accuracy_forces"]
self.compute_forces.set_active(param["compute_forces"])
else:
self.compute_forces.set_active(False)
if param["run_command"] is not None:
self.run_command.set_text(param["run_command"])
if param["species_dir"] is not None:
self.species_defaults.set_text(param["species_dir"])
for (key,val) in param.items():
if key in self.aims_keyword_list and key not in self.aims_keyword_gui_list:
if val is not None: # = existing "expert keyword"
if key == 'output': # 'output' can be used more than once
options = val
if isinstance(options,str): options = [options]
for arg in options:
self.expert_keyword_create([key]+[arg])
else:
if isinstance(val,str):
arg = [key]+val.split()
elif isinstance(val,(tuple,list)):
arg = [key]+[str(a) for a in val]
else:
arg = [key]+[str(val)]
self.expert_keyword_create(arg)
def ok(self, *args):
self.set_attributes(*args)
self.destroy()
def export_control(self, *args):
filename = "control.in"
chooser = gtk.FileChooserDialog(
_('Export parameters ... '), None, gtk.FILE_CHOOSER_ACTION_SAVE,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
chooser.set_filename(filename)
save = chooser.run()
if save == gtk.RESPONSE_OK or save == gtk.RESPONSE_SAVE:
filename = chooser.get_filename()
self.set_attributes(*args)
param = getattr(self.owner, "aims_parameters")
from ase.calculators.aims import Aims
calc_temp = Aims(**param)
atoms_temp = self.owner.atoms.copy()
atoms_temp.set_calculator(calc_temp)
atoms_temp.calc.write_control(file = filename)
atoms_temp.calc.write_species(file = filename)
chooser.destroy()
def import_control(self, *args):
filename = "control.in"
chooser = gtk.FileChooserDialog(
_('Import control.in file ... '), None,
gtk.FILE_CHOOSER_ACTION_SAVE,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
chooser.set_filename(filename)
save = chooser.run()
if save == gtk.RESPONSE_OK:
self.set_defaults()
filename = chooser.get_filename()
control = open(filename,'r')
while True:
line = control.readline()
if not line:
break
if "List of parameters used to initialize the calculator:" in line:
control.readline()
from ase.io.aims import read_aims_calculator
calc = read_aims_calculator(control)
found_aims_calculator = True
control.close()
if found_aims_calculator:
param = calc.float_params
for key in calc.exp_params:
param[key] = calc.exp_params[key]
for key in calc.string_params:
param[key] = calc.string_params[key]
for key in calc.int_params:
param[key] = calc.int_params[key]
for key in calc.bool_params:
param[key] = calc.bool_params[key]
for key in calc.list_params:
param[key] = calc.list_params[key]
for key in calc.input_parameters:
param[key] = calc.input_parameters[key]
self.set_defaults()
self.set_param(param)
chooser.destroy()
def k_changed(self, *args):
size = [self.kpts[i].value * np.sqrt(np.vdot(self.ucell[i],self.ucell[i])) for i in range(3)]
self.kpts_label.set_text(self.kpts_label_format % tuple(size))
def compute_forces_toggled(self, *args):
self.sc_forces_spin.set_sensitive(self.compute_forces.get_active())
def relativity_changed(self, *args):
self.relativity_threshold.set_sensitive(self.relativity_type.get_active() == 2)
def spinpol_changed(self, *args):
self.moment_spin.set_sensitive(self.spinpol.get_active())
def expert_keyword_import(self, *args):
command = self.expert_keyword_set.get_text().split()
if len(command) > 0 and command[0] in self.aims_keyword_list and not command[0] in self.aims_keyword_gui_list:
self.expert_keyword_create(command)
elif command[0] in self.aims_keyword_gui_list:
oops(_("Please use the facilities provided in this window to "
"manipulate the keyword: %s!") % command[0])
else:
oops(_("Don't know this keyword: %s\n"
"\nPlease check!\n\n"
"If you really think it should be available, "
"please add it to the top of ase/calculators/aims.py.")
% command[0])
self.expert_keyword_set.set_text("")
def expert_keyword_create(self, command):
key = command[0]
argument = command[1]
if len(command) > 2:
for a in command[2:]:
argument += ' '+a
index = len(self.expert_keywords)
self.expert_keywords += [[gtk.Label(" " +key+" "),
gtk.Entry(max=45),
ExpertDeleteButton(index),
True]]
self.expert_keywords[index][1].set_text(argument)
self.expert_keywords[index][2].connect('clicked',self.expert_keyword_delete)
if not self.expert_vbox.get_children():
table = gtk.Table(1, 3)
table.attach(self.expert_keywords[index][0], 0, 1, 0, 1, 0)
table.attach(self.expert_keywords[index][1], 1, 2, 0, 1, 0)
table.attach(self.expert_keywords[index][2], 2, 3, 0, 1, 0)
table.show_all()
pack(self.expert_vbox, table)
else:
table = self.expert_vbox.get_children()[0]
nrows = table.get_property('n-rows')
table.resize(nrows + 1, 3)
table.attach(self.expert_keywords[index][0], 0, 1, nrows, nrows + 1, 0)
table.attach(self.expert_keywords[index][1], 1, 2, nrows, nrows + 1, 0)
table.attach(self.expert_keywords[index][2], 2, 3, nrows, nrows + 1, 0)
table.show_all()
def expert_keyword_delete(self, button, *args):
index = button.index # which one to kill
for i in [0,1,2]:
self.expert_keywords[index][i].destroy()
table = self.expert_vbox.get_children()[0]
nrows = table.get_property('n-rows')
table.resize(nrows-1, 3)
self.expert_keywords[index][3] = False
class ExpertDeleteButton(gtk.Button):
def __init__(self, index):
gtk.Button.__init__(self, stock=gtk.STOCK_DELETE)
alignment = self.get_children()[0]
hbox = alignment.get_children()[0]
#self.set_size_request(1, 3)
image, label = hbox.get_children()
if image is not None:
label.set_text('Del')
self.index = index
class VASP_Window(gtk.Window):
vasp_xc_list = ['PW91', 'PBE', 'LDA']
vasp_xc_default = 'PBE'
vasp_prec_default = 'Normal'
def __init__(self, owner, param, attrname):
self.owner = owner
self.attrname = attrname
atoms = owner.atoms
self.periodic = atoms.get_pbc().all()
self.vasp_keyword_gui_list = ['ediff','encut', 'ismear', 'ispin', 'prec', 'sigma']
from ase.calculators.vasp import float_keys,exp_keys,string_keys,int_keys,bool_keys,list_keys,special_keys
self.vasp_keyword_list = float_keys+exp_keys+string_keys+int_keys+bool_keys+list_keys+special_keys
self.expert_keywords = []
natoms = len(atoms)
gtk.Window.__init__(self)
self.set_title(_("VASP parameters"))
vbox = gtk.VBox()
vbox.set_border_width(5)
# Print some info
txt = _("%i atoms.\n") % natoms
self.ucell = atoms.get_cell()
txt += _("Periodic geometry, unit cell is: \n")
for i in range(3):
txt += "(%8.3f %8.3f %8.3f)\n" % (self.ucell[i][0], self.ucell[i][1], self.ucell[i][2])
pack(vbox, [gtk.Label(txt)])
# XC functional ()
self.xc = gtk.combo_box_new_text()
for i, x in enumerate(self.vasp_xc_list):
self.xc.append_text(x)
# Spin polarized
self.spinpol = gtk.CheckButton(_("Spin polarized"))
pack(vbox, [gtk.Label(_("Exchange-correlation functional: ")),
self.xc,
gtk.Label(" "),
self.spinpol])
pack(vbox, gtk.Label(""))
# k-grid
self.kpts = []
self.kpts_spin = []
for i in range(3):
default = np.ceil(20.0 / np.sqrt(np.vdot(self.ucell[i],self.ucell[i])))
g = gtk.Adjustment(default, 1, 100, 1)
s = gtk.SpinButton(g, 0, 0)
self.kpts.append(g)
self.kpts_spin.append(s)
g.connect("value-changed", self.k_changed)
# Precision of calculation
self.prec = gtk.combo_box_new_text()
for i, x in enumerate(['Low', 'Normal', 'Accurate']):
self.prec.append_text(x)
if x == self.vasp_prec_default:
self.prec.set_active(i)
# cutoff energy
if os.environ.has_key('VASP_PP_PATH'):
self.encut_min_default, self.encut_max_default = self.get_min_max_cutoff()
else:
self.encut_max_default = 400.0
self.encut_min_default = 100.0
self.encut = gtk.Adjustment(self.encut_max_default, 0, 9999, 10)
self.encut_spin = gtk.SpinButton(self.encut, 0, 0)
self.encut_spin.set_digits(2)
self.encut_spin.connect("value-changed",self.check_encut_warning)
self.encut_warning = gtk.Label("")
pack(vbox, [gtk.Label(_("k-points k = (")), self.kpts_spin[0],
gtk.Label(", "), self.kpts_spin[1], gtk.Label(", "),
self.kpts_spin[2],
gtk.Label(_(") Cutoff: ")),self.encut_spin,
gtk.Label(_(" Precision: ")),self.prec])
self.kpts_label = gtk.Label("")
self.kpts_label_format = _("k-points x size: (%.1f, %.1f, %.1f) Ã… ")
pack(vbox, [self.kpts_label, self.encut_warning])
self.k_changed()
pack(vbox, gtk.Label(""))
self.ismear = gtk.combo_box_new_text()
for x in ['Fermi', 'Gauss', 'Methfessel-Paxton']:
self.ismear.append_text(x)
self.ismear.set_active(2)
self.smearing_order = gtk.Adjustment(2,0,9,1)
self.smearing_order_spin = gtk.SpinButton(self.smearing_order,0,0)
self.smearing_order_spin.set_digits(0)
self.ismear.connect("changed", self.check_ismear_changed)
self.sigma = gtk.Adjustment(0.1, 0.001, 9.0, 0.1)
self.sigma_spin = gtk.SpinButton(self.sigma,0,0)
self.sigma_spin.set_digits(3)
pack(vbox, [gtk.Label(_("Smearing: ")),
self.ismear,
gtk.Label(_(" order: ")),
self.smearing_order_spin,
gtk.Label(_(" width: ")),
self.sigma_spin])
pack(vbox, gtk.Label(""))
self.ediff = gtk.Adjustment(1e-4, 1e-6, 1e0, 1e-4)
self.ediff_spin = gtk.SpinButton(self.ediff, 0, 0)
self.ediff_spin.set_digits(6)
pack(vbox,[gtk.Label(_("Self-consistency convergence: ")),
self.ediff_spin,
gtk.Label(_(" eV"))])
pack(vbox,gtk.Label(""))
swin = gtk.ScrolledWindow()
swin.set_border_width(0)
swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.expert_keyword_set = gtk.Entry(max = 55)
self.expert_keyword_add = gtk.Button(stock = gtk.STOCK_ADD)
self.expert_keyword_add.connect("clicked", self.expert_keyword_import)
self.expert_keyword_set.connect("activate", self.expert_keyword_import)
pack(vbox,[gtk.Label(_("Additional keywords: ")),
self.expert_keyword_set,
self.expert_keyword_add])
self.expert_vbox = gtk.VBox()
vbox.pack_start(swin, True, True, 0)
swin.add_with_viewport(self.expert_vbox)
self.expert_vbox.get_parent().set_shadow_type(gtk.SHADOW_NONE)
self.expert_vbox.get_parent().set_size_request(-1, 100)
swin.show()
self.expert_vbox.show()
pack(vbox, gtk.Label(""))
# run command and location of POTCAR files:
pack(vbox, gtk.Label(_('VASP execution command: ')))
self.run_command = pack(vbox, gtk.Entry(max=0))
if os.environ.has_key('VASP_COMMAND'):
self.run_command.set_text(os.environ['VASP_COMMAND'])
pack(vbox, gtk.Label(_('Directory for species defaults: ')))
self.pp_path = pack(vbox, gtk.Entry(max=0))
if os.environ.has_key('VASP_PP_PATH'):
self.pp_path.set_text(os.environ['VASP_PP_PATH'])
# Buttons at the bottom
pack(vbox, gtk.Label(""))
butbox = gtk.HButtonBox()
set_default_but = gtk.Button(_("Set Defaults"))
set_default_but.connect("clicked", self.set_defaults)
import_vasp_but = gtk.Button(_("Import VASP files"))
import_vasp_but.connect("clicked", self.import_vasp_files)
export_vasp_but = gtk.Button(_("Export VASP files"))
export_vasp_but.connect("clicked", self.export_vasp_files)
cancel_but = gtk.Button(stock=gtk.STOCK_CANCEL)
cancel_but.connect('clicked', lambda widget: self.destroy())
ok_but = gtk.Button(stock=gtk.STOCK_OK)
ok_but.connect('clicked', self.ok)
butbox.pack_start(set_default_but, 0, 0)
butbox.pack_start(import_vasp_but, 0, 0)
butbox.pack_start(export_vasp_but, 0, 0)
butbox.pack_start(cancel_but, 0, 0)
butbox.pack_start(ok_but, 0, 0)
butbox.show_all()
pack(vbox, [butbox], end=True, bottom=True)
vbox.show()
self.add(vbox)
self.show()
self.grab_add() # Lock all other windows
self.load_attributes()
def load_attributes(self, directory = "."):
"""Sets values of fields of the window according to the values
set inside the INCAR, KPOINTS and POTCAR file in 'directory'."""
from os import chdir
chdir(directory)
# Try and load INCAR, in the current directory
from ase.calculators.vasp import Vasp
calc_temp = Vasp()
try:
calc_temp.read_incar("INCAR")
except IOError:
pass
else:
if calc_temp.spinpol:
self.spinpol.set_active(True)
else:
self.spinpol.set_active(False)
if calc_temp.float_params['encut']:
self.encut.set_value(calc_temp.float_params['encut'])
if calc_temp.int_params['ismear'] == -1: # Fermi
vasp_ismear_default = 'Fermi'
elif calc_temp.int_params['ismear'] == 0: # Gauss
vasp_ismear_default = 'Gauss'
elif calc_temp.int_params['ismear'] > 0: # Methfessel-Paxton
vasp_ismear_default = 'Methfessel-Paxton'
else:
vasp_ismear_default = None
for i, x in enumerate(['Fermi', 'Gauss', 'Methfessel-Paxton']):
if vasp_ismear_default == x:
self.ismear.set_active(i)
if calc_temp.exp_params['ediff']:
self.ediff.set_value(calc_temp.exp_params['ediff'])
for i, x in enumerate(['Low', 'Normal', 'Accurate']):
if x == calc_temp.string_params['prec']:
self.prec.set_active(i)
if calc_temp.float_params['sigma']:
self.sigma.set_value(calc_temp.float_params['sigma'])
import copy
all_params = copy.deepcopy(calc_temp.float_params)
all_params.update(calc_temp.exp_params)
all_params.update(calc_temp.string_params)
all_params.update(calc_temp.int_params)
all_params.update(calc_temp.bool_params)
all_params.update(calc_temp.special_params)
for (key, value) in all_params.items():
if key in self.vasp_keyword_list \
and key not in self.vasp_keyword_gui_list \
and value is not None:
command = key + " " + str(value)
self.expert_keyword_create(command.split())
for (key, value) in calc_temp.list_params.items():
if key == "magmom" and value is not None:
command = key + " "
rep = 1
previous = value[0]
for v in value[1:]:
if v == previous:
rep += 1
else:
if rep > 1:
command += "%d*%f " % (rep, previous)
else:
command += "%f " % previous
rep = 1
previous = v
if rep > 1:
command += "%d*%f " % (rep, previous)
else:
command += "%f" % previous
self.expert_keyword_create(command.split())
elif value is not None:
command = key + " "
for v in value:
command += str(v) + " "
self.expert_keyword_create(command.split())
# Try and load POTCAR, in the current directory
try:
calc_temp.read_potcar()
except IOError:
pass
else:
#Set xc read from POTCAR
for i, x in enumerate(self.vasp_xc_list):
if x == calc_temp.input_params['xc']:
self.xc.set_active(i)
# Try and load KPOINTS, in the current directory
try:
calc_temp.read_kpoints("KPOINTS")
except IOError:
pass
else:
# Set KPOINTS grid dimensions
for i in range(3):
self.kpts_spin[i].set_value(calc_temp.input_params['kpts'][i])
def set_attributes(self, *args):
self.param = {}
self.param["xc"] = self.xc.get_active_text()
self.param["prec"] = self.prec.get_active_text()
self.param["kpts"] = (int(self.kpts[0].value),
int(self.kpts[1].value),
int(self.kpts[2].value))
self.param["encut"] = self.encut.value
self.param["ediff"] = self.ediff.value
self.param["ismear"] = self.get_ismear()
self.param["sigma"] = self.sigma.value
if self.spinpol.get_active():
self.param["ispin"] = 2
else:
self.param["ispin"] = 1
from ase.calculators.vasp import float_keys,exp_keys,string_keys,int_keys,bool_keys,list_keys,special_keys
for option in self.expert_keywords:
if option[3]: # set type of parameter accoding to which list it is in
key = option[0].get_text().split()[0].strip()
val = option[1].get_text().strip()
if key in float_keys or key in exp_keys:
self.param[key] = float(val)
elif key == "magmom":
val = val.replace("*", " * ")
c = val.split()
val = []
i = 0
while i < len(c):
if c[i] == "*":
b = val.pop()
i += 1
for j in range(int(b)):
val.append(float(c[i]))
else:
val.append(float(c[i]))
i += 1
self.param[key] = val
elif key in list_keys:
c = val.split()
val = []
for i in c:
val.append(float(i))
self.param[key] = val
elif key in string_keys:
self.param[key] = val
elif key in int_keys:
self.param[key] = int(val)
elif key in bool_keys:
self.param[key] = bool(val)
setattr(self.owner, self.attrname, self.param)
os.environ['VASP_COMMAND'] = self.run_command.get_text()
os.environ['VASP_PP_PATH'] = self.pp_path.get_text()
def ok(self, *args):
self.set_attributes(*args)
self.destroy()
def get_min_max_cutoff(self, *args):
# determine the recommended energy cutoff limits
from ase.calculators.vasp import Vasp
calc_temp = Vasp()
atoms_temp = self.owner.atoms.copy()
calc_temp.initialize(atoms_temp)
calc_temp.write_potcar(suffix = '.check_energy_cutoff')
enmin = -1e6
enmax = -1e6
for line in open("POTCAR.check_energy_cutoff",'r').readlines():
if "ENMIN" in line:
enmax = max(enmax,float(line.split()[2].split(';')[0]))
enmin = max(enmin,float(line.split()[5]))
from os import system
system("rm POTCAR.check_energy_cutoff")
return enmin, enmax
def k_changed(self, *args):
size = [self.kpts[i].value * np.sqrt(np.vdot(self.ucell[i],self.ucell[i])) for i in range(3)]
self.kpts_label.set_text(self.kpts_label_format % tuple(size))
def check_encut_warning(self,*args):
if self.encut.value < self.encut_min_default:
self.encut_warning.set_markup(_("WARNING: cutoff energy is lower than recommended minimum!"))
else:
self.encut_warning.set_markup("")
def check_ismear_changed(self,*args):
if self.ismear.get_active_text() == 'Methfessel-Paxton':
self.smearing_order_spin.set_sensitive(True)
else:
self.smearing_order_spin.set_sensitive(False)
def get_ismear(self,*args):
type = self.ismear.get_active_text()
if type == 'Methfessel-Paxton':
ismear_value = self.smearing_order.value
elif type == 'Fermi':
ismear_value = -1
else:
ismear_value = 0
return ismear_value
def destroy(self):
self.grab_remove()
gtk.Window.destroy(self)
def set_defaults(self, *args):
# Reset fields to what they were
self.spinpol.set_active(False)
for i, x in enumerate(['Low', 'Normal', 'Accurate']):
if x == self.vasp_prec_default:
self.prec.set_active(i)
self.encut_spin.set_value(self.encut_max_default)
self.ismear.set_active(2)
self.smearing_order.set_value(2)
self.ediff.set_value(1e-4)
for child in self.expert_vbox.children():
self.expert_vbox.remove(child)
for i, x in enumerate(self.vasp_xc_list):
if x == self.vasp_xc_default:
self.xc.set_active(i)
default = np.ceil(20.0 / np.sqrt(np.vdot(self.ucell[i],self.ucell[i])))
for i in range(3):
self.kpts_spin[i].set_value(default)
def import_vasp_files(self, *args):
dirname = ""
chooser = gtk.FileChooserDialog(
_('Import VASP input files: choose directory ... '),
None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
chooser.set_filename(dirname)
openr = chooser.run()
if openr == gtk.RESPONSE_OK or openr == gtk.RESPONSE_SAVE:
dirname = chooser.get_filename()
self.load_attributes(dirname)
chooser.destroy()
def export_vasp_files(self, *args):
filename = ""
chooser = gtk.FileChooserDialog(
_('Export VASP input files: choose directory ... '),
None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
chooser.set_filename(filename)
save = chooser.run()
if save == gtk.RESPONSE_OK or save == gtk.RESPONSE_SAVE:
filename = chooser.get_filename()
from os import chdir
chdir(filename)
self.set_attributes(*args)
param = getattr(self.owner, "vasp_parameters")
from ase.calculators.vasp import Vasp
calc_temp = Vasp(**param)
atoms_temp = self.owner.atoms.copy()
atoms_temp.set_calculator(calc_temp)
calc_temp.initialize(atoms_temp)
calc_temp.write_incar(atoms_temp)
calc_temp.write_potcar()
calc_temp.write_kpoints()
calc_temp.write_sort_file()
from ase.io.vasp import write_vasp
write_vasp('POSCAR', calc_temp.atoms_sorted, symbol_count = calc_temp.symbol_count)
chooser.destroy()
def expert_keyword_import(self, *args):
command = self.expert_keyword_set.get_text().split()
if len(command) > 0 and command[0] in self.vasp_keyword_list and not command[0] in self.vasp_keyword_gui_list:
self.expert_keyword_create(command)
elif command[0] in self.vasp_keyword_gui_list:
oops(_("Please use the facilities provided in this window to "
"manipulate the keyword: %s!") % command[0])
else:
oops(_("Don't know this keyword: %s"
"\nPlease check!\n\n"
"If you really think it should be available, "
"please add it to the top of ase/calculators/vasp.py.")
% command[0])
self.expert_keyword_set.set_text("")
def expert_keyword_create(self, command):
key = command[0]
if command[1] == "=":
command.remove("=")
argument = command[1]
if len(command) > 2:
for a in command[2:]:
argument += ' '+a
index = len(self.expert_keywords)
self.expert_keywords += [[gtk.Label(" " +key+" = "),
gtk.Entry(max=55),
ExpertDeleteButton(index),
True]]
self.expert_keywords[index][1].set_text(argument)
self.expert_keywords[index][2].connect('clicked',self.expert_keyword_delete)
if not self.expert_vbox.get_children():
table = gtk.Table(1, 3)
table.attach(self.expert_keywords[index][0], 0, 1, 0, 1, 0)
table.attach(self.expert_keywords[index][1], 1, 2, 0, 1, 0)
table.attach(self.expert_keywords[index][2], 2, 3, 0, 1, 0)
table.show_all()
pack(self.expert_vbox, table)
else:
table = self.expert_vbox.get_children()[0]
nrows = table.get_property('n-rows')
table.resize(nrows + 1, 3)
table.attach(self.expert_keywords[index][0], 0, 1, nrows, nrows + 1, 0)
table.attach(self.expert_keywords[index][1], 1, 2, nrows, nrows + 1, 0)
table.attach(self.expert_keywords[index][2], 2, 3, nrows, nrows + 1, 0)
table.show_all()
def expert_keyword_delete(self, button, *args):
index = button.index # which one to kill
for i in [0,1,2]:
self.expert_keywords[index][i].destroy()
table = self.expert_vbox.get_children()[0]
nrows = table.get_property('n-rows')
table.resize(nrows-1, 3)
self.expert_keywords[index][3] = False
python-ase-3.6.0.2515/ase/gui/gui.py 0000644 0001754 0001754 00000141626 11711330540 015677 0 ustar askhl askhl # husk:
# Exit*2? remove pylab.show()
# close button
# DFT
# ADOS
# grey-out stuff after one second: vmd, rasmol, ...
# Show with ....
# rasmol: set same rotation as ag
# Graphs: save, Python, 3D
# start from python (interactive mode?)
# ascii-art option (colored)|
# option -o (output) and -f (force overwrite)
# surfacebuilder
# screen-dump
# icon
# ag-community-server
# translate option: record all translations,
# and check for missing translations.
#TODO: Add possible way of choosing orinetations. \
#TODO: Two atoms defines a direction, three atoms their normal does
#TODO: Align orientations chosen in Rot_selected v unselcted
#TODO: Get the atoms_rotate_0 thing string
#TODO: Use set atoms instead og the get atoms
#TODO: Arrow keys will decide how the orientation changes
#TODO: Undo redo que should be implemented
#TODO: Update should have possibility to change positions
#TODO: Window for rotation modes and move moves which can be chosen
#TODO: WHen rotate and move / hide the movie menu
import os
import sys
import weakref
from gettext import gettext as _
from gettext import ngettext
import numpy as np
import pygtk
pygtk.require("2.0")
import gtk
from ase.gui.view import View
from ase.gui.status import Status
from ase.gui.widgets import pack, help, Help, oops
#from ase.gui.languages import translate as _
from ase.gui.settings import Settings
from ase.gui.crystal import SetupBulkCrystal
from ase.gui.surfaceslab import SetupSurfaceSlab
from ase.gui.nanoparticle import SetupNanoparticle
from ase.gui.nanotube import SetupNanotube
from ase.gui.graphene import SetupGraphene
from ase.gui.calculator import SetCalculator
from ase.gui.energyforces import EnergyForces
from ase.gui.minimize import Minimize
from ase.gui.scaling import HomogeneousDeformation
from ase.gui.quickinfo import QuickInfo
from ase.gui.defaults import read_defaults
ui_info = """\
"""
class GUI(View, Status):
def __init__(self, images, rotations='', show_unit_cell=True,
show_bonds=False):
# Try to change into directory of file you are viewing
try:
os.chdir(os.path.split(sys.argv[1])[0])
# This will fail sometimes (e.g. for starting a new session)
except:
pass
self.images = images
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
#self.window.set_icon(gtk.gdk.pixbuf_new_from_file('guiase.png'))
self.window.set_position(gtk.WIN_POS_CENTER)
#self.window.connect("destroy", lambda w: gtk.main_quit())
self.window.connect('delete_event', self.exit)
vbox = gtk.VBox()
self.window.add(vbox)
if gtk.pygtk_version < (2, 12):
self.set_tip = gtk.Tooltips().set_tip
actions = gtk.ActionGroup("Actions")
actions.add_actions([
('FileMenu', None, _('_File')),
('EditMenu', None, _('_Edit')),
('ViewMenu', None, _('_View')),
('ToolsMenu', None, _('_Tools')),
# TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
('SetupMenu', None, _('_Setup')),
('CalculateMenu', None, _('_Calculate')),
('HelpMenu', None, _('_Help')),
('Open', gtk.STOCK_OPEN, _('_Open'), 'O',
_('Create a new file'),
self.open),
('New', gtk.STOCK_NEW, _('_New'), 'N',
_('New ase.gui window'),
lambda widget: os.system('ag &')),
('Save', gtk.STOCK_SAVE, _('_Save'), 'S',
_('Save current file'),
self.save),
('Quit', gtk.STOCK_QUIT, _('_Quit'), 'Q',
_('Quit'),
self.exit),
('SelectAll', None, _('Select _all'), None,
'',
self.select_all),
('Invert', None, _('_Invert selection'), None,
'',
self.invert_selection),
('SelectConstrained', None, _('Select _constrained atoms'), None,
'',
self.select_constrained_atoms),
('SelectImmobile', None, _('Select _immobile atoms'), 'I',
'',
self.select_immobile_atoms),
('Copy', None, _('_Copy'), 'C',
_('Copy current selection and its orientation to clipboard'),
self.copy_atoms),
('Paste', None, _('_Paste'), 'V',
_('Insert current clipboard selection'),
self.paste_atoms),
('Modify', None, _('_Modify'), 'Y',
_('Change tags, moments and atom types of the selected atoms'),
self.modify_atoms),
('AddAtoms', None, _('_Add atoms'), 'A',
_('Insert or import atoms and molecules'),
self.add_atoms),
('DeleteAtoms', None, _('_Delete selected atoms'), 'BackSpace',
_('Delete the selected atoms'),
self.delete_selected_atoms),
('First', gtk.STOCK_GOTO_FIRST, _('_First image'), 'Home',
'',
self.step),
('Previous', gtk.STOCK_GO_BACK, _('_Previous image'), 'Page_Up',
'',
self.step),
('Next', gtk.STOCK_GO_FORWARD, _('_Next image'), 'Page_Down',
'',
self.step),
('Last', gtk.STOCK_GOTO_LAST, _('_Last image'), 'End',
'',
self.step),
('QuickInfo', None, _('Quick Info ...'), None,
'',
self.quick_info_window),
('Repeat', None, _('Repeat ...'), None,
'',
self.repeat_window),
('Rotate', None, _('Rotate ...'), None,
'',
self.rotate_window),
('Colors', None, _('Colors ...'), None, '',
self.colors_window),
# TRANSLATORS: verb
('Focus', gtk.STOCK_ZOOM_FIT, _('Focus'), 'F',
'',
self.focus),
('ZoomIn', gtk.STOCK_ZOOM_IN, _('Zoom in'), 'plus',
'',
self.zoom),
('ZoomOut', gtk.STOCK_ZOOM_OUT, _('Zoom out'), 'minus',
'',
self.zoom),
('ResetView', None, _('Reset View'), 'equal',
'',
self.reset_view),
('Settings', gtk.STOCK_PREFERENCES, _('Settings ...'), None,
'',
self.settings),
('VMD', None, _('VMD'), None,
'',
self.external_viewer),
('RasMol', None, _('RasMol'), None,
'',
self.external_viewer),
('XMakeMol', None, _('xmakemol'), None,
'',
self.external_viewer),
('Avogadro', None, _('avogadro'), None,
'',
self.external_viewer),
('Graphs', None, _('Graphs ...'), None,
'',
self.plot_graphs),
('Movie', None, _('Movie ...'), None,
'',
self.movie),
('EModify', None, _('Expert mode ...'), 'E',
'',
self.execute),
('Constraints', None, _('Constraints ...'), None,
'',
self.constraints_window),
('RenderScene', None, _('Render scene ...'), None,
'',
self.render_window),
('DFT', None, _('DFT ...'), None,
'',
self.dft_window),
('NEB', None, _('NE_B'), None,
'',
self.NEB),
('BulkModulus', None, _('B_ulk Modulus'), None,
'',
self.bulk_modulus),
('Bulk', None, _('_Bulk Crystal'), None,
_("Create a bulk crystal with arbitrary orientation"),
self.bulk_window),
('Surface', None, _('_Surface slab'), None,
_("Create the most common surfaces"),
self.surface_window),
('Nanoparticle', None, _('_Nanoparticle'), None,
_("Create a crystalline nanoparticle"),
self.nanoparticle_window),
('Nanotube', None, _('Nano_tube'), None,
_("Create a nanotube"),
self.nanotube_window),
('Graphene', None, _('Graphene'), None,
_("Create a graphene sheet or nanoribbon"),
self.graphene_window),
('SetCalculator', None, _('Set _Calculator'), None,
_("Set a calculator used in all calculation modules"),
self.calculator_window),
('EnergyForces', None, _('_Energy and Forces'), None,
_("Calculate energy and forces"),
self.energy_window),
('Minimize', None, _('Energy _Minimization'), None,
_("Minimize the energy"),
self.energy_minimize_window),
('Scaling', None, _('Scale system'), None,
_("Deform system by scaling it"),
self.scaling_window),
('About', None, _('_About'), None,
None,
self.about),
('Webpage', gtk.STOCK_HELP, _('Webpage ...'), None, None, webpage),
('Debug', None, _('Debug ...'), None, None, self.debug)])
actions.add_toggle_actions([
('ShowUnitCell', None, _('Show _unit cell'), 'U',
'Bold',
self.toggle_show_unit_cell,
show_unit_cell > 0),
('ShowAxes', None, _('Show _axes'), None,
'Bold',
self.toggle_show_axes,
True),
('ShowBonds', None, _('Show _bonds'), 'B',
'Bold',
self.toggle_show_bonds,
show_bonds),
('MoveAtoms', None, _('_Move atoms'), 'M',
'Bold',
self.toggle_move_mode,
False),
('RotateAtoms', None, _('_Rotate atoms'), 'R',
'Bold',
self.toggle_rotate_mode,
False),
('OrientAtoms', None, _('Orien_t atoms'), 'T',
'Bold',
self.toggle_orient_mode,
False)
])
self.ui = ui = gtk.UIManager()
ui.insert_action_group(actions, 0)
self.window.add_accel_group(ui.get_accel_group())
try:
mergeid = ui.add_ui_from_string(ui_info)
except gobject.GError, msg:
print _('building menus failed: %s') % msg
vbox.pack_start(ui.get_widget('/MenuBar'), False, False, 0)
View.__init__(self, vbox, rotations)
Status.__init__(self, vbox)
vbox.show()
#self.window.set_events(gtk.gdk.BUTTON_PRESS_MASK)
self.window.connect('key-press-event', self.scroll)
self.window.connect('scroll_event', self.scroll_event)
self.window.show()
self.graphs = [] # List of open pylab windows
self.graph_wref = [] # List of weakrefs to Graph objects
self.movie_window = None
self.clipboard = None # initialize copy/paste functions
self.vulnerable_windows = []
self.simulation = {} # Used by modules on Calculate menu.
self.module_state = {} # Used by modules to store their state.
self.config = read_defaults()
def run(self, expr=None):
self.set_colors()
self.set_coordinates(self.images.nimages - 1, focus=True)
if self.images.nimages > 1:
self.movie()
if expr is None and not np.isnan(self.images.E[0]):
expr = self.config['gui_graphs_string']
if expr is not None and expr != '' and self.images.nimages > 1:
self.plot_graphs(expr=expr)
gtk.main()
def step(self, action):
d = {'First': -10000000,
'Previous': -1,
'Next': 1,
'Last': 10000000}[action.get_name()]
i = max(0, min(self.images.nimages - 1, self.frame + d))
self.set_frame(i)
if self.movie_window is not None:
self.movie_window.frame_number.value = i
def _do_zoom(self, x):
"""Utility method for zooming"""
self.scale *= x
self.draw()
def zoom(self, action):
"""Zoom in/out on keypress or clicking menu item"""
x = {'ZoomIn': 1.2, 'ZoomOut':1 /1.2}[action.get_name()]
self._do_zoom(x)
def scroll_event(self, window, event):
"""Zoom in/out when using mouse wheel"""
SHIFT = event.state == gtk.gdk.SHIFT_MASK
x = 1.0
if event.direction == gtk.gdk.SCROLL_UP:
x = 1.0 + (1-SHIFT)*0.2 + SHIFT*0.01
elif event.direction == gtk.gdk.SCROLL_DOWN:
x = 1.0 / (1.0 + (1-SHIFT)*0.2 + SHIFT*0.01)
self._do_zoom(x)
def settings(self, menuitem):
Settings(self)
def scroll(self, window, event):
from copy import copy
CTRL = event.state == gtk.gdk.CONTROL_MASK
SHIFT = event.state == gtk.gdk.SHIFT_MASK
dxdydz = {gtk.keysyms.KP_Add: ('zoom', 1.0 + (1-SHIFT)*0.2 + SHIFT*0.01, 0),
gtk.keysyms.KP_Subtract: ('zoom', 1 / (1.0 + (1-SHIFT)*0.2 + SHIFT*0.01), 0),
gtk.keysyms.Up: ( 0, +1 - CTRL, +CTRL),
gtk.keysyms.Down: ( 0, -1 + CTRL, -CTRL),
gtk.keysyms.Right: (+1, 0, 0),
gtk.keysyms.Left: (-1, 0, 0)}.get(event.keyval, None)
try:
inch = chr(event.keyval)
except:
inch = None
sel = []
atom_move = self.ui.get_widget('/MenuBar/ToolsMenu/MoveAtoms'
).get_active()
atom_rotate = self.ui.get_widget('/MenuBar/ToolsMenu/RotateAtoms'
).get_active()
atom_orient = self.ui.get_widget('/MenuBar/ToolsMenu/OrientAtoms'
).get_active()
if dxdydz is None:
return
dx, dy, dz = dxdydz
if dx == 'zoom':
self._do_zoom(dy)
return
d = self.scale * 0.1
tvec = np.array([dx, dy, dz])
dir_vec = np.dot(self.axes, tvec)
if (atom_move):
rotmat = self.axes
s = 0.1
if SHIFT:
s = 0.01
add = s * dir_vec
for i in range(len(self.R)):
if self.atoms_to_rotate_0[i]:
self.R[i] += add
for jx in range(self.images.nimages):
self.images.P[jx][i] += add
elif atom_rotate:
from rot_tools import rotate_about_vec, \
rotate_vec
sel = self.images.selected
if sum(sel) == 0:
sel = self.atoms_to_rotate_0
nsel = sum(sel)
# this is the first one to get instatiated
if nsel != 2:
self.rot_vec = dir_vec
change = False
z_axis = np.dot(self.axes, np.array([0, 0, 1]))
if self.atoms_to_rotate == None:
change = True
self.z_axis_old = z_axis.copy()
self.dx_change = [0, 0]
self.atoms_to_rotate = self.atoms_to_rotate_0.copy()
self.atoms_selected = sel.copy()
self.rot_vec = dir_vec
if nsel != 2 or sum(self.atoms_to_rotate) == 2:
self.dx_change = [0, 0]
for i in range(len(sel)):
if sel[i] != self.atoms_selected[i]:
change = True
cz = [dx, dy+dz]
if cz[0] or cz[1]:
change = False
if not(cz[0] * (self.dx_change[1])):
change = True
for i in range(2):
if cz[i] and self.dx_change[i]:
self.rot_vec = self.rot_vec * cz[i] * self.dx_change[i]
if cz[1]:
change = False
if np.prod(self.z_axis_old != z_axis):
change = True
self.z_axis_old = z_axis.copy()
self.dx_change = copy(cz)
dihedral_rotation = len(self.images.selected_ordered) == 4
if change:
self.atoms_selected = sel.copy()
if nsel == 2 and sum(self.atoms_to_rotate) != 2:
asel = []
for i, j in enumerate(sel):
if j:
asel.append(i)
a1, a2 = asel
rvx = self.images.P[self.frame][a1] - \
self.images.P[self.frame][a2]
rvy = np.cross(rvx,
np.dot(self.axes,
np.array([0, 0, 1])))
self.rot_vec = rvx * dx + rvy * (dy + dz)
self.dx_change = [dx, dy+dz]
# dihedral rotation?
if dihedral_rotation:
sel = self.images.selected_ordered
self.rot_vec = (dx+dy+dz)*(self.R[sel[2]]-self.R[sel[1]])
rot_cen = np.array([0.0, 0.0, 0.0])
if dihedral_rotation:
sel = self.images.selected_ordered
rot_cen = self.R[sel[1]].copy()
elif nsel:
for i, b in enumerate( sel):
if b:
rot_cen += self.R[i]
rot_cen /= float(nsel)
degrees = 5 * (1 - SHIFT) + SHIFT
degrees = abs(sum(dxdydz)) * 3.1415 / 360.0 * degrees
rotmat = rotate_about_vec(self.rot_vec, degrees)
# now rotate the atoms that are to be rotated
for i in range(len(self.R)):
if self.atoms_to_rotate[i]:
self.R[i] -= rot_cen
for jx in range(self.images.nimages):
self.images.P[jx][i] -= rot_cen
self.R[i] = rotate_vec(rotmat, self.R[i])
for jx in range(self.images.nimages):
self.images.P[jx][i] = rotate_vec(rotmat, self.images.P[jx][i])
self.R[i] += rot_cen
for jx in range(self.images.nimages):
self.images.P[jx][i] += rot_cen
elif atom_orient:
to_vec = np.array([dx, dy, dz])
from rot_tools import rotate_vec_into_newvec
rot_mat = rotate_vec_into_newvec(self.orient_normal, to_vec)
self.axes = rot_mat
self.set_coordinates()
else:
self.center -= (dx * 0.1 * self.axes[:, 0] -
dy * 0.1 * self.axes[:, 1])
self.draw()
def copy_atoms(self, widget):
"Copies selected atoms to a clipboard, if no atoms are selected then the clipboard is cleared."
if self.images.selected.any():
atoms = self.images.get_atoms(self.frame)
lena = len(atoms)
for i in range(len(atoms)):
li = lena-1-i
if not self.images.selected[li]:
del(atoms[li])
for i in atoms:
i.position = np.dot(self.axes.T,i.position)
ref = atoms[0].position
for i in atoms:
if i.position[2] < ref[2]:
ref = i.position
self.clipboard = atoms.copy()
self.clipboard.reference_position = ref
else:
self.clipboard = None
def paste_atoms(self, widget):
"Inserts clipboard selection into the current frame using the add_atoms window."
if self.clipboard is not None:
self.add_atoms(widget, data='Paste', paste=self.clipboard)
def add_atoms(self, widget, data=None, paste=None):
"""
Presents a dialogbox to the user, that allows him to add atoms/molecule to the current slab
or to paste the clipboard.
The molecule/atom is rotated using the current rotation of the coordinate system.
The molecule/atom can be added at a specified position - if the keyword auto+Z is used,
the COM of the selected atoms will be used as COM for the moleculed. The COM is furthermore
translated Z ang towards the user.
If no molecules are selected, the COM of all the atoms will be used for the x-y components of the
active coordinate system, while the z-direction will be chosen from the nearest atom position
along this direction.
Note: If this option is used, all frames except the active one are deleted.
"""
if data == 'load':
chooser = gtk.FileChooserDialog(
_('Open ...'), None, gtk.FILE_CHOOSER_ACTION_OPEN,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
chooser.set_filename(_("<>"))
ok = chooser.run()
if ok == gtk.RESPONSE_OK:
filename = chooser.get_filename()
chooser.destroy()
else:
chooser.destroy()
return
if data == 'OK' or data == 'load':
import ase
if data == 'load':
molecule = filename
else:
molecule = self.add_entries[1].get_text()
tag = self.add_entries[2].get_text()
mom = self.add_entries[3].get_text()
pos = self.add_entries[4].get_text().lower()
if paste is not None:
a = paste.copy()
else:
a = None
if a is None:
try:
a = ase.Atoms([ase.Atom(molecule)])
except:
try:
a = ase.data.molecules.molecule(molecule)
except:
try:
a = ase.io.read(molecule, -1)
except:
self.add_entries[1].set_text('?' + molecule)
return ()
directions = np.transpose(self.axes)
if a != None:
for i in a:
try:
i.set('tag',int(tag))
except:
self.add_entries[2].set_text('?' + tag)
return ()
try:
i.magmom = float(mom)
except:
self.add_entries[3].set_text('?' + mom)
return ()
if self.origin_radio.get_active() and paste:
a.translate(-paste.reference_position)
# apply the current rotation matrix to A
for i in a:
i.position = np.dot(self.axes, i.position)
# find the extent of the molecule in the local coordinate system
if self.centre_radio.get_active():
a_cen_pos = np.array([0.0, 0.0, 0.0])
m_cen_pos = 0.0
for i in a.positions:
a_cen_pos[0] += np.dot(directions[0], i)
a_cen_pos[1] += np.dot(directions[1], i)
a_cen_pos[2] += np.dot(directions[2], i)
m_cen_pos = max(np.dot(-directions[2], i), m_cen_pos)
a_cen_pos[0] /= len(a.positions)
a_cen_pos[1] /= len(a.positions)
a_cen_pos[2] /= len(a.positions)
a_cen_pos[2] -= m_cen_pos
else:
a_cen_pos = np.array([0.0, 0.0, 0.0])
# now find the position
cen_pos = np.array([0.0, 0.0, 0.0])
if sum(self.images.selected) > 0:
for i in range(len(self.R)):
if self.images.selected[i]:
cen_pos += self.R[i]
cen_pos /= sum(self.images.selected)
elif len(self.R) > 0:
px = 0.0
py = 0.0
pz = -1e6
for i in range(len(self.R)):
px += np.dot(directions[0], self.R[i])
py += np.dot(directions[1], self.R[i])
pz = max(np.dot(directions[2], self.R[i]), pz)
px = (px/float(len(self.R)))
py = (py/float(len(self.R)))
cen_pos = directions[0] * px + \
directions[1] * py + \
directions[2] * pz
if 'auto' in pos:
pos = pos.replace('auto', '')
import re
pos = re.sub('\s', '', pos)
if '(' in pos:
sign = eval('%s1' % pos[0])
a_cen_pos -= sign * np.array(eval(pos[1:]), float)
else:
a_cen_pos -= float(pos) * directions[2]
else:
cen_pos = np.array(eval(pos))
for i in a:
i.position += cen_pos - a_cen_pos
# and them to the molecule
atoms = self.images.get_atoms(self.frame)
atoms = atoms + a
self.new_atoms(atoms, init_magmom=True)
# and finally select the new molecule for easy moving and rotation
for i in range(len(a)):
self.images.selected[len(atoms) - i - 1] = True
self.draw()
self.add_entries[0].destroy()
if data == 'Cancel':
self.add_entries[0].destroy()
if data == None or data == 'Paste':
from ase.gui.widgets import pack
molecule = ''
tag = '0'
mom = '0'
pos = 'auto+1'
self.add_entries = []
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.add_entries.append(window)
window.set_title(_('Add atoms'))
if data == 'Paste':
molecule = paste.get_chemical_symbols(True)
window.set_title(_('Paste'))
vbox = gtk.VBox(False, 0)
window.add(vbox)
vbox.show()
packed = False
for i, j in [[_('Insert atom or molecule'), molecule],
[_('Tag'), tag],
[_('Moment'), mom],
[_('Position'), pos]]:
label = gtk.Label(i)
if not packed:
vbox.pack_start(label, True, True, 0)
else:
packed = True
vbox.add(label)
label.show()
entry = gtk.Entry()
entry.set_text(j)
self.add_entries.append(entry)
entry.set_max_length(50)
entry.show()
vbox.add(entry)
pack(vbox,[gtk.Label('atom/molecule reference:')])
self.centre_radio = gtk.RadioButton(None, "centre ")
self.origin_radio = gtk.RadioButton(self.centre_radio, "origin")
pack(vbox,[self.centre_radio, self.origin_radio])
if data == 'Paste':
self.origin_radio.set_active(True)
self.add_entries[1].set_sensitive(False)
if data == None:
button = gtk.Button(_('_Load molecule'))
button.connect('clicked', self.add_atoms, 'load')
button.show()
vbox.add(button)
button = gtk.Button(_('_OK'))
button.connect('clicked', self.add_atoms, 'OK', paste)
button.show()
vbox.add(button)
button = gtk.Button(_('_Cancel'))
button.connect('clicked', self.add_atoms, 'Cancel')
button.show()
vbox.add(button)
window.show()
def modify_atoms(self, widget, data=None):
"""
Presents a dialog box where the user is able to change the atomic type, the magnetic
moment and tags of the selected atoms. An item marked with X will not be changed.
"""
if data:
if data == 'OK':
import ase
symbol = self.add_entries[1].get_text()
tag = self.add_entries[2].get_text()
mom = self.add_entries[3].get_text()
a = None
if symbol != 'X':
try:
a = ase.Atoms([ase.Atom(symbol)])
except:
self.add_entries[1].set_text('?' + symbol)
return ()
y = self.images.selected.copy()
# and them to the molecule
atoms = self.images.get_atoms(self.frame)
for i in range(len(atoms)):
if self.images.selected[i]:
if a:
atoms[i].symbol = symbol
try:
if tag != 'X':
atoms[i].tag = int(tag)
except:
self.add_entries[2].set_text('?' + tag)
return ()
try:
if mom != 'X':
atoms[i].magmom = float(mom)
except:
self.add_entries[3].set_text('?' + mom)
return ()
self.new_atoms(atoms, init_magmom=True)
# and finally select the new molecule for easy moving and rotation
self.images.selected = y
self.draw()
self.add_entries[0].destroy()
if data == None and sum(self.images.selected):
atoms = self.images.get_atoms(self.frame)
s_tag = ''
s_mom = ''
s_symbol = ''
# Get the tags, moments and symbols of the selected atomsa
for i in range(len(atoms)):
if self.images.selected[i]:
if not(s_tag):
s_tag = str(atoms[i].tag)
elif s_tag != str(atoms[i].tag):
s_tag = 'X'
if not(s_mom):
s_mom = ("%2.2f" % (atoms[i].magmom))
elif s_mom != ("%2.2f" % (atoms[i].magmom)):
s_mom = 'X'
if not(s_symbol):
s_symbol = str(atoms[i].symbol)
elif s_symbol != str(atoms[i].symbol):
s_symbol = 'X'
self.add_entries = []
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.add_entries.append(window)
window.set_title(_('Modify'))
vbox = gtk.VBox(False, 0)
window.add(vbox)
vbox.show()
pack = False
for i, j in [[_('Atom'), s_symbol],
[_('Tag'), s_tag],
[_('Moment'), s_mom]]:
label = gtk.Label(i)
if not pack:
vbox.pack_start(label, True, True, 0)
else:
pack = True
vbox.add(label)
label.show()
entry = gtk.Entry()
entry.set_text(j)
self.add_entries.append(entry)
entry.set_max_length(50)
entry.show()
vbox.add(entry)
button = gtk.Button(_('_OK'))
button.connect('clicked', self.modify_atoms, 'OK')
button.show()
vbox.add(button)
button = gtk.Button(_('_Cancel'))
button.connect('clicked', self.modify_atoms, 'Cancel')
button.show()
vbox.add(button)
window.show()
def delete_selected_atoms(self, widget=None, data=None):
if data == 'OK':
atoms = self.images.get_atoms(self.frame)
lena = len(atoms)
for i in range(len(atoms)):
li = lena-1-i
if self.images.selected[li]:
del(atoms[li])
self.new_atoms(atoms)
self.draw()
if data:
self.delete_window.destroy()
if not(data) and sum(self.images.selected):
nselected = sum(self.images.selected)
self.delete_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.delete_window.set_title(_('Confirmation'))
self.delete_window.set_border_width(10)
self.box1 = gtk.HBox(False, 0)
self.delete_window.add(self.box1)
self.button1 = gtk.Button(ngettext('Delete selected atom?',
'Delete selected atoms?',
nselected))
self.button1.connect("clicked", self.delete_selected_atoms, "OK")
self.box1.pack_start(self.button1, True, True, 0)
self.button1.show()
self.button2 = gtk.Button(_("Cancel"))
self.button2.connect("clicked", self.delete_selected_atoms, "Cancel")
self.box1.pack_start(self.button2, True, True, 0)
self.button2.show()
self.box1.show()
self.delete_window.show()
def debug(self, x):
from ase.gui.debug import Debug
Debug(self)
def execute(self, widget=None):
from ase.gui.execute import Execute
Execute(self)
def constraints_window(self, widget=None):
from ase.gui.constraints import Constraints
Constraints(self)
def dft_window(self, widget=None):
from ase.gui.dft import DFT
DFT(self)
def select_all(self, widget):
self.images.selected[:] = True
self.draw()
def invert_selection(self, widget):
self.images.selected[:] = ~self.images.selected
self.draw()
def select_constrained_atoms(self, widget):
self.images.selected[:] = ~self.images.dynamic
self.draw()
def select_immobile_atoms(self, widget):
if self.images.nimages > 1:
R0 = self.images.P[0]
for R in self.images.P[1:]:
self.images.selected[:] =~ (np.abs(R - R0) > 1.0e-10).any(1)
self.draw()
def movie(self, widget=None):
from ase.gui.movie import Movie
self.movie_window = Movie(self)
def plot_graphs(self, x=None, expr=None):
from ase.gui.graphs import Graphs
g = Graphs(self)
if expr is not None:
g.plot(expr=expr)
self.graph_wref.append(weakref.ref(g))
def plot_graphs_newatoms(self):
"Notify any Graph objects that they should make new plots."
new_wref = []
found = 0
for wref in self.graph_wref:
ref = wref()
if ref is not None:
ref.plot()
new_wref.append(wref) # Preserve weakrefs that still work.
found += 1
self.graph_wref = new_wref
return found
def NEB(self, action):
from ase.gui.neb import NudgedElasticBand
NudgedElasticBand(self.images)
def bulk_modulus(self, action):
from ase.gui.bulk_modulus import BulkModulus
BulkModulus(self.images)
def open(self, button=None, filenames=None):
if filenames == None:
chooser = gtk.FileChooserDialog(
_('Open ...'), None, gtk.FILE_CHOOSER_ACTION_OPEN,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
chooser.set_filename(_("<>"))
# Add a file type filter
name_to_suffix = {}
types = gtk.combo_box_new_text()
for name, suffix in [(_('Automatic'), None),
(_('Dacapo netCDF output file'),'dacapo'),
(_('Virtual Nano Lab file'),'vnl'),
(_('ASE pickle trajectory'),'traj'),
(_('ASE bundle trajectory'),'bundle'),
(_('GPAW text output'),'gpaw-text'),
(_('CUBE file'),'cube'),
(_('XCrySDen Structure File'),'xsf'),
(_('Dacapo text output'),'dacapo-text'),
(_('XYZ-file'),'xyz'),
(_('VASP POSCAR/CONTCAR file'),'vasp'),
(_('VASP OUTCAR file'),'vasp_out'),
(_('Protein Data Bank'),'pdb'),
(_('CIF-file'),'cif'),
(_('FHI-aims geometry file'),'aims'),
(_('FHI-aims output file'),'aims_out'),
(_('TURBOMOLE coord file'),'tmol'),
(_('exciting input'),'exi'),
(_('WIEN2k structure file'),'struct'),
(_('DftbPlus input file'),'dftb'),
(_('ETSF format'),'etsf.nc'),
(_('CASTEP geom file'),'cell'),
(_('CASTEP output file'),'castep'),
(_('CASTEP trajectory file'),'geom'),
(_('DFTBPlus GEN format'),'gen')
]:
types.append_text(name)
name_to_suffix[name] = suffix
types.set_active(0)
img_vbox = gtk.VBox()
pack(img_vbox, [gtk.Label(_('File type:')), types])
img_vbox.show()
chooser.set_extra_widget(img_vbox)
ok = chooser.run() == gtk.RESPONSE_OK
if ok:
filenames = [chooser.get_filename()]
filetype = types.get_active_text()
chooser.destroy()
if not ok:
return
n_current = self.images.nimages
self.reset_tools_modes()
self.images.read(filenames, slice(None), name_to_suffix[filetype])
self.set_colors()
self.set_coordinates(self.images.nimages - 1, focus=True)
def import_atoms (self, button=None, filenames=None):
if filenames == None:
chooser = gtk.FileChooserDialog(
_('Open ...'), None, gtk.FILE_CHOOSER_ACTION_OPEN,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
ok = chooser.run()
if ok == gtk.RESPONSE_OK:
filenames = [chooser.get_filename()]
chooser.destroy()
if not ok:
return
self.images.import_atoms(filenames, self.frame)
self.set_colors()
self.set_coordinates(self.images.nimages - 1, focus=True)
def save(self, action):
chooser = gtk.FileChooserDialog(
_('Save ...'), None, gtk.FILE_CHOOSER_ACTION_SAVE,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
try:
fname = sys.argv[1]
except IndexError:
fname = "<>"
chooser.set_filename(fname)
# Add a file type filter
types = []
name_to_suffix = {}
for name, suffix in [(_('Automatic'), None),
(_('XYZ file'), 'xyz'),
(_('ASE trajectory'), 'traj'),
(_('PDB file'), 'pdb'),
(_('Gaussian cube file'), 'cube'),
(_('Python script'), 'py'),
(_('VNL file'), 'vnl'),
(_('Portable Network Graphics'), 'png'),
(_('Persistence of Vision'), 'pov'),
(_('Encapsulated PostScript'), 'eps'),
(_('FHI-aims geometry input'), 'in'),
(_('CASTEP geom file'),'cell'),
(_('VASP geometry input'), 'POSCAR'),
(_('ASE bundle trajectory'), 'bundle'),
(_('cif file'), 'cif'),
]:
if suffix is None:
name = _(name)
else:
name = '%s (%s)' % (_(name), suffix)
filt = gtk.FileFilter()
filt.set_name(name)
if suffix is None:
filt.add_pattern('*')
elif suffix == 'POSCAR':
filt.add_pattern('*POSCAR*')
else:
filt.add_pattern('*.'+suffix)
if suffix is not None:
types.append(suffix)
name_to_suffix[name] = suffix
chooser.add_filter(filt)
if self.images.nimages > 1:
img_vbox = gtk.VBox()
button = gtk.CheckButton(_('Save current image only (#%d)') %
self.frame)
pack(img_vbox, button)
entry = gtk.Entry(10)
pack(img_vbox, [gtk.Label(_('Slice: ')), entry,
help(_('Help for slice ...'))])
entry.set_text('0:%d' % self.images.nimages)
img_vbox.show()
chooser.set_extra_widget(img_vbox)
while True:
# Loop until the user selects a proper file name, or cancels.
response = chooser.run()
if response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
chooser.destroy()
return
elif response != gtk.RESPONSE_OK:
print >>sys.stderr, _("AG INTERNAL ERROR: strange response in Save,"), response
chooser.destroy()
return
filename = chooser.get_filename()
suffix = os.path.splitext(filename)[1][1:]
if 'POSCAR' in filename or 'CONTCAR' in filename:
suffix = 'POSCAR'
if suffix == '':
# No suffix given. If the user has chosen a special
# file type, use the corresponding suffix.
filt = chooser.get_filter().get_name()
suffix = name_to_suffix[filt]
filename = filename + '.' + suffix
# XXX FIXME the window saying unknown output format
# cannot be closed
if suffix not in types:
oops(message=_('Unknown output format!'),
message2=_('Use one of: %s') % ', '.join(types[1:]))
continue
if self.images.nimages > 1:
if button.get_active():
filename += '@%d' % self.frame
else:
filename += '@' + entry.get_text()
break
chooser.destroy()
bbox = np.empty(4)
size = np.array([self.width, self.height]) / self.scale
bbox[0:2] = np.dot(self.center, self.axes[:, :2]) - size / 2
bbox[2:] = bbox[:2] + size
suc = self.ui.get_widget('/MenuBar/ViewMenu/ShowUnitCell').get_active()
extra_args = {}
if suffix in ['eps', 'png', 'pov', 'png']:
extra_args['colors'] = self.get_colors(rgb=True)
self.images.write(filename, self.axes, show_unit_cell=suc, bbox=bbox, **extra_args)
def quick_info_window(self, menuitem):
QuickInfo(self)
def bulk_window(self, menuitem):
SetupBulkCrystal(self)
def surface_window(self, menuitem):
SetupSurfaceSlab(self)
def nanoparticle_window(self, menuitem):
SetupNanoparticle(self)
def graphene_window(self, menuitem):
SetupGraphene(self)
def nanotube_window(self, menuitem):
SetupNanotube(self)
def calculator_window(self, menuitem):
SetCalculator(self)
def energy_window(self, menuitem):
EnergyForces(self)
def energy_minimize_window(self, menuitem):
Minimize(self)
def scaling_window(self, menuitem):
HomogeneousDeformation(self)
def new_atoms(self, atoms, init_magmom=False):
"Set a new atoms object."
self.reset_tools_modes()
rpt = getattr(self.images, 'repeat', None)
self.images.repeat_images(np.ones(3, int))
self.images.initialize([atoms], init_magmom=init_magmom)
self.frame = 0 # Prevent crashes
self.images.repeat_images(rpt)
self.set_colors()
self.set_coordinates(frame=0, focus=True)
self.notify_vulnerable()
def prepare_new_atoms(self):
"Marks that the next call to append_atoms should clear the images."
self.images.prepare_new_atoms()
def append_atoms(self, atoms):
"Set a new atoms object."
#self.notify_vulnerable() # Do this manually after last frame.
frame = self.images.append_atoms(atoms)
self.set_coordinates(frame=frame-1, focus=True)
def notify_vulnerable(self):
"""Notify windows that would break when new_atoms is called.
The notified windows may adapt to the new atoms. If that is not
possible, they should delete themselves.
"""
new_vul = [] # Keep weakrefs to objects that still exist.
for wref in self.vulnerable_windows:
ref = wref()
if ref is not None:
new_vul.append(wref)
ref.notify_atoms_changed()
self.vulnerable_windows = new_vul
def register_vulnerable(self, obj):
"""Register windows that are vulnerable to changing the images.
Some windows will break if the atoms (and in particular the
number of images) are changed. They can register themselves
and be closed when that happens.
"""
self.vulnerable_windows.append(weakref.ref(obj))
def exit(self, button, event=None):
self.window.destroy()
gtk.main_quit()
return True
def xxx(self, x=None,
message1=_('Not implemented!'),
message2=_('do you really need it?')):
oops(message1, message2)
def about(self, action):
try:
dialog = gtk.AboutDialog()
except AttributeError:
self.xxx()
else:
dialog.run()
def webpage(widget):
import webbrowser
webbrowser.open('https://wiki.fysik.dtu.dk/ase/ase/gui.html')
python-ase-3.6.0.2515/ase/gui/images.py 0000644 0001754 0001754 00000035271 11672656022 016372 0 ustar askhl askhl from math import sqrt
import numpy as np
from ase.data import covalent_radii
from ase.atoms import Atoms
from ase.calculators.singlepoint import SinglePointCalculator
from ase.io import read, write, string2index
from ase.constraints import FixAtoms
from ase.gui.defaults import read_defaults
from ase.quaternions import Quaternion
class Images:
def __init__(self, images=None):
if images is not None:
self.initialize(images)
def initialize(self, images, filenames=None, init_magmom=False):
self.natoms = len(images[0])
self.nimages = len(images)
if hasattr(images[0], 'get_shapes'):
self.shapes = images[0].get_shapes()
self.Q = []
else:
self.shapes = None
if filenames is None:
filenames = [None] * self.nimages
self.filenames = filenames
self.P = np.empty((self.nimages, self.natoms, 3))
self.V = np.empty((self.nimages, self.natoms, 3))
self.E = np.empty(self.nimages)
self.K = np.empty(self.nimages)
self.F = np.empty((self.nimages, self.natoms, 3))
self.M = np.empty((self.nimages, self.natoms))
self.T = np.empty((self.nimages, self.natoms), int)
self.A = np.empty((self.nimages, 3, 3))
self.Z = images[0].get_atomic_numbers()
self.pbc = images[0].get_pbc()
self.covalent_radii = covalent_radii
config = read_defaults()
if config['covalent_radii'] is not None:
for data in config['covalent_radii']:
self.covalent_radii[data[0]] = data[1]
warning = False
for i, atoms in enumerate(images):
natomsi = len(atoms)
if (natomsi != self.natoms or
(atoms.get_atomic_numbers() != self.Z).any()):
raise RuntimeError('Can not handle different images with ' +
'different numbers of atoms or different ' +
'kinds of atoms!')
self.P[i] = atoms.get_positions()
self.V[i] = atoms.get_velocities()
if hasattr(self, 'Q'):
for q in atoms.get_quaternions():
self.Q.append(Quaternion(q))
self.A[i] = atoms.get_cell()
if (atoms.get_pbc() != self.pbc).any():
warning = True
try:
self.E[i] = atoms.get_potential_energy()
except RuntimeError:
self.E[i] = np.nan
self.K[i] = atoms.get_kinetic_energy()
try:
self.F[i] = atoms.get_forces(apply_constraint=False)
except RuntimeError:
self.F[i] = np.nan
try:
if init_magmom:
self.M[i] = atoms.get_initial_magnetic_moments()
else:
self.M[i] = atoms.get_magnetic_moments()
except (RuntimeError, AttributeError):
self.M[i] = atoms.get_initial_magnetic_moments()
# added support for tags
try:
self.T[i] = atoms.get_tags()
except RuntimeError:
self.T[i] = 0
if warning:
print('WARNING: Not all images have the same bondary conditions!')
self.selected = np.zeros(self.natoms, bool)
self.selected_ordered = []
self.atoms_to_rotate_0 = np.zeros(self.natoms, bool)
self.visible = np.ones(self.natoms, bool)
self.nselected = 0
self.set_dynamic(constraints = images[0].constraints)
self.repeat = np.ones(3, int)
self.set_radii(0.89)
def prepare_new_atoms(self):
"Marks that the next call to append_atoms should clear the images."
self.next_append_clears = True
def append_atoms(self, atoms, filename=None):
"Append an atoms object to the images already stored."
assert len(atoms) == self.natoms
if self.next_append_clears:
i = 0
else:
i = self.nimages
for name in ('P', 'V', 'E', 'K', 'F', 'M', 'A', 'T'):
a = getattr(self, name)
newa = np.empty( (i+1,) + a.shape[1:], a.dtype )
if not self.next_append_clears:
newa[:-1] = a
setattr(self, name, newa)
self.next_append_clears = False
self.P[i] = atoms.get_positions()
self.V[i] = atoms.get_velocities()
self.A[i] = atoms.get_cell()
try:
self.E[i] = atoms.get_potential_energy()
except RuntimeError:
self.E[i] = np.nan
self.K[i] = atoms.get_kinetic_energy()
try:
self.F[i] = atoms.get_forces(apply_constraint=False)
except RuntimeError:
self.F[i] = np.nan
try:
self.M[i] = atoms.get_magnetic_moments()
except (RuntimeError, AttributeError):
self.M[i] = np.nan
try:
self.T[i] = atoms.get_tags()
except AttributeError:
if i == 0:
self.T[i] = 0
else:
self.T[i] = self.T[i-1]
self.nimages = i + 1
self.filenames.append(filename)
self.set_dynamic()
return self.nimages
def set_radii(self, scale):
if self.shapes == None:
self.r = self.covalent_radii[self.Z] * scale
else:
self.r = np.sqrt(np.sum(self.shapes**2, axis=1)) * scale
def read(self, filenames, index=-1, filetype=None):
images = []
names = []
for filename in filenames:
i = read(filename, index,filetype)
if not isinstance(i, list):
i = [i]
images.extend(i)
names.extend([filename] * len(i))
self.initialize(images, names)
def import_atoms(self, filename, cur_frame):
if filename:
filename = filename[0]
old_a = self.get_atoms(cur_frame)
imp_a = read(filename, -1)
new_a = old_a + imp_a
self.initialize([new_a], [filename])
def repeat_images(self, repeat):
n = self.repeat.prod()
repeat = np.array(repeat)
self.repeat = repeat
N = repeat.prod()
natoms = self.natoms // n
P = np.empty((self.nimages, natoms * N, 3))
V = np.empty((self.nimages, natoms * N, 3))
M = np.empty((self.nimages, natoms * N))
T = np.empty((self.nimages, natoms * N), int)
F = np.empty((self.nimages, natoms * N, 3))
Z = np.empty(natoms * N, int)
r = np.empty(natoms * N)
dynamic = np.empty(natoms * N, bool)
a0 = 0
for i0 in range(repeat[0]):
for i1 in range(repeat[1]):
for i2 in range(repeat[2]):
a1 = a0 + natoms
for i in range(self.nimages):
P[i, a0:a1] = (self.P[i, :natoms] +
np.dot((i0, i1, i2), self.A[i]))
V[:, a0:a1] = self.V[:, :natoms]
F[:, a0:a1] = self.F[:, :natoms]
M[:, a0:a1] = self.M[:, :natoms]
T[:, a0:a1] = self.T[:, :natoms]
Z[a0:a1] = self.Z[:natoms]
r[a0:a1] = self.r[:natoms]
dynamic[a0:a1] = self.dynamic[:natoms]
a0 = a1
self.P = P
self.V = V
self.F = F
self.Z = Z
self.T = T
self.M = M
self.r = r
self.dynamic = dynamic
self.natoms = natoms * N
self.selected = np.zeros(natoms * N, bool)
self.atoms_to_rotate_0 = np.zeros(self.natoms, bool)
self.visible = np.ones(natoms * N, bool)
self.nselected = 0
def center(self):
""" center each image in the existing unit cell, keeping the cell constant. """
c = self.A.sum(axis=1) / 2.0 - self.P.mean(axis=1)
self.P += c[:, np.newaxis, :]
def graph(self, expr):
""" routine to create the data in ag graphs, defined by the string expr. """
import ase.units as units
code = compile(expr + ',', 'atoms.py', 'eval')
n = self.nimages
def d(n1, n2):
return sqrt(((R[n1] - R[n2])**2).sum())
def a(n1, n2, n3):
v1 = R[n1]-R[n2]
v2 = R[n3]-R[n2]
arg = np.vdot(v1,v2)/(sqrt((v1**2).sum()*(v2**2).sum()))
if arg > 1.0: arg = 1.0
if arg < -1.0: arg = -1.0
return 180.0*np.arccos(arg)/np.pi
def dih(n1, n2, n3, n4):
# vector 0->1, 1->2, 2->3 and their normalized cross products:
a = R[n2]-R[n1]
b = R[n3]-R[n2]
c = R[n4]-R[n3]
bxa = np.cross(b,a)
bxa /= np.sqrt(np.vdot(bxa,bxa))
cxb = np.cross(c,b)
cxb /= np.sqrt(np.vdot(cxb,cxb))
angle = np.vdot(bxa,cxb)
# check for numerical trouble due to finite precision:
if angle < -1: angle = -1
if angle > 1: angle = 1
angle = np.arccos(angle)
if (np.vdot(bxa,c)) > 0: angle = 2*np.pi-angle
return angle*180.0/np.pi
# get number of mobile atoms for temperature calculation
ndynamic = 0
for dyn in self.dynamic:
if dyn: ndynamic += 1
S = self.selected
D = self.dynamic[:, np.newaxis]
E = self.E
s = 0.0
data = []
for i in range(n):
R = self.P[i]
V = self.V[i]
F = self.F[i]
A = self.A[i]
M = self.M[i]
f = ((F * D)**2).sum(1)**.5
fmax = max(f)
fave = f.mean()
epot = E[i]
ekin = self.K[i]
e = epot + ekin
T = 2.0 * ekin / (3.0 * ndynamic * units.kB)
data = eval(code)
if i == 0:
m = len(data)
xy = np.empty((m, n))
xy[:, i] = data
if i + 1 < n:
s += sqrt(((self.P[i + 1] - R)**2).sum())
return xy
def set_dynamic(self, constraints = None):
self.dynamic = np.ones(self.natoms, bool)
if constraints is not None:
for con in constraints:
if isinstance(con,FixAtoms):
self.dynamic[con.index] = False
def write(self, filename, rotations='', show_unit_cell=False, bbox=None, **kwargs):
indices = range(self.nimages)
p = filename.rfind('@')
if p != -1:
try:
slice = string2index(filename[p + 1:])
except ValueError:
pass
else:
indices = indices[slice]
filename = filename[:p]
if isinstance(indices, int):
indices = [indices]
images = [self.get_atoms(i) for i in indices]
if len(filename) > 4 and filename[-4:] in ['.eps', '.png', '.pov']:
write(filename, images,
rotation=rotations, show_unit_cell=show_unit_cell,
bbox=bbox, **kwargs)
else:
write(filename, images, **kwargs)
def get_atoms(self, frame):
atoms = Atoms(positions=self.P[frame],
numbers=self.Z,
magmoms=self.M[0],
tags=self.T[frame],
cell=self.A[frame],
pbc=self.pbc)
if not np.isnan(self.V).any():
atoms.set_velocities(self.V[frame])
# check for constrained atoms and add them accordingly:
if not self.dynamic.all():
atoms.set_constraint(FixAtoms(mask=1-self.dynamic))
atoms.set_calculator(SinglePointCalculator(self.E[frame],
self.F[frame],
None, None, atoms))
return atoms
def delete(self, i):
self.nimages -= 1
P = np.empty((self.nimages, self.natoms, 3))
V = np.empty((self.nimages, self.natoms, 3))
F = np.empty((self.nimages, self.natoms, 3))
A = np.empty((self.nimages, 3, 3))
E = np.empty(self.nimages)
P[:i] = self.P[:i]
P[i:] = self.P[i + 1:]
self.P = P
V[:i] = self.V[:i]
V[i:] = self.V[i + 1:]
self.V = V
F[:i] = self.F[:i]
F[i:] = self.F[i + 1:]
self.F = F
A[:i] = self.A[:i]
A[i:] = self.A[i + 1:]
self.A = A
E[:i] = self.E[:i]
E[i:] = self.E[i + 1:]
self.E = E
del self.filenames[i]
def aneb(self):
n = self.nimages
assert n % 5 == 0
levels = n // 5
n = self.nimages = 2 * levels + 3
P = np.empty((self.nimages, self.natoms, 3))
V = np.empty((self.nimages, self.natoms, 3))
F = np.empty((self.nimages, self.natoms, 3))
E = np.empty(self.nimages)
for L in range(levels):
P[L] = self.P[L * 5]
P[n - L - 1] = self.P[L * 5 + 4]
V[L] = self.V[L * 5]
V[n - L - 1] = self.V[L * 5 + 4]
F[L] = self.F[L * 5]
F[n - L - 1] = self.F[L * 5 + 4]
E[L] = self.E[L * 5]
E[n - L - 1] = self.E[L * 5 + 4]
for i in range(3):
P[levels + i] = self.P[levels * 5 - 4 + i]
V[levels + i] = self.V[levels * 5 - 4 + i]
F[levels + i] = self.F[levels * 5 - 4 + i]
E[levels + i] = self.E[levels * 5 - 4 + i]
self.P = P
self.V = V
self.F = F
self.E = E
def interpolate(self, m):
assert self.nimages == 2
self.nimages = 2 + m
P = np.empty((self.nimages, self.natoms, 3))
V = np.empty((self.nimages, self.natoms, 3))
F = np.empty((self.nimages, self.natoms, 3))
A = np.empty((self.nimages, 3, 3))
E = np.empty(self.nimages)
P[0] = self.P[0]
V[0] = self.V[0]
F[0] = self.F[0]
A[0] = self.A[0]
E[0] = self.E[0]
for i in range(1, m + 1):
x = i / (m + 1.0)
y = 1 - x
P[i] = y * self.P[0] + x * self.P[1]
V[i] = y * self.V[0] + x * self.V[1]
F[i] = y * self.F[0] + x * self.F[1]
A[i] = y * self.A[0] + x * self.A[1]
E[i] = y * self.E[0] + x * self.E[1]
P[-1] = self.P[1]
V[-1] = self.V[1]
F[-1] = self.F[1]
A[-1] = self.A[1]
E[-1] = self.E[1]
self.P = P
self.V = V
self.F = F
self.A = A
self.E = E
self.filenames[1:1] = [None] * m
if __name__ == '__main__':
import os
os.system('python gui.py')
python-ase-3.6.0.2515/ase/gui/repeat.py 0000644 0001754 0001754 00000002463 11706276516 016406 0 ustar askhl askhl #!/usr/bin/env python
import gtk
from math import sqrt
from gettext import gettext as _
import numpy as np
from ase.gui.widgets import pack, Help
class Repeat(gtk.Window):
def __init__(self, gui):
gtk.Window.__init__(self)
self.set_title(_('Repeat'))
vbox = gtk.VBox()
pack(vbox, gtk.Label(_('Repeat atoms:')))
self.repeat = [gtk.Adjustment(r, 1, 9, 1) for r in gui.images.repeat]
pack(vbox, [gtk.SpinButton(r, 0, 0) for r in self.repeat])
for r in self.repeat:
r.connect('value-changed', self.change)
button = pack(vbox, gtk.Button(_('Set unit cell')))
button.connect('clicked', self.set_unit_cell)
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
def change(self, adjustment):
self.gui.images.repeat_images([int(r.value) for r in self.repeat])
self.gui.repeat_colors([int(r.value) for r in self.repeat])
self.gui.set_coordinates()
return True
def set_unit_cell(self, button):
self.gui.images.A *= self.gui.images.repeat.reshape((3, 1))
self.gui.images.E *= self.gui.images.repeat.prod()
self.gui.images.repeat = np.ones(3, int)
for r in self.repeat:
r.value = 1
self.gui.set_coordinates()
python-ase-3.6.0.2515/ase/gui/dft.py 0000644 0001754 0001754 00000002701 11706276516 015676 0 ustar askhl askhl #!/usr/bin/env python
from math import sqrt
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack, Help
class DFT(gtk.Window):
def __init__(self, gui):
gtk.Window.__init__(self)
self.set_title(_('DFT'))
vbox = gtk.VBox()
combo = gtk.combo_box_new_text()
self.xcfuncs = 'None LDA PBE revPBE RPBE PW91 EXX PBE0'.split()
for xc in self.xcfuncs:
combo.append_text(xc)
pack(vbox, [gtk.Label(_('XC-functional: ')), combo])
button=radio(None,monkhorstpack)
button=radio(button, special)
pack(vbox, gtk.Label(_('Repeat atoms:')))
self.kpts = [gtk.Adjustment(r, 1, 99, 1) for r in gui.atoms.repeat]
pack(vbox, [gtk.SpinButton(r, 0, 0) for r in self.repeat])
for r in self.repeat:
r.connect('value-changed', self.change)
close = pack(vbox, gtk.Button(_('Close')))
close.connect('clicked', lambda widget: self.destroy())
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
xc = gui.atoms.dft.get('xc', 'None')
combo.set_active(self.xcfuncs.index(xc))
def selected(self, button):
self.gui.atoms.dynamic = ~self.gui.atoms.selected
self.gui.draw()
def immobile(self, button):
self.gui.atoms.set_dynamic()
self.gui.draw()
def clear(self, button):
self.gui.atoms.dynamic[:] = True
self.gui.draw()
python-ase-3.6.0.2515/ase/gui/pybutton.py 0000644 0001754 0001754 00000004635 11711330540 016775 0 ustar askhl askhl
"""pybutton.py - a button for displaying Python code.
This module defines two classes, together they implement a button that
a module can use to display Python.
PyButton
--------
PyButton is a gkt.Button with the label 'Python'. When pressed, it
opens a PyWindow displaying some Python code, or an error message if
no Python code is ready.
The script is stored in the attribute .python, it is the
responsability of the owning object to keep this attribute up to date:
when pressing the Apply button would result in a sensible
configuration being created, the python attribute must be set to a
string creating this code. When pressing Apply would cause an error,
the python attribute must be set to None.
PyWindow
--------
Displays the Python code. This object is created by the PyButton
object when needed.
"""
import gtk
from gettext import gettext as _
import time
from ase.gui.widgets import oops, pack
class PyButton(gtk.Button):
"A button for displaying Python code."
def __init__(self, title):
gtk.Button.__init__(self, _("Python"))
self.title = title
self.python = None
self.connect_after('clicked', self.run)
def run(self, *args):
"The method called when the button is clicked."
if self.python:
now = time.ctime()
win = PyWindow(self.title, now, self.python)
else:
oops(_("No Python code"),
_("You have not (yet) specified a "
"consistent set of parameters."))
fr1_template = _("""
Title: %(title)s
Time: %(time)s
""")
class PyWindow(gtk.Window):
"A window displaying Python code."
def __init__(self, title, time, code):
gtk.Window.__init__(self)
self.set_title(_("ag: Python code"))
vbox = gtk.VBox()
lbl = gtk.Label(fr1_template % dict(title=title, time=time))
lbl.set_alignment(0.0, 0.5)
fr = gtk.Frame(_("Information:"))
fr.add(lbl)
pack(vbox, fr)
txtbuf = gtk.TextBuffer()
txtbuf.set_text(code)
txtview = gtk.TextView(txtbuf)
txtview.set_editable(False)
fr = gtk.Frame(_("Python code:"))
fr.add(txtview)
fr.set_label_align(0.0, 0.5)
pack(vbox, fr)
but = gtk.Button(stock=gtk.STOCK_OK)
but.connect('clicked', lambda x: self.destroy())
pack(vbox, [but], end=True, bottom=True)
self.add(vbox)
self.show_all()
python-ase-3.6.0.2515/ase/gui/i18n.py 0000644 0001754 0001754 00000000646 11706327763 015707 0 ustar askhl askhl import os
import locale
import gettext
# This module enables localization using gettext. If this module has
# been imported, translations will be loaded from mo-files when
# possible.
domain = 'ag'
localedir = '%s/po/' % os.path.dirname(__file__)
gettext.bindtextdomain(domain, localedir)
gettext.textdomain(domain)
translation = gettext.translation(domain, localedir, fallback=True)
translation.install(unicode=True)
python-ase-3.6.0.2515/ase/gui/rot_tools.py 0000644 0001754 0001754 00000003121 11401652206 017124 0 ustar askhl askhl # Gives the rotation matrix which rotates theta degrees about
# vecU
# Generates the rotation matrix that rotate theta degrees about the vecU
def rotate_about_vec(vecU, theta):
import numpy as np
vecU = np.array(vecU)
vecU = vecU / (sum(vecU ** 2) ** 0.5)
ux, uy, uz = vecU
st = np.sin(theta)
ct = np.cos(theta)
mat = np.array([[ux ** 2 + ct * (1 - ux ** 2),
ux * uy * (1 - ct) - uz * st,
uz * ux * (1 - ct) + uy * st],
[ux * uy * (1 - ct) + uz * st,
uy ** 2 + ct * (1 - uy ** 2),
uy * uz * (1 - ct) - ux * st],
[uz * ux * (1 - ct) - uy * st,
uy * uz * (1 - ct) + ux * st,
uz ** 2 + ct * (1 - uz **2)]])
return (mat)
# Generates the rotation matrix which rotates aVec into intoVec
def rotate_vec_into_newvec(aVec, intoVec):
def length(v):
return((sum(v ** 2)) ** 0.5)
import numpy as np
from math import acos
fac = 1.0
aVec = np.array(aVec)
intoVec = np.array(intoVec)
nor = np.cross(aVec, intoVec)
if length(nor) == 0:
nor = np.array([1, 0, 0])
nor = nor / length(nor)
theta = acos(np.dot(aVec, intoVec) / (length(aVec) * length(intoVec)))
if np.dot(aVec, intoVec) < 0:
theta = theta + np.pi
fac = -1
return(fac * rotate_about_vec(nor, theta))
# Applies the rotation matrix to the vector and returns the rotated vector
def rotate_vec (rot_mat, vec):
import numpy as np
rot_vec = np.dot(rot_mat, vec)
return (rot_vec)
python-ase-3.6.0.2515/ase/gui/view.py 0000644 0001754 0001754 00000070457 11715550644 016105 0 ustar askhl askhl #!/usr/bin/env python
# Emacs: treat this as -*- python -*-
import os
import gtk
import tempfile
from math import cos, sin, sqrt, atan
from os.path import basename
import numpy as np
from ase.data.colors import jmol_colors
from ase.gui.repeat import Repeat
from ase.gui.rotate import Rotate
from ase.gui.render import Render
from ase.gui.colors import ColorWindow
from ase.utils import rotate
class View:
def __init__(self, vbox, rotations):
self.colormode = 'jmol' # The default colors
self.nselected = 0
self.light_green_markings = 0
self.axes = rotate(rotations)
# this is a hack, in order to be able to toggle menu actions off/on
# without getting into an infinte loop
self.menu_change = 0
self.atoms_to_rotate = None
self.drawing_area = gtk.DrawingArea()
self.drawing_area.set_size_request(450, 450)
self.drawing_area.connect('button_press_event', self.press)
self.drawing_area.connect('button_release_event', self.release)
self.drawing_area.connect('motion-notify-event', self.move)
# Signals used to handle backing pixmap:
self.drawing_area.connect('expose_event', self.expose_event)
self.drawing_area.connect('configure_event', self.configure_event)
self.drawing_area.set_events(gtk.gdk.BUTTON_PRESS_MASK |
gtk.gdk.BUTTON_RELEASE_MASK |
gtk.gdk.BUTTON_MOTION_MASK |
gtk.gdk.POINTER_MOTION_HINT_MASK)
vbox.pack_start(self.drawing_area)
self.drawing_area.show()
self.configured = False
self.frame = None
def set_coordinates(self, frame=None, focus=None):
if frame is None:
frame = self.frame
self.make_box()
self.bind(frame)
n = self.images.natoms
self.X = np.empty((n + len(self.B1) + len(self.bonds), 3))
#self.X[n:] = np.dot(self.B1, self.images.A[frame])
#self.B = np.dot(self.B2, self.images.A[frame])
self.set_frame(frame, focus=focus, init=True)
def set_frame(self, frame=None, focus=False, init=False):
if frame is None:
frame = self.frame
n = self.images.natoms
if self.frame > self.images.nimages:
self.frame = self.images.nimages - 1
if init or frame != self.frame:
A = self.images.A
nc = len(self.B1)
nb = len(self.bonds)
if init or (A[frame] != A[self.frame]).any():
self.X[n:n + nc] = np.dot(self.B1, A[frame])
self.B = np.empty((nc + nb, 3))
self.B[:nc] = np.dot(self.B2, A[frame])
if nb > 0:
P = self.images.P[frame]
Af = self.images.repeat[:, np.newaxis] * A[frame]
a = P[self.bonds[:, 0]]
b = P[self.bonds[:, 1]] + np.dot(self.bonds[:, 2:], Af) - a
d = (b**2).sum(1)**0.5
r = 0.65 * self.images.r
x0 = (r[self.bonds[:, 0]] / d).reshape((-1, 1))
x1 = (r[self.bonds[:, 1]] / d).reshape((-1, 1))
self.X[n + nc:] = a + b * x0
b *= 1.0 - x0 - x1
b[self.bonds[:, 2:].any(1)] *= 0.5
self.B[nc:] = self.X[n + nc:] + b
filenames = self.images.filenames
filename = filenames[frame]
if self.frame is None or filename != filenames[self.frame] or filename is None:
if filename is None:
filename = 'ase.gui'
filename = basename(filename)
self.window.set_title(filename)
self.frame = frame
self.X[:n] = self.images.P[frame]
self.R = self.X[:n]
if focus:
self.focus()
else:
self.draw()
def set_colors(self):
self.colormode = 'jmol'
self.set_jmol_colors()
def set_jmol_colors(self):
self.colors = [None] * (len(jmol_colors) + 1)
self.colordata = []
new = self.drawing_area.window.new_gc
alloc = self.colormap.alloc_color
for z in self.images.Z:
if self.colors[z] is None:
c, p, k = jmol_colors[z]
self.colors[z] = new(alloc(int(65535 * c),
int(65535 * p),
int(65535 * k)))
hasfound = {}
for z in self.images.Z:
if z not in hasfound:
hasfound[z] = True
self.colordata.append([z, jmol_colors[z]])
def plot_cell(self):
V = self.images.A[0]
R1 = []
R2 = []
for c in range(3):
v = V[c]
d = sqrt(np.dot(v, v))
n = max(2, int(d / 0.3))
h = v / (2 * n - 1)
R = np.arange(n)[:, None] * (2 * h)
for i, j in [(0, 0), (0, 1), (1, 0), (1, 1)]:
R1.append(R + i * V[(c + 1) % 3] + j * V[(c + 2) % 3])
R2.append(R1[-1] + h)
return np.concatenate(R1), np.concatenate(R2)
def make_box(self):
if not self.ui.get_widget('/MenuBar/ViewMenu/ShowUnitCell'
).get_active():
self.B1 = self.B2 = np.zeros((0, 3))
return
V = self.images.A[0]
nn = []
for c in range(3):
v = V[c]
d = sqrt(np.dot(v, v))
n = max(2, int(d / 0.3))
nn.append(n)
self.B1 = np.zeros((2, 2, sum(nn), 3))
self.B2 = np.zeros((2, 2, sum(nn), 3))
n1 = 0
for c, n in enumerate(nn):
n2 = n1 + n
h = 1.0 / (2 * n - 1)
R = np.arange(n) * (2 * h)
for i, j in [(0, 0), (0, 1), (1, 0), (1, 1)]:
self.B1[i, j, n1:n2, c] = R
self.B1[i, j, n1:n2, (c + 1) % 3] = i
self.B1[i, j, n1:n2, (c + 2) % 3] = j
self.B2[:, :, n1:n2] = self.B1[:, :, n1:n2]
self.B2[:, :, n1:n2, c] += h
n1 = n2
self.B1.shape = (-1, 3)
self.B2.shape = (-1, 3)
def bind(self, frame):
if not self.ui.get_widget('/MenuBar/ViewMenu/ShowBonds'
).get_active():
self.bonds = np.empty((0, 5), int)
return
from ase.atoms import Atoms
from ase.calculators.neighborlist import NeighborList
nl = NeighborList(self.images.r * 1.5, skin=0, self_interaction=False)
nl.update(Atoms(positions=self.images.P[frame],
cell=(self.images.repeat[:, np.newaxis] *
self.images.A[frame]),
pbc=self.images.pbc))
nb = nl.nneighbors + nl.npbcneighbors
self.bonds = np.empty((nb, 5), int)
if nb == 0:
return
n1 = 0
for a in range(self.images.natoms):
indices, offsets = nl.get_neighbors(a)
n2 = n1 + len(indices)
self.bonds[n1:n2, 0] = a
self.bonds[n1:n2, 1] = indices
self.bonds[n1:n2, 2:] = offsets
n1 = n2
i = self.bonds[:n2, 2:].any(1)
self.bonds[n2:, 0] = self.bonds[i, 1]
self.bonds[n2:, 1] = self.bonds[i, 0]
self.bonds[n2:, 2:] = -self.bonds[i, 2:]
def toggle_show_unit_cell(self, action):
self.set_coordinates()
def reset_tools_modes(self):
dummy = self.menu_change
self.menu_change = 1
self.atoms_to_rotate = None
for c_mode in ['Rotate', 'Orient', 'Move']:
self.ui.get_widget('/MenuBar/ToolsMenu/%sAtoms' % c_mode).set_active(False)
self.light_green_markings = 0
self.menu_change = 0
self.draw()
def toggle_mode(self, mode):
self.menu_change = 1
i_sum = 0
for c_mode in ['Rotate', 'Orient', 'Move']:
i_sum += self.ui.get_widget('/MenuBar/ToolsMenu/%sAtoms' % c_mode).get_active()
if i_sum == 0 or (i_sum == 1 and sum(self.images.selected) == 0):
self.reset_tools_modes()
return()
if i_sum == 2:
try:
self.images.selected = self.atoms_to_rotate_0.copy()
except:
self.atoms_to_rotate_0 = self.images.selected.copy()
if i_sum == 1:
self.atoms_to_rotate_0 = self.images.selected.copy()
for c_mode in ['Rotate', 'Orient', 'Move']:
if c_mode != mode:
self.ui.get_widget('/MenuBar/ToolsMenu/%sAtoms' % c_mode).set_active(False)
if self.ui.get_widget('/MenuBar/ToolsMenu/%sAtoms' % mode).get_active():
self.atoms_to_rotate_0 = self.images.selected.copy()
for i in range(len(self.images.selected)):
self.images.selected[i] = False
self.light_green_markings = 1
else:
try:
atr = self.atoms_to_rotate_0
for i in range(len(self.images.selected)):
self.images.selected[i] = atr[i]
except:
pass
self.menu_change = 0
self.draw()
def toggle_move_mode(self, action):
"""
Toggles the move mode, where the selected atoms can be moved with the arrow
keys and pg up/dn. If the shift key is pressed, the movement will be reduced.
The movement will be relative to the current rotation of the coordinate system.
The implementation of the move mode is found in the gui.scroll
"""
if not (self.menu_change):
self.toggle_mode('Move')
def toggle_rotate_mode(self, action):
"""
Toggles the rotate mode, where the selected atoms can be rotated with the arrow keys
and pg up/dn. If the shift key is pressed, the rotation angle will be reduced.
The atoms to be rotated will be marked with light green - and the COM of the selected
atoms will be used as the COM of the rotation. This can be changed while rotating the
selected atoms.
If only two atoms are seleceted, and the number of atoms to be rotated is different from
two, the selected atoms will define the axis of rotation.
The implementation of the rotate mode is found in the gui.scroll
"""
if not (self.menu_change):
self.toggle_mode('Rotate')
def toggle_orient_mode(self, action):
"""
Toggle the orientation mode - the orientation of the atoms will be changed
according to the arrow keys selected.
If nothing is selected, standard directions are x, y and z
if two atoms are selected, the standard directions are along their displacement vector
if three atoms are selected, the orientation is changed according to the normal of these
three vectors.
"""
if not (self.menu_change):
self.toggle_mode('Orient')
self.orient_normal = np.array([1.0, 0.0, 0.0])
sel_pos = []
for i, j in enumerate(self.atoms_to_rotate_0):
if j:
sel_pos.append(self.R[i])
if len(sel_pos) == 2:
self.orient_normal = sel_pos[0] - sel_pos[1]
if len(sel_pos) == 3:
v1 = sel_pos[1] - sel_pos[0]
v2 = sel_pos[1] - sel_pos[2]
self.orient_normal = np.cross(v1, v2)
self.orient_normal /= sum(self.orient_normal ** 2) ** 0.5
def toggle_show_axes(self, action):
self.draw()
def toggle_show_bonds(self, action):
self.set_coordinates()
def repeat_window(self, menuitem):
self.reset_tools_modes()
Repeat(self)
def rotate_window(self, menuitem):
Rotate(self)
def colors_window(self, menuitem):
ColorWindow(self)
def focus(self, x=None):
if (self.images.natoms == 0 and not
self.ui.get_widget('/MenuBar/ViewMenu/ShowUnitCell').get_active()):
self.scale = 1.0
self.center = np.zeros(3)
self.draw()
return
P = np.dot(self.X, self.axes)
n = self.images.natoms
P[:n] -= self.images.r[:, None]
P1 = P.min(0)
P[:n] += 2 * self.images.r[:, None]
P2 = P.max(0)
self.center = np.dot(self.axes, (P1 + P2) / 2)
S = 1.3 * (P2 - P1)
if S[0] * self.height < S[1] * self.width:
self.scale = self.height / S[1]
else:
self.scale = self.width / S[0]
self.draw()
def reset_view(self, menuitem):
self.axes = rotate('0.0x,0.0y,0.0z')
self.set_coordinates()
self.focus(self)
def get_colors(self, rgb = False):
Z = self.images.Z
if rgb:
# create a shape that is equivalent to self.colors,
# but contains rgb data instead gtk.gdk.GCX11 objects
colarray = [None] * max(len(jmol_colors)+1,len(self.colordata))
for z, c in self.colordata:
colarray[z] = c
else:
colarray = self.colors
if self.colormode == 'jmol' or self.colormode == 'atno':
colors = np.array(colarray)[Z]
elif self.colormode == 'tags':
colors = np.array(colarray)[self.images.T[self.frame]]
elif self.colormode == 'force':
F = self.images.F[self.frame]
F = np.sqrt(((F*self.images.dynamic[:,np.newaxis])**2).sum(axis=-1)) # The absolute force
nF = (F - self.colormode_force_data[0]) * self.colormode_force_data[1]
nF = np.clip(nF.astype(int), 0, len(self.colors)-1)
colors = np.array(colarray)[nF]
elif self.colormode == 'velocity':
V = self.images.V[self.frame]
V = np.sqrt((V*V).sum(axis=-1)) # The absolute velocity
nV = (V - self.colormode_velocity_data[0]) * self.colormode_velocity_data[1]
nV = np.clip(nV.astype(int), 0, len(self.colors)-1)
colors = np.array(colarray)[nV]
elif self.colormode == 'manual':
colors = colarray
elif self.colormode == 'same':
colors = [colarray[0]] * self.images.natoms
else:
raise RuntimeError('Unknown color mode: %s' % (self.colormode,))
return colors
def repeat_colors(self, repeat):
natoms = self.images.natoms
if self.colormode == 'manual':
a0 = 0
colors = self.colors
colordata = self.colordata
for i0 in range(repeat[0]):
for i1 in range(repeat[1]):
for i2 in range(repeat[2]):
a1 = a0 + natoms
colors[a0:a1] = self.colors[:natoms]
colordata[a0:a1] = self.colordata[:natoms]
a0 = a1
self.colors = colors
self.colordata = colordata
def my_arc(self, gc, fill, j, X, r, n, A):
if self.images.shapes is not None:
rx = (self.images.shapes[j, 0]).round().astype(int)
ry = (self.images.shapes[j, 1]).round().astype(int)
rz = (self.images.shapes[j, 2]).round().astype(int)
circle = rx == ry and ry == rz
else:
circle = True
if not circle:
Q = self.images.Q[j]
X2d = np.array([X[j][0], X[j][1]])
Ellipsoid = np.array([[1. / (rx*rx), 0, 0],
[0, 1. / (ry*ry), 0],
[0, 0, 1. / (rz*rz)]
])
# Ellipsoid rotatet by quaternion as Matrix X' = R X R_transpose
El_r = np.dot(Q.rotation_matrix(),
np.dot(Ellipsoid,
np.transpose(Q.rotation_matrix())))
# Ellipsoid rotated by quaternion and axes as
# Matrix X' = R_axes X' R_axes
El_v = np.dot(np.transpose(self.axes), np.dot(El_r, self.axes))
# Projection of rotatet ellipsoid on xy plane
El_p = Ell = np.array([
[El_v[0][0] - El_v[0][2] * El_v[0][2] / El_v[2][2],
El_v[0][1] - El_v[0][2] * El_v[1][2] / El_v[2][2]],
[El_v[0][1] - El_v[0][2] * El_v[1][2] / El_v[2][2],
El_v[1][1] - El_v[1][2] * El_v[1][2] / El_v[2][2]]
])
# diagonal matrix der Ellipse gibt halbachsen
El_p_diag = np.linalg.eig(El_p)
# Winkel mit dem Ellipse in xy gedreht ist aus
# eigenvektor der diagonal matrix
phi = atan(El_p_diag[1][0][1] / El_p_diag[1][0][0])
tupl = []
alpha = np.array(range(20)) *2* np.pi /20
El_xy = np.array([sqrt(1. / (El_p_diag[0][0])) *
np.cos(alpha)*np.cos(phi)
- sqrt(1./(El_p_diag[0][1])) *
np.sin(alpha) * np.sin(phi),
sqrt(1./(El_p_diag[0][0])) *
np.cos(alpha)*np.sin(phi)
+ sqrt(1./(El_p_diag[0][1])) *
np.sin(alpha) * np.cos(phi)])
tupl = (El_xy.transpose() * self.scale +
X[j][:2]).round().astype(int)
# XXX there must be a better way
tupl = [tuple(i) for i in tupl]
return self.pixmap.draw_polygon( gc, fill, tupl)
dx = dy = (2 * r).round().astype(int)
rj = dx[j]
return self.pixmap.draw_arc(gc, fill, A[j, 0], A[j, 1], rj, rj,
0, 23040)
def draw(self, status=True):
self.pixmap.draw_rectangle(self.white_gc, True, 0, 0,
self.width, self.height)
axes = self.scale * self.axes * (1, -1, 1)
offset = (np.dot(self.center, axes) -
(0.5 * self.width, 0.5 * self.height, 0))
X = np.dot(self.X, axes) - offset
n = self.images.natoms
self.indices = X[:, 2].argsort()
if self.ui.get_widget('/MenuBar/ViewMenu/ShowBonds').get_active():
r = self.images.r * (0.65 * self.scale)
else:
r = self.images.r * self.scale
P = self.P = X[:n, :2]
A = (P - r[:, None]).round().astype(int)
X1 = X[n:, :2].round().astype(int)
X2 = (np.dot(self.B, axes) - offset).round().astype(int)
d = (2 * r).round().astype(int)
selected_gc = self.selected_gc
colors = self.get_colors()
arc = self.pixmap.draw_arc
line = self.pixmap.draw_line
black_gc = self.black_gc
dynamic = self.images.dynamic
selected = self.images.selected
visible = self.images.visible
for a in self.indices:
if a < n:
ra = d[a]
if visible[a]:
self.my_arc(colors[a], True, a, X, r, n, A)
if self.light_green_markings and self.atoms_to_rotate_0[a]:
arc(self.green, False, A[a, 0] + 2, A[a, 1] + 2,
ra - 4, ra - 4, 0, 23040)
if not dynamic[a]:
R1 = int(0.14644 * ra)
R2 = int(0.85355 * ra)
line(black_gc,
A[a, 0] + R1, A[a, 1] + R1,
A[a, 0] + R2, A[a, 1] + R2)
line(black_gc,
A[a, 0] + R2, A[a, 1] + R1,
A[a, 0] + R1, A[a, 1] + R2)
if selected[a]:
self.my_arc(selected_gc, False, a, X, r, n, A)
elif visible[a]:
self.my_arc(black_gc, False, a, X, r, n, A)
else:
a -= n
line(black_gc, X1[a, 0], X1[a, 1], X2[a, 0], X2[a, 1])
if self.ui.get_widget('/MenuBar/ViewMenu/ShowAxes').get_active():
self.draw_axes()
if self.images.nimages > 1:
self.draw_frame_number()
self.drawing_area.window.draw_drawable(self.white_gc, self.pixmap,
0, 0, 0, 0,
self.width, self.height)
if status:
self.status()
def draw_axes(self):
from ase.quaternions import Quaternion
q = Quaternion().from_matrix(self.axes)
L = np.zeros((10, 2, 3))
L[:3, 1] = self.axes * 15
L[3:5] = self.axes[0] * 20
L[5:7] = self.axes[1] * 20
L[7:] = self.axes[2] * 20
L[3:, :, :2] += (((-4, -5), (4, 5)), ((-4, 5), ( 4, -5)),
((-4, 5), (0, 0)), ((-4, -5), ( 4, 5)),
((-4, 5), (4, 5)), (( 4, 5), (-4, -5)),
((-4, -5), (4, -5)))
L = L.round().astype(int)
L[:, :, 0] += 20
L[:, :, 1] = self.height - 20 - L[:, :, 1]
line = self.pixmap.draw_line
colors = ([self.black_gc] * 3 +
[self.red] * 2 + [self.green] * 2 + [self.blue] * 3)
for i in L[:, 1, 2].argsort():
(a, b), (c, d) = L[i, :, :2]
line(colors[i], a, b, c, d)
digits = np.array(((1, 1, 1, 1, 1, 1, 0),
(0, 1, 1, 0, 0, 0, 0),
(1, 0, 1, 1, 0, 1, 1),
(1, 1, 1, 1, 0, 0, 1),
(0, 1, 1, 0, 1, 0, 1),
(1, 1, 0, 1, 1, 0, 1),
(1, 1, 0, 1, 1, 1, 1),
(0, 1, 1, 1, 0, 0, 0),
(1, 1, 1, 1, 1, 1, 1),
(0, 1, 1, 1, 1, 0, 1)), bool)
bars = np.array(((0, 2, 1, 2),
(1, 2, 1, 1),
(1, 1, 1, 0),
(1, 0, 0, 0),
(0, 0, 0, 1),
(0, 1, 0, 2),
(0, 1, 1, 1))) * 5
def draw_frame_number(self):
n = str(self.frame)
x = self.width - 3 - 8 * len(n)
y = self.height - 27
color = self.black_gc
line = self.pixmap.draw_line
for c in n:
bars = View.bars[View.digits[int(c)]]
for a, b, c, d in bars:
line(color, a + x, b + y, c + x, d + y)
x += 8
def release(self, drawing_area, event):
if event.button != 1:
return
selected = self.images.selected
selected_ordered = self.images.selected_ordered
if event.time < self.t0 + 200: # 200 ms
d = self.P - self.xy
hit = np.less((d**2).sum(1), (self.scale * self.images.r)**2)
for a in self.indices[::-1]:
if a < self.images.natoms and hit[a]:
if event.state & gtk.gdk.CONTROL_MASK:
selected[a] = not selected[a]
if selected[a]:
selected_ordered += [a]
elif len(selected_ordered) > 0:
if selected_ordered[-1] == a:
selected_ordered = selected_ordered[:-1]
else:
selected_ordered = []
else:
selected[:] = False
selected[a] = True
selected_ordered = [a]
break
else:
selected[:] = False
selected_ordered = []
self.draw()
else:
A = (event.x, event.y)
C1 = np.minimum(A, self.xy)
C2 = np.maximum(A, self.xy)
hit = np.logical_and(self.P > C1, self.P < C2)
indices = np.compress(hit.prod(1), np.arange(len(hit)))
if not (event.state & gtk.gdk.CONTROL_MASK):
selected[:] = False
selected[indices] = True
if len(indices) == 1 and indices[0] not in self.images.selected_ordered:
selected_ordered += [indices[0]]
elif len(indices) > 1:
selected_ordered = []
self.draw()
indices = np.arange(self.images.natoms)[self.images.selected]
if len(indices) != len(selected_ordered):
selected_ordered = []
self.images.selected_ordered = selected_ordered
def press(self, drawing_area, event):
self.button = event.button
self.xy = (event.x, event.y)
self.t0 = event.time
self.axes0 = self.axes
self.center0 = self.center
def move(self, drawing_area, event):
x, y, state = event.window.get_pointer()
x0, y0 = self.xy
if self.button == 1:
window = self.drawing_area.window
window.draw_drawable(self.white_gc, self.pixmap,
0, 0, 0, 0,
self.width, self.height)
x0 = int(round(x0))
y0 = int(round(y0))
window.draw_rectangle(self.selected_gc, False,
min(x, x0), min(y, y0),
abs(x - x0), abs(y - y0))
return
if self.button == 2:
return
if state & gtk.gdk.SHIFT_MASK:
self.center = (self.center0 -
np.dot(self.axes, (x - x0, y0 - y, 0)) / self.scale)
else:
# Snap mode: the a-b angle and t should multipla of 15 degrees ???
a = x - x0
b = y0 - y
t = sqrt(a * a + b * b)
if t > 0:
a /= t
b /= t
else:
a = 1.0
b = 0.0
c = cos(0.01 * t)
s = -sin(0.01 * t)
rotation = np.array([(c * a * a + b * b, (c - 1) * b * a, s * a),
((c - 1) * a * b, c * b * b + a * a, s * b),
(-s * a, -s * b, c)])
self.axes = np.dot(self.axes0, rotation)
if self.images.natoms > 0:
com = self.X[:self.images.natoms].mean(0)
else:
com = self.images.A[self.frame].mean(0)
self.center = com - np.dot(com - self.center0,
np.dot(self.axes0, self.axes.T))
self.draw(status=False)
# Create a new backing pixmap of the appropriate size
def configure_event(self, drawing_area, event):
if self.configured:
w = self.width
h = self.height
else:
self.colormap = self.drawing_area.get_colormap()
self.black_gc = self.drawing_area.get_style().black_gc
self.white_gc = self.drawing_area.get_style().white_gc
self.red = self.drawing_area.window.new_gc(
self.colormap.alloc_color(62345, 0, 0), line_width=2)
self.green = self.drawing_area.window.new_gc(
self.colormap.alloc_color(0, 54456, 0), line_width=2)
self.blue = self.drawing_area.window.new_gc(
self.colormap.alloc_color(0, 0, 54456), line_width=2)
self.selected_gc = self.drawing_area.window.new_gc(
self.colormap.alloc_color(0, 16456, 0),
line_width=3)
x, y, self.width, self.height = drawing_area.get_allocation()
self.pixmap = gtk.gdk.Pixmap(drawing_area.window,
self.width, self.height)
if self.configured:
self.scale *= sqrt(1.0 * self.width * self.height / (w * h))
self.draw()
self.configured = True
# Redraw the screen from the backing pixmap
def expose_event(self, drawing_area, event):
x , y, width, height = event.area
gc = self.white_gc
drawing_area.window.draw_drawable(gc, self.pixmap,
x, y, x, y, width, height)
def external_viewer(self, action):
name = action.get_name()
command = {'Avogadro' : 'avogadro',
'XMakeMol': 'xmakemol -f',
'RasMol':'rasmol -xyz',
'VMD': 'vmd'}[name]
fd, filename = tempfile.mkstemp('.xyz', 'ase.gui-')
os.close(fd)
self.images.write(filename)
os.system('(%s %s &); (sleep 60; rm %s) &' %
(command, filename, filename))
def render_window(self, action):
Render(self)
python-ase-3.6.0.2515/ase/gui/widgets.py 0000644 0001754 0001754 00000012461 11706276516 016573 0 ustar askhl askhl from gettext import gettext as _
import gtk
class Number(gtk.SpinButton):
def __init__(self, value=0,
lower=0, upper=10000,
step_incr=1, page_incr=10,
climb_rate=0.5, digits=0):
self.adj = gtk.Adjustment(value, lower, upper, step_incr, page_incr, 0)
gtk.SpinButton.__init__(self, self.adj, climb_rate, digits)
def connect(self, *args):
return self.adj.connect(*args)
class Menu:
def __init__(self, menubar, name, items):
self.items = {}
menu = gtk.Menu()
for data in items:
text = data[0]
callback = data[1]
args = data[2:]
menuitem = gtk.MenuItem(text)
menu.append(menuitem)
menuitem.connect('activate', callback, *args)
menuitem.show()
self.items[text] = menuitem
menuitem = gtk.MenuItem(name)
menubar.append(menuitem)
menuitem.set_submenu(menu)
menuitem.show()
class Help(gtk.Window):
__instance = None
def __new__(cls, *args, **kwargs):
# Make this a singleton.
if Help.__instance is None:
Help.__instance = gtk.Window.__new__(cls, *args, **kwargs)
return Help.__instance
def __init__(self, text):
# Now, __init__ may be called multiple times!
if not hasattr(self, '_initialized'):
self.initialize(text)
else:
self.set_text(text)
self.present() # Show the window.
def initialize(self, text):
gtk.Window.__init__(self)
self.set_title(_("Help"))
self._initialized = True
vbox = gtk.VBox()
self.add(vbox)
self.label = pack(vbox, gtk.Label())
self.label.set_line_wrap(True)
self.set_text(text)
close = gtk.Button(_('Close'))
pack(vbox, [close])
close.connect('clicked', self.destroy)
self.connect("delete-event", self.destroy)
self.show_all()
def set_text(self, text):
# Count line length
linelen = max([len(x) for x in text.split('\n')])
text = text.replace('', '')
text = text.replace('', '')
self.label.set_width_chars(linelen)
self.label.set_line_wrap(False)
self.label.set_markup(text)
def destroy(self, *args):
self.hide()
return True # Prevents destruction of the window.
def help(text):
button = gtk.Button(_('Help'))
button.connect('clicked', lambda widget, text=text: Help(text))
return button
class Window(gtk.Window):
def __init__(self, gui):
self.gui = gui
gtk.Window.__init__(self)
self.set_title(_('Constraints'))
vbox = gtk.VBox()
b = pack(vbox, [gtk.Button(_('Constrain')),
gtk.Label(_(' selected atoms'))])[0]
b.connect('clicked', self.selected)
b = pack(vbox, [gtk.Button(_('Constrain')),
gtk.Label(_(' immobile atoms:'))])[0]
b.connect('clicked', self.immobile)
b = pack(vbox, gtk.Button(_('Clear constraint')))
b.connect('clicked', self.clear)
close = pack(vbox, gtk.Button(_('Close')))
close.connect('clicked', lambda widget: self.destroy())
self.add(vbox)
vbox.show()
self.show()
def pack(vbox, widgets, end=False, bottom=False, expand=False, padding=0):
if not isinstance(widgets, list):
widgets.show()
if bottom:
vbox.pack_end(widgets, expand, expand, padding)
else:
vbox.pack_start(widgets, expand, expand, padding)
return widgets
hbox = gtk.HBox(0, 0)
hbox.show()
if bottom:
vbox.pack_end(hbox, expand, expand, padding)
else:
vbox.pack_start(hbox, expand, expand, padding)
for widget in widgets:
if type(widget) is gtk.Entry:
widget.set_size_request(widget.get_max_length() * 9, 24)
widget.show()
if end and widget is widgets[-1]:
hbox.pack_end(widget, expand, expand, padding)
else:
hbox.pack_start(widget, expand, expand, padding)
return widgets
class cancel_apply_ok(gtk.HButtonBox):
"Widget with Cancel, Apply and OK buttons. The arguments are callbacks."
def __init__(self, cancel, apply, ok):
gtk.HButtonBox.__init__(self)
cancel_but = gtk.Button(stock=gtk.STOCK_CANCEL)
cancel_but.connect('clicked', cancel)
apply_but = gtk.Button(stock=gtk.STOCK_APPLY)
apply_but.connect('clicked', apply)
ok_but = gtk.Button(stock=gtk.STOCK_OK)
ok_but.connect('clicked', ok)
for w in (cancel_but, apply_but, ok_but):
self.pack_start(w, 0, 0)
w.show()
#self.show_all()
def oops(message, message2=None):
dialog = gtk.MessageDialog(flags=gtk.DIALOG_MODAL,
type=gtk.MESSAGE_WARNING,
buttons=gtk.BUTTONS_CLOSE,
message_format=message)
try:
dialog.format_secondary_text(message2)
except AttributeError:
print >>sys.stderr, message
print >>sys.stderr, message2
dialog.connect('response', lambda x, y, dialog=dialog: dialog.destroy())
dialog.show()
class AseGuiCancelException(Exception):
pass
python-ase-3.6.0.2515/ase/gui/defaults.py 0000644 0001754 0001754 00000001126 11546636754 016736 0 ustar askhl askhl """ This is a module to handle generic ASE (gui) defaults from a ~/.ase/gui.py configuration file, if it exists.
It is imported when opening ag and can then be modified at runtime, if necessary.
syntax for each entry:
gui_default_settings['key'] = value
"""
gui_default_settings = {
'gui_graphs_string' : 'i, e - E[-1]', # default for the graph command in the gui
'covalent_radii' : None
}
def read_defaults():
import os.path
name = os.path.expanduser('~/.ase/gui.py')
config = gui_default_settings
if os.path.exists(name):
execfile(name)
return config
python-ase-3.6.0.2515/ase/gui/settings.py 0000644 0001754 0001754 00000006441 11706276516 016766 0 ustar askhl askhl #!/usr/bin/env python
import gtk
from ase.gui.widgets import pack
from gettext import gettext as _
class Settings(gtk.Window):
def __init__(self, gui):
gtk.Window.__init__(self)
self.set_title('Settings')
self.gui = gui
vbox = gtk.VBox()
# Constraints
a = pack(vbox, gtk.Label())
a.set_markup(''
'%s' % _('Constraints:'))
a, b = pack(vbox, [gtk.Button(_('Constrain')),
gtk.Label('/'),
gtk.Button(_('release')),
gtk.Label(_(' selected atoms'))])[::2]
a.connect('clicked', self.constrain_selected)
b.connect('clicked', self.release_selected)
a = pack(vbox, gtk.Button(_('Constrain immobile atoms')))
a.connect('clicked', self.immobile)
a = pack(vbox, gtk.Button(_('Clear all constraints')))
a.connect('clicked', self.clear_constraints)
# Visibility
a = pack(vbox, gtk.Label())
a.set_markup('\n'
'%s' % _('Visibility:'))
a, b = pack(vbox, [gtk.Button(_('Hide')),
gtk.Label('/'),
gtk.Button(_('show')),
gtk.Label(_(' selected atoms'))])[::2]
a.connect('clicked', self.hide_selected)
b.connect('clicked', self.show_selected)
a = pack(vbox, gtk.Button(_('View all atoms')))
a.connect('clicked', self.view_all)
# Miscellaneous
a = pack(vbox, gtk.Label())
a.set_markup('\n'
'%s' % _('Miscellaneous:'))
self.scale = gtk.Adjustment(value=.89, lower=0.2, upper=2.0,
step_incr=0.1, page_incr=0.5)
pack(vbox, [gtk.Label(_('Scale atomic radii:')),
gtk.SpinButton(self.scale, climb_rate=0, digits=2)])
self.scale.connect('value-changed', self.scale_radii)
# A close button
pack(vbox, gtk.Label(_('\n')))
close = pack(vbox, gtk.Button(_('Close')))
close.connect('clicked', lambda widget: self.destroy())
# Add elements and show frame
self.add(vbox)
vbox.show()
self.show()
def scale_radii(self, adjustment):
self.gui.images.set_radii(float(self.scale.value))
self.gui.draw()
return True
def hide_selected(self, button):
self.gui.images.visible[self.gui.images.selected] = False
self.gui.draw()
def show_selected(self, button):
self.gui.images.visible[self.gui.images.selected] = True
self.gui.draw()
def view_all(self, button):
self.gui.images.visible[:] = True
self.gui.draw()
def constrain_selected(self, button):
self.gui.images.dynamic[self.gui.images.selected] = False
self.gui.draw()
def release_selected(self, button):
self.gui.images.dynamic[self.gui.images.selected] = True
self.gui.draw()
def immobile(self, button):
self.gui.images.set_dynamic()
self.gui.draw()
def clear_constraints(self, button):
self.gui.images.dynamic[:] = True
self.gui.draw()
python-ase-3.6.0.2515/ase/gui/nanotube.py 0000644 0001754 0001754 00000011716 11716573517 016744 0 ustar askhl askhl # encoding: utf-8
"""nanotube.py - Window for setting up Carbon nanotubes and similar tubes.
"""
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack, cancel_apply_ok, oops
from ase.gui.setupwindow import SetupWindow
from ase.gui.pybutton import PyButton
from ase.structure import nanotube
import ase
import numpy as np
introtext = _("""\
Set up a Carbon nanotube by specifying the (n,m) roll-up vector.
Please note that m <= n.
Nanotubes of other elements can be made by specifying the element
and bond length.\
""")
py_template = """
from ase.structure import nanotube
atoms = nanotube(%(n)i, %(m)i, length=%(length)i, bond=%(bl).3f, symbol='%(symb)s')
"""
class SetupNanotube(SetupWindow):
"Window for setting up a (Carbon) nanotube."
def __init__(self, gui):
SetupWindow.__init__(self)
self.set_title(_("Nanotube"))
vbox = gtk.VBox()
# Intoductory text
self.packtext(vbox, introtext)
# Choose the element and bond length
label1 = gtk.Label(_("Element: "))
#label.set_alignment(0.0, 0.2)
self.element = gtk.Entry(max=3)
self.element.set_text("C")
self.element.connect('activate', self.update_element)
self.bondlength = gtk.Adjustment(1.42, 0.0, 1000.0, 0.01)
label2 = gtk.Label(_(" Bond length: "))
label3 = gtk.Label(_("Ã…"))
bond_box = gtk.SpinButton(self.bondlength, 10.0, 3)
pack(vbox, [label1, self.element, label2, bond_box, label3])
self.elementinfo = gtk.Label("")
self.elementinfo.modify_fg(gtk.STATE_NORMAL,
gtk.gdk.color_parse('#FF0000'))
pack(vbox, [self.elementinfo])
pack(vbox, gtk.Label(""))
# Choose the structure.
pack(vbox, [gtk.Label(_("Select roll-up vector (n,m) "
"and tube length:"))])
label1 = gtk.Label("n: ")
label2 = gtk.Label(" m: ")
self.n = gtk.Adjustment(5, 1, 100, 1)
self.m = gtk.Adjustment(5, 0, 100, 1)
spinn = gtk.SpinButton(self.n, 0, 0)
spinm = gtk.SpinButton(self.m, 0, 0)
label3 = gtk.Label(_(" Length: "))
self.length = gtk.Adjustment(1, 1, 100, 1)
spinl = gtk.SpinButton(self.length, 0, 0)
pack(vbox, [label1, spinn, label2, spinm, label3, spinl])
self.err = gtk.Label("")
self.err.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#FF0000'))
pack(vbox, [self.err])
pack(vbox, gtk.Label(""))
# Buttons
self.pybut = PyButton(_("Creating a nanoparticle."))
self.pybut.connect('clicked', self.makeatoms)
buts = cancel_apply_ok(cancel=lambda widget: self.destroy(),
apply=self.apply,
ok=self.ok)
pack(vbox, [self.pybut, buts], end=True, bottom=True)
# Finalize setup
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
def update_element(self, *args):
"Called when a new element may have been entered."
# Assumes the element widget is self.element and that a label
# for errors is self.elementinfo. The chemical symbol is
# placed in self.legalelement - or None if the element is
# invalid.
elem = self.element.get_text()
if not elem:
self.invalid_element(_(" No element specified!"))
return False
try:
z = int(elem)
except ValueError:
# Probably a symbol
try:
z = ase.data.atomic_numbers[elem]
except KeyError:
self.invalid_element()
return False
try:
symb = ase.data.chemical_symbols[z]
except KeyError:
self.invalid_element()
return False
self.elementinfo.set_text("")
self.legal_element = symb
return True
def makeatoms(self, *args):
self.update_element()
if self.legal_element is None:
self.atoms = None
self.pybut.python = None
else:
n = int(self.n.value)
m = int(self.m.value)
symb = self.legal_element
length = int(self.length.value)
bl = self.bondlength.value
self.atoms = nanotube(n, m, length=length, bond=bl, symbol=symb)
# XXX can this be translated?
self.pybut.python = py_template % {'n': n, 'm':m, 'length':length,
'symb':symb, 'bl':bl}
def apply(self, *args):
self.makeatoms()
if self.atoms is not None:
self.gui.new_atoms(self.atoms)
return True
else:
oops(_("No valid atoms."),
_("You have not (yet) specified a consistent "
"set of parameters."))
return False
def ok(self, *args):
if self.apply():
self.destroy()
python-ase-3.6.0.2515/ase/gui/energyforces.py 0000644 0001754 0001754 00000006535 11711330540 017605 0 ustar askhl askhl # encoding: utf-8
"Module for calculating energies and forces."
import gtk
from gettext import gettext as _
from ase.gui.simulation import Simulation
from ase.gui.widgets import oops, pack
class OutputFieldMixin:
def makeoutputfield(self, box, label=_("Output:"), heading = None):
frame = gtk.Frame(label)
if box is not None:
box.pack_start(frame, True, True, 0)
box2 = gtk.VBox()
frame.add(box2)
if heading is not None:
pack(box2, [gtk.Label(heading)])
#pack(box, [gtk.Label("Output:")])
scrwin = gtk.ScrolledWindow()
scrwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.output = gtk.TextBuffer()
txtview = gtk.TextView(self.output)
txtview.set_editable(False)
scrwin.add(txtview)
scrwin.show_all()
box2.pack_start(scrwin, True, True, 0)
self.savebutton = gtk.Button(stock=gtk.STOCK_SAVE)
self.savebutton.connect('clicked', self.saveoutput)
self.savebutton.set_sensitive(False)
pack(box2, [self.savebutton])
box2.show()
frame.show()
return frame
def activate_output(self):
self.savebutton.set_sensitive(True)
def saveoutput(self, widget):
chooser = gtk.FileChooserDialog(
_('Save output'), None, gtk.FILE_CHOOSER_ACTION_SAVE,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
ok = chooser.run()
if ok == gtk.RESPONSE_OK:
filename = chooser.get_filename()
txt = self.output.get_text(self.output.get_start_iter(),
self.output.get_end_iter())
f = open(filename, "w")
f.write(txt)
f.close()
chooser.destroy()
class EnergyForces(Simulation, OutputFieldMixin):
def __init__(self, gui):
Simulation.__init__(self, gui)
self.set_title(_("Potential energy and forces"))
self.set_default_size(-1, 400)
vbox = gtk.VBox()
self.packtext(vbox,
_("Calculate potential energy and the force on all "
"atoms"))
self.packimageselection(vbox)
pack(vbox, gtk.Label(""))
self.forces = gtk.CheckButton(_("Write forces on the atoms"))
self.forces.set_active(True)
pack(vbox, [self.forces])
pack(vbox, [gtk.Label("")])
self.makeoutputfield(vbox)
pack(vbox, gtk.Label(""))
self.makebutbox(vbox)
vbox.show()
self.add(vbox)
self.show()
self.gui.register_vulnerable(self)
def run(self, *args):
if not self.setup_atoms():
return
self.begin()
e = self.atoms.get_potential_energy()
txt = _("Potential Energy:\n")
txt += _(" %8.2f eV\n") % (e,)
txt += _(" %8.4f eV/atom\n\n") % (e/len(self.atoms),)
if self.forces.get_active():
txt += _("Forces:\n")
forces = self.atoms.get_forces()
for f in forces:
txt += " %8.3f, %8.3f, %8.3f eV/Ã…\n" % tuple(f)
self.output.set_text(txt)
self.activate_output()
self.end()
def notify_atoms_changed(self):
"When atoms have changed, check for the number of images."
self.setupimageselection()
python-ase-3.6.0.2515/ase/gui/debug.py 0000644 0001754 0001754 00000000746 11706276516 016216 0 ustar askhl askhl import sys
import gtk
from gettext import gettext as _
import numpy as np
class Debug(gtk.Window):
def __init__(self, gui):
self.gui = gui
gtk.Window.__init__(self)
self.set_title(_('Debug'))
entry = gtk.Entry(200)
self.add(entry)
entry.connect('activate', self.enter, entry)
entry.show()
self.show()
def enter(self, widget, entry):
g = self.gui
print >> sys.stderr, eval(entry.get_text())
python-ase-3.6.0.2515/ase/gui/po/ 0000755 0001754 0001754 00000000000 11757245036 015164 5 ustar askhl askhl python-ase-3.6.0.2515/ase/gui/po/da_DK/ 0000755 0001754 0001754 00000000000 11757245036 016126 5 ustar askhl askhl python-ase-3.6.0.2515/ase/gui/po/da_DK/LC_MESSAGES/ 0000755 0001754 0001754 00000000000 11757245036 017713 5 ustar askhl askhl python-ase-3.6.0.2515/ase/gui/po/da_DK/LC_MESSAGES/ag.po 0000644 0001754 0001754 00000227410 11716573517 020653 0 ustar askhl askhl # Danish translations for ASE package
# Danske oversættelser for pakken ASE.
# Copyright (C) 2011 CAMD
# This file is distributed under the same license as the ASE package.
#
# Ask Hjorth Larsen , 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: ase-3.5.2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-01 16:08+0100\n"
"PO-Revision-Date: 2012-02-15 00:54+0100\n"
"Last-Translator: Ask Hjorth Larsen \n"
"Language-Team: Danish \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: da\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../ag.py:130
msgid ""
"\n"
"An exception occurred! Please report the issue to\n"
"ase-developers@listserv.fysik.dtu.dk - thanks! Please also report this if\n"
"it was a user error, so that a better error message can be provided\n"
"next time."
msgstr ""
"\n"
"Der opstod en undtagelse! Rapportér venligst dette problem til \n"
"ase-developers@listserv.fysik.dtu.dk - mange tak! Rapportér også gerne "
"dette\n"
"hvis det var en brugerfejl, så der kan gives en bedre fejlmeddelelse næste\n"
"gang."
#. Asap and GPAW may be imported if selected.
#: ../calculator.py:18
msgid ""
"To make most calculations on the atoms, a Calculator object must first\n"
"be associated with it. ASE supports a number of calculators, supporting\n"
"different elements, and implementing different physical models for the\n"
"interatomic interactions."
msgstr ""
"For at kunne foretage de fleste typer atomare beregninger, skal der\n"
"først tilknyttes et beregnerobject (Calculator). ASE tilbyder\n"
"adskillige beregnere, som understøtter forskellige grundstoffer, og\n"
"implementerer forskellige fysiske modeller for atomernes vekselvirkning."
#. Informational text about the calculators
#: ../calculator.py:26
msgid ""
"The Lennard-Jones pair potential is one of the simplest\n"
"possible models for interatomic interactions, mostly\n"
"suitable for noble gasses and model systems.\n"
"\n"
"Interactions are described by an interaction length and an\n"
"interaction strength."
msgstr ""
"Lennard-Jones-parpotentialet er en af de simpleste mulige modeller for\n"
"atomare interaktioner, og er især nyttigt til ædelgasser og\n"
"modelsystemer.\n"
"\n"
"Interaktionerne beskrives ved en interaktionslængde og en\n"
"interaktionsstyrke."
#: ../calculator.py:35
msgid ""
"The EMT potential is a many-body potential, giving a\n"
"good description of the late transition metals crystalling\n"
"in the FCC crystal structure. The elements described by the\n"
"main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and\n"
"Au, the Al potential is however not suitable for materials\n"
"science application, as the stacking fault energy is wrong.\n"
"\n"
"A number of parameter sets are provided.\n"
"\n"
"Default parameters:\n"
"\n"
"The default EMT parameters, as published in K. W. Jacobsen,\n"
"P. Stoltze and J. K. Nørskov, Surf. Sci. 366, 394 (1996).\n"
"\n"
"Alternative Cu, Ag and Au:\n"
"\n"
"An alternative set of parameters for Cu, Ag and Au,\n"
"reoptimized to experimental data including the stacking\n"
"fault energies by Torben Rasmussen (partly unpublished).\n"
"\n"
"Ruthenium:\n"
"\n"
"Parameters for Ruthenium, as published in J. Gavnholt and\n"
"J. Schiøtz, Phys. Rev. B 77, 035404 (2008).\n"
"\n"
"Metallic glasses:\n"
"\n"
"Parameters for MgCu and CuZr metallic glasses. MgCu\n"
"parameters are in N. P. Bailey, J. Schiøtz and\n"
"K. W. Jacobsen, Phys. Rev. B 69, 144205 (2004).\n"
"CuZr in A. Paduraru, A. Kenoufi, N. P. Bailey and\n"
"J. Schiøtz, Adv. Eng. Mater. 9, 505 (2007).\n"
msgstr ""
"EMT-potentialet er et mangepartikelpotential, som giver en god\n"
"beskrivelse af de sene overgangsmetaller som danner FCC-strukturer.\n"
"Grundstofferne som beskrives af hoveddelen af EMT-parametrene er Al,\n"
"Ni, Cu, Pd, Ag, Pt og Au. Dog er Al-potentialet ikke egnet til\n"
"anvendelse i materialevidenskab, da energien for fejl i krystalstrukturen\n"
"er forkert.\n"
"\n"
"Der medfølger en række standardparametre.\n"
"\n"
"Standardparametre:\n"
"\n"
"Standardparametrene som udgivet i K. W. Jacobsen,\n"
"P. Stoltze og J. K. Nørskov, Surf. Sci. 366, 394 (1996).\n"
"\n"
"Alternativ Cu, Ag og Au:\n"
"\n"
"Et alternativt sæt parametre for Cu, Ag og Au, genoptimeret til\n"
"eksperimentelle data inklusive energier for krystalfejl af Torben\n"
"Rasmussen (delvis upubliceret).\n"
"\n"
"Ruthenium:\n"
"\n"
"Parametre for ruthenium som udgivet i J. Gavnholt og\n"
"J. Schiøtz, Phys. Rev. B 77, 035404 (2008).\n"
"\n"
"Metalglas:\n"
"\n"
"Parametre for MgCu- og CuZr-metalglas. MgCu-parametrene findes i\n"
"N. P. Bailey, J. Schiøtz anog K. W. Jacobsen, Phys. Rev. B 69"
"b>, \n"
"144205 (2004).\n"
"CuZr findes i A. Paduraru, A. Kenoufi, N. P. Bailey og\n"
"J. Schiøtz, Adv. Eng. Mater. 9, 505 (2007).\n"
#: ../calculator.py:70
msgid ""
"The EMT potential is a many-body potential, giving a\n"
"good description of the late transition metals crystalling\n"
"in the FCC crystal structure. The elements described by the\n"
"main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and\n"
"Au. In addition, this implementation allows for the use of\n"
"H, N, O and C adatoms, although the description of these is\n"
"most likely not very good.\n"
"\n"
"This is the ASE implementation of EMT. For large\n"
"simulations the ASAP implementation is more suitable; this\n"
"implementation is mainly to make EMT available when ASAP is\n"
"not installed.\n"
msgstr ""
"EMT-potentialet er et mangepartikelpotential, som giver en god\n"
"beskrivelse af de sene overgangsmetaller som danner FCC-strukturer.\n"
"Grundstofferne som beskrives af hoveddelen af EMT-parametrene er Al,\n"
"Ni, Cu, Pd, Ag, Pt og Au. Yderligere tillader denne implementation\n"
"bruben af H-, N-, O- og C-adatomer, selvom beskrivelsen af disse\n"
"sandsynligvis er dårlig.\n"
"\n"
"Dette er ASE's implementation af EMT. For støre simulationer er\n"
"ASAP-implementationen bedre; denne implementation bruges hovedsageligt\n"
"for at tilbyde en EMT-beskrivelse når ASAP ikke er installeret.\n"
#: ../calculator.py:85
msgid ""
"The Brenner potential is a reactive bond-order potential for\n"
"carbon and hydrocarbons. As a bond-order potential, it takes\n"
"into account that carbon orbitals can hybridize in different\n"
"ways, and that carbon can form single, double and triple\n"
"bonds. That the potential is reactive means that it can\n"
"handle gradual changes in the bond order as chemical bonds\n"
"are formed or broken.\n"
"\n"
"The Brenner potential is implemented in Asap, based on a\n"
"C implentation published at http://www.rahul.net/pcm/brenner/ .\n"
"\n"
"The potential is documented here:\n"
" Donald W Brenner, Olga A Shenderova, Judith A Harrison,\n"
" Steven J Stuart, Boris Ni and Susan B Sinnott:\n"
" \"A second-generation reactive empirical bond order (REBO)\n"
" potential energy expression for hydrocarbons\",\n"
" J. Phys.: Condens. Matter 14 (2002) 783-802.\n"
" doi: 10.1088/0953-8984/14/4/312\n"
msgstr ""
"Brennerpotentialet er et reaktivt bindingsordenspotential til kulstof og "
"kulbrinter. Som et bindingsordenspotential tager det højde for at "
"kulstoforbitaler kan hybridisere på forskellige måder, og at kulstof kan "
"danne enkelt- dobbelt- og tripelbindinger. At potentialet er reaktivt "
"betyder, at det kan beskrive gradvise ændringer i bindingsorden efterhånden "
"som kemiske bindinger dannes eller brydes.\n"
"\n"
"Brennerpotentialet er implementeret i ASAP baseret på en C-implementation "
"publiceret på siden http://www.rahul.net/pcm/brenner/ .\n"
"\n"
"Potentialet dokumenteres her:\n"
" Donald W Brenner, Olga A Shenderova, Judith A Harrison,\n"
" Steven J Stuart, Boris Ni and Susan B Sinnott:\n"
" \"A second-generation reactive empirical bond order (REBO)\n"
" potential energy expression for hydrocarbons\",\n"
" J. Phys.: Condens. Matter 14 (2002) 783-802.\n"
" doi: 10.1088/0953-8984/14/4/312\n"
#: ../calculator.py:107
msgid ""
"GPAW implements Density Functional Theory using a\n"
"Grid-based real-space representation of the wave\n"
"functions, and the Projector Augmented Wave\n"
"method for handling the core regions. \n"
msgstr ""
"GPAW implementerer tæthedsfunktionalteori med en Gitterbaseret\n"
"repræsentation af bølgefunktioner i det reelle rum, samt\n"
"Projector Augmented Wave-metoden til behandling\n"
"af regionen omkring atomkerner. \n"
#: ../calculator.py:114
msgid ""
"FHI-aims is an external package implementing density \n"
"functional theory and quantum chemical methods using \n"
"all-electron methods and a numeric local orbital basis set. \n"
"For full details, see http://www.fhi-berlin.mpg.de/aims/ \n"
"or Comp. Phys. Comm. v180 2175 (2009). The ASE \n"
"documentation contains information on the keywords and \n"
"functionalities available within this interface. \n"
msgstr ""
"FHI-aims er en ekstern pakke, der implementerer tæthedsfunktionalteori\n"
"og kvantekemiske metoder ved brug af \"all-electron\"-metoder og et\n"
"numerisk lokaliseret atomart basissæt. De fulde detaljer kan findes på\n"
"http://www.fhi-berlin.mpg.de/aims/ eller i Comp. Phys. Comm. v180 2175\n"
"(2009). ASE-dokumentationen indeholder oplysninger om nøgleord og\n"
"funktioner, som er tilgængelige i denne grænseflade. \n"
#: ../calculator.py:124
msgid ""
"WARNING:\n"
"Your system seems to have more than zero but less than \n"
"three periodic dimensions. Please check that this is \n"
"really what you want to compute. Assuming full \n"
"3D periodicity for this calculator."
msgstr ""
"ADVARSEL:\n"
"Dit system skal have flere end nul men mindre end tre periodiske\n"
"dimensioner. Kontrollér venligst at dette virkelig er hvad du godt\n"
"vil beregne. Antager fuld 3D-periodicitet for denne beregner."
#: ../calculator.py:131
msgid ""
"VASP is an external package implementing density \n"
"functional functional theory using pseudopotentials \n"
"or the projector-augmented wave method together \n"
"with a plane wave basis set. For full details, see\n"
"http://cms.mpi.univie.ac.at/vasp/vasp/\n"
msgstr ""
"VASP er en ekstern pakke, der implementerer tæthedsfunktionalteori med\n"
"pseudopotentialer eller PAW-metoden (projector augmented wave method)\n"
"sammen med en planbølgebasis. De fulde detaljer kan findes på\n"
"http://cms.mpi.univie.ac.at/vasp/vasp/\n"
#: ../calculator.py:140
msgid "Default (Al, Ni, Cu, Pd, Ag, Pt, Au)"
msgstr "Standard (Al, Ni, Cu, Pd, Ag, Pt, Au)"
#: ../calculator.py:141
msgid "Alternative Cu, Ag and Au"
msgstr "Alternativ Cu, Ag og Au"
#: ../calculator.py:142
msgid "Ruthenium"
msgstr "Ruthenium"
#: ../calculator.py:143
msgid "CuMg and CuZr metallic glass"
msgstr "Metallisk glas med CuMg og CuZr"
#: ../calculator.py:158
msgid "Select calculator"
msgstr "Vælg beregner"
#: ../calculator.py:164
msgid "Calculator:"
msgstr "Beregner:"
#. No calculator (the default)
#: ../calculator.py:167
msgid "None"
msgstr "Ingen"
#: ../calculator.py:172
msgid "Lennard-Jones (ASAP)"
msgstr "Lennard-Jones (ASAP)"
#: ../calculator.py:173 ../calculator.py:206 ../calculator.py:215
#: ../calculator.py:224
msgid "Setup"
msgstr "Opsætning"
#: ../calculator.py:180
msgid "EMT - Effective Medium Theory (ASAP)"
msgstr "EMT - Effective Medium Theory (ASAP)"
#: ../calculator.py:192
msgid "EMT - Effective Medium Theory (ASE)"
msgstr "EMT - Effective Medium Theory (ASE)"
#: ../calculator.py:198
msgid "Brenner Potential (ASAP)"
msgstr "Brenner-potentialet (ASAP)"
#: ../calculator.py:204
msgid "Density Functional Theory (GPAW)"
msgstr "Tæthedsfunktionalteori (GPAW)"
#: ../calculator.py:213
msgid "Density Functional Theory (FHI-aims)"
msgstr "Tæthedsfunktionalteori (FHI-aims)"
#: ../calculator.py:222
msgid "Density Functional Theory (VASP)"
msgstr "Tæthedsfunktionalteori (VASP)"
#: ../calculator.py:235
msgid "Check that the calculator is reasonable."
msgstr "Kontrollér at beregneren er rimelig."
#: ../calculator.py:298 ../simulation.py:114
msgid "No atoms present"
msgstr "Ingen atomer til stede"
#: ../calculator.py:388 ../calculator.py:422 ../calculator.py:456
msgid "ASAP is not installed. (Failed to import asap3)"
msgstr "ASAP er ikke installeret. (Kunne ikke importere asap3)"
#: ../calculator.py:391
msgid "You must set up the Lennard-Jones parameters"
msgstr "Du skal indstille Lennard-Jones-parametrene"
#: ../calculator.py:396
msgid "Could not create useful Lennard-Jones calculator."
msgstr "Kunne ikke oprette en nyttig Lennard-Jones-beregner."
#: ../calculator.py:430
msgid "Could not attach EMT calculator to the atoms."
msgstr "Kunne ikke knytte EMT-beregner til atomerne."
#: ../calculator.py:472 ../calculator.py:484
msgid "GPAW is not installed. (Failed to import gpaw)"
msgstr "GPAW er ikke installeret. (Kunne ikke importere gpaw)"
#: ../calculator.py:475
msgid "You must set up the GPAW parameters"
msgstr "Du skal angive GPAW-parametrene"
#: ../calculator.py:516
msgid "You must set up the FHI-aims parameters"
msgstr "Du skal angive FHI-aims-parametrene"
#: ../calculator.py:530
msgid "You must set up the VASP parameters"
msgstr "Du skal angive VASP-parametrene"
#: ../calculator.py:554
#, python-format
msgid "Element %(sym)s not allowed by the '%(name)s' calculator"
msgstr "Grundstoffet %(sym)s tillades ikke af \"%(name)s\"-beregneren"
#: ../calculator.py:561
msgid "Info"
msgstr "Info"
#: ../calculator.py:577
msgid "Lennard-Jones parameters"
msgstr "Lennard-Jones-parametre"
#: ../calculator.py:589
msgid "Specify the Lennard-Jones parameters here"
msgstr "Angiv Lennard-Jones-parametrene her"
#: ../calculator.py:592
msgid "Epsilon (eV):"
msgstr "Epsilon (eV):"
#: ../calculator.py:596
msgid "Sigma (Ã…):"
msgstr "Sigma (Ã…):"
#. TRANSLATORS: Shift roughly means adjust (about a potential)
#: ../calculator.py:600
msgid "Shift to make smooth at cutoff"
msgstr "Skift for at blødgøre ved afskæring"
#: ../calculator.py:681
msgid "GPAW parameters"
msgstr "GPAW-parametre"
#. label = gtk.Label("Specify the GPAW parameters here")
#. pack(vbox, [label])
#. Print some info
#: ../calculator.py:696 ../calculator.py:985 ../calculator.py:1473
#, python-format
msgid "%i atoms.\n"
msgstr "%i atomer.\n"
#: ../calculator.py:698
#, python-format
msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Ã…."
msgstr "Ortogonal enhedscelle: %.2f x %.2f x %.2f Ã…."
#: ../calculator.py:700
msgid "Non-orthogonal unit cell:\n"
msgstr "Ikke-ortogonal enhedscelle:\n"
#: ../calculator.py:710 ../calculator.py:1001 ../calculator.py:1488
msgid "Exchange-correlation functional: "
msgstr "Udvekslings- og korrelationsfunktional: "
#. Grid spacing
#: ../calculator.py:714
msgid "Grid spacing"
msgstr "Gitterafstand"
#: ../calculator.py:718 ../graphene.py:67 ../graphene.py:79 ../graphene.py:102
#: ../nanotube.py:47 ../surfaceslab.py:97
msgid "Ã…"
msgstr "Ã…"
#: ../calculator.py:719
msgid "Grid points"
msgstr "Gitterpunkter"
#: ../calculator.py:728
#, python-format
msgid "heff = (%.3f, %.3f, %.3f) Ã…"
msgstr "heff = (%.3f, %.3f, %.3f) Ã…"
#: ../calculator.py:754 ../calculator.py:1016 ../calculator.py:1524
msgid "k-points k = ("
msgstr "k-punkter k = ("
#: ../calculator.py:758 ../calculator.py:1020
#, python-format
msgid "k-points x size: (%.1f, %.1f, %.1f) Ã…"
msgstr "k-punkter x størrelse: (%.1f, %.1f, %.1f) Å"
#. Spin polarized
#: ../calculator.py:763 ../calculator.py:1486
msgid "Spin polarized"
msgstr "Spinpolariseret"
#: ../calculator.py:769
msgid "FD - Finite Difference (grid) mode"
msgstr "FD - Finite Difference-tilstand (gitter)"
#: ../calculator.py:770
msgid "LCAO - Linear Combination of Atomic Orbitals"
msgstr "LCAO - linearkombination af atomare orbitaler"
#: ../calculator.py:773
msgid "Mode: "
msgstr "Tilstand: "
#: ../calculator.py:775
msgid "sz - Single Zeta"
msgstr "sz - Enkelt-zeta"
#: ../calculator.py:776
msgid "szp - Single Zeta polarized"
msgstr "szp - Enkelt-zeta polariseret"
#: ../calculator.py:777
msgid "dzp - Double Zeta polarized"
msgstr "dzp - dobbelt-zeta polariseret"
#. dzp
#: ../calculator.py:779
msgid "Basis functions: "
msgstr "Basisfunktioner: "
#. Mixer
#: ../calculator.py:785
msgid "Non-standard mixer parameters"
msgstr "Særlige mikserparametre"
#: ../calculator.py:981
msgid "FHI-aims parameters"
msgstr "FHI-aims-parametre"
#: ../calculator.py:988
msgid "Periodic geometry, unit cell is:\n"
msgstr "Periodisk geometri; enhedscellen er:\n"
#: ../calculator.py:993
msgid "Non-periodic geometry.\n"
msgstr "Ikke-periodisk geometri.\n"
# XXX ikke Hirschfeld?
#: ../calculator.py:1000
msgid "Hirshfeld-based dispersion correction"
msgstr "Hirshfeld-baseret dispersionskorrektion"
#. Spin polarized, charge, relativity
#: ../calculator.py:1026
msgid "Spin / initial moment "
msgstr "Spin / startmoment "
#: ../calculator.py:1044
msgid " Charge"
msgstr " Ladning"
#: ../calculator.py:1046
msgid " Relativity"
msgstr " Relativitet"
#: ../calculator.py:1048
msgid " Threshold"
msgstr " Tærskel"
#. self-consistency criteria
#: ../calculator.py:1053
msgid "Self-consistency convergence:"
msgstr "Selfkonsistenskonvergens:"
#: ../calculator.py:1066
msgid "Compute forces"
msgstr "Beregn kræfter"
#. XXX: use gtk table for layout. Spaces will not work well otherwise
#. (depend on fonts, widget style, ...)
#. TRANSLATORS: Don't care too much about these, just get approximately
#. the same string lengths
#: ../calculator.py:1077
msgid "Energy: "
msgstr "Energi: "
#: ../calculator.py:1079
msgid " eV Sum of eigenvalues: "
msgstr " eV Sum af egenværdier: "
#: ../calculator.py:1081 ../calculator.py:1559
msgid " eV"
msgstr " eV"
#: ../calculator.py:1082
msgid "Electron density: "
msgstr "Elektrontæthed: "
#: ../calculator.py:1084
msgid " Force convergence: "
msgstr " Kraftkonvergens: "
#: ../calculator.py:1086
msgid " eV/Ang "
msgstr " eV/Ã… "
#: ../calculator.py:1099 ../calculator.py:1570
msgid "Additional keywords: "
msgstr "Yderligere nøgleord: "
#. run command and species defaults:
#: ../calculator.py:1113
msgid "FHI-aims execution command: "
msgstr "Kørselskommando til FHI-aims: "
# ??
#: ../calculator.py:1115 ../calculator.py:1587
msgid "Directory for species defaults: "
msgstr "Mappe for grundstofstandarder: "
#: ../calculator.py:1127 ../calculator.py:1595
msgid "Set Defaults"
msgstr "Brug standardværdier"
#: ../calculator.py:1129
msgid "Import control.in"
msgstr "Importér control.in"
#: ../calculator.py:1131
msgid "Export control.in"
msgstr "Eksportér control.in"
#: ../calculator.py:1317
msgid "Export parameters ... "
msgstr "Eksportér parametre ... "
#: ../calculator.py:1337
msgid "Import control.in file ... "
msgstr "Importér control.in-fil ... "
#: ../calculator.py:1393 ../calculator.py:1907
#, python-format
msgid ""
"Please use the facilities provided in this window to manipulate the keyword: "
"%s!"
msgstr ""
"Brug venligst faciliteterne i dette vindue til at manipulere nøgleordet: %s!"
#: ../calculator.py:1396
#, python-format
msgid ""
"Don't know this keyword: %s\n"
"\n"
"Please check!\n"
"\n"
"If you really think it should be available, please add it to the top of ase/"
"calculators/aims.py."
msgstr ""
"Kender ikke dette nøgleord: %s\n"
"\n"
"Kontrollér venligst!\n"
"\n"
"Hvis du virkelig mener det børe være tilgængeligt, så tilføj det venligst "
"øverst i ase/calculators/aims.py."
#: ../calculator.py:1469
msgid "VASP parameters"
msgstr "VASP-parametre"
#: ../calculator.py:1475
msgid "Periodic geometry, unit cell is: \n"
msgstr "Periodisk geometri; enhedscelle er: \n"
#: ../calculator.py:1527
msgid ") Cutoff: "
msgstr ") Afskæring: "
#: ../calculator.py:1528
msgid " Precision: "
msgstr " Præcision: "
#: ../calculator.py:1530
#, python-format
msgid "k-points x size: (%.1f, %.1f, %.1f) Ã… "
msgstr "k-punkter x størrelse: (%.1f, %.1f, %.1f) Å "
#: ../calculator.py:1546
msgid "Smearing: "
msgstr "Udjævning: "
#: ../calculator.py:1548
msgid " order: "
msgstr " orden: "
#: ../calculator.py:1550
msgid " width: "
msgstr " bredde: "
#: ../calculator.py:1557
msgid "Self-consistency convergence: "
msgstr "Selfkonsistenskonvergens: "
#. run command and location of POTCAR files:
#: ../calculator.py:1583
msgid "VASP execution command: "
msgstr "Kørselskommando til VASP: "
#: ../calculator.py:1597
msgid "Import VASP files"
msgstr "Importér VASP-filer"
#: ../calculator.py:1599
msgid "Export VASP files"
msgstr "Eksportér VASP-filer"
#: ../calculator.py:1810
msgid "WARNING: cutoff energy is lower than recommended minimum!"
msgstr ""
"ADVARSEL: afskæringsenergi er lavere end det anbefalede minimum!"
#: ../calculator.py:1862
msgid "Import VASP input files: choose directory ... "
msgstr "Importér VASP-inputfiler: vælg mappe ... "
#: ../calculator.py:1877
msgid "Export VASP input files: choose directory ... "
msgstr "Eksportér VASP-inputfiler: vælg mappe ... "
#: ../calculator.py:1910
#, python-format
msgid ""
"Don't know this keyword: %s\n"
"Please check!\n"
"\n"
"If you really think it should be available, please add it to the top of ase/"
"calculators/vasp.py."
msgstr ""
"Kender ikke dette nøgleord:: %s\n"
"Kontrollér venligst!\n"
"\n"
"Hvis du virkelig tror det bør være tilgængeligt, så tilføj det venligst "
"øverst i ase/calculators/vasp.py."
#: ../colors.py:24
msgid "Colors"
msgstr "Farver"
#. Upper left: Choose how the atoms are colored.
#: ../colors.py:41
msgid "Choose how the atoms are colored:"
msgstr "Vælg hvordan atomerne farves:"
#: ../colors.py:43
msgid "By atomic number, default \"jmol\" colors"
msgstr "Efter atomnummer; \"jmol\"-farver som standard"
#: ../colors.py:45
msgid "By atomic number, user specified"
msgstr "Efter atomnummer, brugerdefineret"
#: ../colors.py:46
msgid "By tag"
msgstr "Efter mærke"
#: ../colors.py:47
msgid "By force"
msgstr "Efter kraft"
#: ../colors.py:48
msgid "By velocity"
msgstr "Efter hastighed"
#: ../colors.py:49
msgid "Manually specified"
msgstr "Manuelt angivet"
#: ../colors.py:50
msgid "All the same color"
msgstr "Alle med samme farve"
#. Now fill in the box for additional information in case the force is used.
#: ../colors.py:60
msgid "This should not be displayed!"
msgstr "Dette bør ikke blive vist!"
#: ../colors.py:65 ../colors.py:82 ../rotate.py:25
msgid "Update"
msgstr "Opdatér"
#: ../colors.py:67 ../colors.py:84
msgid "Min: "
msgstr "Min: "
#: ../colors.py:69 ../colors.py:86
msgid " Max: "
msgstr " Maks: "
#: ../colors.py:71 ../colors.py:88
msgid " Steps: "
msgstr " Trin: "
#: ../colors.py:95
msgid "Create a color scale:"
msgstr "Opret en farveskala:"
#: ../colors.py:98
msgid "Black - white"
msgstr "Sort - hvid"
#: ../colors.py:99
msgid "Black - red - yellow - white"
msgstr "Sort - rød - gul - hvid"
#: ../colors.py:100
msgid "Black - green - white"
msgstr "Sort - grøn - hvid"
#: ../colors.py:101
msgid "Black - blue - cyan"
msgstr "Sort - blå - cyan"
#: ../colors.py:102
msgid "Hue"
msgstr "Farvetone"
#: ../colors.py:103
msgid "Named colors"
msgstr "Navngivne farver"
#: ../colors.py:109
msgid "Create"
msgstr "Opret"
#: ../colors.py:367
#, python-format
msgid "Max force: %.2f (this frame), %.2f (all frames)"
msgstr "Maks kraft: %.2f (dette billede), %.2f (alle billeder)"
#: ../colors.py:369
#, python-format
msgid "Max force: %.2f."
msgstr "Maks kraft: %.2f."
#: ../colors.py:383
#, python-format
msgid "Max velocity: %.2f (this frame), %.2f (all frames)"
msgstr "Maks. hastighed: %.2f (dette billede), %.2f (alle billeder)"
#: ../colors.py:385
#, python-format
msgid "Max velocity: %.2f."
msgstr "Maks. hastighed: %.2f."
#: ../colors.py:426
msgid "ERROR"
msgstr "FEJL"
#: ../colors.py:455
msgid "ERR"
msgstr "FEJL"
#: ../colors.py:542
msgid "Incorrect color specification"
msgstr "Forkert farveangivelse"
#: ../constraints.py:13 ../widgets.py:89
msgid "Constraints"
msgstr "Begrænsninger"
#: ../constraints.py:15 ../constraints.py:18 ../settings.py:17
#: ../widgets.py:91 ../widgets.py:94
msgid "Constrain"
msgstr "Begræns"
#: ../constraints.py:16 ../settings.py:20 ../settings.py:35 ../widgets.py:92
msgid " selected atoms"
msgstr " markerede atomer"
#: ../constraints.py:19 ../widgets.py:95
msgid " immobile atoms:"
msgstr " immobile atomer:"
#: ../constraints.py:21
msgid "Unconstrain"
msgstr "Fjern begrænsninger"
#: ../constraints.py:22
msgid " selected atoms:"
msgstr " markerede atomer:"
#: ../constraints.py:24
msgid "Clear constraints"
msgstr "Ryd begrænsninger"
#: ../constraints.py:26 ../dft.py:29 ../settings.py:53 ../widgets.py:60
#: ../widgets.py:99
msgid "Close"
msgstr "Luk"
#: ../crystal.py:16
msgid ""
" Use this dialog to create crystal lattices. First select the structure,\n"
" either from a set of common crystal structures, or by space group "
"description.\n"
" Then add all other lattice parameters.\n"
"\n"
" If an experimental crystal structure is available for an atom, you can\n"
" look up the crystal type and lattice constant, otherwise you have to "
"specify it\n"
" yourself. "
msgstr ""
" Brug denne dialog til at oprette krystalstrukturer. Vælg først "
"strukturen,\n"
" enten fra en samling almindelige krystalstrukturer eller ud fra en\n"
" rumgruppebeskrivelse. Tilføj så alle andre gitterparametre.\n"
"\n"
" Hvis der er en eksperimentel krystalstruktur tilgængelig for at\n"
" atom, kan du slå krystaltypen samt gitterkonstanten op - ellers skal\n"
" du angive den selv. "
#: ../crystal.py:33
#, python-format
msgid " %(natoms)i atoms: %(symbols)s, Volume: %(volume).3f A3"
msgstr " %(natoms)i atomer: %(symbols)s, Volumen: %(volume).3f A3"
#: ../crystal.py:58
msgid "Create Bulk Crystal by Spacegroup"
msgstr "Opret krystalstruktur fra rumgruppe"
#: ../crystal.py:72
msgid "Number: 1"
msgstr "Nummer: 1"
# slice ~ opdel
#: ../crystal.py:73
msgid "Lattice: "
msgstr "Gitter: "
#: ../crystal.py:73
msgid "\tSpace group: "
msgstr "\tRumgruppe: "
#: ../crystal.py:77
msgid "Size: x: "
msgstr "Størrelse: x: "
#: ../crystal.py:78 ../crystal.py:138
msgid " y: "
msgstr " y: "
#: ../crystal.py:79 ../crystal.py:139
msgid " z: "
msgstr " z: "
#: ../crystal.py:80 ../surfaceslab.py:127 ../surfaceslab.py:129
msgid " unit cells"
msgstr " enhedsceller"
#: ../crystal.py:92 ../crystal.py:96 ../crystal.py:100 ../crystal.py:104
#: ../crystal.py:108 ../crystal.py:112
msgid "free"
msgstr "fri"
#: ../crystal.py:93 ../crystal.py:102
msgid "equals b"
msgstr "lig med b"
#: ../crystal.py:94 ../crystal.py:98
msgid "equals c"
msgstr "lig med c"
#: ../crystal.py:95 ../crystal.py:99 ../crystal.py:103 ../crystal.py:107
#: ../crystal.py:111 ../crystal.py:115
msgid "fixed"
msgstr "fast"
#: ../crystal.py:97 ../crystal.py:101
msgid "equals a"
msgstr "lig med a"
#: ../crystal.py:105 ../crystal.py:114
msgid "equals beta"
msgstr "lig med beta"
#: ../crystal.py:106 ../crystal.py:110
msgid "equals gamma"
msgstr "lig med gamma"
#: ../crystal.py:109 ../crystal.py:113
msgid "equals alpha"
msgstr "lig med alfa"
#: ../crystal.py:119
msgid "Lattice parameters"
msgstr "Gitterparametre"
#: ../crystal.py:120
msgid "\t\ta:\t"
msgstr "\t\ta:\t"
#: ../crystal.py:121
msgid "\talpha:\t"
msgstr "\talfa:\t"
#: ../crystal.py:122
msgid "\t\tb:\t"
msgstr "\t\tb:\t"
#: ../crystal.py:123
msgid "\tbeta:\t"
msgstr "\tbeta:\t"
#: ../crystal.py:124
msgid "\t\tc:\t"
msgstr "\t\tc:\t"
#: ../crystal.py:125
msgid "\tgamma:\t"
msgstr "\tgamma:\t"
#: ../crystal.py:126 ../surfaceslab.py:99
msgid "Get from database"
msgstr "Hent fra database"
#: ../crystal.py:131
msgid "Basis: "
msgstr "Basis: "
#: ../crystal.py:137
msgid " Element:\t"
msgstr " Grundstof:\t"
#: ../crystal.py:137
msgid "\tx: "
msgstr "\tx: "
#: ../crystal.py:157
msgid "Creating a crystal."
msgstr "Oprettelse af krystal."
#: ../crystal.py:202
#, python-format
msgid "Symbol: %s"
msgstr "Symbol: %s"
#: ../crystal.py:207
#, python-format
msgid "Number: %s"
msgstr "Nummer: %s"
#: ../crystal.py:210
msgid "Invalid Spacegroup!"
msgstr "Ugyldig rumgruppe!"
#: ../crystal.py:336 ../crystal.py:339
msgid "Please specify a consistent set of atoms."
msgstr "Angiv venligst en konsistent samling atomer."
#: ../crystal.py:348 ../graphene.py:230 ../nanoparticle.py:613
#: ../nanotube.py:139 ../surfaceslab.py:248
msgid "No valid atoms."
msgstr "Ingen gyldige atomer."
#: ../crystal.py:465
msgid "Can't find lattice definition!"
msgstr "Kan ikke finde gitterdefinition!"
#: ../debug.py:11
msgid "Debug"
msgstr "Fejlsøgning"
#: ../dft.py:13
msgid "DFT"
msgstr "DFT"
#: ../dft.py:19
msgid "XC-functional: "
msgstr "XC-funktional: "
#: ../dft.py:23 ../repeat.py:16
msgid "Repeat atoms:"
msgstr "Gentag atomer:"
#: ../energyforces.py:11
msgid "Output:"
msgstr "Uddata:"
#: ../energyforces.py:41
msgid "Save output"
msgstr "Gem uddata"
#: ../energyforces.py:57
msgid "Potential energy and forces"
msgstr "Potentiel energi og kræfter"
#: ../energyforces.py:61
msgid "Calculate potential energy and the force on all atoms"
msgstr "Beregn potentiel energi og kræfter på alle atomer"
#: ../energyforces.py:65
msgid "Write forces on the atoms"
msgstr "Skriv kræfter på atomerne"
#: ../energyforces.py:82
msgid "Potential Energy:\n"
msgstr "Potentiel energi:\n"
#: ../energyforces.py:83
#, python-format
msgid " %8.2f eV\n"
msgstr " %8.2f eV\n"
#: ../energyforces.py:84
#, python-format
msgid ""
" %8.4f eV/atom\n"
"\n"
msgstr ""
" %8.4f eV/atom\n"
"\n"
#: ../energyforces.py:86
msgid "Forces:\n"
msgstr "Kræfter:\n"
#: ../execute.py:23
msgid ""
"\n"
" Global commands work on all frames or only on the current frame\n"
" - Assignment of a global variable may not reference a local one\n"
" - use 'Current frame' switch to switch off application to all frames\n"
" e:\t\ttotal energy of one frame\n"
" fmax:\tmaximal force in one frame\n"
" A:\tunit cell\n"
" E:\t\ttotal energy array of all frames\n"
" F:\t\tall forces in one frame\n"
" M:\tall magnetic moments\n"
" R:\t\tall atomic positions\n"
" S:\tall selected atoms (boolean array)\n"
" D:\tall dynamic atoms (boolean array)\n"
" examples: frame = 1, A[0][1] += 4, e-E[-1]\n"
"\n"
" Atom commands work on each atom (or a selection) individually\n"
" - these can use global commands on the RHS of an equation\n"
" - use 'selected atoms only' to restrict application of command\n"
" x,y,z:\tatomic coordinates\n"
" r,g,b:\tatom display color, range is [0..1]\n"
" rad:\tatomic radius for display\n"
" s:\t\tatom is selected\n"
" d:\t\tatom is movable\n"
" f:\t\tforce\n"
" Z:\tatomic number\n"
" m:\tmagnetic moment\n"
" examples: x -= A[0][0], s = z > 5, Z = 6\n"
"\n"
" Special commands and objects:\n"
" sa,cf:\t(un)restrict to selected atoms/current frame\n"
" frame:\tframe number\n"
" center:\tcenters the system in its existing unit cell\n"
" del S:\tdelete selection\n"
" CM:\tcenter of mass\n"
" ans[-i]:\tith last calculated result\n"
" exec file: executes commands listed in file\n"
" cov[Z]:(read only): covalent radius of atomic number Z\n"
" gui:\tadvanced: ag window python object\n"
" img:\tadvanced: ag images object\n"
" "
msgstr ""
"\n"
" Globale kommandoer virker på alle billeder, eller kun på nuværende "
"billede\n"
" - Tildeling af en global variabel refererer måske ikke til en lokal\n"
" - brug \"Nuværende billede\"-knappen til at slå anvendelse på alle "
"billeder\n"
" til eller fra\n"
" e:\t\ttotalenergi af et billede\n"
" fmax:\tmaksimal kraft i et billede\n"
" A:\tenhedscelle\n"
" E:\t\ttotalenergi som array for alle billeder\n"
" F:\t\talle kræfter i et billede\n"
" M:\talle magnetiske momenter\n"
" R:\t\talle atompositioner\n"
" S:\talle markerede atoms (boolesk array)\n"
" D:\talle dynamiske atomer (boolesk array)\n"
" eksempler: billede = 1, A[0][1] += 4, e-E[-1]\n"
"\n"
" Atomkommandoer virker på hvert atom (eller en markering) enkeltvis\n"
" - disse kan bruge globale kommandoer på højresiden af en ligning\n"
" - brug \"kun markerede atomer\" for at begrænse anvendelsen af en "
"kommando\n"
" x,y,z:\tatomkoordinater\n"
" r,g,b:\tatomvisningsfarve; interval er [0..1]\n"
" rad:\tatomradius (grafisk)\n"
" s:\t\tatom er markeret\n"
" d:\t\tatom kan flyttes\n"
" f:\t\tkraft\n"
" Z:\tatomnummer\n"
" m:\tmagnetisk moment\n"
" eksempler: x -= A[0][0], s = z > 5, Z = 6\n"
"\n"
" Specialkommandoer og objekter:\n"
" sa,cf:\tslå begrænsning til markerede atomer/nuværende atomer \n"
" til eller fra\n"
" frame:\tbillednummer\n"
" center:\tcentrerer systemet i dets eksisterende enhedscelle\n"
" del S:\tfjern markering\n"
" CM:\tmassemidtpunkt\n"
" ans[-i]:\ti'te sidst udregnede resultat\n"
" exec file: kører kommandoerne i en fil\n"
" cov[Z]:(skrivebeskyttet): kovalent radius for atomnummer Z\n"
" gui:\tavanceret: python-objekt for ag-vinduet\n"
" img:\tavanceret: ag-billeder som objekt\n"
" "
#: ../execute.py:67
msgid "Expert user mode"
msgstr "Eksperttilstand"
#: ../execute.py:80
msgid "Welcome to the ASE Expert user mode"
msgstr "Velkommen til ASE's eksperttilstand"
#: ../execute.py:87
msgid "Only selected atoms (sa) "
msgstr "Kun markerede atomer (sa) "
#: ../execute.py:89
msgid "Only current frame (cf) "
msgstr "Kun nuværende billede (cf) "
#: ../execute.py:99
msgid ""
"Global: Use A, D, E, M, N, R, S, n, frame; Atoms: Use a, f, m, s, x, y, z, "
"Z "
msgstr ""
"Globalt: Brug A, D, E, M, N, R, S, n, frame; Atomer: Brug a, f, m, s, x, y, "
"z, Z "
#: ../execute.py:198
#, python-format
msgid "*** WARNING: file does not exist - %s"
msgstr "*** ADVARSEL: filen findes ikke - %s"
#: ../execute.py:203
msgid "*** WARNING: No atoms selected to work with"
msgstr "*** ADVARSEL: Ingen atomer markeret til at arbejde på"
#: ../execute.py:277
msgid "*** Only working on selected atoms"
msgstr "*** Arbejder kun på markerede atomer"
#: ../execute.py:279
msgid "*** Working on all atoms"
msgstr "*** Arbejder på alle atomer"
#: ../execute.py:283
msgid "*** Only working on current image"
msgstr "*** Arbejder kun på nuværende billede"
#: ../execute.py:285
msgid "*** Working on all images"
msgstr "*** Arbejder på alle billeder"
#: ../execute.py:301
msgid "Save Terminal text ..."
msgstr "Gem terminaltekst ..."
#: ../graphene.py:15
msgid ""
"Set up a graphene sheet or a graphene nanoribbon. A nanoribbon may\n"
"optionally be saturated with hydrogen (or another element)."
msgstr ""
"Konstruér et grafénlag eller et grafénnanobånd. Et nanobånd kan eventuelt\n"
"mættes med hydrogen (eller et andet grundstof)."
#: ../graphene.py:30 ../gui.py:298
msgid "Graphene"
msgstr "Grafén"
#. Choose structure
#. The structure and lattice constant
#. Choose the surface structure
#: ../graphene.py:37 ../nanoparticle.py:138 ../surfaceslab.py:78
msgid "Structure: "
msgstr "Struktur: "
#: ../graphene.py:39
msgid "Infinite sheet"
msgstr "Uendeligt lag"
#: ../graphene.py:39
msgid "Unsaturated ribbon"
msgstr "Umættet bånd"
#: ../graphene.py:40
msgid "Saturated ribbon"
msgstr "Mættet bånd"
#. Orientation
#: ../graphene.py:47
msgid "Orientation: "
msgstr "Orientering: "
#: ../graphene.py:50
msgid "zigzag"
msgstr "zigzag"
#: ../graphene.py:50
msgid "armchair"
msgstr "lænestol"
#: ../graphene.py:66 ../graphene.py:78 ../nanotube.py:46
msgid " Bond length: "
msgstr " Bindingslængde: "
#. Choose the saturation element and bond length
#: ../graphene.py:72
msgid "Saturation: "
msgstr "Mætning: "
#: ../graphene.py:75
msgid "H"
msgstr "H"
#. Size
#: ../graphene.py:91
msgid "Width: "
msgstr "Bredde: "
#: ../graphene.py:92 ../nanotube.py:65
msgid " Length: "
msgstr " Længde: "
#. Vacuum
#: ../graphene.py:100
msgid "Vacuum: "
msgstr "Vakuum: "
#: ../graphene.py:138 ../nanotube.py:96 ../setupwindow.py:32
msgid " No element specified!"
msgstr " Intet grundstof angivet!"
#: ../graphene.py:231 ../nanoparticle.py:614 ../nanotube.py:140
#: ../pybutton.py:49 ../surfaceslab.py:249
msgid "You have not (yet) specified a consistent set of parameters."
msgstr "Du har (endnu) ikke angivet konsistente parametre."
#: ../graphs.py:19
msgid "Help for plot ..."
msgstr "Hjælp til grafer ..."
#: ../graphs.py:30 ../graphs.py:33
msgid "Plot"
msgstr "Graf"
#: ../graphs.py:38
msgid "clear"
msgstr "ryd"
#: ../graphs.py:92
msgid "Save data to file ... "
msgstr "Gem data til fil ... "
#: ../gtkexcepthook.py:117
msgid "Bug Detected"
msgstr "Fejl fundet"
#: ../gtkexcepthook.py:121
msgid "A programming error has been detected."
msgstr "Der blev fundet en programmeringsfejl."
#: ../gtkexcepthook.py:124
msgid ""
"It probably isn't fatal, but the details should be reported to the "
"developers nonetheless."
msgstr ""
"Den er nok ikke fatal, men detaljerne bør alligevel rapporteres til "
"udviklerne."
#: ../gtkexcepthook.py:140
msgid "Report..."
msgstr "Rapportér..."
#: ../gtkexcepthook.py:144
msgid "Details..."
msgstr "Detaljer..."
#: ../gtkexcepthook.py:160
#, python-format
msgid ""
"From: buggy_application\"\n"
"To: bad_programmer\n"
"Subject: Exception feedback\n"
"\n"
"%s"
msgstr ""
"Fra: fejlagtigt_program\"\n"
"Til: dårlig_programmør\n"
"Emne: Exception feedback\n"
"\n"
"%s"
#. Show details...
#: ../gtkexcepthook.py:173
msgid "Bug Details"
msgstr "Detaljer om fejl"
#: ../gui.py:164
msgid "_File"
msgstr "_Fil"
#: ../gui.py:165
msgid "_Edit"
msgstr "_Redigér"
#: ../gui.py:166
msgid "_View"
msgstr "_Vis"
#: ../gui.py:167
msgid "_Tools"
msgstr "_Værktøjer"
#. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
#: ../gui.py:169
msgid "_Setup"
msgstr "_Byg"
#: ../gui.py:170
msgid "_Calculate"
msgstr "_Beregn"
#: ../gui.py:171
msgid "_Help"
msgstr "_Hjælp"
#: ../gui.py:172
msgid "_Open"
msgstr "_Ã…bn"
#: ../gui.py:173
msgid "Create a new file"
msgstr "Opret en ny fil"
#: ../gui.py:175
msgid "_New"
msgstr "_Ny"
#: ../gui.py:176
msgid "New ase.gui window"
msgstr "Nyt ase.gui-vindue"
#: ../gui.py:178
msgid "_Save"
msgstr "_Gem"
#: ../gui.py:179
msgid "Save current file"
msgstr "Gem den aktuelle fil"
#: ../gui.py:181
msgid "_Quit"
msgstr "_Afslut"
#: ../gui.py:182
msgid "Quit"
msgstr "Afslut"
#: ../gui.py:184
msgid "Select _all"
msgstr "Vælg _alle"
#: ../gui.py:187
msgid "_Invert selection"
msgstr "_Omvend markering"
#: ../gui.py:190
msgid "Select _constrained atoms"
msgstr "Vælg _fastgjorte atomer"
#: ../gui.py:193
msgid "Select _immobile atoms"
msgstr "Vælg _immobile atomer"
#: ../gui.py:196
msgid "_Copy"
msgstr "_Kopiér"
#: ../gui.py:197
msgid "Copy current selection and its orientation to clipboard"
msgstr "Kopiér nuværende markering og dens orientering til udklipsholderen"
#: ../gui.py:199
msgid "_Paste"
msgstr "_Indsæt"
#: ../gui.py:200
msgid "Insert current clipboard selection"
msgstr "Indsæt nuværende markering fra udklipsholderen"
#: ../gui.py:202
msgid "_Modify"
msgstr "_Ændr"
#: ../gui.py:203
msgid "Change tags, moments and atom types of the selected atoms"
msgstr "Ændr mærker, impuls og atomnummer for de valgte atomer"
#: ../gui.py:205
msgid "_Add atoms"
msgstr "_Tilføj atomer"
#: ../gui.py:206
msgid "Insert or import atoms and molecules"
msgstr "Indsæt eller importér atomer og molekyler"
#: ../gui.py:208
msgid "_Delete selected atoms"
msgstr "_Slet markerede atomer"
#: ../gui.py:209
msgid "Delete the selected atoms"
msgstr "Slet de markerede atomer"
#: ../gui.py:211
msgid "_First image"
msgstr "_Første billede"
#: ../gui.py:214
msgid "_Previous image"
msgstr "_Forrige billede"
#: ../gui.py:217
msgid "_Next image"
msgstr "_Næste billede"
#: ../gui.py:220
msgid "_Last image"
msgstr "_Sidste billede"
#: ../gui.py:223
msgid "Quick Info ..."
msgstr "Hurtig info ..."
#: ../gui.py:226
msgid "Repeat ..."
msgstr "Gentag ..."
#: ../gui.py:229
msgid "Rotate ..."
msgstr "Rotér ..."
#: ../gui.py:232
msgid "Colors ..."
msgstr "Farver ..."
#. TRANSLATORS: verb
#: ../gui.py:235
msgid "Focus"
msgstr "Fokusér"
#: ../gui.py:238
msgid "Zoom in"
msgstr "Zoom ind"
#: ../gui.py:241
msgid "Zoom out"
msgstr "Zoom ud"
#: ../gui.py:244
msgid "Reset View"
msgstr "Nulstil perspektiv"
#: ../gui.py:247
msgid "Settings ..."
msgstr "Indstillinger ..."
#: ../gui.py:250
msgid "VMD"
msgstr "VMD"
#: ../gui.py:253
msgid "RasMol"
msgstr "RasMol"
#: ../gui.py:256
msgid "xmakemol"
msgstr "xmakemol"
#: ../gui.py:259
msgid "avogadro"
msgstr "avogadro"
#: ../gui.py:262
msgid "Graphs ..."
msgstr "Grafer ..."
#: ../gui.py:265
msgid "Movie ..."
msgstr "Film ..."
#: ../gui.py:268
msgid "Expert mode ..."
msgstr "Eksperttilstand ..."
#: ../gui.py:271
msgid "Constraints ..."
msgstr "Begrænsninger ..."
# gemmer et billede af atomerne
#: ../gui.py:274
msgid "Render scene ..."
msgstr "Tegn struktur ..."
#: ../gui.py:277
msgid "DFT ..."
msgstr "DFT ..."
#: ../gui.py:280
msgid "NE_B"
msgstr "NE_B"
#: ../gui.py:283
msgid "B_ulk Modulus"
msgstr "K_ompressibilitetsmodul"
#: ../gui.py:286
msgid "_Bulk Crystal"
msgstr "_Krystal"
#: ../gui.py:287
msgid "Create a bulk crystal with arbitrary orientation"
msgstr "Opret en krystalstruktur med arbitrær orientering"
#: ../gui.py:289
msgid "_Surface slab"
msgstr "_Overflade"
#: ../gui.py:290
msgid "Create the most common surfaces"
msgstr "Opret de mest almindelige overflader"
#: ../gui.py:292
msgid "_Nanoparticle"
msgstr "_Nanopartikel"
#: ../gui.py:293
msgid "Create a crystalline nanoparticle"
msgstr "Opret en krystallinsk nanopartikel"
#: ../gui.py:295
msgid "Nano_tube"
msgstr "Nano_rør"
#: ../gui.py:296
msgid "Create a nanotube"
msgstr "Opret et nanorør"
#: ../gui.py:299
msgid "Create a graphene sheet or nanoribbon"
msgstr "Opret et lag eller bånd af grafén"
#: ../gui.py:301
msgid "Set _Calculator"
msgstr "Angiv _beregner"
#: ../gui.py:302
msgid "Set a calculator used in all calculation modules"
msgstr "Angiv en beregner der skal bruges i alle beregningsmoduler"
#: ../gui.py:304
msgid "_Energy and Forces"
msgstr "_Energi og kræfter"
#: ../gui.py:305
msgid "Calculate energy and forces"
msgstr "Beregn energi og kræfter"
#: ../gui.py:307
msgid "Energy _Minimization"
msgstr "Energi_minimering"
#: ../gui.py:308
msgid "Minimize the energy"
msgstr "Minimér energien"
#: ../gui.py:310
msgid "Scale system"
msgstr "Skalér systemet"
#: ../gui.py:311
msgid "Deform system by scaling it"
msgstr "Deformér systemet ved skalering"
#: ../gui.py:313
msgid "_About"
msgstr "_Om"
#: ../gui.py:316
msgid "Webpage ..."
msgstr "Webside ..."
#: ../gui.py:317
msgid "Debug ..."
msgstr "Fejlsøgning ..."
#: ../gui.py:319
msgid "Show _unit cell"
msgstr "Vis _enhedscelle"
#: ../gui.py:323
msgid "Show _axes"
msgstr "Vis _akser"
#: ../gui.py:327
msgid "Show _bonds"
msgstr "Vis _bindinger"
#: ../gui.py:331
msgid "_Move atoms"
msgstr "_Flyt atomer"
#: ../gui.py:335
msgid "_Rotate atoms"
msgstr "_Rotér atomer"
#: ../gui.py:339
msgid "Orien_t atoms"
msgstr "Orien_tér atomer"
#: ../gui.py:351
#, python-format
msgid "building menus failed: %s"
msgstr "bygning af menuer mislykkedes: %s"
#: ../gui.py:620 ../gui.py:1016 ../gui.py:1076
msgid "Open ..."
msgstr "Ã…bn ..."
#: ../gui.py:624 ../gui.py:1019
msgid "<>"
msgstr "<>"
#: ../gui.py:756
msgid "Add atoms"
msgstr "Tilføj atomer"
#: ../gui.py:759
msgid "Paste"
msgstr "Indsæt"
#: ../gui.py:765
msgid "Insert atom or molecule"
msgstr "Indsæt atom eller molekyle"
#: ../gui.py:766 ../gui.py:883
msgid "Tag"
msgstr "Mærke"
#: ../gui.py:767 ../gui.py:884
msgid "Moment"
msgstr "Moment"
#: ../gui.py:768
msgid "Position"
msgstr "Position"
#: ../gui.py:793
msgid "_Load molecule"
msgstr "_Indlæs molekyle"
#: ../gui.py:797 ../gui.py:899
msgid "_OK"
msgstr "_O.k."
#: ../gui.py:801 ../gui.py:903
msgid "_Cancel"
msgstr "_Annullér"
#: ../gui.py:876
msgid "Modify"
msgstr "Ændr"
#: ../gui.py:882
msgid "Atom"
msgstr "Atom"
#: ../gui.py:927
msgid "Confirmation"
msgstr "Bekræftelse"
#: ../gui.py:931
msgid "Delete selected atom?"
msgid_plural "Delete selected atoms?"
msgstr[0] "Slet det valgte atom?"
msgstr[1] "Slet de valgte atomer?"
#: ../gui.py:938
msgid "Cancel"
msgstr "Annullér"
#: ../gui.py:1024 ../gui.py:1106
msgid "Automatic"
msgstr "Automatisk"
#: ../gui.py:1025
msgid "Dacapo netCDF output file"
msgstr "netCDF-uddatafil fra Dacapo"
#: ../gui.py:1026
msgid "Virtual Nano Lab file"
msgstr "Virtual Nano Lab-fil"
#: ../gui.py:1027
msgid "ASE pickle trajectory"
msgstr "Pickletrajectory fra ASE"
#: ../gui.py:1028 ../gui.py:1119
msgid "ASE bundle trajectory"
msgstr "Bundletrajectory fra ASE"
#: ../gui.py:1029
msgid "GPAW text output"
msgstr "Textudskrift fra GPAW"
#: ../gui.py:1030
msgid "CUBE file"
msgstr "CUBE-fil"
#: ../gui.py:1031
msgid "XCrySDen Structure File"
msgstr "XCrySDen-strukturfil"
#: ../gui.py:1032
msgid "Dacapo text output"
msgstr "Tekstudskrift fra Dacapo"
#: ../gui.py:1033
msgid "XYZ-file"
msgstr "XYZ-fil"
#: ../gui.py:1034
msgid "VASP POSCAR/CONTCAR file"
msgstr "POSCAR/CONTCAR-fil fra VASP"
#: ../gui.py:1035
msgid "VASP OUTCAR file"
msgstr "OUTCAR-fil fra VASP"
#: ../gui.py:1036
msgid "Protein Data Bank"
msgstr "Proteindatabank"
#: ../gui.py:1037
msgid "CIF-file"
msgstr "CIF-fil"
#: ../gui.py:1038
msgid "FHI-aims geometry file"
msgstr "FHI-aims-geometrifil"
#: ../gui.py:1039
msgid "FHI-aims output file"
msgstr "Uddatafil fra FHI-aims"
#: ../gui.py:1040
msgid "TURBOMOLE coord file"
msgstr "TURBOMOLE-koordinatfil"
# exciting er et program
#: ../gui.py:1041
msgid "exciting input"
msgstr "exciting-inddata"
#: ../gui.py:1042
msgid "WIEN2k structure file"
msgstr "WIEN2k-strukturfil"
#: ../gui.py:1043
msgid "DftbPlus input file"
msgstr "DftbPlus-inddatafil"
#: ../gui.py:1044
msgid "ETSF format"
msgstr "ETSF-format"
#: ../gui.py:1045 ../gui.py:1117
msgid "CASTEP geom file"
msgstr "CASTEP-geom-fil"
#: ../gui.py:1046
msgid "CASTEP output file"
msgstr "Uddatafil fra CASTEP"
#: ../gui.py:1047
msgid "CASTEP trajectory file"
msgstr "Trajectory-fil fra CASTEP"
#: ../gui.py:1048
msgid "DFTBPlus GEN format"
msgstr "GEN-format fra DFTBPlus"
#: ../gui.py:1054
msgid "File type:"
msgstr "Filtype:"
#: ../gui.py:1094
msgid "Save ..."
msgstr "Gem ..."
#: ../gui.py:1107
msgid "XYZ file"
msgstr "XYZ-fil"
#: ../gui.py:1108
msgid "ASE trajectory"
msgstr "Trajectory fra ASE"
#: ../gui.py:1109
msgid "PDB file"
msgstr "PDB-fil"
#: ../gui.py:1110
msgid "Gaussian cube file"
msgstr "Cube-fil fra Gaussian"
#: ../gui.py:1111
msgid "Python script"
msgstr "Pythonscript"
#: ../gui.py:1112
msgid "VNL file"
msgstr "VNL-fil"
#: ../gui.py:1113
msgid "Portable Network Graphics"
msgstr "Portable Network Graphics"
#: ../gui.py:1114
msgid "Persistence of Vision"
msgstr "Persistence of Vision"
#: ../gui.py:1115
msgid "Encapsulated PostScript"
msgstr "Encapsulated PostScript"
#: ../gui.py:1116
msgid "FHI-aims geometry input"
msgstr "Geometriinddata til FHI-aims"
#: ../gui.py:1118
msgid "VASP geometry input"
msgstr "Geometriinddata til VASP"
#: ../gui.py:1120
msgid "cif file"
msgstr "cif-fil"
#: ../gui.py:1142
#, python-format
msgid "Save current image only (#%d)"
msgstr "Gem kun nuværende billede (#%d)"
# slice ~ opdel
#: ../gui.py:1146
msgid "Slice: "
msgstr "Del: "
#: ../gui.py:1147
msgid "Help for slice ..."
msgstr "Hjælp til opdeling ..."
#: ../gui.py:1159
msgid "AG INTERNAL ERROR: strange response in Save,"
msgstr "INTERN FEJL I AG: mystisk svar i Save,"
#: ../gui.py:1178
msgid "Unknown output format!"
msgstr "Ukendt uddataformat!"
#: ../gui.py:1179
#, python-format
msgid "Use one of: %s"
msgstr "Brug et af: %s"
#: ../gui.py:1284
msgid "Not implemented!"
msgstr "Ikke implementeret!"
#: ../gui.py:1285
msgid "do you really need it?"
msgstr "har du virkelig brug for dette?"
#: ../minimize.py:20
msgid "Algorithm: "
msgstr "Algoritme: "
#: ../minimize.py:25 ../progress.py:67
msgid "Convergence criterion: Fmax = "
msgstr "Konvergenskriterium: Fmax = "
#: ../minimize.py:30 ../progress.py:70
msgid "Max. number of steps: "
msgstr "Maksimalt antal trin: "
#. Special stuff for MDMin
#: ../minimize.py:33
msgid "Pseudo time step: "
msgstr "Pseudotidsskridt: "
#: ../minimize.py:54
msgid "Energy minimization"
msgstr "Energiminimering"
#: ../minimize.py:58
msgid "Minimize the energy with respect to the positions."
msgstr "Minimér energien med hensyn til positionerne."
#. Don't catch errors in the function.
#. Display status message
#: ../minimize.py:90 ../scaling.py:299
msgid "Running ..."
msgstr "Kører ..."
#. Update display to reflect cancellation of simulation.
#: ../minimize.py:107
#, python-format
msgid "Minimization CANCELLED after %i steps."
msgstr "Minimering AFBRUDT efter %i trin."
#: ../minimize.py:113 ../scaling.py:350
msgid "Out of memory, consider using LBFGS instead"
msgstr "Løbet tør for hukommelse; overvej at bruge LBFGS i stedet"
#. Update display to reflect succesful end of simulation.
#: ../minimize.py:120
#, python-format
msgid "Minimization completed in %i steps."
msgstr "Minimering fuldført på %i trin."
#. self.connect('delete_event', self.exit2)
#: ../movie.py:14
msgid "Movie"
msgstr "Film"
#: ../movie.py:16
msgid "Image number:"
msgstr "Billednummer:"
#: ../movie.py:38
msgid "Play"
msgstr "Afspil"
#: ../movie.py:40
msgid "Stop"
msgstr "Stop"
#. TRANSLATORS: This function plays an animation forwards and backwards
#. alternatingly, e.g. for displaying vibrational movement
#: ../movie.py:44
msgid "Rock"
msgstr "Pendul"
#: ../movie.py:60
msgid " Frame rate: "
msgstr " Billedrate: "
#: ../movie.py:61
msgid " Skip frames: "
msgstr " Overspring billeder: "
#: ../nanoparticle.py:19
msgid ""
"Create a nanoparticle either by specifying the number of layers, or using "
"the\n"
"Wulff construction. Please press the [Help] button for instructions on how "
"to\n"
"specify the directions.\n"
"WARNING: The Wulff construction currently only works with cubic crystals!\n"
msgstr ""
"Opret en nanopartikel enten ved at angive antallet af lag, eller ved\n"
"brug af Wulffkonstruktion. Tryk på knappen [Hjælp] for at få\n"
"instruktioner om hvordan retninger angives.\n"
"\n"
"ADVARSEL: Wulffkonstruktion fungerer i øjeblikket kun med kubiske "
"krystaller!\n"
#: ../nanoparticle.py:26
msgid ""
"\n"
"The nanoparticle module sets up a nano-particle or a cluster with a given\n"
"crystal structure.\n"
"\n"
"1) Select the element, the crystal structure and the lattice constant(s).\n"
" The [Get structure] button will find the data for a given element.\n"
"\n"
"2) Choose if you want to specify the number of layers in each direction, or "
"if\n"
" you want to use the Wulff construction. In the latter case, you must "
"specify\n"
" surface energies in each direction, and the size of the cluster.\n"
"\n"
"How to specify the directions:\n"
"------------------------------\n"
"\n"
"First time a direction appears, it is interpreted as the entire family of\n"
"directions, i.e. (0,0,1) also covers (1,0,0), (-1,0,0) etc. If one of "
"these\n"
"directions is specified again, the second specification overrules that "
"specific\n"
"direction. For this reason, the order matters and you can rearrange the\n"
"directions with the [Up] and [Down] keys. You can also add a new "
"direction,\n"
"remember to press [Add] or it will not be included.\n"
"\n"
"Example: (1,0,0) (1,1,1), (0,0,1) would specify the {100} family of "
"directions,\n"
"the {111} family and then the (001) direction, overruling the value given "
"for\n"
"the whole family of directions.\n"
msgstr ""
"\n"
"Nanopartikelmodulet konstruerer en nanopartikel eller klynge med en\n"
"given krystalstruktur.\n"
"\n"
"1) Vælg grundstoffet, krystalstrukturen og gitterkonstanterne.\n"
" Knappen [Hent struktur] vil finde data for et givet grundstof.\n"
"\n"
"2) Vælg om du vil angive antallet af lag i hver retning, eller om du\n"
" vil benytte en Wulffkonstruktion. I sidstnævnte tilfælde skal du\n"
" angive overfladeenergier for hver retning samt klyngens størrelse.\n"
"\n"
"Hvordan retninger angives\n"
"-------------------------\n"
"\n"
"Første gang en retning dukker op, fortolkes den som en hel familie af\n"
"retninger - f.eks. dækker (0,0,1) også (1,0,0), (-1,0,0) osv. Hvis en af\n"
"disse retninger angives igen, vil anden specifikation særligt gælde\n"
"denne specifikke retning. Derfor er rækkefølgen ikke ligegyldig, og du kan\n"
"omarrangere retningerne med knapperne [Op] og [Ned]. Du kan også tilføje in "
"ny retning - husk at trykke [Tilføj], eller den vil ikke blive inkluderet.\n"
"\n"
"Eksempel: (1,0,0), (1,1,1), (0,0,1) ville angive familien {100} af "
"retninger,\n"
"{111}-familien og så (001) retningen, der tilsidesætter værdien givet til\n"
"selve familien af retninger.\n"
#. Structures: Abbreviation, name, 4-index (boolean), two lattice const (bool), factory
#: ../nanoparticle.py:83
msgid "Face centered cubic (fcc)"
msgstr "Face centered cubic (fcc)"
#: ../nanoparticle.py:84
msgid "Body centered cubic (bcc)"
msgstr "Body centered cubic (bcc)"
#: ../nanoparticle.py:85
msgid "Simple cubic (sc)"
msgstr "Simpel kubisk (sc)"
#: ../nanoparticle.py:86
msgid "Hexagonal closed-packed (hcp)"
msgstr "Heksagonal tætpakket (hcp)"
#: ../nanoparticle.py:87
msgid "Graphite"
msgstr "Grafit"
#: ../nanoparticle.py:116
msgid "Nanoparticle"
msgstr "Nanopartikel"
#. Choose the element
#. Choose the element and bond length
#. Choose the element
#: ../nanoparticle.py:126 ../nanotube.py:40 ../surfaceslab.py:69
msgid "Element: "
msgstr "Grundstof: "
#: ../nanoparticle.py:130
msgid "Get structure"
msgstr "Hent struktur"
#: ../nanoparticle.py:154
msgid "Lattice constant: a ="
msgstr "Gitterkonstant: a ="
#. Choose specification method
#: ../nanoparticle.py:171
msgid "Method: "
msgstr "Metode: "
#: ../nanoparticle.py:173
msgid "Layer specification"
msgstr "Lagspecifikation"
#: ../nanoparticle.py:173
msgid "Wulff construction"
msgstr "Wulffkonstruktion"
#: ../nanoparticle.py:193
msgid "Dummy placeholder object"
msgstr "Stedfortræderobjekt"
#: ../nanoparticle.py:195
msgid "Add new direction:"
msgstr "Tilføj ny retning:"
#: ../nanoparticle.py:211
msgid "Add"
msgstr "Tilføj"
#: ../nanoparticle.py:219
msgid "Set all directions to default values"
msgstr "Sæt alle retninger til standardværdier"
#: ../nanoparticle.py:227
msgid "Particle size: "
msgstr "Partikelstørrelse: "
#: ../nanoparticle.py:228 ../nanoparticle.py:265 ../progress.py:196
msgid "Number of atoms: "
msgstr "Antal atomer: "
#: ../nanoparticle.py:233
msgid "Volume: "
msgstr "Volumen: "
#: ../nanoparticle.py:238
msgid "ų"
msgstr "ų"
#: ../nanoparticle.py:243
msgid "Rounding: If exact size is not possible, choose the size"
msgstr "Afrunding: Hvis eksakt størrelse ikke kan opnås, så vælg størrelsen"
#: ../nanoparticle.py:246
msgid "above "
msgstr "over "
#: ../nanoparticle.py:247
msgid "below "
msgstr "under "
#: ../nanoparticle.py:248
msgid "closest "
msgstr "tættest på "
#: ../nanoparticle.py:251
msgid "Smaller"
msgstr "Mindre"
#: ../nanoparticle.py:252
msgid "Larger"
msgstr "Større"
#: ../nanoparticle.py:267
msgid " Approx. diameter: "
msgstr " Diameter omtrent: "
#: ../nanoparticle.py:271
msgid "Information about the created cluster:"
msgstr "Information om den konstruerede klynge:"
#. Buttons
#: ../nanoparticle.py:277 ../nanotube.py:75
msgid "Creating a nanoparticle."
msgstr "Konstruktion af nanopartikel."
#: ../nanoparticle.py:284
msgid "Automatic Apply"
msgstr "Anvend automatisk"
#: ../nanoparticle.py:332
msgid "Up"
msgstr "Op"
#: ../nanoparticle.py:337
msgid "Down"
msgstr "Ned"
#: ../nanoparticle.py:342
msgid "Delete"
msgstr "Slet"
#: ../nanoparticle.py:383
msgid "Surface energies (as energy/area, NOT per atom):"
msgstr "Overfladeenergier (som energi/areal, IKKE per atom):"
#: ../nanoparticle.py:389
msgid "Number of layers:"
msgstr "Antal lag:"
#: ../nanoparticle.py:418
msgid "At least one index must be non-zero"
msgstr "Mindst et indeks skal være forskelligt fra nul"
#: ../nanoparticle.py:421
msgid "Invalid hexagonal indices"
msgstr "Ugyldige heksagonale indeks"
#: ../nanoparticle.py:476 ../surfaceslab.py:218
msgid "Invalid element."
msgstr "Ugyldigt grundstof."
#: ../nanoparticle.py:486
msgid "Unsupported or unknown structure"
msgstr "Uunderstøttet eller ukendt struktur"
#: ../nanoparticle.py:603
#, python-format
msgid "%.1f Ã…"
msgstr "%.1f Ã…"
#: ../nanotube.py:14
msgid ""
"Set up a Carbon nanotube by specifying the (n,m) roll-up vector.\n"
"Please note that m <= n.\n"
"\n"
"Nanotubes of other elements can be made by specifying the element\n"
"and bond length."
msgstr ""
"Byg et kulstofnanorør ved at angive uprulningsvektoren (n, m).\n"
"Bemærk at m <= n.\n"
"\n"
"Nanorør af andre grundstoffer kan bygges ved at angive hvilket grundstof,\n"
"samt bindingslængde."
#: ../nanotube.py:33
msgid "Nanotube"
msgstr "Nanorør"
#. Choose the structure.
#: ../nanotube.py:57
msgid "Select roll-up vector (n,m) and tube length:"
msgstr "Vælg oprulningsvektor (n,m) og rørlængde:"
#: ../progress.py:25
msgid "Progress"
msgstr "Fremgang"
#: ../progress.py:32
msgid "Scaling deformation:"
msgstr "Skaleringsdeformation:"
#: ../progress.py:38
#, python-format
msgid "Step number %s of %s."
msgstr "Trin nummer %s af %s."
#. Minimization progress frame
#. Box containing frame and spacing
#: ../progress.py:53
msgid "Energy minimization:"
msgstr "Energiminimering:"
#: ../progress.py:60
msgid "Step number: "
msgstr "Trinnummer: "
#: ../progress.py:62
msgid "Fmax: "
msgstr "Fmax: "
#: ../progress.py:102
msgid "unknown"
msgstr "ukendt"
#: ../progress.py:179
msgid "Status: "
msgstr "Status: "
#: ../progress.py:181
msgid "Iteration: "
msgstr "Iteration: "
#: ../progress.py:184
msgid "log10(change):"
msgstr "log10(skift):"
#: ../progress.py:187
msgid "Wave functions: "
msgstr "Bølgefunktioner: "
#: ../progress.py:189
msgid "Density: "
msgstr "Tæthed: "
#: ../progress.py:191
msgid "Energy: "
msgstr "Energi: "
#: ../progress.py:194
msgid "GPAW version: "
msgstr "GPAW-version: "
#: ../progress.py:197
msgid "N/A"
msgstr "-"
#: ../progress.py:198
msgid "Memory estimate: "
msgstr "Hukommelsesestimat: "
#: ../progress.py:233
msgid "No info"
msgstr "Ingen info"
#: ../progress.py:243
msgid "Initializing"
msgstr "Klargør"
#: ../progress.py:244
msgid "Positions:"
msgstr "Positioner:"
#: ../progress.py:248
msgid "Starting calculation"
msgstr "Starter beregning"
#: ../progress.py:285
msgid "unchanged"
msgstr "uændret"
#: ../progress.py:295
msgid "Self-consistency loop"
msgstr "Selvkonsistensløkke"
#: ../progress.py:300
msgid "Calculating forces"
msgstr "Beregner kræfter"
#: ../progress.py:301
msgid " (converged)"
msgstr " (konvergeret)"
#: ../pybutton.py:37
msgid "Python"
msgstr "Python"
#: ../pybutton.py:48
msgid "No Python code"
msgstr "Ingen Pythonkode"
#: ../pybutton.py:52
#, python-format
msgid ""
"\n"
"Title: %(title)s\n"
"Time: %(time)s\n"
msgstr ""
"\n"
"Titel: %(title)s\n"
"Tid: %(time)s\n"
#: ../pybutton.py:61
msgid "ag: Python code"
msgstr "ag: Pythonkode"
#: ../pybutton.py:65
msgid "Information:"
msgstr "Information:"
#: ../pybutton.py:72
msgid "Python code:"
msgstr "Pythonkode:"
#: ../quickinfo.py:9
msgid "Single image loaded."
msgstr "Enkelt billede indlæst."
#: ../quickinfo.py:10
#, python-format
msgid "Image %d loaded (0 - %d)."
msgstr "Billede %d indlæst (0 - %d)."
#: ../quickinfo.py:11
msgid "Unit cell is fixed."
msgstr "Enhedscelle fastholdes."
#: ../quickinfo.py:12
msgid "Unit cell varies."
msgstr "Enhedscelle varierer."
#: ../quickinfo.py:14
#, python-format
msgid ""
"%s\n"
"\n"
"Number of atoms: %d.\n"
"\n"
"Unit cell:\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
"%s\n"
msgstr ""
"%s\n"
"\n"
"Antal atomer: %d.\n"
"\n"
"Enhedscelle:\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
"%s\n"
#: ../quickinfo.py:29
msgid "Quick Info"
msgstr "Hurtig info"
#: ../quickinfo.py:33
msgid "No atoms loaded."
msgstr "Ingen atomer indlæst."
#: ../render.py:14
msgid ""
" Textures can be used to highlight different parts of\n"
" an atomic structure. This window applies the default\n"
" texture to the entire structure and optionally\n"
" applies a different texture to subsets of atoms that\n"
" can be selected using the mouse.\n"
" An alternative selection method is based on a boolean\n"
" expression in the entry box provided, using the\n"
" variables x, y, z, or Z. For example, the expression\n"
" Z == 11 and x > 10 and y > 10 \n"
" will mark all sodium atoms with x or coordinates \n"
" larger than 10. In either case, the button labeled\n"
" `Create new texture from selection` will enable\n"
" to change the attributes of the current selection. \n"
" "
msgstr ""
" Teksturer kan bruges til at fremhæve forskellige dele af en\n"
" atomar struktur. Dette vindue anvender standardteksturen på hele\n"
" strukturen, og anvender valgfrit en anden tekstur til bestemte\n"
" atomer som kan markeres med musen.\n"
" En alternativ markeringsmetode baseret på booleske udtryk\n"
" i et tekstfelt kan bruges med variabelnavnene x, y, z eller Z.\n"
" For eksempel vil udtrykket Z == 11 and x > 10 and y > 10\n"
" markere alle natriumatomer med x- eller y-koordinater\n"
" større end 10. I begge tilfælde vil knappen med teksten\n"
" \"Opret ny tekstur fra markering\" tillade ændring af\n"
" attributterne for den nuværende markering.\n"
" "
# gemmer et billede af atomerne
#: ../render.py:32
msgid "Render current view in povray ... "
msgstr "Tegn nuværende struktur i povray ... "
#: ../render.py:36
#, python-format
msgid "Rendering %d atoms."
msgstr "Tegner %d atomer."
#: ../render.py:41
msgid "Render constraints"
msgstr "Tegn begrænsninger"
#: ../render.py:44
msgid "Width"
msgstr "Bredde"
#: ../render.py:45
msgid " Height"
msgstr " Højde"
#: ../render.py:52
msgid "Render unit cell"
msgstr "Tegn _enhedscelle"
#: ../render.py:61
msgid "Line width"
msgstr "Linjebredde"
#: ../render.py:63
msgid "Angstrom "
msgstr "Ångström "
#: ../render.py:73
msgid "Set"
msgstr "Angiv"
#: ../render.py:75
msgid "Output basename: "
msgstr "Basisnavn for output: "
#: ../render.py:77
msgid " Filename: "
msgstr " Filnavn: "
#: ../render.py:88
msgid " Default texture for atoms: "
msgstr " Standardtekstur for atomer: "
#: ../render.py:89
msgid " transparency: "
msgstr " gennemsigtighed: "
#: ../render.py:90
msgid "Define atom selection for new texture:"
msgstr "Definér atommarkering til ny tekstur:"
#: ../render.py:92
msgid "Select"
msgstr "Vælg"
#: ../render.py:96
msgid "Create new texture from selection"
msgstr "Opret ny tekstur fra markering"
#: ../render.py:98
msgid "Help on textures"
msgstr "Hjælp til teksturer"
#: ../render.py:111
msgid "Camera type: "
msgstr "Kameratype: "
#: ../render.py:112
msgid " Camera distance"
msgstr " Kameraafstand"
#: ../render.py:113
msgid "Render current frame"
msgstr "Tegn det aktuelle billede"
#: ../render.py:117
#, python-format
msgid "Render all %d frames"
msgstr "Tegn alle %d billeder"
#: ../render.py:122
msgid "Transparent background"
msgstr "Gennemsigtig baggrund"
#: ../render.py:125
msgid "Run povray "
msgstr "Kør povray "
#: ../render.py:128
msgid "Keep povray files "
msgstr "Behold povray-filer "
#: ../render.py:131
msgid "Show output window"
msgstr "Vis outputvindue"
#: ../render.py:212
msgid " transparency: "
msgstr " gennemsigtighed: "
#: ../render.py:218
msgid ""
"Can not create new texture! Must have some atoms selected to create a new "
"material!"
msgstr ""
"Kan ikke oprette ny tekstur! Der skal være atomer markeret for at kunne "
"oprette nyt materiale!"
#: ../repeat.py:14
msgid "Repeat"
msgstr "Gentag"
#: ../repeat.py:21
msgid "Set unit cell"
msgstr "Angiv enhedscelle"
#: ../rotate.py:15
msgid "Rotate"
msgstr "Rotér"
#: ../rotate.py:17
msgid "Rotation angles:"
msgstr "Rotationsvinkler:"
#: ../rotate.py:27
msgid ""
"Note:\n"
"You can rotate freely\n"
"with the mouse, by holding\n"
"down mouse button 2."
msgstr ""
"Bemærk:\n"
"Du kan frit rotere med\n"
"musen ved at holde\n"
"musetast 2 nede."
#: ../scaling.py:49
msgid "Homogeneous scaling"
msgstr "Homogen skalering"
#: ../scaling.py:59
msgid "3D deformation "
msgstr "3D-deformation "
#: ../scaling.py:60
msgid "2D deformation "
msgstr "2D-deformation "
#: ../scaling.py:61
msgid "1D deformation "
msgstr "1D-deformation "
#: ../scaling.py:64
msgid "Bulk"
msgstr "Krystal"
#: ../scaling.py:66
msgid "xy-plane"
msgstr "xy-plan"
#: ../scaling.py:68
msgid "xz-plane"
msgstr "xz-plan"
#: ../scaling.py:70
msgid "yz-plane"
msgstr "yz-plan"
#: ../scaling.py:72
msgid "x-axis"
msgstr "x-akse"
#: ../scaling.py:74
msgid "y-axis"
msgstr "y-akse"
#: ../scaling.py:76
msgid "z-axis"
msgstr "z-akse"
#: ../scaling.py:89
msgid "Allow deformation along non-periodic directions."
msgstr "Tillad deformation langs ikke-periodiske retninger."
#. Parameters for the deformation
#: ../scaling.py:94
msgid "Deformation:"
msgstr "Deformation:"
#: ../scaling.py:100
msgid "Maximal scale factor: "
msgstr "Maksimal skaleringsfaktor: "
#: ../scaling.py:103
msgid "Scale offset: "
msgstr "Forskydning ved skalering: "
#: ../scaling.py:106
msgid "Number of steps: "
msgstr "Antal trin: "
#: ../scaling.py:107
msgid "Only positive deformation"
msgstr "Kun positiv deformation"
#. Atomic relaxations
#: ../scaling.py:112
msgid "Atomic relaxations:"
msgstr "Atomrelakseringer:"
#: ../scaling.py:116
msgid "On "
msgstr "Til "
#: ../scaling.py:117
msgid "Off"
msgstr "Fra"
#. Results
#: ../scaling.py:128
msgid "Results:"
msgstr "Resultater:"
#: ../scaling.py:130
msgid "Keep original configuration"
msgstr "Behold oprindelig konfiguration"
#: ../scaling.py:132
msgid "Load optimal configuration"
msgstr "Indlæs optimal konfiguration"
#: ../scaling.py:134
msgid "Load all configurations"
msgstr "Indlæs alle konfigurationer"
#: ../scaling.py:143
msgid "Strain\t\tEnergy [eV]"
msgstr "Spænding\t\tEnergi [eV]"
#: ../scaling.py:144
msgid "Fit:"
msgstr "Fit:"
#: ../scaling.py:148
msgid "2nd"
msgstr "2."
#: ../scaling.py:149
msgid "3rd"
msgstr "3."
#: ../scaling.py:153
msgid "Order of fit: "
msgstr "Orden for fit: "
#. Update display to reflect cancellation of simulation.
#: ../scaling.py:346
msgid "Calculation CANCELLED."
msgstr "Beregning AFBRUDT."
#. Update display to reflect succesful end of simulation.
#: ../scaling.py:357
msgid "Calculation completed."
msgstr "Beregning fuldført."
#: ../scaling.py:380
msgid "No trustworthy minimum: Old configuration kept."
msgstr "Intet troværdigt minimum: Gammel konfiguration beholdt."
#: ../scaling.py:420
#, python-format
msgid ""
"Insufficent data for a fit\n"
"(only %i data points)\n"
msgstr ""
"Utilstrækkelige data til fit\n"
"(kun %i datapunkter)\n"
#: ../scaling.py:424
msgid ""
"REVERTING TO 2ND ORDER FIT\n"
"(only 3 data points)\n"
"\n"
msgstr ""
"GÃ…R NED TIL ANDENORDENS FIT\n"
"(kun 3 datapunkter)\n"
"\n"
#: ../scaling.py:440
msgid "No minimum found!"
msgstr "Intet minimum fundet!"
#: ../scaling.py:454
msgid ""
"\n"
"WARNING: Minimum is outside interval\n"
msgstr ""
"\n"
"ADVARSEL: Minimum ligger uden for interval\n"
#: ../scaling.py:455
msgid "It is UNRELIABLE!\n"
msgstr "Det er UTILREGNELIGT!\n"
#: ../settings.py:16
msgid "Constraints:"
msgstr "Begrænsninger:"
#: ../settings.py:19
msgid "release"
msgstr "frigiv"
# I dette tilfælde er constrain = fastgøre
#: ../settings.py:23
msgid "Constrain immobile atoms"
msgstr "Fastgør immobile atomer"
#: ../settings.py:25
msgid "Clear all constraints"
msgstr "Ryd alle begrænsninger"
#: ../settings.py:31
msgid "Visibility:"
msgstr "Synlighed:"
#: ../settings.py:32
msgid "Hide"
msgstr "Skjul"
#: ../settings.py:34
msgid "show"
msgstr "vis"
#: ../settings.py:38
msgid "View all atoms"
msgstr "Vis alle atomer"
#: ../settings.py:44
msgid "Miscellaneous:"
msgstr "Diverse:"
#: ../settings.py:47
msgid "Scale atomic radii:"
msgstr "Skalér atomradier:"
#. A close button
#: ../settings.py:52
msgid "\n"
msgstr "\n"
#: ../setupwindow.py:51
msgid "No crystal structure data"
msgstr "Ingen data for krystalstruktur"
#: ../setupwindow.py:62
msgid " ERROR: Invalid element!"
msgstr " FEJL: ugyldigt grundstof!"
#: ../simulation.py:24
msgid " (rerun simulation)"
msgstr " (kør simulation igen)"
#: ../simulation.py:25
msgid " (continue simulation)"
msgstr " (fortsæt simulation)"
#: ../simulation.py:27
msgid "Select starting configuration:"
msgstr "Vælg startkonfiguration:"
#: ../simulation.py:32
#, python-format
msgid "There are currently %i configurations loaded."
msgstr "Der er i øjeblikket indlæst %i konfigurationer."
#: ../simulation.py:36
msgid "Choose which one to use as the initial configuration"
msgstr "Vælg hvilken, der skal bruges som begyndelseskonfiguration"
#: ../simulation.py:40
#, python-format
msgid "The first configuration %s."
msgstr "Første konfiguration %s."
#: ../simulation.py:43
msgid "Configuration number "
msgstr "Konfiguration nummer "
#: ../simulation.py:49
#, python-format
msgid "The last configuration %s."
msgstr "Sidste konfiguration %s."
#: ../simulation.py:85
msgid "Run"
msgstr "Kør"
#: ../simulation.py:105
msgid "No calculator: Use Calculate/Set Calculator on the menu."
msgstr "Ingen beregner: Brug Beregn/Angiv beregner i menuen."
#: ../status.py:37 ../status.py:39
msgid "Tip for status box ..."
msgstr "Fif til statusboks ..."
#. TRANSLATORS: mom refers to magnetic moment
#: ../status.py:63
#, python-format
msgid " tag=%(tag)s mom=%(mom)1.2f"
msgstr " mærke=%(tag)s mom=%(mom)1.2f"
#: ../status.py:104
msgid "dihedral"
msgstr "dihedral"
#: ../surfaceslab.py:14
msgid ""
" Use this dialog to create surface slabs. Select the element by\n"
"writing the chemical symbol or the atomic number in the box. Then\n"
"select the desired surface structure. Note that some structures can\n"
"be created with an othogonal or a non-orthogonal unit cell, in these\n"
"cases the non-orthogonal unit cell will contain fewer atoms.\n"
"\n"
" If the structure matches the experimental crystal structure, you can\n"
"look up the lattice constant, otherwise you have to specify it\n"
"yourself."
msgstr ""
" Brug denne dialog til at oprette overflader. Vælg grundstoffet ved at \n"
"skrive det kemiske symbol eller atomnummeret i boksen. Vælg så den ønskede\n"
"overfladestruktur. Bemærk at visse strukturer kan oprettes med både en\n"
"ortogonal og en ikke-ortogonal enhedscelle; i disse tilfælde vil\n"
"den ikke-ortogonale enhedscelle indeholde færre atomer.\n"
"\n"
" Hvis strukturen svarer til den eksperimentelle krystalstruktur, kan\n"
"du slå gitterkonstanten op. Ellers skal du angive den selv."
#. Name, structure, orthogonal, support-nonorthogonal, function
#: ../surfaceslab.py:26
msgid "FCC(100)"
msgstr "FCC(100)"
#: ../surfaceslab.py:26 ../surfaceslab.py:27 ../surfaceslab.py:28
#: ../surfaceslab.py:30
msgid "fcc"
msgstr "fcc"
#: ../surfaceslab.py:27
msgid "FCC(110)"
msgstr "FCC(110)"
#: ../surfaceslab.py:28
msgid "FCC(111) non-orthogonal"
msgstr "FCC(111) ikke-ortogonal"
#: ../surfaceslab.py:30
msgid "FCC(111) orthogonal"
msgstr "FCC(111) ortogonal"
#: ../surfaceslab.py:31
msgid "BCC(100)"
msgstr "BCC(100)"
#: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:34
#: ../surfaceslab.py:35 ../surfaceslab.py:37
msgid "bcc"
msgstr "bcc"
#: ../surfaceslab.py:32
msgid "BCC(110) non-orthogonal"
msgstr "BCC(110) ikke-ortogonal"
#: ../surfaceslab.py:34
msgid "BCC(110) orthogonal"
msgstr "BCC(110) ortogonal"
#: ../surfaceslab.py:35
msgid "BCC(111) non-orthogonal"
msgstr "BCC(111) ikke-ortogonal"
#: ../surfaceslab.py:37
msgid "BCC(111) orthogonal"
msgstr "BCC(111) ortogonal"
#: ../surfaceslab.py:38
msgid "HCP(0001) non-orthogonal"
msgstr "HCP(0001) ikke-ortogonal"
#: ../surfaceslab.py:38 ../surfaceslab.py:40 ../surfaceslab.py:41
msgid "hcp"
msgstr "hcp"
#: ../surfaceslab.py:40
msgid "HCP(0001) orthogonal"
msgstr "HCP(0001) ortogonal"
#: ../surfaceslab.py:41
msgid "HCP(10-10) orthogonal"
msgstr "HCP(10-10) ortogonal"
#: ../surfaceslab.py:43
msgid "DIAMOND(100) orthogonal"
msgstr "DIAMOND(100) ortogonal"
#: ../surfaceslab.py:43 ../surfaceslab.py:45
msgid "diamond"
msgstr "diamant"
#: ../surfaceslab.py:45
msgid "DIAMOND(111) non-orthogonal"
msgstr "DIAMANT(111) ikke-ortogonal"
#: ../surfaceslab.py:60
msgid "Surface"
msgstr "Overflade"
#: ../surfaceslab.py:90
msgid "Lattice constant: "
msgstr "Gitterkonstant: "
#: ../surfaceslab.py:97
msgid "a:"
msgstr "a:"
#: ../surfaceslab.py:109
#, python-format
msgid "(%.1f %% of ideal)"
msgstr "(%.1f %% af ideel)"
#: ../surfaceslab.py:126
msgid "Size: \tx: "
msgstr "Størr.:\tx: "
#: ../surfaceslab.py:128
msgid "\t\ty: "
msgstr "\t\ty: "
#: ../surfaceslab.py:130
msgid " \t\tz: "
msgstr " \t\tz: "
#: ../surfaceslab.py:131
msgid " layers, "
msgstr " lag, "
#: ../surfaceslab.py:132
msgid " Ã… vacuum"
msgstr " Ã… vakuum"
#: ../surfaceslab.py:133
msgid "\t\tNo size information yet."
msgstr "\t\tEndnu ingen størrelsesoplysninger."
#. Buttons
#: ../surfaceslab.py:142
msgid "Creating a surface slab."
msgstr "Oprettelse af overflade."
#: ../surfaceslab.py:212
#, python-format
msgid "%i atoms."
msgstr "%i atomer."
#: ../surfaceslab.py:224
msgid "No structure specified!"
msgstr "Ingen struktur angivet!"
# %s ~ BCC
#: ../surfaceslab.py:233
#, python-format
msgid "%(struct)s lattice constant unknown for %(element)s."
msgstr "%(struct)s-gitterkonstant ukendt for %(element)s."
#: ../widgets.py:53 ../widgets.py:80
msgid "Help"
msgstr "Hjælp"
#: ../widgets.py:97
msgid "Clear constraint"
msgstr "Ryd begrænsninger"
#~ msgid " %8.3f, %8.3f, %8.3f eV/Ã…\n"
#~ msgstr " %8.3f, %8.3f, %8.3f eV/Ã…\n"
#~ msgid "%s (a=%.3f Ã…)"
#~ msgstr "%s (a=%.3f Ã…)"
#~ msgid " %s: %s, Z=%i, %s"
#~ msgstr " %s: %s, Z=%i, %s"
#~ msgid " #%d %s (%s): %.3f Ã…, %.3f Ã…, %.3f Ã… "
#~ msgstr " #%d %s (%s): %.3f Ã…, %.3f Ã…, %.3f Ã… "
#~ msgid " %s-%s: %.3f Ã…"
#~ msgstr " %s-%s: %.3f Ã…"
#~ msgid " %s-%s-%s: %.1f°, %.1f°, %.1f°"
#~ msgstr " %s-%s-%s: %.1f°, %.1f°, %.1f°"
#~ msgid "dihedral %s->%s->%s->%s: %.1f°"
#~ msgstr "dihedral %s->%s->%s->%s: %.1f°"
#~ msgid "c:"
#~ msgstr "c:"
#~ msgid "\t\t%.2f Ã… x %.2f Ã… x %.2f Ã…, %i atoms."
#~ msgstr "\t\t%.2f Ã… x %.2f Ã… x %.2f Ã…, %i atomer."
#~ msgid "FILE"
#~ msgstr "FIL"
#~ msgid "%prog [options] [file[, file2, ...]]"
#~ msgstr "%prog [tilvalg] [fil[, fil2, ...]]"
#~ msgid "NUMBER"
#~ msgstr "NUMMER"
#~ msgid ""
#~ "Pick image(s) from trajectory. NUMBER can be a single number (use a "
#~ "negative number to count from the back) or a range: start:stop:step, "
#~ "where the \":step\" part can be left out - default values are 0:nimages:1."
#~ msgstr ""
#~ "Vælg billeder fra traj-fil. NUMMER kan være et enkelt tal (brug et "
#~ "negativt tal til at tælle bagfra) eller et interval på formen start:stop:"
#~ "trin, hvor elementet \":trin\" kan udelades. Standardværdi er 0:"
#~ "antalbilleder:1."
#~ msgid "I"
#~ msgstr "I"
#~ msgid ""
#~ "0: Don't show unit cell. 1: Show unit cell. 2: Show all of unit cell."
#~ msgstr ""
#~ "0: Vis ikke enhedscellen. 1: Vis enhedscellen. 2: Vis hele enhedscellen."
#~ msgid "Repeat unit cell. Use \"-r 2\" or \"-r 2,3,1\"."
#~ msgstr "Gentag enhedscellen. Brug \"-r 2\" eller \"-r 2,3,1\"."
#~ msgid "Examples: \"-R -90x\", \"-R 90z,-30x\"."
#~ msgstr "Eksempler: \"-R -90x\", \"-R 90z,-30x\"."
#~ msgid "Write configurations to FILE."
#~ msgstr "Skriv konfigurationer til FIL."
#~ msgid "EXPR"
#~ msgstr "UDTRYK"
#~ msgid ""
#~ "Plot x,y1,y2,... graph from configurations or write data to sdtout in "
#~ "terminal mode. Use the symbols: i, s, d, fmax, e, ekin, A, R, E and F. "
#~ "See https://wiki.fysik.dtu.dk/ase/ase/gui.html#plotting-data for more "
#~ "details."
#~ msgstr ""
#~ "Tegn graf for x,y1,y2,... fra konfigurationer, eller skriv data til "
#~ "stdout i teksttilstand. Brug symbolerne i, s, d, fmax, e, ekin, A, R, E "
#~ "og F. Yderligere detaljer kan findes på https://wiki.fysik.dtu.dk/ase/"
#~ "ase/gui.html#plotting-data for more details."
#~ msgid "Run in terminal window - no GUI."
#~ msgstr "Kør i terminalvindue - uden grafisk grænseflade."
#~ msgid "Read ANEB data."
#~ msgstr "Læs ANEB-data."
#~ msgid "N"
#~ msgstr "N"
#~ msgid "Interpolate N images between 2 given images."
#~ msgstr "Interpolér N billeder mellem to givne billeder."
#~ msgid "Draw bonds between atoms."
#~ msgstr "Tegn bindinger mellem atomer."
python-ase-3.6.0.2515/ase/gui/po/es_ES/ 0000755 0001754 0001754 00000000000 11757245036 016162 5 ustar askhl askhl python-ase-3.6.0.2515/ase/gui/po/es_ES/LC_MESSAGES/ 0000755 0001754 0001754 00000000000 11757245036 017747 5 ustar askhl askhl python-ase-3.6.0.2515/ase/gui/po/es_ES/LC_MESSAGES/ag.po 0000644 0001754 0001754 00000232221 11716573517 020703 0 ustar askhl askhl # Spanish translations for ASE package.
# Copyright (C) 2012 CAMD
# This file is distributed under the same license as the ASE package.
# Ask Hjorth Larsen , 2012.
# Max Ramirez , 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: ase-3.5.2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-01 16:08+0100\n"
"PO-Revision-Date: 2012-02-02 00:15+0100\n"
"Last-Translator: Max Ramirez \n"
"Language-Team: Spanish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../ag.py:130
msgid ""
"\n"
"An exception occurred! Please report the issue to\n"
"ase-developers@listserv.fysik.dtu.dk - thanks! Please also report this if\n"
"it was a user error, so that a better error message can be provided\n"
"next time."
msgstr ""
"\n"
"Se produjo un error! Por favor, reporte el problema a\n"
"\n"
"ase-developers@listserv.fysik.dtu.dk \n"
"\n"
"Muchas gracias! Por favor, reporte también el problema si\n"
"fue un error de usuario, de esta forma podemos proveer un\n"
"mejor mensaje de error la próxima vez."
#. Asap and GPAW may be imported if selected.
#: ../calculator.py:18
msgid ""
"To make most calculations on the atoms, a Calculator object must first\n"
"be associated with it. ASE supports a number of calculators, supporting\n"
"different elements, and implementing different physical models for the\n"
"interatomic interactions."
msgstr ""
"Para realizar la mayorÃa de los calculos sobre los átomos,\n"
"se debe primero definir y asociar un objeto calculador \n"
"(Calculator) con éstos. ASE soporta un número de calculadores, \n"
"los cuales además de poder realizar cálculos sobre distintos \n"
"elementos, implementan también modelos fÃsicos diferentes para \n"
"las interacciones interatómicas."
#. Informational text about the calculators
#: ../calculator.py:26
msgid ""
"The Lennard-Jones pair potential is one of the simplest\n"
"possible models for interatomic interactions, mostly\n"
"suitable for noble gasses and model systems.\n"
"\n"
"Interactions are described by an interaction length and an\n"
"interaction strength."
msgstr ""
"El potencial de pares de Lennard-Jones es uno de los \n"
"modelos más simples para las interacciones atómicas. \n"
"Éste es adecuado para describir y modelar sistemas \n"
"compuestos de gases nobles.\n"
"\n"
"Las interacciones en este potencial son descritas por \n"
"un largo de interacción y una fuerza de interacción."
#: ../calculator.py:35
msgid ""
"The EMT potential is a many-body potential, giving a\n"
"good description of the late transition metals crystalling\n"
"in the FCC crystal structure. The elements described by the\n"
"main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and\n"
"Au, the Al potential is however not suitable for materials\n"
"science application, as the stacking fault energy is wrong.\n"
"\n"
"A number of parameter sets are provided.\n"
"\n"
"Default parameters:\n"
"\n"
"The default EMT parameters, as published in K. W. Jacobsen,\n"
"P. Stoltze and J. K. Nørskov, Surf. Sci. 366, 394 (1996).\n"
"\n"
"Alternative Cu, Ag and Au:\n"
"\n"
"An alternative set of parameters for Cu, Ag and Au,\n"
"reoptimized to experimental data including the stacking\n"
"fault energies by Torben Rasmussen (partly unpublished).\n"
"\n"
"Ruthenium:\n"
"\n"
"Parameters for Ruthenium, as published in J. Gavnholt and\n"
"J. Schiøtz, Phys. Rev. B 77, 035404 (2008).\n"
"\n"
"Metallic glasses:\n"
"\n"
"Parameters for MgCu and CuZr metallic glasses. MgCu\n"
"parameters are in N. P. Bailey, J. Schiøtz and\n"
"K. W. Jacobsen, Phys. Rev. B 69, 144205 (2004).\n"
"CuZr in A. Paduraru, A. Kenoufi, N. P. Bailey and\n"
"J. Schiøtz, Adv. Eng. Mater. 9, 505 (2007).\n"
msgstr ""
"El potencial EMT es un potencial de muchos cuerpos, el cual describe\n"
"de manera correcta a los metales de transición que cristalizan en una\n"
"estructura tipo FCC. Los elementos descritos por el conjunto de pará-\n"
"metros del EMT son Al, Ni, Cu, Pd, Ag, Pt y Au. Sin embargo, la descripción\n"
"de este potencial para el aluminio no es adecuado para su uso en la\n"
"ciencia de materiales, ya que la energÃa de apilamiento es incorrecta.\n"
"\n"
"Con ASE se provee un conjunto de parámetros para este potencial.\n"
"\n"
"Parámetros por defecto:\n"
"\n"
"Los parámetros por defecto de este potencial son extraÃdos de la siguiente\n"
"publicación: K. W. Jacobsen, P. Stoltze y J. K. Nørskov, Surf. Sci."
"i> \n"
"366, 394 (1996).\n"
"\n"
"Parámetros alternativos para Cu, Ag y Au:\n"
"\n"
"Un conjunto de parámetros alternativo para Cu, Ag y Au fueron reoptimizados\n"
"con datos experimentales incluyendo la energÃa de apilamiento (parcialmente "
"no\n"
"publicada) por Torben Rasmussen.\n"
"\n"
"Rutenio:\n"
"\n"
"Los parámetros para Rutenio fueron extraÃdos de la publicación J. Gavnholt "
"y\n"
"J. Schiøtz, Phys. Rev. B 77, 035404 (2008).\n"
"\n"
"Vidrios metálicos:\n"
"\n"
"Conjunto de parámetros para vidrios metálicos compuestos de MgCu y CuZr. "
"Los\n"
"parámetros para MgCu fueron extraÃdos desde N. P. Bailey, J. Schiøtz y \n"
"K. W. Jacobsen, Phys. Rev. B 69, 144205 (2004). Para CuZr los\n"
"parámetros fueron extraÃdos de la publicación A. Paduraru, A. Kenoufi, \n"
"N. P. Bailey y J. Schiøtz, Adv. Eng. Mater. 9, 505 (2007).\n"
#: ../calculator.py:70
msgid ""
"The EMT potential is a many-body potential, giving a\n"
"good description of the late transition metals crystalling\n"
"in the FCC crystal structure. The elements described by the\n"
"main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and\n"
"Au. In addition, this implementation allows for the use of\n"
"H, N, O and C adatoms, although the description of these is\n"
"most likely not very good.\n"
"\n"
"This is the ASE implementation of EMT. For large\n"
"simulations the ASAP implementation is more suitable; this\n"
"implementation is mainly to make EMT available when ASAP is\n"
"not installed.\n"
msgstr ""
"El potencial EMT es un potencial de muchos cuerpos, el\n"
"cual describe de manera correcta a los metales de tran-\n"
"sición que cristalizan en una estructura tipo FCC. Los \n"
"elementos descritos por el conjunto de parámetros del \n"
"EMT son Al, Ni, Cu, Pd, Ag, Pt y Au. Adicionalmente, esta\n"
"implementación permite el uso de H, N, O y C. Sin embargo, \n"
"la descripción de estos no es muy buena.\n"
"\n"
"Esta es la implementación de ASE de EMT. Para simu-\n"
"laciones más grandes la implementación ASAP es más confiable.\n"
"Esta implemetación es para tener un EMT cuando ASAP no está\n"
"instalado.\n"
#: ../calculator.py:85
msgid ""
"The Brenner potential is a reactive bond-order potential for\n"
"carbon and hydrocarbons. As a bond-order potential, it takes\n"
"into account that carbon orbitals can hybridize in different\n"
"ways, and that carbon can form single, double and triple\n"
"bonds. That the potential is reactive means that it can\n"
"handle gradual changes in the bond order as chemical bonds\n"
"are formed or broken.\n"
"\n"
"The Brenner potential is implemented in Asap, based on a\n"
"C implentation published at http://www.rahul.net/pcm/brenner/ .\n"
"\n"
"The potential is documented here:\n"
" Donald W Brenner, Olga A Shenderova, Judith A Harrison,\n"
" Steven J Stuart, Boris Ni and Susan B Sinnott:\n"
" \"A second-generation reactive empirical bond order (REBO)\n"
" potential energy expression for hydrocarbons\",\n"
" J. Phys.: Condens. Matter 14 (2002) 783-802.\n"
" doi: 10.1088/0953-8984/14/4/312\n"
msgstr ""
"El potencial de Brenner es un potencial reactivo al orden\n"
"del enlace para carbón e hidrocarbones. Como es un potencial\n"
"con orden de enlace, toma en cuenta que los orbitales de \n"
"carbono pueden hibridizarse de diferentes maneras, y que el\n"
"carbon puede formar enlaces simples, dobles y triples. \n"
"Que el potencial sea reactivo significa que puede manejar \n"
"cambios graduales en el orden del enlace, como por ejemplo\n"
" que los enlaces quÃmicos se pueden crear y destruir.\n"
"\n"
"El potencial de Brenner está implementado en ASAP, basado \n"
"en una implementación de C publicada en \n"
"\n"
"http://www.rahul.net/pcm/brenner/ .\n"
"\n"
"El potencial está documentado aquÃ:\n"
" Donald W Brenner, Olga A Shenderova, Judith A Harrison,\n"
" Steven J Stuart, Boris Ni and Susan B Sinnott:\n"
" \"A second-generation reactive empirical bond order (REBO)\n"
" potential energy expression for hydrocarbons\",\n"
" J. Phys.: Condens. Matter 14 (2002) 783-802. \n"
" doi: 10.1088/0953-8984/14/4/312\n"
#: ../calculator.py:107
msgid ""
"GPAW implements Density Functional Theory using a\n"
"Grid-based real-space representation of the wave\n"
"functions, and the Projector Augmented Wave\n"
"method for handling the core regions. \n"
msgstr ""
"GPAW implementa la teorÃa del funcional de la densidad\n"
"utilizando una representación en el espacio real basado\n"
"en grillas de las funciones de onda, y el método de las\n"
"ondas aumentadas proyectadas para manejar las regiones\n"
"del núcleo.\n"
#: ../calculator.py:114
msgid ""
"FHI-aims is an external package implementing density \n"
"functional theory and quantum chemical methods using \n"
"all-electron methods and a numeric local orbital basis set. \n"
"For full details, see http://www.fhi-berlin.mpg.de/aims/ \n"
"or Comp. Phys. Comm. v180 2175 (2009). The ASE \n"
"documentation contains information on the keywords and \n"
"functionalities available within this interface. \n"
msgstr ""
"FHI-aims es un paquete externo que implementa la teorÃa del \n"
"funcional de la densidad y métodos quÃmicos cuánticos utilizando\n"
"métodos con todos los electrones y bases numéricas locales. \n"
"\n"
"Para mayores detalles, visite\n"
"\n"
"http://www.fhi-berlin.mpg.de/aims/ \n"
"\n"
"o revise la referencia Comp. Phys. Comm. v180 2175 (2009). \n"
"La documentación de ASE contiene información sobre las \n"
"palabras clave y las funcionalidades disponibles en esta \n"
"interfaz.\n"
#: ../calculator.py:124
msgid ""
"WARNING:\n"
"Your system seems to have more than zero but less than \n"
"three periodic dimensions. Please check that this is \n"
"really what you want to compute. Assuming full \n"
"3D periodicity for this calculator."
msgstr ""
"ADVERTENCIA: al parecer su sistema tiene más de una pero menos\n"
"de tres dimensiones periódicas. Por favor, compruebe que esto es\n"
"realmente lo que desea calcular. Asumiendo periodicidad 3D completa\n"
"para éste cálculo."
#: ../calculator.py:131
msgid ""
"VASP is an external package implementing density \n"
"functional functional theory using pseudopotentials \n"
"or the projector-augmented wave method together \n"
"with a plane wave basis set. For full details, see\n"
"http://cms.mpi.univie.ac.at/vasp/vasp/\n"
msgstr ""
"VASP es un paquete externo, el cual implementa la\n"
"teorÃa del funcional de la densidad utilizando\n"
"pseudopotenciales ó el método de las ondas proyectadas\n"
"y aumentadas en conjunto con un conjunto de ondas planas.\n"
"Para más detalles, visite\n"
"\n"
"http://cms.mpi.univie.ac.at/vasp/vasp/\n"
#: ../calculator.py:140
msgid "Default (Al, Ni, Cu, Pd, Ag, Pt, Au)"
msgstr "Por defecto (Al, Ni, Cu, Pd, Ag, Pt, Au)"
#: ../calculator.py:141
msgid "Alternative Cu, Ag and Au"
msgstr "Parámetros alternativos para Cu, Ag y Au"
#: ../calculator.py:142
msgid "Ruthenium"
msgstr "Rutenio"
#: ../calculator.py:143
msgid "CuMg and CuZr metallic glass"
msgstr "Vidrios metálicos de CuMg y CuZr"
#: ../calculator.py:158
msgid "Select calculator"
msgstr "Seleccione Calculador (Calculator)"
#: ../calculator.py:164
msgid "Calculator:"
msgstr "Calculador:"
#. No calculator (the default)
#: ../calculator.py:167
msgid "None"
msgstr "Ninguno"
#: ../calculator.py:172
msgid "Lennard-Jones (ASAP)"
msgstr "Lennard-Jones (ASAP)"
#: ../calculator.py:173 ../calculator.py:206 ../calculator.py:215
#: ../calculator.py:224
msgid "Setup"
msgstr "Configuración"
# EMT - Effective Medium Theory (ASAP)
#: ../calculator.py:180
msgid "EMT - Effective Medium Theory (ASAP)"
msgstr "EMT - TeorÃa Media Efectiva (ASAP)"
#: ../calculator.py:192
msgid "EMT - Effective Medium Theory (ASE)"
msgstr "EMT - TeorÃa Media Efectiva (ASE)"
#: ../calculator.py:198
msgid "Brenner Potential (ASAP)"
msgstr "Potencial de Brenner (ASAP)"
#: ../calculator.py:204
msgid "Density Functional Theory (GPAW)"
msgstr "TeorÃa del funcional de la densidad (GPAW)"
#: ../calculator.py:213
msgid "Density Functional Theory (FHI-aims)"
msgstr "TeorÃa del funcional de la densidad (FHI-aims)"
#: ../calculator.py:222
msgid "Density Functional Theory (VASP)"
msgstr "TeorÃa del funcional de la densidad (VASP)"
#: ../calculator.py:235
msgid "Check that the calculator is reasonable."
msgstr "Compruebe que el calculador sea razonable."
#: ../calculator.py:298 ../simulation.py:114
msgid "No atoms present"
msgstr "No hay átomos presentes"
#: ../calculator.py:388 ../calculator.py:422 ../calculator.py:456
msgid "ASAP is not installed. (Failed to import asap3)"
msgstr "ASAP no está instalado. (Error al importar asap3)"
#: ../calculator.py:391
msgid "You must set up the Lennard-Jones parameters"
msgstr "Usted debe establecer los parámetros del potencial de Lennard-Jones"
#: ../calculator.py:396
msgid "Could not create useful Lennard-Jones calculator."
msgstr "No se pudo crear un calculador Lennard-Jones útil."
#: ../calculator.py:430
msgid "Could not attach EMT calculator to the atoms."
msgstr "No se pudo adjuntar el calculador EMT a los átomos."
#: ../calculator.py:472 ../calculator.py:484
msgid "GPAW is not installed. (Failed to import gpaw)"
msgstr "GPAW no está instalado (Error al importar gpaw)"
#: ../calculator.py:475
msgid "You must set up the GPAW parameters"
msgstr "Debe establecer los parámetros para GPAW"
#: ../calculator.py:516
msgid "You must set up the FHI-aims parameters"
msgstr "Debe establecer los parámetros para FHI-aims"
#: ../calculator.py:530
msgid "You must set up the VASP parameters"
msgstr "Debe establecer los parámetros para VASP"
#: ../calculator.py:554
#, python-format
msgid "Element %(sym)s not allowed by the '%(name)s' calculator"
msgstr "El elemento %(sym)s no esta permitido para el calculador '%(name)s'"
#: ../calculator.py:561
msgid "Info"
msgstr "Información"
#: ../calculator.py:577
msgid "Lennard-Jones parameters"
msgstr "Parámetros de Lennard-Jones"
#: ../calculator.py:589
msgid "Specify the Lennard-Jones parameters here"
msgstr "Especifique los parámetros de Lennard-Jones aquÃ"
# Epsilon (eV)
#: ../calculator.py:592
msgid "Epsilon (eV):"
msgstr "Epsilon (eV):"
#: ../calculator.py:596
msgid "Sigma (Ã…):"
msgstr "Sigma (Ã…):"
#. TRANSLATORS: Shift roughly means adjust (about a potential)
#: ../calculator.py:600
msgid "Shift to make smooth at cutoff"
msgstr "Cambie para que el corte sea suave"
#: ../calculator.py:681
msgid "GPAW parameters"
msgstr "Parámetros de GPAW"
#. label = gtk.Label("Specify the GPAW parameters here")
#. pack(vbox, [label])
#. Print some info
#: ../calculator.py:696 ../calculator.py:985 ../calculator.py:1473
#, python-format
msgid "%i atoms.\n"
msgstr "átomos %i.\n"
#: ../calculator.py:698
#, python-format
msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Ã…."
msgstr "Celda unitaria ortogonal: %.2f x %.2f x %.2f Ã…."
#: ../calculator.py:700
msgid "Non-orthogonal unit cell:\n"
msgstr "Celda unitaria no ortogonal:\n"
#: ../calculator.py:710 ../calculator.py:1001 ../calculator.py:1488
msgid "Exchange-correlation functional: "
msgstr "Funcional de intercambio y correlación: "
#. Grid spacing
#: ../calculator.py:714
msgid "Grid spacing"
msgstr "Espacio de grilla"
#: ../calculator.py:718 ../graphene.py:67 ../graphene.py:79 ../graphene.py:102
#: ../nanotube.py:47 ../surfaceslab.py:97
msgid "Ã…"
msgstr "Ã…"
#: ../calculator.py:719
msgid "Grid points"
msgstr "Puntos de grilla"
#: ../calculator.py:728
#, python-format
msgid "heff = (%.3f, %.3f, %.3f) Ã…"
msgstr "heff = (%.3f, %.3f, %.3f) Ã…"
#: ../calculator.py:754 ../calculator.py:1016 ../calculator.py:1524
msgid "k-points k = ("
msgstr "puntos k k=("
#: ../calculator.py:758 ../calculator.py:1020
#, python-format
msgid "k-points x size: (%.1f, %.1f, %.1f) Ã…"
msgstr "Tamaño de los puntos k: (%.1f, %.1f, %.1f) Å"
#. Spin polarized
#: ../calculator.py:763 ../calculator.py:1486
msgid "Spin polarized"
msgstr "Polarizado de espÃn"
#: ../calculator.py:769
msgid "FD - Finite Difference (grid) mode"
msgstr "Modo de grilla tipo diferencias finitas"
#: ../calculator.py:770
msgid "LCAO - Linear Combination of Atomic Orbitals"
msgstr "LCAO - Combinaciones lineales de orbitales atómicos"
#: ../calculator.py:773
msgid "Mode: "
msgstr "Modo: "
#: ../calculator.py:775
msgid "sz - Single Zeta"
msgstr "sz - Single Zeta"
#: ../calculator.py:776
msgid "szp - Single Zeta polarized"
msgstr "szp - Single Zeta polarizado"
#: ../calculator.py:777
msgid "dzp - Double Zeta polarized"
msgstr "dzp - Doble Zeta polarizado"
#. dzp
#: ../calculator.py:779
msgid "Basis functions: "
msgstr "Funciones base: "
#. Mixer
#: ../calculator.py:785
msgid "Non-standard mixer parameters"
msgstr "Parámetros combinados no estándar"
#: ../calculator.py:981
msgid "FHI-aims parameters"
msgstr "Parámetros de FHI-aims"
#: ../calculator.py:988
msgid "Periodic geometry, unit cell is:\n"
msgstr "GeometrÃa periódica, la celda unitaria es:\n"
#: ../calculator.py:993
msgid "Non-periodic geometry.\n"
msgstr "GeometrÃa no periódica\n"
#: ../calculator.py:1000
msgid "Hirshfeld-based dispersion correction"
msgstr "Corrección a la dispersión basada en el método de Hirshfeld"
#. Spin polarized, charge, relativity
#: ../calculator.py:1026
msgid "Spin / initial moment "
msgstr "Spin / momento inicial"
#: ../calculator.py:1044
msgid " Charge"
msgstr " Carga"
#: ../calculator.py:1046
msgid " Relativity"
msgstr " Relatividad"
#: ../calculator.py:1048
msgid " Threshold"
msgstr " Umbral"
#. self-consistency criteria
#: ../calculator.py:1053
msgid "Self-consistency convergence:"
msgstr "Convergencia auto-consistente:"
#: ../calculator.py:1066
msgid "Compute forces"
msgstr "Calcule las fuerzas"
#. XXX: use gtk table for layout. Spaces will not work well otherwise
#. (depend on fonts, widget style, ...)
#. TRANSLATORS: Don't care too much about these, just get approximately
#. the same string lengths
#: ../calculator.py:1077
msgid "Energy: "
msgstr "EnergÃa: "
#: ../calculator.py:1079
msgid " eV Sum of eigenvalues: "
msgstr " eV Suma de los autovalores: "
#: ../calculator.py:1081 ../calculator.py:1559
msgid " eV"
msgstr " eV"
#: ../calculator.py:1082
msgid "Electron density: "
msgstr "Densidad electrónica: "
#: ../calculator.py:1084
msgid " Force convergence: "
msgstr " Convergencia de la fuerza: "
#: ../calculator.py:1086
msgid " eV/Ang "
msgstr " eV/Ã… "
#: ../calculator.py:1099 ../calculator.py:1570
msgid "Additional keywords: "
msgstr "Palabras clave adicionales: "
#. run command and species defaults:
#: ../calculator.py:1113
msgid "FHI-aims execution command: "
msgstr "Comando de ejecución por FHI-aims: "
#: ../calculator.py:1115 ../calculator.py:1587
msgid "Directory for species defaults: "
msgstr "Directorio para las especies por defecto: "
#: ../calculator.py:1127 ../calculator.py:1595
msgid "Set Defaults"
msgstr "Establecer por defecto"
#: ../calculator.py:1129
msgid "Import control.in"
msgstr "Importar control.in"
#: ../calculator.py:1131
msgid "Export control.in"
msgstr "Exportar control.in"
#: ../calculator.py:1317
msgid "Export parameters ... "
msgstr "Exportar parámetros ... "
#: ../calculator.py:1337
msgid "Import control.in file ... "
msgstr "Importar el archivo control.in ... "
#: ../calculator.py:1393 ../calculator.py:1907
#, python-format
msgid ""
"Please use the facilities provided in this window to manipulate the keyword: "
"%s!"
msgstr ""
"Por favor use las interfases previstas en esta ventana para manipular la "
"palabra clave: \n"
"%s!"
#: ../calculator.py:1396
#, python-format
msgid ""
"Don't know this keyword: %s\n"
"\n"
"Please check!\n"
"\n"
"If you really think it should be available, please add it to the top of ase/"
"calculators/aims.py."
msgstr ""
"No conozco la palabra clave %s\n"
"\n"
"Por favor, compruebe que la palabra clave esté correcta!\n"
"\n"
"Si usted realmente piensa que deberÃa estar disponible, por favor agrégela "
"al inicio de\n"
"\n"
"ase/calculators/aims.py"
#: ../calculator.py:1469
msgid "VASP parameters"
msgstr "Parámetros de VASP"
#: ../calculator.py:1475
msgid "Periodic geometry, unit cell is: \n"
msgstr "GeometrÃa periódica, la celda unitaria es: \n"
#: ../calculator.py:1527
msgid ") Cutoff: "
msgstr ") radio de corte: "
#: ../calculator.py:1528
msgid " Precision: "
msgstr " Precisión: "
#: ../calculator.py:1530
#, python-format
msgid "k-points x size: (%.1f, %.1f, %.1f) Ã… "
msgstr "Tamaño de los puntos k: (%.1f, %.1f, %.1f) Å "
# Smearing:
#: ../calculator.py:1546
msgid "Smearing: "
msgstr "Smearing: "
#: ../calculator.py:1548
msgid " order: "
msgstr " orden: "
#: ../calculator.py:1550
msgid " width: "
msgstr " ancho: "
#: ../calculator.py:1557
msgid "Self-consistency convergence: "
msgstr "Convergencia auto-consistente: "
#. run command and location of POTCAR files:
#: ../calculator.py:1583
msgid "VASP execution command: "
msgstr "Comando de ejecución de VASP: "
#: ../calculator.py:1597
msgid "Import VASP files"
msgstr "Importar archivos de VASP"
#: ../calculator.py:1599
msgid "Export VASP files"
msgstr "Exportar archivos de VASP"
#: ../calculator.py:1810
msgid "WARNING: cutoff energy is lower than recommended minimum!"
msgstr ""
"ADVERTENCIA: ¡La energÃa de corte es más baja que el mÃnimo "
"recomendado! "
#: ../calculator.py:1862
msgid "Import VASP input files: choose directory ... "
msgstr "Importando archivos de entrada de VASP: elija directorio ... "
#: ../calculator.py:1877
msgid "Export VASP input files: choose directory ... "
msgstr "Exportando archivos de salida de VASP: elija directorio ... "
#: ../calculator.py:1910
#, python-format
msgid ""
"Don't know this keyword: %s\n"
"Please check!\n"
"\n"
"If you really think it should be available, please add it to the top of ase/"
"calculators/vasp.py."
msgstr ""
"No conozco esta palabra clave: %s\n"
"¡Por favor, revÃsela!\n"
"\n"
"Si usted realmente cree que deberÃa estar disponible, por favor\n"
"agrégela al inicio del archivo\n"
"calculators/vasp.py"
#: ../colors.py:24
msgid "Colors"
msgstr "Colores"
#. Upper left: Choose how the atoms are colored.
#: ../colors.py:41
msgid "Choose how the atoms are colored:"
msgstr "Elija el color de los átomos:"
#: ../colors.py:43
msgid "By atomic number, default \"jmol\" colors"
msgstr "Por número atómico, colores de \"jmol\" por defecto"
#: ../colors.py:45
msgid "By atomic number, user specified"
msgstr "Por número atómico, especificado por el usuario"
#: ../colors.py:46
msgid "By tag"
msgstr "Por etiqueta"
#: ../colors.py:47
msgid "By force"
msgstr "Por fuerza"
#: ../colors.py:48
msgid "By velocity"
msgstr "Por velocidad"
#: ../colors.py:49
msgid "Manually specified"
msgstr "Especificado manualmente"
#: ../colors.py:50
msgid "All the same color"
msgstr "Todos del mismo color"
#. Now fill in the box for additional information in case the force is used.
#: ../colors.py:60
msgid "This should not be displayed!"
msgstr "¡Esto no deberÃa ser desplegado!"
#: ../colors.py:65 ../colors.py:82 ../rotate.py:25
msgid "Update"
msgstr "Actualizar"
#: ../colors.py:67 ../colors.py:84
msgid "Min: "
msgstr "MÃn: "
#: ../colors.py:69 ../colors.py:86
msgid " Max: "
msgstr " Máx: "
#: ../colors.py:71 ../colors.py:88
msgid " Steps: "
msgstr " Pasos: "
#: ../colors.py:95
msgid "Create a color scale:"
msgstr "Crear una escala de colores:"
#: ../colors.py:98
msgid "Black - white"
msgstr "Negro - blanco"
#: ../colors.py:99
msgid "Black - red - yellow - white"
msgstr "Negro - rojo - amarillo - blanco"
#: ../colors.py:100
msgid "Black - green - white"
msgstr "Negro - verde - blanco"
#: ../colors.py:101
msgid "Black - blue - cyan"
msgstr "Negro - azul - cian"
#: ../colors.py:102
msgid "Hue"
msgstr "Tonalidad"
#: ../colors.py:103
msgid "Named colors"
msgstr "Colores con nombre"
#: ../colors.py:109
msgid "Create"
msgstr "Crear"
#: ../colors.py:367
#, python-format
msgid "Max force: %.2f (this frame), %.2f (all frames)"
msgstr "Fuerza máx: %.2f (este cuadro), %.2f (todos los cuadros)"
#: ../colors.py:369
#, python-format
msgid "Max force: %.2f."
msgstr "Fuerza máx: %.2f."
#: ../colors.py:383
#, python-format
msgid "Max velocity: %.2f (this frame), %.2f (all frames)"
msgstr "Velocidad máxima: %.2f (este cuadro), %.2f (todos los cuadros)"
#: ../colors.py:385
#, python-format
msgid "Max velocity: %.2f."
msgstr "Velocidad máxima: %.2f."
#: ../colors.py:426
msgid "ERROR"
msgstr "ERROR"
#: ../colors.py:455
msgid "ERR"
msgstr "ERR"
#: ../colors.py:542
msgid "Incorrect color specification"
msgstr "Especificación de color incorrecta"
#: ../constraints.py:13 ../widgets.py:89
msgid "Constraints"
msgstr "Restricciones"
#: ../constraints.py:15 ../constraints.py:18 ../settings.py:17
#: ../widgets.py:91 ../widgets.py:94
msgid "Constrain"
msgstr "Restricción"
#: ../constraints.py:16 ../settings.py:20 ../settings.py:35 ../widgets.py:92
msgid " selected atoms"
msgstr " átomos seleccionados"
#: ../constraints.py:19 ../widgets.py:95
msgid " immobile atoms:"
msgstr " átomos inamovibles:"
#: ../constraints.py:21
msgid "Unconstrain"
msgstr "Liberar restriccciones"
#: ../constraints.py:22
msgid " selected atoms:"
msgstr " átomos seleccionados:"
#: ../constraints.py:24
msgid "Clear constraints"
msgstr "Quitar las restricciones"
#: ../constraints.py:26 ../dft.py:29 ../settings.py:53 ../widgets.py:60
#: ../widgets.py:99
msgid "Close"
msgstr "Cerrar"
#: ../crystal.py:16
msgid ""
" Use this dialog to create crystal lattices. First select the structure,\n"
" either from a set of common crystal structures, or by space group "
"description.\n"
" Then add all other lattice parameters.\n"
"\n"
" If an experimental crystal structure is available for an atom, you can\n"
" look up the crystal type and lattice constant, otherwise you have to "
"specify it\n"
" yourself. "
msgstr ""
" Utilice este diálogo para crear estructuras cristalinas.\n"
" Seleccione primero la estructura, desde un conjunto común\n"
" de estructuras cristalinas ó desde la descripción del grupo\n"
" espacial.\n"
" Luego añada todos los parámetros de red.\n"
"\n"
" Si dispone de una estructura cristalina experimental para un\n"
" átomo, puede buscar el tipo de cristal y la constante de red,\n"
" de otra manera tendrá que especificarlas."
#: ../crystal.py:33
#, python-format
msgid " %(natoms)i atoms: %(symbols)s, Volume: %(volume).3f A3"
msgstr " %(natoms)i átomos: %(symbols)s, Volumen: %(volume).3f A3"
# Crear cristal por grupo espacial
#: ../crystal.py:58
msgid "Create Bulk Crystal by Spacegroup"
msgstr "Crear cristal por grupo espacial"
#: ../crystal.py:72
msgid "Number: 1"
msgstr "Número: 1"
#: ../crystal.py:73
msgid "Lattice: "
msgstr "Red: "
#: ../crystal.py:73
msgid "\tSpace group: "
msgstr "\tGrupo espacial: "
# Tamaño: x:
#: ../crystal.py:77
msgid "Size: x: "
msgstr "Tamaño: x: "
#: ../crystal.py:78 ../crystal.py:138
msgid " y: "
msgstr " y: "
#: ../crystal.py:79 ../crystal.py:139
msgid " z: "
msgstr " z: "
#: ../crystal.py:80 ../surfaceslab.py:127 ../surfaceslab.py:129
msgid " unit cells"
msgstr " celdas unitarias"
#: ../crystal.py:92 ../crystal.py:96 ../crystal.py:100 ../crystal.py:104
#: ../crystal.py:108 ../crystal.py:112
msgid "free"
msgstr "libre"
#: ../crystal.py:93 ../crystal.py:102
msgid "equals b"
msgstr "igual a b"
#: ../crystal.py:94 ../crystal.py:98
msgid "equals c"
msgstr "igual a c"
#: ../crystal.py:95 ../crystal.py:99 ../crystal.py:103 ../crystal.py:107
#: ../crystal.py:111 ../crystal.py:115
msgid "fixed"
msgstr "fijo"
#: ../crystal.py:97 ../crystal.py:101
msgid "equals a"
msgstr "igual a a"
#: ../crystal.py:105 ../crystal.py:114
msgid "equals beta"
msgstr "igual a beta"
#: ../crystal.py:106 ../crystal.py:110
msgid "equals gamma"
msgstr "igual a gama"
#: ../crystal.py:109 ../crystal.py:113
msgid "equals alpha"
msgstr "igual a alfa"
#: ../crystal.py:119
msgid "Lattice parameters"
msgstr "Parámetros de red"
#: ../crystal.py:120
msgid "\t\ta:\t"
msgstr "\t\ta:\t"
#: ../crystal.py:121
msgid "\talpha:\t"
msgstr "\talfa:\t"
#: ../crystal.py:122
msgid "\t\tb:\t"
msgstr "\t\tb:\t"
#: ../crystal.py:123
msgid "\tbeta:\t"
msgstr "\tbeta:\t"
#: ../crystal.py:124
msgid "\t\tc:\t"
msgstr "\t\tc:\t"
#: ../crystal.py:125
msgid "\tgamma:\t"
msgstr "\tgamma:\t"
#: ../crystal.py:126 ../surfaceslab.py:99
msgid "Get from database"
msgstr "Obtener desde la base de datos"
#: ../crystal.py:131
msgid "Basis: "
msgstr "Base: "
#: ../crystal.py:137
msgid " Element:\t"
msgstr " Elemento:%t"
#: ../crystal.py:137
msgid "\tx: "
msgstr "\tx: "
#: ../crystal.py:157
msgid "Creating a crystal."
msgstr "Creando un cristal."
#: ../crystal.py:202
#, python-format
msgid "Symbol: %s"
msgstr "SÃmbolo: %s"
#: ../crystal.py:207
#, python-format
msgid "Number: %s"
msgstr "Número: %s"
#: ../crystal.py:210
msgid "Invalid Spacegroup!"
msgstr "¡Grupo espacial inválido!"
#: ../crystal.py:336 ../crystal.py:339
msgid "Please specify a consistent set of atoms."
msgstr "Por favor, especifique un conjunto consistente de átomos."
#: ../crystal.py:348 ../graphene.py:230 ../nanoparticle.py:613
#: ../nanotube.py:139 ../surfaceslab.py:248
msgid "No valid atoms."
msgstr "Los átomos no son válidos."
#: ../crystal.py:465
msgid "Can't find lattice definition!"
msgstr "¡No puedo encontrar la definición de red!"
#: ../debug.py:11
msgid "Debug"
msgstr "Depurar"
#: ../dft.py:13
msgid "DFT"
msgstr "DFT"
#: ../dft.py:19
msgid "XC-functional: "
msgstr "Funcional de XC: "
#: ../dft.py:23 ../repeat.py:16
msgid "Repeat atoms:"
msgstr "Repetir átomos:"
#: ../energyforces.py:11
msgid "Output:"
msgstr "Salida:"
#: ../energyforces.py:41
msgid "Save output"
msgstr "Guardar salida"
#: ../energyforces.py:57
msgid "Potential energy and forces"
msgstr "EnergÃa potencial y fuerzas"
#: ../energyforces.py:61
msgid "Calculate potential energy and the force on all atoms"
msgstr "Calcular la energÃa potencial y la fuerza en todos los átomos"
#: ../energyforces.py:65
msgid "Write forces on the atoms"
msgstr "Escribir las fuerzas en los átomos"
#: ../energyforces.py:82
msgid "Potential Energy:\n"
msgstr "EnergÃa potencial:\n"
#: ../energyforces.py:83
#, python-format
msgid " %8.2f eV\n"
msgstr " %8.2f eV\n"
#: ../energyforces.py:84
#, python-format
msgid ""
" %8.4f eV/atom\n"
"\n"
msgstr ""
" %8.4f eV/átomo\n"
"\n"
#: ../energyforces.py:86
msgid "Forces:\n"
msgstr "Fuerzas:\n"
#: ../execute.py:23
msgid ""
"\n"
" Global commands work on all frames or only on the current frame\n"
" - Assignment of a global variable may not reference a local one\n"
" - use 'Current frame' switch to switch off application to all frames\n"
" e:\t\ttotal energy of one frame\n"
" fmax:\tmaximal force in one frame\n"
" A:\tunit cell\n"
" E:\t\ttotal energy array of all frames\n"
" F:\t\tall forces in one frame\n"
" M:\tall magnetic moments\n"
" R:\t\tall atomic positions\n"
" S:\tall selected atoms (boolean array)\n"
" D:\tall dynamic atoms (boolean array)\n"
" examples: frame = 1, A[0][1] += 4, e-E[-1]\n"
"\n"
" Atom commands work on each atom (or a selection) individually\n"
" - these can use global commands on the RHS of an equation\n"
" - use 'selected atoms only' to restrict application of command\n"
" x,y,z:\tatomic coordinates\n"
" r,g,b:\tatom display color, range is [0..1]\n"
" rad:\tatomic radius for display\n"
" s:\t\tatom is selected\n"
" d:\t\tatom is movable\n"
" f:\t\tforce\n"
" Z:\tatomic number\n"
" m:\tmagnetic moment\n"
" examples: x -= A[0][0], s = z > 5, Z = 6\n"
"\n"
" Special commands and objects:\n"
" sa,cf:\t(un)restrict to selected atoms/current frame\n"
" frame:\tframe number\n"
" center:\tcenters the system in its existing unit cell\n"
" del S:\tdelete selection\n"
" CM:\tcenter of mass\n"
" ans[-i]:\tith last calculated result\n"
" exec file: executes commands listed in file\n"
" cov[Z]:(read only): covalent radius of atomic number Z\n"
" gui:\tadvanced: ag window python object\n"
" img:\tadvanced: ag images object\n"
" "
msgstr ""
"\n"
" Los comandos globales funcionan tanto en todos los cuadros como\n"
" en el cuadro actual\n"
" - La asignación de una variable global puede no ser refernciada\n"
" a una local.\n"
" - Utilice el interruptor 'Cuadro actual' para apagar la aplicación\n"
" a todos los cuadros.\n"
" e: energÃa total de un cuadro\n"
" fmáx: fuerza máxima en un cuadro\n"
" A: celda unitaria\n"
" E: arreglo con las energÃas totales en todos los cuadros\n"
" F: todas las fuerzas en un cuadro\n"
" M: todos los momentos magnéticos\n"
" R: todas las posiciones atómicas\n"
" S: arreglo booleano, todos los átomos seleccionados\n"
" D: arreglo booleano, todos los átomos dinámicos\n"
" Ejemplos: cuadro = 1, A[0][1] += 4, e-E[-1]\n"
"\n"
" Los comandos atómicos funcionan en una selección o en cada uno de\n"
" los átomos.\n"
" - Éstos pueden utilizar comandos globales en el lado derecho de\n"
" una ecuación.\n"
" - Utilice 'Sólo los átomos seleccionados' para restringir la\n"
" aplicación del comando.\n"
" x,y,z: coordenadas atómicas\n"
" r,g,b: color del átomo, el rango es [0..1]\n"
" rad: radio atómico a mostrar\n"
" s: átomo es seleccionado\n"
" d: átomo es movible\n"
" f: fuerza\n"
" Z: número atómico\n"
" m: momento magnético\n"
" ejemplos: x -= A[0][0], s = z > 5, Z = 6\n"
"\n"
" Comandos especiales y objetos:\n"
" sa,cf:(un)restrict to selected atoms/current frame\n"
" cuadro: número del cuadro\n"
" centrar: centra el sistema con respecto a su celda unitaria\n"
" borra S: borra la selección\n"
" CM: centro de masa\n"
" ans[-i]: el i-ésimo resultado calculado\n"
" exec archivo: ejecuta el comando listado en archivo\n"
" cov[Z]:(sólo lectura): radio covalente del número atómico Z\n"
" gui:avanzado: objeto de Pythom, ventana de ag\n"
" img:avanzado: objeto de imágenes de ag\n"
" "
#: ../execute.py:67
msgid "Expert user mode"
msgstr "Modo de usuario experto"
#: ../execute.py:80
msgid "Welcome to the ASE Expert user mode"
msgstr "Bienvenido al modo de usuario experto de ASE"
#: ../execute.py:87
msgid "Only selected atoms (sa) "
msgstr "Sólo los átomos seleccionados (sa) "
#: ../execute.py:89
msgid "Only current frame (cf) "
msgstr "Sólo el cuadro actual (cf) "
#: ../execute.py:99
msgid ""
"Global: Use A, D, E, M, N, R, S, n, frame; Atoms: Use a, f, m, s, x, y, z, "
"Z "
msgstr ""
"Global: utilice los cuadros A, D, E, M, N, R, S y n; Ãtomos: utilice a, f, "
"m, s, x, y, z y Z"
#: ../execute.py:198
#, python-format
msgid "*** WARNING: file does not exist - %s"
msgstr "*** ADVERTENCIA: el archivo no existe - %s"
#: ../execute.py:203
msgid "*** WARNING: No atoms selected to work with"
msgstr "***ADVERTENCIA: No hay átomos seleccionados para trabajar"
#: ../execute.py:277
msgid "*** Only working on selected atoms"
msgstr "*** Trabajando sólo en los átomos seleccionados"
#: ../execute.py:279
msgid "*** Working on all atoms"
msgstr "*** Trabajando en todos los átomos"
#: ../execute.py:283
msgid "*** Only working on current image"
msgstr "*** Trabajando solamente en la imagen actual"
#: ../execute.py:285
msgid "*** Working on all images"
msgstr "*** Trabajando en todas las imágenes"
#: ../execute.py:301
msgid "Save Terminal text ..."
msgstr "Guarde texto a Terminal ..."
#: ../graphene.py:15
msgid ""
"Set up a graphene sheet or a graphene nanoribbon. A nanoribbon may\n"
"optionally be saturated with hydrogen (or another element)."
msgstr ""
"Configure una sábana de grafeno o una nanocinta. Opcionalmente,\n"
"la nanocinta puede ser saturada con hidrógeno u otro elemento."
#: ../graphene.py:30 ../gui.py:298
msgid "Graphene"
msgstr "Grafeno"
#. Choose structure
#. The structure and lattice constant
#. Choose the surface structure
#: ../graphene.py:37 ../nanoparticle.py:138 ../surfaceslab.py:78
msgid "Structure: "
msgstr "Estructura: "
#: ../graphene.py:39
msgid "Infinite sheet"
msgstr "Sábana infinita"
#: ../graphene.py:39
msgid "Unsaturated ribbon"
msgstr "Cinta no saturada"
#: ../graphene.py:40
msgid "Saturated ribbon"
msgstr "Cinta saturada"
#. Orientation
#: ../graphene.py:47
msgid "Orientation: "
msgstr "Orientación: "
#: ../graphene.py:50
msgid "zigzag"
msgstr "Zigzag"
#: ../graphene.py:50
msgid "armchair"
msgstr "Sillón"
#: ../graphene.py:66 ../graphene.py:78 ../nanotube.py:46
msgid " Bond length: "
msgstr " Largo del enlace: "
#. Choose the saturation element and bond length
#: ../graphene.py:72
msgid "Saturation: "
msgstr "Saturación: "
#: ../graphene.py:75
msgid "H"
msgstr "H"
#. Size
#: ../graphene.py:91
msgid "Width: "
msgstr "Ancho: "
#: ../graphene.py:92 ../nanotube.py:65
msgid " Length: "
msgstr " Largo: "
#. Vacuum
#: ../graphene.py:100
msgid "Vacuum: "
msgstr "VacÃo: "
#: ../graphene.py:138 ../nanotube.py:96 ../setupwindow.py:32
msgid " No element specified!"
msgstr " ¡No se especifica el elemento!"
#: ../graphene.py:231 ../nanoparticle.py:614 ../nanotube.py:140
#: ../pybutton.py:49 ../surfaceslab.py:249
msgid "You have not (yet) specified a consistent set of parameters."
msgstr "No ha especificado aún un conjunto consistente de parámetros."
#: ../graphs.py:19
msgid "Help for plot ..."
msgstr "Ayuda para graficar ..."
#: ../graphs.py:30 ../graphs.py:33
msgid "Plot"
msgstr "Graficar"
#: ../graphs.py:38
msgid "clear"
msgstr "Limpiar"
#: ../graphs.py:92
msgid "Save data to file ... "
msgstr "Salve los datos a un archivo ..."
#: ../gtkexcepthook.py:117
msgid "Bug Detected"
msgstr "Error detectado"
#: ../gtkexcepthook.py:121
msgid "A programming error has been detected."
msgstr "Un error de programación ha sido detectado."
#: ../gtkexcepthook.py:124
msgid ""
"It probably isn't fatal, but the details should be reported to the "
"developers nonetheless."
msgstr ""
"Probablemente no es fatal. Sin embargo, los detalles deberÃan\n"
"ser reportados a los desarrolladores."
#: ../gtkexcepthook.py:140
msgid "Report..."
msgstr "Reporte..."
#: ../gtkexcepthook.py:144
msgid "Details..."
msgstr "Detalles..."
#: ../gtkexcepthook.py:160
#, python-format
msgid ""
"From: buggy_application\"\n"
"To: bad_programmer\n"
"Subject: Exception feedback\n"
"\n"
"%s"
msgstr ""
"Desde: buggy_application\"\n"
"A: bad_programmer\n"
"Asunto: Retroalimentación de un error\n"
"\n"
"%s"
#. Show details...
#: ../gtkexcepthook.py:173
msgid "Bug Details"
msgstr "Detalles del error"
#: ../gui.py:164
msgid "_File"
msgstr "_Archivo"
#: ../gui.py:165
msgid "_Edit"
msgstr "_Editar"
#: ../gui.py:166
msgid "_View"
msgstr "_Ver"
#: ../gui.py:167
msgid "_Tools"
msgstr "_Herramientas"
#. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
#: ../gui.py:169
msgid "_Setup"
msgstr "_Configurar"
#: ../gui.py:170
msgid "_Calculate"
msgstr "_Calcular"
#: ../gui.py:171
msgid "_Help"
msgstr "_Ayuda"
#: ../gui.py:172
msgid "_Open"
msgstr "_Abrir"
#: ../gui.py:173
msgid "Create a new file"
msgstr "Crear un archivo nuevo"
#: ../gui.py:175
msgid "_New"
msgstr "_Nuevo"
#: ../gui.py:176
msgid "New ase.gui window"
msgstr "Nueva ventana ase.gui"
#: ../gui.py:178
msgid "_Save"
msgstr "_Guardar"
#: ../gui.py:179
msgid "Save current file"
msgstr "Guardar archivo actual"
#: ../gui.py:181
msgid "_Quit"
msgstr "_Salir"
#: ../gui.py:182
msgid "Quit"
msgstr "Salir"
#: ../gui.py:184
msgid "Select _all"
msgstr "Seleccionar _todo"
#: ../gui.py:187
msgid "_Invert selection"
msgstr "_Invertir selección"
#: ../gui.py:190
msgid "Select _constrained atoms"
msgstr "Seleccionar los átomos _restringidos"
#: ../gui.py:193
msgid "Select _immobile atoms"
msgstr "Seleccionar los átomos _inmóbiles"
#: ../gui.py:196
msgid "_Copy"
msgstr "_Copiar"
#: ../gui.py:197
msgid "Copy current selection and its orientation to clipboard"
msgstr "Copiar la selección actual y su orientación"
#: ../gui.py:199
msgid "_Paste"
msgstr "_Pegar"
#: ../gui.py:200
msgid "Insert current clipboard selection"
msgstr "Insertar selección actual"
#: ../gui.py:202
msgid "_Modify"
msgstr "_Modificar"
#: ../gui.py:203
msgid "Change tags, moments and atom types of the selected atoms"
msgstr ""
"Cambiar etiquetas, momentos magnéticos y tipo de los átomos seleccionados"
#: ../gui.py:205
msgid "_Add atoms"
msgstr "_Añadir átomos"
#: ../gui.py:206
msgid "Insert or import atoms and molecules"
msgstr "Insertar o importar átomos y moléculas"
#: ../gui.py:208
msgid "_Delete selected atoms"
msgstr "_Borrar átomos seleccionados"
#: ../gui.py:209
msgid "Delete the selected atoms"
msgstr "Borrar los átomos seleccionados"
#: ../gui.py:211
msgid "_First image"
msgstr "_Primera imagen"
#: ../gui.py:214
msgid "_Previous image"
msgstr "_Imagen previa"
#: ../gui.py:217
msgid "_Next image"
msgstr "_Próxima imagen"
#: ../gui.py:220
msgid "_Last image"
msgstr "Ú_ltima imagen"
#: ../gui.py:223
msgid "Quick Info ..."
msgstr "Información rápida ..."
#: ../gui.py:226
msgid "Repeat ..."
msgstr "Repetir ..."
#: ../gui.py:229
msgid "Rotate ..."
msgstr "Rotar ..."
#: ../gui.py:232
msgid "Colors ..."
msgstr "Colores ..."
#. TRANSLATORS: verb
#: ../gui.py:235
msgid "Focus"
msgstr "Enfocar"
#: ../gui.py:238
msgid "Zoom in"
msgstr "Ampliar"
#: ../gui.py:241
msgid "Zoom out"
msgstr "Alejar"
#: ../gui.py:244
msgid "Reset View"
msgstr "Reiniciar la vista"
#: ../gui.py:247
msgid "Settings ..."
msgstr "Ajustes ..."
#: ../gui.py:250
msgid "VMD"
msgstr "VMD"
#: ../gui.py:253
msgid "RasMol"
msgstr "RasMol"
#: ../gui.py:256
msgid "xmakemol"
msgstr "xmakemol"
#: ../gui.py:259
msgid "avogadro"
msgstr "avogadro"
#: ../gui.py:262
msgid "Graphs ..."
msgstr "Gráficos ..."
#: ../gui.py:265
msgid "Movie ..."
msgstr "PelÃcula ..."
#: ../gui.py:268
msgid "Expert mode ..."
msgstr "Modo experto ..."
#: ../gui.py:271
msgid "Constraints ..."
msgstr "Restricciones ..."
#: ../gui.py:274
msgid "Render scene ..."
msgstr "Dibujar escena ... "
#: ../gui.py:277
msgid "DFT ..."
msgstr "DFT ..."
#: ../gui.py:280
msgid "NE_B"
msgstr "NE_B"
#: ../gui.py:283
msgid "B_ulk Modulus"
msgstr "Módulo de b_ulto"
#: ../gui.py:286
msgid "_Bulk Crystal"
msgstr "Cristal en _bulto"
#: ../gui.py:287
msgid "Create a bulk crystal with arbitrary orientation"
msgstr "Crear un cristal en bulto con orientación arbitraria"
#: ../gui.py:289
msgid "_Surface slab"
msgstr "Trozo de _superficie"
#: ../gui.py:290
msgid "Create the most common surfaces"
msgstr "Crear las superficies más comunes"
#: ../gui.py:292
msgid "_Nanoparticle"
msgstr "_NanopartÃcula"
#: ../gui.py:293
msgid "Create a crystalline nanoparticle"
msgstr "Crear una nanoparticula cristalina"
#: ../gui.py:295
msgid "Nano_tube"
msgstr "Nano_tubo"
#: ../gui.py:296
msgid "Create a nanotube"
msgstr "Crear un nanotubo"
#: ../gui.py:299
msgid "Create a graphene sheet or nanoribbon"
msgstr "Crear una sábana de grafeno o una nanocinta"
#: ../gui.py:301
msgid "Set _Calculator"
msgstr "Fijar el _calculador"
#: ../gui.py:302
msgid "Set a calculator used in all calculation modules"
msgstr "Fijar un calculador utilizado en todos los módulos de cálculo"
#: ../gui.py:304
msgid "_Energy and Forces"
msgstr "_EnergÃa y Fuerzas"
#: ../gui.py:305
msgid "Calculate energy and forces"
msgstr "Calcular energÃa y fuerzas"
#: ../gui.py:307
msgid "Energy _Minimization"
msgstr "_Minimización de energÃa"
#: ../gui.py:308
msgid "Minimize the energy"
msgstr "Minimize la energÃa"
#: ../gui.py:310
msgid "Scale system"
msgstr "Escale el sistema"
#: ../gui.py:311
msgid "Deform system by scaling it"
msgstr "Deforme el sistema escalándolo"
#: ../gui.py:313
msgid "_About"
msgstr "_Acerca de ag"
#: ../gui.py:316
msgid "Webpage ..."
msgstr "Página web ..."
#: ../gui.py:317
msgid "Debug ..."
msgstr "Quitar errores"
#: ../gui.py:319
msgid "Show _unit cell"
msgstr "Mostrar la celda _unitaria"
#: ../gui.py:323
msgid "Show _axes"
msgstr "Mostrar los _ejes"
#: ../gui.py:327
msgid "Show _bonds"
msgstr "Mostrar los _enlaces"
#: ../gui.py:331
msgid "_Move atoms"
msgstr "_Mover los átomos"
#: ../gui.py:335
msgid "_Rotate atoms"
msgstr "_Rotar los átomos"
#: ../gui.py:339
msgid "Orien_t atoms"
msgstr "Orien_tar los átomos"
#: ../gui.py:351
#, python-format
msgid "building menus failed: %s"
msgstr "La construcción de los menús ha fallado: %s"
#: ../gui.py:620 ../gui.py:1016 ../gui.py:1076
msgid "Open ..."
msgstr "Abrir ..."
#: ../gui.py:624 ../gui.py:1019
msgid "<>"
msgstr "<>"
#: ../gui.py:756
msgid "Add atoms"
msgstr "Agregar átomos"
#: ../gui.py:759
msgid "Paste"
msgstr "Pegar"
#: ../gui.py:765
msgid "Insert atom or molecule"
msgstr "Insertar átomo o molécula"
#: ../gui.py:766 ../gui.py:883
msgid "Tag"
msgstr "Etiqueta"
#: ../gui.py:767 ../gui.py:884
msgid "Moment"
msgstr "Momento magnético"
#: ../gui.py:768
msgid "Position"
msgstr "Posición"
#: ../gui.py:793
msgid "_Load molecule"
msgstr "_Cargar molécula"
#: ../gui.py:797 ../gui.py:899
msgid "_OK"
msgstr "_OK"
#: ../gui.py:801 ../gui.py:903
msgid "_Cancel"
msgstr "_Cancelar"
#: ../gui.py:876
msgid "Modify"
msgstr "Modificar"
#: ../gui.py:882
msgid "Atom"
msgstr "Ãtomo"
#: ../gui.py:927
msgid "Confirmation"
msgstr "Confirmación"
#: ../gui.py:931
msgid "Delete selected atom?"
msgid_plural "Delete selected atoms?"
msgstr[0] "¿Borrar el átomo seleccionado?"
msgstr[1] "¿Borrar los átomos seleccionados?"
#: ../gui.py:938
msgid "Cancel"
msgstr "Cancelar"
#: ../gui.py:1024 ../gui.py:1106
msgid "Automatic"
msgstr "Automático"
#: ../gui.py:1025
msgid "Dacapo netCDF output file"
msgstr "Archivo de salida Dacapo (.netCDF)"
#: ../gui.py:1026
msgid "Virtual Nano Lab file"
msgstr "Archivo Virtual Nano Lab"
#: ../gui.py:1027
msgid "ASE pickle trajectory"
msgstr "Trajectoria ASE pickle"
#: ../gui.py:1028 ../gui.py:1119
msgid "ASE bundle trajectory"
msgstr "Trajectoria ASE ligada"
#: ../gui.py:1029
msgid "GPAW text output"
msgstr "Archivo de salida de texto (GPAW)"
#: ../gui.py:1030
msgid "CUBE file"
msgstr "Archivo CUBE"
#: ../gui.py:1031
msgid "XCrySDen Structure File"
msgstr "Archivo de estructura XCrySDen"
#: ../gui.py:1032
msgid "Dacapo text output"
msgstr "Archivo de salida de texto (Dacapo)"
#: ../gui.py:1033
msgid "XYZ-file"
msgstr "Archivo XYZ"
#: ../gui.py:1034
msgid "VASP POSCAR/CONTCAR file"
msgstr "Archivo POSCAR/CONTCAR (VASP)"
#: ../gui.py:1035
msgid "VASP OUTCAR file"
msgstr "Archivo OUTCAR (VASP)"
#: ../gui.py:1036
msgid "Protein Data Bank"
msgstr "Banco de datos de proteÃnas"
#: ../gui.py:1037
msgid "CIF-file"
msgstr "Archivo CIF"
#: ../gui.py:1038
msgid "FHI-aims geometry file"
msgstr "Archivo de geometrÃa (FHI-aims)"
#: ../gui.py:1039
msgid "FHI-aims output file"
msgstr "Archivo de salida (FHI-aims)"
#: ../gui.py:1040
msgid "TURBOMOLE coord file"
msgstr "Archivo de coordenadas (TURBOMOLE)"
#: ../gui.py:1041
msgid "exciting input"
msgstr "Archivo de entrada (exciting)"
#: ../gui.py:1042
msgid "WIEN2k structure file"
msgstr "Archivo de estructura (WIEN2k)"
#: ../gui.py:1043
msgid "DftbPlus input file"
msgstr "Archivo de entrada (DFTBPlus)"
#: ../gui.py:1044
msgid "ETSF format"
msgstr "Formato ETSF"
#: ../gui.py:1045 ../gui.py:1117
msgid "CASTEP geom file"
msgstr "Archivo de geometrÃa (CASTEP)"
#: ../gui.py:1046
msgid "CASTEP output file"
msgstr "Archivo de salida (CASTEP)"
#: ../gui.py:1047
msgid "CASTEP trajectory file"
msgstr "Archivo de trajectoria (CASTEP)"
#: ../gui.py:1048
msgid "DFTBPlus GEN format"
msgstr "Formato GEN (DFTBPlus)"
#: ../gui.py:1054
msgid "File type:"
msgstr "Tipo de archivo:"
#: ../gui.py:1094
msgid "Save ..."
msgstr "Guardar ..."
#: ../gui.py:1107
msgid "XYZ file"
msgstr "Archivo XYZ"
#: ../gui.py:1108
msgid "ASE trajectory"
msgstr "Trajectoria ASE"
#: ../gui.py:1109
msgid "PDB file"
msgstr "Archivo PDB"
#: ../gui.py:1110
msgid "Gaussian cube file"
msgstr "Archivo cube (Gaussian)"
#: ../gui.py:1111
msgid "Python script"
msgstr "Script de Python"
#: ../gui.py:1112
msgid "VNL file"
msgstr "Archivo VNL"
#: ../gui.py:1113
msgid "Portable Network Graphics"
msgstr "Archivo PNG"
#: ../gui.py:1114
msgid "Persistence of Vision"
msgstr "Archivo POV"
#: ../gui.py:1115
msgid "Encapsulated PostScript"
msgstr "Archivo EPS"
#: ../gui.py:1116
msgid "FHI-aims geometry input"
msgstr "GeometrÃa de entrada (FHI-aims)"
#: ../gui.py:1118
msgid "VASP geometry input"
msgstr "GeometrÃa de entrada (VASP)"
#: ../gui.py:1120
msgid "cif file"
msgstr "Archivo cif"
#: ../gui.py:1142
#, python-format
msgid "Save current image only (#%d)"
msgstr "Guardar solamente la imagen actual (#%d)"
#: ../gui.py:1146
msgid "Slice: "
msgstr "Trozo: "
#: ../gui.py:1147
msgid "Help for slice ..."
msgstr "Ayuda para trozar ..."
#: ../gui.py:1159
msgid "AG INTERNAL ERROR: strange response in Save,"
msgstr "ERROR INTERNO DE AG: respuesta extraña en guardar,"
#: ../gui.py:1178
msgid "Unknown output format!"
msgstr "¡Formato de salida desconocido!"
#: ../gui.py:1179
#, python-format
msgid "Use one of: %s"
msgstr "Use uno de: %s"
#: ../gui.py:1284
msgid "Not implemented!"
msgstr "No implementado!"
#: ../gui.py:1285
msgid "do you really need it?"
msgstr "¿realmente necesita esto?"
#: ../minimize.py:20
msgid "Algorithm: "
msgstr "Algoritmo: "
#: ../minimize.py:25 ../progress.py:67
msgid "Convergence criterion: Fmax = "
msgstr "Criterio de convergencia: Fmáx = "
#: ../minimize.py:30 ../progress.py:70
msgid "Max. number of steps: "
msgstr "Número máximo de pasos: "
#. Special stuff for MDMin
#: ../minimize.py:33
msgid "Pseudo time step: "
msgstr "Paso de pseudotiempo: "
#: ../minimize.py:54
msgid "Energy minimization"
msgstr "Minimización de energÃa"
#: ../minimize.py:58
msgid "Minimize the energy with respect to the positions."
msgstr "Minimize la energÃa con respecto a las posiciones."
#. Don't catch errors in the function.
#. Display status message
#: ../minimize.py:90 ../scaling.py:299
msgid "Running ..."
msgstr "Calculando ..."
#. Update display to reflect cancellation of simulation.
#: ../minimize.py:107
#, python-format
msgid "Minimization CANCELLED after %i steps."
msgstr "Minimización CANCELADO después de %i iteraciones."
#: ../minimize.py:113 ../scaling.py:350
msgid "Out of memory, consider using LBFGS instead"
msgstr "No hay más memoria, considere usar el algoritmo LBFGS"
#. Update display to reflect succesful end of simulation.
#: ../minimize.py:120
#, python-format
msgid "Minimization completed in %i steps."
msgstr "Minimización hecha en %i pasos."
#. self.connect('delete_event', self.exit2)
#: ../movie.py:14
msgid "Movie"
msgstr "PelÃcula"
#: ../movie.py:16
msgid "Image number:"
msgstr "Imagen número:"
#: ../movie.py:38
msgid "Play"
msgstr "Reproducir"
#: ../movie.py:40
msgid "Stop"
msgstr "Detener"
#. TRANSLATORS: This function plays an animation forwards and backwards
#. alternatingly, e.g. for displaying vibrational movement
#: ../movie.py:44
msgid "Rock"
msgstr "Repetir cuadro"
#: ../movie.py:60
msgid " Frame rate: "
msgstr "Velocidad del cuadro: "
#: ../movie.py:61
msgid " Skip frames: "
msgstr "Saltar los cuadros: "
#: ../nanoparticle.py:19
msgid ""
"Create a nanoparticle either by specifying the number of layers, or using "
"the\n"
"Wulff construction. Please press the [Help] button for instructions on how "
"to\n"
"specify the directions.\n"
"WARNING: The Wulff construction currently only works with cubic crystals!\n"
msgstr ""
"Crear una nanopartÃcula especificando el número de capas,\n"
"ó utilizando la construcción de Wulff. Por favor, presione\n"
"el boton de ayuda para leer las instrucciones sobre cómo\n"
"especificar las direcciones.\n"
"¡ADVERTENCIA: En esta versión, la construcción de Wulff \n"
"sólo funciona para cristales cúbicos!\n"
#: ../nanoparticle.py:26
msgid ""
"\n"
"The nanoparticle module sets up a nano-particle or a cluster with a given\n"
"crystal structure.\n"
"\n"
"1) Select the element, the crystal structure and the lattice constant(s).\n"
" The [Get structure] button will find the data for a given element.\n"
"\n"
"2) Choose if you want to specify the number of layers in each direction, or "
"if\n"
" you want to use the Wulff construction. In the latter case, you must "
"specify\n"
" surface energies in each direction, and the size of the cluster.\n"
"\n"
"How to specify the directions:\n"
"------------------------------\n"
"\n"
"First time a direction appears, it is interpreted as the entire family of\n"
"directions, i.e. (0,0,1) also covers (1,0,0), (-1,0,0) etc. If one of "
"these\n"
"directions is specified again, the second specification overrules that "
"specific\n"
"direction. For this reason, the order matters and you can rearrange the\n"
"directions with the [Up] and [Down] keys. You can also add a new "
"direction,\n"
"remember to press [Add] or it will not be included.\n"
"\n"
"Example: (1,0,0) (1,1,1), (0,0,1) would specify the {100} family of "
"directions,\n"
"the {111} family and then the (001) direction, overruling the value given "
"for\n"
"the whole family of directions.\n"
msgstr ""
"\n"
"Este módulo crea una nanopartÃcula o un cúmulo dada una\n"
"estructura cristalina.\n"
"\n"
"1) Seleccione el elemento, la estructura cristalina y la(s)\n"
" constante(s) de red. El botón \"Obtener estructura\" \n"
" encontrará los datos para el elemento seleccionado.\n"
"\n"
"2) Elija si desea especificar el número de capas en cada \n"
" dirección, o si desea utilizar la construcción de Wulff.\n"
" En el último caso, se debe especificar las energÃas de \n"
" superficie en cada dirección, y el tamaño del cúmulo.\n"
"\n"
"Cómo especificar las direcciones:\n"
"---------------------------------\n"
"\n"
"La primera vez una dirección aparece, la cual es interpretada\n"
"como la familia completa de las direcciones, es decir, (0,0,1)\n"
"también cubre la dirección (1,0,0), (-1,0,0) etc. Si una de estas\n"
"direcciones es especificada nuevamente, la segunda especificación\n"
"reemplaza esa dirección en especÃfico. Debido a esto, el orden\n"
"importa y se puede rearreglar la dirección con los botones Arriba y\n"
"Abajo. También se puede añadir una nueva dirección, recuerde presionar\n"
"el botón Añadir o ésta no será incluida.\n"
"\n"
"Ejemplo: (1,0,0) (1,1,1), (0,0,1) especificará la familia {100} de\n"
"direcciones, la familia {111} y luego la dirección (001), \n"
"sobreescribiendo el valor dado por toda la familia de direcciones.\n"
#. Structures: Abbreviation, name, 4-index (boolean), two lattice const (bool), factory
#: ../nanoparticle.py:83
msgid "Face centered cubic (fcc)"
msgstr "Cúbico centrado en las caras (fcc)"
#: ../nanoparticle.py:84
msgid "Body centered cubic (bcc)"
msgstr "Cúbico centrado en el cuerpo (bcc)"
#: ../nanoparticle.py:85
msgid "Simple cubic (sc)"
msgstr "Cúbico simple (sc)"
#: ../nanoparticle.py:86
msgid "Hexagonal closed-packed (hcp)"
msgstr "Empacamiento hexagonal cerrado (hcp)"
#: ../nanoparticle.py:87
msgid "Graphite"
msgstr "Grafito"
#: ../nanoparticle.py:116
msgid "Nanoparticle"
msgstr "NanopartÃcula"
#. Choose the element
#. Choose the element and bond length
#. Choose the element
#: ../nanoparticle.py:126 ../nanotube.py:40 ../surfaceslab.py:69
msgid "Element: "
msgstr "Elemento: "
#: ../nanoparticle.py:130
msgid "Get structure"
msgstr "Obtener la estructura"
#: ../nanoparticle.py:154
msgid "Lattice constant: a ="
msgstr "Constante de red: a ="
#. Choose specification method
#: ../nanoparticle.py:171
msgid "Method: "
msgstr "Método: "
#: ../nanoparticle.py:173
msgid "Layer specification"
msgstr "Especificación de capas"
#: ../nanoparticle.py:173
msgid "Wulff construction"
msgstr "Construcción de Wulff"
#: ../nanoparticle.py:193
msgid "Dummy placeholder object"
msgstr "Objeto marcador de posición ficticia"
#: ../nanoparticle.py:195
msgid "Add new direction:"
msgstr "Agregar nueva dirección:"
#: ../nanoparticle.py:211
msgid "Add"
msgstr "Agregar"
#: ../nanoparticle.py:219
msgid "Set all directions to default values"
msgstr "Fijar en todas las direcciones los valores por defecto"
#: ../nanoparticle.py:227
msgid "Particle size: "
msgstr "Tamaño de la partÃcula: "
#: ../nanoparticle.py:228 ../nanoparticle.py:265 ../progress.py:196
msgid "Number of atoms: "
msgstr "Número de átomos: "
#: ../nanoparticle.py:233
msgid "Volume: "
msgstr "Volumen: "
#: ../nanoparticle.py:238
msgid "ų"
msgstr "ų"
#: ../nanoparticle.py:243
msgid "Rounding: If exact size is not possible, choose the size"
msgstr "Redondear: si el tamaño exacto no es posible, elegir el tamaño"
#: ../nanoparticle.py:246
msgid "above "
msgstr "sobre "
#: ../nanoparticle.py:247
msgid "below "
msgstr "abajo "
#: ../nanoparticle.py:248
msgid "closest "
msgstr "más cercano "
#: ../nanoparticle.py:251
msgid "Smaller"
msgstr "Mas pequeño"
#: ../nanoparticle.py:252
msgid "Larger"
msgstr "Más largo"
#: ../nanoparticle.py:267
msgid " Approx. diameter: "
msgstr " Diámetro aproximado: "
#: ../nanoparticle.py:271
msgid "Information about the created cluster:"
msgstr "Información sobre el cluster creado:"
#. Buttons
#: ../nanoparticle.py:277 ../nanotube.py:75
msgid "Creating a nanoparticle."
msgstr "Creando una nanopartÃcula."
#: ../nanoparticle.py:284
msgid "Automatic Apply"
msgstr "Aplicar automáticamente"
#: ../nanoparticle.py:332
msgid "Up"
msgstr "Arriba"
#: ../nanoparticle.py:337
msgid "Down"
msgstr "Abajo"
#: ../nanoparticle.py:342
msgid "Delete"
msgstr "Borrar"
#: ../nanoparticle.py:383
msgid "Surface energies (as energy/area, NOT per atom):"
msgstr "EnergÃa de superficie (se reporta energÃa por área, NO por átomo):"
#: ../nanoparticle.py:389
msgid "Number of layers:"
msgstr "Número de capas:"
#: ../nanoparticle.py:418
msgid "At least one index must be non-zero"
msgstr "Al menos un Ãndice debe ser distinto de cero"
#: ../nanoparticle.py:421
msgid "Invalid hexagonal indices"
msgstr "Ãndices hexagonales inválidos"
#: ../nanoparticle.py:476 ../surfaceslab.py:218
msgid "Invalid element."
msgstr "Elemento inválido."
#: ../nanoparticle.py:486
msgid "Unsupported or unknown structure"
msgstr "Estructura no soportada o desconocida"
#: ../nanoparticle.py:603
#, python-format
msgid "%.1f Ã…"
msgstr "%.1f Ã…"
#: ../nanotube.py:14
msgid ""
"Set up a Carbon nanotube by specifying the (n,m) roll-up vector.\n"
"Please note that m <= n.\n"
"\n"
"Nanotubes of other elements can be made by specifying the element\n"
"and bond length."
msgstr ""
#: ../nanotube.py:33
msgid "Nanotube"
msgstr "Nanotubo"
#. Choose the structure.
#: ../nanotube.py:57
msgid "Select roll-up vector (n,m) and tube length:"
msgstr "Seleccione vector de roll-up (n,m) y largo del tubo:"
#: ../progress.py:25
msgid "Progress"
msgstr "Progreso"
#: ../progress.py:32
msgid "Scaling deformation:"
msgstr "Escala de deformación:"
#: ../progress.py:38
#, python-format
msgid "Step number %s of %s."
msgstr "Paso número %s de %s."
#. Minimization progress frame
#. Box containing frame and spacing
#: ../progress.py:53
msgid "Energy minimization:"
msgstr "Minimización de energÃa:"
#: ../progress.py:60
msgid "Step number: "
msgstr "Paso número: "
#: ../progress.py:62
msgid "Fmax: "
msgstr "Fmáx: "
#: ../progress.py:102
msgid "unknown"
msgstr "desconocido"
#: ../progress.py:179
msgid "Status: "
msgstr "Estado: "
#: ../progress.py:181
msgid "Iteration: "
msgstr "Iteración: "
#: ../progress.py:184
msgid "log10(change):"
msgstr "log10 (cambio):"
#: ../progress.py:187
msgid "Wave functions: "
msgstr "Funciones de onda: "
#: ../progress.py:189
msgid "Density: "
msgstr "Densidad: "
#: ../progress.py:191
msgid "Energy: "
msgstr "EnergÃa: "
#: ../progress.py:194
msgid "GPAW version: "
msgstr "Versión de GPAW: "
#: ../progress.py:197
msgid "N/A"
msgstr "No disponible"
#: ../progress.py:198
msgid "Memory estimate: "
msgstr "Memoria estimada: "
#: ../progress.py:233
msgid "No info"
msgstr "No hay información"
#: ../progress.py:243
msgid "Initializing"
msgstr "Iniciando"
#: ../progress.py:244
msgid "Positions:"
msgstr "Posiciones:"
#: ../progress.py:248
msgid "Starting calculation"
msgstr "Comenzando cálculo"
#: ../progress.py:285
msgid "unchanged"
msgstr "sin cambios"
#: ../progress.py:295
msgid "Self-consistency loop"
msgstr "Bucle de auto consistencia"
#: ../progress.py:300
msgid "Calculating forces"
msgstr "Calculando fuerzas"
#: ../progress.py:301
msgid " (converged)"
msgstr " (convergido)"
#: ../pybutton.py:37
msgid "Python"
msgstr "Python"
#: ../pybutton.py:48
msgid "No Python code"
msgstr "No es código de Python"
#: ../pybutton.py:52
#, python-format
msgid ""
"\n"
"Title: %(title)s\n"
"Time: %(time)s\n"
msgstr ""
"\n"
"TÃtulo: %(title)s\n"
"Tiempo: %(time)s\n"
#: ../pybutton.py:61
msgid "ag: Python code"
msgstr "ag: código en Python"
#: ../pybutton.py:65
msgid "Information:"
msgstr "Información:"
#: ../pybutton.py:72
msgid "Python code:"
msgstr "Código en Python:"
#: ../quickinfo.py:9
msgid "Single image loaded."
msgstr "Una imagen cargada."
#: ../quickinfo.py:10
#, python-format
msgid "Image %d loaded (0 - %d)."
msgstr "Imagen %d cargada (0 - %d)."
#: ../quickinfo.py:11
msgid "Unit cell is fixed."
msgstr "La celda unitaria está fija."
#: ../quickinfo.py:12
msgid "Unit cell varies."
msgstr "La celda unitaria varÃa."
#: ../quickinfo.py:14
#, python-format
msgid ""
"%s\n"
"\n"
"Number of atoms: %d.\n"
"\n"
"Unit cell:\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
"%s\n"
msgstr ""
"%s\n"
"\n"
"Número de átomos: %d.\n"
"\n"
"Celda unitaria:\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
"%s\n"
#: ../quickinfo.py:29
msgid "Quick Info"
msgstr "Información rápida"
#: ../quickinfo.py:33
msgid "No atoms loaded."
msgstr "No hay átomos seleccionados."
#: ../render.py:14
msgid ""
" Textures can be used to highlight different parts of\n"
" an atomic structure. This window applies the default\n"
" texture to the entire structure and optionally\n"
" applies a different texture to subsets of atoms that\n"
" can be selected using the mouse.\n"
" An alternative selection method is based on a boolean\n"
" expression in the entry box provided, using the\n"
" variables x, y, z, or Z. For example, the expression\n"
" Z == 11 and x > 10 and y > 10 \n"
" will mark all sodium atoms with x or coordinates \n"
" larger than 10. In either case, the button labeled\n"
" `Create new texture from selection` will enable\n"
" to change the attributes of the current selection. \n"
" "
msgstr ""
" Las texturas pueden ser utilizadas para destacar diferentes partes\n"
" de una estructura atómica. Esta ventana aplica la textura por defecto\n"
" a la estructura completa. Opcionalmente, aplica una textura distinta\n"
" a subconjuntos de átomos, los cuales pueden ser seleccionados "
"utilizando\n"
" el ratón.\n"
" Además, en esta versión de ASE, se implementa un método de selección \n"
" alternativo, el cual está basado en expresiones booleanas. Estas se "
"pueden\n"
" fijar en la caja de entrada, utilizando las variables x, y, z ó Z. Por\n"
" ejemplo, la expresión\n"
" Z == 11 and x > 10 and y > 10\n"
" marcará todos los átomos de sodio con x o coordenadas mayores que 10.\n"
" En cualquier caso, el botón 'Crear nueva estructura desde la selección'\n"
" activará los cambios a los atributos de la selección actual.\n"
" "
#: ../render.py:32
msgid "Render current view in povray ... "
msgstr "Dibujar vista actual en povray ... "
#: ../render.py:36
#, python-format
msgid "Rendering %d atoms."
msgstr "Dibujando %d átomos."
#: ../render.py:41
msgid "Render constraints"
msgstr "Restricciones del dibujo"
#: ../render.py:44
msgid "Width"
msgstr "Ancho"
#: ../render.py:45
msgid " Height"
msgstr " Altura"
#: ../render.py:52
msgid "Render unit cell"
msgstr "Dibujar celda unitaria"
#: ../render.py:61
msgid "Line width"
msgstr "Ancho de la lÃnea"
#: ../render.py:63
msgid "Angstrom "
msgstr "Angstrom "
#: ../render.py:73
msgid "Set"
msgstr "Fijar"
#: ../render.py:75
msgid "Output basename: "
msgstr "Nombre base para el archivo de salida: "
#: ../render.py:77
msgid " Filename: "
msgstr " Nombre de archivo: "
#: ../render.py:88
msgid " Default texture for atoms: "
msgstr " Textura por defecto para los átomos: "
#: ../render.py:89
msgid " transparency: "
msgstr " transparencia: "
#: ../render.py:90
msgid "Define atom selection for new texture:"
msgstr "Definir al selección del átomo para la nueva textura:"
#: ../render.py:92
msgid "Select"
msgstr "Seleccionar"
#: ../render.py:96
msgid "Create new texture from selection"
msgstr "Crear nueva textura desde selección"
#: ../render.py:98
msgid "Help on textures"
msgstr "Ayuda en texturas"
#: ../render.py:111
msgid "Camera type: "
msgstr "Tipo de cámara: "
#: ../render.py:112
msgid " Camera distance"
msgstr " Distancia de la cámara"
#: ../render.py:113
msgid "Render current frame"
msgstr "Dibujar el cuadro actual"
#: ../render.py:117
#, python-format
msgid "Render all %d frames"
msgstr "Dibujar todos los %d cuadros"
#: ../render.py:122
msgid "Transparent background"
msgstr "Fondo transparente"
#: ../render.py:125
msgid "Run povray "
msgstr "Ejecutar povray "
#: ../render.py:128
msgid "Keep povray files "
msgstr "Mantener los archivos povray "
#: ../render.py:131
msgid "Show output window"
msgstr "Mostrar ventana de salida"
#: ../render.py:212
msgid " transparency: "
msgstr " transparencia: "
#: ../render.py:218
msgid ""
"Can not create new texture! Must have some atoms selected to create a new "
"material!"
msgstr ""
"¡No se puede crear la nueva textura! ¡Se debe seleccionar algunos átomos "
"para crear un nuevo material!"
#: ../repeat.py:14
msgid "Repeat"
msgstr "Repetir"
#: ../repeat.py:21
msgid "Set unit cell"
msgstr "Fijar la celda unitaria"
#: ../rotate.py:15
msgid "Rotate"
msgstr "Rotar"
#: ../rotate.py:17
msgid "Rotation angles:"
msgstr "Ãngulos de rotación:"
#: ../rotate.py:27
msgid ""
"Note:\n"
"You can rotate freely\n"
"with the mouse, by holding\n"
"down mouse button 2."
msgstr ""
"Nota:\n"
"Usted puede rotar libremente\n"
"con el ratón, presionando el\n"
"botón número 2 del ratón."
#: ../scaling.py:49
msgid "Homogeneous scaling"
msgstr "Escala homogénea"
#: ../scaling.py:59
msgid "3D deformation "
msgstr "Deformación en tres dimensiones "
#: ../scaling.py:60
msgid "2D deformation "
msgstr "Deformación en dos dimensiones "
#: ../scaling.py:61
msgid "1D deformation "
msgstr "Deformación en una dimensión "
#: ../scaling.py:64
msgid "Bulk"
msgstr "Bulto"
#: ../scaling.py:66
msgid "xy-plane"
msgstr "plano xy"
#: ../scaling.py:68
msgid "xz-plane"
msgstr "plano xz"
#: ../scaling.py:70
msgid "yz-plane"
msgstr "plano yz"
#: ../scaling.py:72
msgid "x-axis"
msgstr "eje x"
#: ../scaling.py:74
msgid "y-axis"
msgstr "eje y"
#: ../scaling.py:76
msgid "z-axis"
msgstr "eje z"
#: ../scaling.py:89
msgid "Allow deformation along non-periodic directions."
msgstr "Permitir deformaciones a lo largo de direcciones no periódicas."
#. Parameters for the deformation
#: ../scaling.py:94
msgid "Deformation:"
msgstr "Deformación:"
#: ../scaling.py:100
msgid "Maximal scale factor: "
msgstr "Factor de escala máximo: "
#: ../scaling.py:103
msgid "Scale offset: "
msgstr "Compensación de escala: "
#: ../scaling.py:106
msgid "Number of steps: "
msgstr "Número de pasos: "
#: ../scaling.py:107
msgid "Only positive deformation"
msgstr "Sólo deformaciones positivas"
#. Atomic relaxations
#: ../scaling.py:112
msgid "Atomic relaxations:"
msgstr "Relajaciones atómicas:"
#: ../scaling.py:116
msgid "On "
msgstr "Encendido "
#: ../scaling.py:117
msgid "Off"
msgstr "Apagado"
#. Results
#: ../scaling.py:128
msgid "Results:"
msgstr "Resultados:"
#: ../scaling.py:130
msgid "Keep original configuration"
msgstr "Mantener la configuración original"
#: ../scaling.py:132
msgid "Load optimal configuration"
msgstr "Cargar la configuración óptima"
#: ../scaling.py:134
msgid "Load all configurations"
msgstr "Cargar todas las configuraciones"
#: ../scaling.py:143
msgid "Strain\t\tEnergy [eV]"
msgstr "EnergÃa de deformación [eV]"
#: ../scaling.py:144
msgid "Fit:"
msgstr "Ajuste:"
#: ../scaling.py:148
msgid "2nd"
msgstr "Segundo"
#: ../scaling.py:149
msgid "3rd"
msgstr "Tercero"
#: ../scaling.py:153
msgid "Order of fit: "
msgstr "Grado del ajuste: "
#. Update display to reflect cancellation of simulation.
#: ../scaling.py:346
msgid "Calculation CANCELLED."
msgstr "Cálculo CANCELADO."
#. Update display to reflect succesful end of simulation.
#: ../scaling.py:357
msgid "Calculation completed."
msgstr "Cálculo terminado."
#: ../scaling.py:380
msgid "No trustworthy minimum: Old configuration kept."
msgstr "El mÃnimo no es confiable: se mantiene la configuración anterior."
#: ../scaling.py:420
#, python-format
msgid ""
"Insufficent data for a fit\n"
"(only %i data points)\n"
msgstr ""
"Datos insuficientes para un ajuste\n"
"(sólo hay %i puntos)\n"
#: ../scaling.py:424
msgid ""
"REVERTING TO 2ND ORDER FIT\n"
"(only 3 data points)\n"
"\n"
msgstr ""
"VOLVIENDO A UN AJUSTE DE SEGUNDO ORDEN\n"
"(sólo con 3 puntos)\n"
"\n"
#: ../scaling.py:440
msgid "No minimum found!"
msgstr "¡No se encontró el mÃnimo!"
#: ../scaling.py:454
msgid ""
"\n"
"WARNING: Minimum is outside interval\n"
msgstr ""
"\n"
"ADVERTENCIA: El mÃnimo está fuera del intervalo\n"
#: ../scaling.py:455
msgid "It is UNRELIABLE!\n"
msgstr "¡Esto NO es confiable!\n"
#: ../settings.py:16
msgid "Constraints:"
msgstr "Restricciones:"
#: ../settings.py:19
msgid "release"
msgstr "Soltar"
#: ../settings.py:23
msgid "Constrain immobile atoms"
msgstr "Restringir los átomos inmóbiles"
#: ../settings.py:25
msgid "Clear all constraints"
msgstr "Eliminar todas las restricciones"
#: ../settings.py:31
msgid "Visibility:"
msgstr "Visibilidad:"
#: ../settings.py:32
msgid "Hide"
msgstr "Esconder"
#: ../settings.py:34
msgid "show"
msgstr "Mostrar"
#: ../settings.py:38
msgid "View all atoms"
msgstr "Ver todos los átomos"
#: ../settings.py:44
msgid "Miscellaneous:"
msgstr "Misceláneos:"
#: ../settings.py:47
msgid "Scale atomic radii:"
msgstr "Radio de escala atómica:"
#. A close button
#: ../settings.py:52
msgid "\n"
msgstr "\n"
#: ../setupwindow.py:51
msgid "No crystal structure data"
msgstr "No existen los datos de estructura cristalina"
#: ../setupwindow.py:62
msgid " ERROR: Invalid element!"
msgstr " ERROR: ¡elemento inválido!"
#: ../simulation.py:24
msgid " (rerun simulation)"
msgstr " (recalcular la simulación)"
#: ../simulation.py:25
msgid " (continue simulation)"
msgstr " (continuar simulación)"
#: ../simulation.py:27
msgid "Select starting configuration:"
msgstr "Seleccione la configuración inicial:"
#: ../simulation.py:32
#, python-format
msgid "There are currently %i configurations loaded."
msgstr "Actualmente hay %i configuraciones cargadas."
# Elegir cual será utilizada como la configuración inicial
#: ../simulation.py:36
msgid "Choose which one to use as the initial configuration"
msgstr "Elegir cual será utilizada como la configuración inicial"
#: ../simulation.py:40
#, python-format
msgid "The first configuration %s."
msgstr "La primera configuración %s."
#: ../simulation.py:43
msgid "Configuration number "
msgstr "Configuración número "
#: ../simulation.py:49
#, python-format
msgid "The last configuration %s."
msgstr "La última configuración %s."
#: ../simulation.py:85
msgid "Run"
msgstr "Calcular"
#: ../simulation.py:105
msgid "No calculator: Use Calculate/Set Calculator on the menu."
msgstr "No hay un calculador. Use Calcular/Fijar Calculador en el menú."
#: ../status.py:37 ../status.py:39
msgid "Tip for status box ..."
msgstr "Consejo para la ventana de estado ..."
#. TRANSLATORS: mom refers to magnetic moment
#: ../status.py:63
#, python-format
msgid " tag=%(tag)s mom=%(mom)1.2f"
msgstr " etiqueta=%(tag)s momento magnético=%(mom)1.2f"
#: ../status.py:104
msgid "dihedral"
msgstr "diedral"
#: ../surfaceslab.py:14
msgid ""
" Use this dialog to create surface slabs. Select the element by\n"
"writing the chemical symbol or the atomic number in the box. Then\n"
"select the desired surface structure. Note that some structures can\n"
"be created with an othogonal or a non-orthogonal unit cell, in these\n"
"cases the non-orthogonal unit cell will contain fewer atoms.\n"
"\n"
" If the structure matches the experimental crystal structure, you can\n"
"look up the lattice constant, otherwise you have to specify it\n"
"yourself."
msgstr ""
"Use esta ventana para crear un trozo de superficie. Seleccione el\n"
"elemento escribiendo el sÃmbolo quÃmico ó el número atómico en la\n"
"caja. Luego, seleccione la estructura de la superficie deseada. Note\n"
"que algunas estructuras pueden ser creadas con una celda unitaria or-\n"
"togonal u no ortogonal. En estos casos, la celda unitaria no ortogonal\n"
"contendrá menos átomos.\n"
"\n"
"Si la estructura coincide con la estructura cristalina experimental, usted\n"
"podrá buscar la constante de red en la base de datos de ASE. En otro caso, \n"
"tendrá que especificarla manualmente."
#. Name, structure, orthogonal, support-nonorthogonal, function
#: ../surfaceslab.py:26
msgid "FCC(100)"
msgstr "FCC(100)"
#: ../surfaceslab.py:26 ../surfaceslab.py:27 ../surfaceslab.py:28
#: ../surfaceslab.py:30
msgid "fcc"
msgstr "fcc"
#: ../surfaceslab.py:27
msgid "FCC(110)"
msgstr "FCC(110)"
#: ../surfaceslab.py:28
msgid "FCC(111) non-orthogonal"
msgstr "FCC (111) no ortogonal"
#: ../surfaceslab.py:30
msgid "FCC(111) orthogonal"
msgstr "FCC (111) ortogonal"
#: ../surfaceslab.py:31
msgid "BCC(100)"
msgstr "BCC(100)"
#: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:34
#: ../surfaceslab.py:35 ../surfaceslab.py:37
msgid "bcc"
msgstr "bcc"
#: ../surfaceslab.py:32
msgid "BCC(110) non-orthogonal"
msgstr "BCC (110) no ortogonal"
#: ../surfaceslab.py:34
msgid "BCC(110) orthogonal"
msgstr "BCC (110) ortogonal"
#: ../surfaceslab.py:35
msgid "BCC(111) non-orthogonal"
msgstr "BCC (111) no ortogonal"
#: ../surfaceslab.py:37
msgid "BCC(111) orthogonal"
msgstr "BCC (111) ortogonal"
#: ../surfaceslab.py:38
msgid "HCP(0001) non-orthogonal"
msgstr "HCP (0001) no ortogonal"
#: ../surfaceslab.py:38 ../surfaceslab.py:40 ../surfaceslab.py:41
msgid "hcp"
msgstr "hcp"
#: ../surfaceslab.py:40
msgid "HCP(0001) orthogonal"
msgstr "HCP (0001) ortogonal"
#: ../surfaceslab.py:41
msgid "HCP(10-10) orthogonal"
msgstr "HCP (10-10) ortogonal"
#: ../surfaceslab.py:43
msgid "DIAMOND(100) orthogonal"
msgstr "Diamante (100) ortogonal"
#: ../surfaceslab.py:43 ../surfaceslab.py:45
msgid "diamond"
msgstr "diamante"
#: ../surfaceslab.py:45
msgid "DIAMOND(111) non-orthogonal"
msgstr "Diamante (111) no ortogonal"
#: ../surfaceslab.py:60
msgid "Surface"
msgstr "Superficie"
#: ../surfaceslab.py:90
msgid "Lattice constant: "
msgstr "Constante de red: "
#: ../surfaceslab.py:97
msgid "a:"
msgstr "a:"
#: ../surfaceslab.py:109
#, python-format
msgid "(%.1f %% of ideal)"
msgstr "(%.1f %% de ideal)"
#: ../surfaceslab.py:126
msgid "Size: \tx: "
msgstr "Tamaño en\tx:"
#: ../surfaceslab.py:128
msgid "\t\ty: "
msgstr "\t\ty: "
#: ../surfaceslab.py:130
msgid " \t\tz: "
msgstr " \t\tz: "
#: ../surfaceslab.py:131
msgid " layers, "
msgstr " capas, "
#: ../surfaceslab.py:132
msgid " Ã… vacuum"
msgstr " vacÃo en Ã…"
#: ../surfaceslab.py:133
msgid "\t\tNo size information yet."
msgstr "\t\tNo hay información sobre el tamaño aún."
#. Buttons
#: ../surfaceslab.py:142
msgid "Creating a surface slab."
msgstr "Creando un trozo de superficie."
#: ../surfaceslab.py:212
#, python-format
msgid "%i atoms."
msgstr "Ãtomos %i."
#: ../surfaceslab.py:224
msgid "No structure specified!"
msgstr "¡No se especificó la estructura!"
#: ../surfaceslab.py:233
#, python-format
msgid "%(struct)s lattice constant unknown for %(element)s."
msgstr ""
"La constante de red %(struct)s es desconocida para el elemento %(element)s."
#: ../widgets.py:53 ../widgets.py:80
msgid "Help"
msgstr "Ayuda"
#: ../widgets.py:97
msgid "Clear constraint"
msgstr "Borrar restricción"
#~ msgid " %8.3f, %8.3f, %8.3f eV/Ã…\n"
#~ msgstr " %8.3f, %8.3f, %8.3f eV/Ã…\n"
#~ msgid "%s (a=%.3f Ã…)"
#~ msgstr "%s (a=%.3f Ã…)"
#~ msgid " %s: %s, Z=%i, %s"
#~ msgstr " %s: %s, Z=%i, %s"
#~ msgid " #%d %s (%s): %.3f Ã…, %.3f Ã…, %.3f Ã… "
#~ msgstr " #%d %s (%s): %.3f Ã…, %.3f Ã…, %.3f Ã… "
#~ msgid " %s-%s: %.3f Ã…"
#~ msgstr " %s-%s: %.3f Ã…"
#~ msgid " %s-%s-%s: %.1f°, %.1f°, %.1f°"
#~ msgstr " %s-%s-%s: %.1f°, %.1f°, %.1f°"
#~ msgid "c:"
#~ msgstr "c:"
#~ msgid "FILE"
#~ msgstr "ARCHIVO"
#~ msgid "%prog [options] [file[, file2, ...]]"
#~ msgstr "%prog [opciones] [archivo[, archivo2, ...]]"
#~ msgid "NUMBER"
#~ msgstr "NÚMERO"
#~ msgid "I"
#~ msgstr "I"
#~ msgid "Examples: \"-R -90x\", \"-R 90z,-30x\"."
#~ msgstr "Ejemplos: \"-R -90x\", \"-R 90z,-30x\"."
#~ msgid "EXPR"
#~ msgstr "EXPR"
#~ msgid "N"
#~ msgstr "N"
python-ase-3.6.0.2515/ase/gui/po/en_GB/ 0000755 0001754 0001754 00000000000 11757245036 016136 5 ustar askhl askhl python-ase-3.6.0.2515/ase/gui/po/en_GB/LC_MESSAGES/ 0000755 0001754 0001754 00000000000 11757245036 017723 5 ustar askhl askhl python-ase-3.6.0.2515/ase/gui/po/en_GB/LC_MESSAGES/ag.po 0000644 0001754 0001754 00000225230 11716573517 020661 0 ustar askhl askhl # English translations for ASE package
# Copyright (C) 2011 CAMD
# This file is distributed under the same license as the ASE package.
#
# Ask Hjorth Larsen , 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: ase-3.5.2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-01 16:08+0100\n"
"PO-Revision-Date: 2012-02-01 16:10+0100\n"
"Last-Translator: Ask Hjorth Larsen \n"
"Language-Team: English (British) \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: en_GB\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../ag.py:130
msgid ""
"\n"
"An exception occurred! Please report the issue to\n"
"ase-developers@listserv.fysik.dtu.dk - thanks! Please also report this if\n"
"it was a user error, so that a better error message can be provided\n"
"next time."
msgstr ""
"\n"
"An exception occurred! Please report the issue to\n"
"ase-developers@listserv.fysik.dtu.dk - thanks! Please also report this if\n"
"it was a user error, so that a better error message can be provided\n"
"next time."
#. Asap and GPAW may be imported if selected.
#: ../calculator.py:18
msgid ""
"To make most calculations on the atoms, a Calculator object must first\n"
"be associated with it. ASE supports a number of calculators, supporting\n"
"different elements, and implementing different physical models for the\n"
"interatomic interactions."
msgstr ""
"To make most calculations on the atoms, a Calculator object must first\n"
"be associated with it. ASE supports a number of calculators, supporting\n"
"different elements, and implementing different physical models for the\n"
"interatomic interactions."
#. Informational text about the calculators
#: ../calculator.py:26
msgid ""
"The Lennard-Jones pair potential is one of the simplest\n"
"possible models for interatomic interactions, mostly\n"
"suitable for noble gasses and model systems.\n"
"\n"
"Interactions are described by an interaction length and an\n"
"interaction strength."
msgstr ""
"The Lennard-Jones pair potential is one of the simplest\n"
"possible models for interatomic interactions, mostly\n"
"suitable for noble gasses and model systems.\n"
"\n"
"Interactions are described by an interaction length and an\n"
"interaction strength."
#: ../calculator.py:35
msgid ""
"The EMT potential is a many-body potential, giving a\n"
"good description of the late transition metals crystalling\n"
"in the FCC crystal structure. The elements described by the\n"
"main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and\n"
"Au, the Al potential is however not suitable for materials\n"
"science application, as the stacking fault energy is wrong.\n"
"\n"
"A number of parameter sets are provided.\n"
"\n"
"Default parameters:\n"
"\n"
"The default EMT parameters, as published in K. W. Jacobsen,\n"
"P. Stoltze and J. K. Nørskov, Surf. Sci. 366, 394 (1996).\n"
"\n"
"Alternative Cu, Ag and Au:\n"
"\n"
"An alternative set of parameters for Cu, Ag and Au,\n"
"reoptimized to experimental data including the stacking\n"
"fault energies by Torben Rasmussen (partly unpublished).\n"
"\n"
"Ruthenium:\n"
"\n"
"Parameters for Ruthenium, as published in J. Gavnholt and\n"
"J. Schiøtz, Phys. Rev. B 77, 035404 (2008).\n"
"\n"
"Metallic glasses:\n"
"\n"
"Parameters for MgCu and CuZr metallic glasses. MgCu\n"
"parameters are in N. P. Bailey, J. Schiøtz and\n"
"K. W. Jacobsen, Phys. Rev. B 69, 144205 (2004).\n"
"CuZr in A. Paduraru, A. Kenoufi, N. P. Bailey and\n"
"J. Schiøtz, Adv. Eng. Mater. 9, 505 (2007).\n"
msgstr ""
"The EMT potential is a many-body potential, giving a\n"
"good description of the late transition metals crystalling\n"
"in the FCC crystal structure. The elements described by the\n"
"main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and\n"
"Au, the Al potential is however not suitable for materials\n"
"science application, as the stacking fault energy is wrong.\n"
"\n"
"A number of parameter sets are provided.\n"
"\n"
"Default parameters:\n"
"\n"
"The default EMT parameters, as published in K. W. Jacobsen,\n"
"P. Stoltze and J. K. Nørskov, Surf. Sci. 366, 394 (1996).\n"
"\n"
"Alternative Cu, Ag and Au:\n"
"\n"
"An alternative set of parameters for Cu, Ag and Au,\n"
"reoptimised to experimental data including the stacking\n"
"fault energies by Torben Rasmussen (partly unpublished).\n"
"\n"
"Ruthenium:\n"
"\n"
"Parameters for Ruthenium, as published in J. Gavnholt and\n"
"J. Schiøtz, Phys. Rev. B 77, 035404 (2008).\n"
"\n"
"Metallic glasses:\n"
"\n"
"Parameters for MgCu and CuZr metallic glasses. MgCu\n"
"parameters are in N. P. Bailey, J. Schiøtz and\n"
"K. W. Jacobsen, Phys. Rev. B 69, 144205 (2004).\n"
"CuZr in A. Paduraru, A. Kenoufi, N. P. Bailey and\n"
"J. Schiøtz, Adv. Eng. Mater. 9, 505 (2007).\n"
#: ../calculator.py:70
msgid ""
"The EMT potential is a many-body potential, giving a\n"
"good description of the late transition metals crystalling\n"
"in the FCC crystal structure. The elements described by the\n"
"main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and\n"
"Au. In addition, this implementation allows for the use of\n"
"H, N, O and C adatoms, although the description of these is\n"
"most likely not very good.\n"
"\n"
"This is the ASE implementation of EMT. For large\n"
"simulations the ASAP implementation is more suitable; this\n"
"implementation is mainly to make EMT available when ASAP is\n"
"not installed.\n"
msgstr ""
"The EMT potential is a many-body potential, giving a\n"
"good description of the late transition metals crystalling\n"
"in the FCC crystal structure. The elements described by the\n"
"main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and\n"
"Au. In addition, this implementation allows for the use of\n"
"H, N, O and C adatoms, although the description of these is\n"
"most likely not very good.\n"
"\n"
"This is the ASE implementation of EMT. For large\n"
"simulations the ASAP implementation is more suitable; this\n"
"implementation is mainly to make EMT available when ASAP is\n"
"not installed.\n"
#: ../calculator.py:85
msgid ""
"The Brenner potential is a reactive bond-order potential for\n"
"carbon and hydrocarbons. As a bond-order potential, it takes\n"
"into account that carbon orbitals can hybridize in different\n"
"ways, and that carbon can form single, double and triple\n"
"bonds. That the potential is reactive means that it can\n"
"handle gradual changes in the bond order as chemical bonds\n"
"are formed or broken.\n"
"\n"
"The Brenner potential is implemented in Asap, based on a\n"
"C implentation published at http://www.rahul.net/pcm/brenner/ .\n"
"\n"
"The potential is documented here:\n"
" Donald W Brenner, Olga A Shenderova, Judith A Harrison,\n"
" Steven J Stuart, Boris Ni and Susan B Sinnott:\n"
" \"A second-generation reactive empirical bond order (REBO)\n"
" potential energy expression for hydrocarbons\",\n"
" J. Phys.: Condens. Matter 14 (2002) 783-802.\n"
" doi: 10.1088/0953-8984/14/4/312\n"
msgstr ""
"The Brenner potential is a reactive bond-order potential for\n"
"carbon and hydrocarbons. As a bond-order potential, it takes\n"
"into account that carbon orbitals can hybridise in different\n"
"ways, and that carbon can form single, double and triple\n"
"bonds. That the potential is reactive means that it can\n"
"handle gradual changes in the bond order as chemical bonds\n"
"are formed or broken.\n"
"\n"
"The Brenner potential is implemented in Asap, based on a\n"
"C implentation published at http://www.rahul.net/pcm/brenner/ .\n"
"\n"
"The potential is documented here:\n"
" Donald W Brenner, Olga A Shenderova, Judith A Harrison,\n"
" Steven J Stuart, Boris Ni and Susan B Sinnott:\n"
" \"A second-generation reactive empirical bond order (REBO)\n"
" potential energy expression for hydrocarbons\",\n"
" J. Phys.: Condens. Matter 14 (2002) 783-802.\n"
" doi: 10.1088/0953-8984/14/4/312\n"
#: ../calculator.py:107
msgid ""
"GPAW implements Density Functional Theory using a\n"
"Grid-based real-space representation of the wave\n"
"functions, and the Projector Augmented Wave\n"
"method for handling the core regions. \n"
msgstr ""
"GPAW implements Density Functional Theory using a\n"
"Grid-based real-space representation of the wave\n"
"functions, and the Projector Augmented Wave\n"
"method for handling the core regions. \n"
#: ../calculator.py:114
msgid ""
"FHI-aims is an external package implementing density \n"
"functional theory and quantum chemical methods using \n"
"all-electron methods and a numeric local orbital basis set. \n"
"For full details, see http://www.fhi-berlin.mpg.de/aims/ \n"
"or Comp. Phys. Comm. v180 2175 (2009). The ASE \n"
"documentation contains information on the keywords and \n"
"functionalities available within this interface. \n"
msgstr ""
"FHI-aims is an external package implementing density \n"
"functional theory and quantum chemical methods using \n"
"all-electron methods and a numeric local orbital basis set. \n"
"For full details, see http://www.fhi-berlin.mpg.de/aims/ \n"
"or Comp. Phys. Comm. v180 2175 (2009). The ASE \n"
"documentation contains information on the keywords and \n"
"functionalities available within this interface. \n"
#: ../calculator.py:124
msgid ""
"WARNING:\n"
"Your system seems to have more than zero but less than \n"
"three periodic dimensions. Please check that this is \n"
"really what you want to compute. Assuming full \n"
"3D periodicity for this calculator."
msgstr ""
"WARNING:\n"
"Your system seems to have more than zero but less than \n"
"three periodic dimensions. Please check that this is \n"
"really what you want to compute. Assuming full \n"
"3D periodicity for this calculator."
#: ../calculator.py:131
msgid ""
"VASP is an external package implementing density \n"
"functional functional theory using pseudopotentials \n"
"or the projector-augmented wave method together \n"
"with a plane wave basis set. For full details, see\n"
"http://cms.mpi.univie.ac.at/vasp/vasp/\n"
msgstr ""
"VASP is an external package implementing density \n"
"functional functional theory using pseudopotentials \n"
"or the projector-augmented wave method together \n"
"with a plane wave basis set. For full details, see\n"
"http://cms.mpi.univie.ac.at/vasp/vasp/\n"
#: ../calculator.py:140
msgid "Default (Al, Ni, Cu, Pd, Ag, Pt, Au)"
msgstr "Default (Al, Ni, Cu, Pd, Ag, Pt, Au)"
#: ../calculator.py:141
msgid "Alternative Cu, Ag and Au"
msgstr "Alternative Cu, Ag and Au"
#: ../calculator.py:142
msgid "Ruthenium"
msgstr "Ruthenium"
#: ../calculator.py:143
msgid "CuMg and CuZr metallic glass"
msgstr "CuMg and CuZr metallic glass"
#: ../calculator.py:158
msgid "Select calculator"
msgstr "Select calculator"
#: ../calculator.py:164
msgid "Calculator:"
msgstr "Calculator:"
#. No calculator (the default)
#: ../calculator.py:167
msgid "None"
msgstr "None"
#: ../calculator.py:172
msgid "Lennard-Jones (ASAP)"
msgstr "Lennard-Jones (ASAP)"
#: ../calculator.py:173 ../calculator.py:206 ../calculator.py:215
#: ../calculator.py:224
msgid "Setup"
msgstr "Setup"
#: ../calculator.py:180
msgid "EMT - Effective Medium Theory (ASAP)"
msgstr "EMT - Effective Medium Theory (ASAP)"
#: ../calculator.py:192
msgid "EMT - Effective Medium Theory (ASE)"
msgstr "EMT - Effective Medium Theory (ASE)"
#: ../calculator.py:198
msgid "Brenner Potential (ASAP)"
msgstr "Brenner Potential (ASAP)"
#: ../calculator.py:204
msgid "Density Functional Theory (GPAW)"
msgstr "Density Functional Theory (GPAW)"
#: ../calculator.py:213
msgid "Density Functional Theory (FHI-aims)"
msgstr "Density Functional Theory (FHI-aims)"
#: ../calculator.py:222
msgid "Density Functional Theory (VASP)"
msgstr "Density Functional Theory (VASP)"
#: ../calculator.py:235
msgid "Check that the calculator is reasonable."
msgstr "Check that the calculator is reasonable."
#: ../calculator.py:298 ../simulation.py:114
msgid "No atoms present"
msgstr "No atoms present"
#: ../calculator.py:388 ../calculator.py:422 ../calculator.py:456
msgid "ASAP is not installed. (Failed to import asap3)"
msgstr "ASAP is not installed. (Failed to import asap3)"
#: ../calculator.py:391
msgid "You must set up the Lennard-Jones parameters"
msgstr "You must set up the Lennard-Jones parameters"
#: ../calculator.py:396
msgid "Could not create useful Lennard-Jones calculator."
msgstr "Could not create useful Lennard-Jones calculator."
#: ../calculator.py:430
msgid "Could not attach EMT calculator to the atoms."
msgstr "Could not attach EMT calculator to the atoms."
#: ../calculator.py:472 ../calculator.py:484
msgid "GPAW is not installed. (Failed to import gpaw)"
msgstr "GPAW is not installed. (Failed to import gpaw)"
#: ../calculator.py:475
msgid "You must set up the GPAW parameters"
msgstr "You must set up the GPAW parameters"
#: ../calculator.py:516
msgid "You must set up the FHI-aims parameters"
msgstr "You must set up the FHI-aims parameters"
#: ../calculator.py:530
msgid "You must set up the VASP parameters"
msgstr "You must set up the VASP parameters"
#: ../calculator.py:554
#, python-format
msgid "Element %(sym)s not allowed by the '%(name)s' calculator"
msgstr "Element %(sym)s not allowed by the '%(name)s' calculator"
#: ../calculator.py:561
msgid "Info"
msgstr "Info"
#: ../calculator.py:577
msgid "Lennard-Jones parameters"
msgstr "Lennard-Jones parameters"
#: ../calculator.py:589
msgid "Specify the Lennard-Jones parameters here"
msgstr "Specify the Lennard-Jones parameters here"
#: ../calculator.py:592
msgid "Epsilon (eV):"
msgstr "Epsilon (eV):"
#: ../calculator.py:596
msgid "Sigma (Ã…):"
msgstr "Sigma (Ã…):"
#. TRANSLATORS: Shift roughly means adjust (about a potential)
#: ../calculator.py:600
msgid "Shift to make smooth at cutoff"
msgstr "Shift to make smooth at cutoff"
#: ../calculator.py:681
msgid "GPAW parameters"
msgstr "GPAW parameters"
#. label = gtk.Label("Specify the GPAW parameters here")
#. pack(vbox, [label])
#. Print some info
#: ../calculator.py:696 ../calculator.py:985 ../calculator.py:1473
#, python-format
msgid "%i atoms.\n"
msgstr "%i atoms.\n"
#: ../calculator.py:698
#, python-format
msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Ã…."
msgstr "Orthogonal unit cell: %.2f x %.2f x %.2f Ã…."
#: ../calculator.py:700
msgid "Non-orthogonal unit cell:\n"
msgstr "Non-orthogonal unit cell:\n"
#: ../calculator.py:710 ../calculator.py:1001 ../calculator.py:1488
msgid "Exchange-correlation functional: "
msgstr "Exchange-correlation functional: "
#. Grid spacing
#: ../calculator.py:714
msgid "Grid spacing"
msgstr "Grid spacing"
#: ../calculator.py:718 ../graphene.py:67 ../graphene.py:79 ../graphene.py:102
#: ../nanotube.py:47 ../surfaceslab.py:97
msgid "Ã…"
msgstr "Ã…"
#: ../calculator.py:719
msgid "Grid points"
msgstr "Grid points"
#: ../calculator.py:728
#, python-format
msgid "heff = (%.3f, %.3f, %.3f) Ã…"
msgstr "heff = (%.3f, %.3f, %.3f) Ã…"
#: ../calculator.py:754 ../calculator.py:1016 ../calculator.py:1524
msgid "k-points k = ("
msgstr "k-points k = ("
#: ../calculator.py:758 ../calculator.py:1020
#, python-format
msgid "k-points x size: (%.1f, %.1f, %.1f) Ã…"
msgstr "k-points x size: (%.1f, %.1f, %.1f) Ã…"
#. Spin polarized
#: ../calculator.py:763 ../calculator.py:1486
msgid "Spin polarized"
msgstr "Spin polarised"
#: ../calculator.py:769
msgid "FD - Finite Difference (grid) mode"
msgstr "FD - Finite Difference (grid) mode"
#: ../calculator.py:770
msgid "LCAO - Linear Combination of Atomic Orbitals"
msgstr "LCAO - Linear Combination of Atomic Orbitals"
#: ../calculator.py:773
msgid "Mode: "
msgstr "Mode: "
#: ../calculator.py:775
msgid "sz - Single Zeta"
msgstr "sz - Single Zeta"
#: ../calculator.py:776
msgid "szp - Single Zeta polarized"
msgstr "szp - Single Zeta polarised"
#: ../calculator.py:777
msgid "dzp - Double Zeta polarized"
msgstr "dzp - Double Zeta polarised"
#. dzp
#: ../calculator.py:779
msgid "Basis functions: "
msgstr "Basis functions: "
#. Mixer
#: ../calculator.py:785
msgid "Non-standard mixer parameters"
msgstr "Non-standard mixer parameters"
#: ../calculator.py:981
msgid "FHI-aims parameters"
msgstr "FHI-aims parameters"
#: ../calculator.py:988
msgid "Periodic geometry, unit cell is:\n"
msgstr "Periodic geometry, unit cell is:\n"
#: ../calculator.py:993
msgid "Non-periodic geometry.\n"
msgstr "Non-periodic geometry.\n"
#: ../calculator.py:1000
msgid "Hirshfeld-based dispersion correction"
msgstr "Hirshfeld-based dispersion correction"
#. Spin polarized, charge, relativity
#: ../calculator.py:1026
msgid "Spin / initial moment "
msgstr "Spin / initial moment "
#: ../calculator.py:1044
msgid " Charge"
msgstr " Charge"
#: ../calculator.py:1046
msgid " Relativity"
msgstr " Relativity"
#: ../calculator.py:1048
msgid " Threshold"
msgstr " Threshold"
#. self-consistency criteria
#: ../calculator.py:1053
msgid "Self-consistency convergence:"
msgstr "Self-consistency convergence:"
#: ../calculator.py:1066
msgid "Compute forces"
msgstr "Compute forces"
#. XXX: use gtk table for layout. Spaces will not work well otherwise
#. (depend on fonts, widget style, ...)
#. TRANSLATORS: Don't care too much about these, just get approximately
#. the same string lengths
#: ../calculator.py:1077
msgid "Energy: "
msgstr "Energy: "
#: ../calculator.py:1079
msgid " eV Sum of eigenvalues: "
msgstr " eV Sum of eigenvalues: "
#: ../calculator.py:1081 ../calculator.py:1559
msgid " eV"
msgstr " eV"
#: ../calculator.py:1082
msgid "Electron density: "
msgstr "Electron density: "
#: ../calculator.py:1084
msgid " Force convergence: "
msgstr " Force convergence: "
#: ../calculator.py:1086
msgid " eV/Ang "
msgstr " eV/Ang "
#: ../calculator.py:1099 ../calculator.py:1570
msgid "Additional keywords: "
msgstr "Additional keywords: "
#. run command and species defaults:
#: ../calculator.py:1113
msgid "FHI-aims execution command: "
msgstr "FHI-aims execution command: "
#: ../calculator.py:1115 ../calculator.py:1587
msgid "Directory for species defaults: "
msgstr "Directory for species defaults: "
#: ../calculator.py:1127 ../calculator.py:1595
msgid "Set Defaults"
msgstr "Set Defaults"
#: ../calculator.py:1129
msgid "Import control.in"
msgstr "Import control.in"
#: ../calculator.py:1131
msgid "Export control.in"
msgstr "Export control.in"
#: ../calculator.py:1317
msgid "Export parameters ... "
msgstr "Export parameters ... "
#: ../calculator.py:1337
msgid "Import control.in file ... "
msgstr "Import control.in file ... "
#: ../calculator.py:1393 ../calculator.py:1907
#, python-format
msgid ""
"Please use the facilities provided in this window to manipulate the keyword: "
"%s!"
msgstr ""
"Please use the facilities provided in this window to manipulate the keyword: "
"%s!"
#: ../calculator.py:1396
#, python-format
msgid ""
"Don't know this keyword: %s\n"
"\n"
"Please check!\n"
"\n"
"If you really think it should be available, please add it to the top of ase/"
"calculators/aims.py."
msgstr ""
"Don't know this keyword: %s\n"
"\n"
"Please check!\n"
"\n"
"If you really think it should be available, please add it to the top of ase/"
"calculators/aims.py."
#: ../calculator.py:1469
msgid "VASP parameters"
msgstr "VASP parameters"
#: ../calculator.py:1475
msgid "Periodic geometry, unit cell is: \n"
msgstr "Periodic geometry, unit cell is: \n"
#: ../calculator.py:1527
msgid ") Cutoff: "
msgstr ") Cutoff: "
#: ../calculator.py:1528
msgid " Precision: "
msgstr " Precision: "
#: ../calculator.py:1530
#, python-format
msgid "k-points x size: (%.1f, %.1f, %.1f) Ã… "
msgstr "k-points x size: (%.1f, %.1f, %.1f) Ã… "
#: ../calculator.py:1546
msgid "Smearing: "
msgstr "Smearing: "
#: ../calculator.py:1548
msgid " order: "
msgstr " order: "
#: ../calculator.py:1550
msgid " width: "
msgstr " width: "
#: ../calculator.py:1557
msgid "Self-consistency convergence: "
msgstr "Self-consistency convergence: "
#. run command and location of POTCAR files:
#: ../calculator.py:1583
msgid "VASP execution command: "
msgstr "VASP execution command: "
#: ../calculator.py:1597
msgid "Import VASP files"
msgstr "Import VASP files"
#: ../calculator.py:1599
msgid "Export VASP files"
msgstr "Export VASP files"
#: ../calculator.py:1810
msgid "WARNING: cutoff energy is lower than recommended minimum!"
msgstr "WARNING: cutoff energy is lower than recommended minimum!"
#: ../calculator.py:1862
msgid "Import VASP input files: choose directory ... "
msgstr "Import VASP input files: choose directory ... "
#: ../calculator.py:1877
msgid "Export VASP input files: choose directory ... "
msgstr "Export VASP input files: choose directory ... "
#: ../calculator.py:1910
#, python-format
msgid ""
"Don't know this keyword: %s\n"
"Please check!\n"
"\n"
"If you really think it should be available, please add it to the top of ase/"
"calculators/vasp.py."
msgstr ""
"Don't know this keyword: %s\n"
"Please check!\n"
"\n"
"If you really think it should be available, please add it to the top of ase/"
"calculators/vasp.py."
#: ../colors.py:24
msgid "Colors"
msgstr "Colours"
#. Upper left: Choose how the atoms are colored.
#: ../colors.py:41
msgid "Choose how the atoms are colored:"
msgstr "Choose how the atoms are coloured:"
#: ../colors.py:43
msgid "By atomic number, default \"jmol\" colors"
msgstr "By atomic number, default \"jmol\" colours"
#: ../colors.py:45
msgid "By atomic number, user specified"
msgstr "By atomic number, user specified"
#: ../colors.py:46
msgid "By tag"
msgstr "By tag"
#: ../colors.py:47
msgid "By force"
msgstr "By force"
#: ../colors.py:48
msgid "By velocity"
msgstr "By velocity"
#: ../colors.py:49
msgid "Manually specified"
msgstr "Manually specified"
#: ../colors.py:50
msgid "All the same color"
msgstr "All the same colour"
#. Now fill in the box for additional information in case the force is used.
#: ../colors.py:60
msgid "This should not be displayed!"
msgstr "This should not be displayed!"
#: ../colors.py:65 ../colors.py:82 ../rotate.py:25
msgid "Update"
msgstr "Update"
#: ../colors.py:67 ../colors.py:84
msgid "Min: "
msgstr "Min: "
#: ../colors.py:69 ../colors.py:86
msgid " Max: "
msgstr " Max: "
#: ../colors.py:71 ../colors.py:88
msgid " Steps: "
msgstr " Steps: "
#: ../colors.py:95
msgid "Create a color scale:"
msgstr "Create a colour scale:"
#: ../colors.py:98
msgid "Black - white"
msgstr "Black - white"
#: ../colors.py:99
msgid "Black - red - yellow - white"
msgstr "Black - red - yellow - white"
#: ../colors.py:100
msgid "Black - green - white"
msgstr "Black - green - white"
#: ../colors.py:101
msgid "Black - blue - cyan"
msgstr "Black - blue - cyan"
#: ../colors.py:102
msgid "Hue"
msgstr "Hue"
#: ../colors.py:103
msgid "Named colors"
msgstr "Named colours"
#: ../colors.py:109
msgid "Create"
msgstr "Create"
#: ../colors.py:367
#, python-format
msgid "Max force: %.2f (this frame), %.2f (all frames)"
msgstr "Max force: %.2f (this frame), %.2f (all frames)"
#: ../colors.py:369
#, python-format
msgid "Max force: %.2f."
msgstr "Max force: %.2f."
#: ../colors.py:383
#, python-format
msgid "Max velocity: %.2f (this frame), %.2f (all frames)"
msgstr "Max velocity: %.2f (this frame), %.2f (all frames)"
#: ../colors.py:385
#, python-format
msgid "Max velocity: %.2f."
msgstr "Max velocity: %.2f."
#: ../colors.py:426
msgid "ERROR"
msgstr "ERROR"
#: ../colors.py:455
msgid "ERR"
msgstr "ERR"
#: ../colors.py:542
msgid "Incorrect color specification"
msgstr "Incorrect colour specification"
#: ../constraints.py:13 ../widgets.py:89
msgid "Constraints"
msgstr "Constraints"
#: ../constraints.py:15 ../constraints.py:18 ../settings.py:17
#: ../widgets.py:91 ../widgets.py:94
msgid "Constrain"
msgstr "Constrain"
#: ../constraints.py:16 ../settings.py:20 ../settings.py:35 ../widgets.py:92
msgid " selected atoms"
msgstr " selected atoms"
#: ../constraints.py:19 ../widgets.py:95
msgid " immobile atoms:"
msgstr " immobile atoms:"
#: ../constraints.py:21
msgid "Unconstrain"
msgstr "Unconstrain"
#: ../constraints.py:22
msgid " selected atoms:"
msgstr " selected atoms:"
#: ../constraints.py:24
msgid "Clear constraints"
msgstr "Clear constraints"
#: ../constraints.py:26 ../dft.py:29 ../settings.py:53 ../widgets.py:60
#: ../widgets.py:99
msgid "Close"
msgstr "Close"
#: ../crystal.py:16
msgid ""
" Use this dialog to create crystal lattices. First select the structure,\n"
" either from a set of common crystal structures, or by space group "
"description.\n"
" Then add all other lattice parameters.\n"
"\n"
" If an experimental crystal structure is available for an atom, you can\n"
" look up the crystal type and lattice constant, otherwise you have to "
"specify it\n"
" yourself. "
msgstr ""
" Use this dialog to create crystal lattices. First select the structure,\n"
" either from a set of common crystal structures, or by space group "
"description.\n"
" Then add all other lattice parameters.\n"
"\n"
" If an experimental crystal structure is available for an atom, you can\n"
" look up the crystal type and lattice constant, otherwise you have to "
"specify it\n"
" yourself. "
#: ../crystal.py:33
#, python-format
msgid " %(natoms)i atoms: %(symbols)s, Volume: %(volume).3f A3"
msgstr " %(natoms)i atoms: %(symbols)s, Volume: %(volume).3f A3"
#: ../crystal.py:58
msgid "Create Bulk Crystal by Spacegroup"
msgstr "Create Bulk Crystal by Spacegroup"
#: ../crystal.py:72
msgid "Number: 1"
msgstr "Number: 1"
#: ../crystal.py:73
msgid "Lattice: "
msgstr "Lattice: "
#: ../crystal.py:73
msgid "\tSpace group: "
msgstr "\tSpace group: "
#: ../crystal.py:77
msgid "Size: x: "
msgstr "Size: x: "
#: ../crystal.py:78 ../crystal.py:138
msgid " y: "
msgstr " y: "
#: ../crystal.py:79 ../crystal.py:139
msgid " z: "
msgstr " z: "
#: ../crystal.py:80 ../surfaceslab.py:127 ../surfaceslab.py:129
msgid " unit cells"
msgstr " unit cells"
#: ../crystal.py:92 ../crystal.py:96 ../crystal.py:100 ../crystal.py:104
#: ../crystal.py:108 ../crystal.py:112
msgid "free"
msgstr "free"
#: ../crystal.py:93 ../crystal.py:102
msgid "equals b"
msgstr "equals b"
#: ../crystal.py:94 ../crystal.py:98
msgid "equals c"
msgstr "equals c"
#: ../crystal.py:95 ../crystal.py:99 ../crystal.py:103 ../crystal.py:107
#: ../crystal.py:111 ../crystal.py:115
msgid "fixed"
msgstr "fixed"
#: ../crystal.py:97 ../crystal.py:101
msgid "equals a"
msgstr "equals a"
#: ../crystal.py:105 ../crystal.py:114
msgid "equals beta"
msgstr "equals beta"
#: ../crystal.py:106 ../crystal.py:110
msgid "equals gamma"
msgstr "equals gamma"
#: ../crystal.py:109 ../crystal.py:113
msgid "equals alpha"
msgstr "equals alpha"
#: ../crystal.py:119
msgid "Lattice parameters"
msgstr "Lattice parameters"
#: ../crystal.py:120
msgid "\t\ta:\t"
msgstr "\t\ta:\t"
#: ../crystal.py:121
msgid "\talpha:\t"
msgstr "\talpha:\t"
#: ../crystal.py:122
msgid "\t\tb:\t"
msgstr "\t\tb:\t"
#: ../crystal.py:123
msgid "\tbeta:\t"
msgstr "\tbeta:\t"
#: ../crystal.py:124
msgid "\t\tc:\t"
msgstr "\t\tc:\t"
#: ../crystal.py:125
msgid "\tgamma:\t"
msgstr "\tgamma:\t"
#: ../crystal.py:126 ../surfaceslab.py:99
msgid "Get from database"
msgstr "Get from database"
#: ../crystal.py:131
msgid "Basis: "
msgstr "Basis: "
#: ../crystal.py:137
msgid " Element:\t"
msgstr " Element:\t"
#: ../crystal.py:137
msgid "\tx: "
msgstr "\tx: "
#: ../crystal.py:157
msgid "Creating a crystal."
msgstr "Creating a crystal."
#: ../crystal.py:202
#, python-format
msgid "Symbol: %s"
msgstr "Symbol: %s"
#: ../crystal.py:207
#, python-format
msgid "Number: %s"
msgstr "Number: %s"
#: ../crystal.py:210
msgid "Invalid Spacegroup!"
msgstr "Invalid Spacegroup!"
#: ../crystal.py:336 ../crystal.py:339
msgid "Please specify a consistent set of atoms."
msgstr "Please specify a consistent set of atoms."
#: ../crystal.py:348 ../graphene.py:230 ../nanoparticle.py:613
#: ../nanotube.py:139 ../surfaceslab.py:248
msgid "No valid atoms."
msgstr "No valid atoms."
#: ../crystal.py:465
msgid "Can't find lattice definition!"
msgstr "Can't find lattice definition!"
#: ../debug.py:11
msgid "Debug"
msgstr "Debug"
#: ../dft.py:13
msgid "DFT"
msgstr "DFT"
#: ../dft.py:19
msgid "XC-functional: "
msgstr "XC-functional: "
#: ../dft.py:23 ../repeat.py:16
msgid "Repeat atoms:"
msgstr "Repeat atoms:"
#: ../energyforces.py:11
msgid "Output:"
msgstr "Output:"
#: ../energyforces.py:41
msgid "Save output"
msgstr "Save output"
#: ../energyforces.py:57
msgid "Potential energy and forces"
msgstr "Potential energy and forces"
#: ../energyforces.py:61
msgid "Calculate potential energy and the force on all atoms"
msgstr "Calculate potential energy and the force on all atoms"
#: ../energyforces.py:65
msgid "Write forces on the atoms"
msgstr "Write forces on the atoms"
#: ../energyforces.py:82
msgid "Potential Energy:\n"
msgstr "Potential Energy:\n"
#: ../energyforces.py:83
#, python-format
msgid " %8.2f eV\n"
msgstr " %8.2f eV\n"
#: ../energyforces.py:84
#, python-format
msgid ""
" %8.4f eV/atom\n"
"\n"
msgstr ""
" %8.4f eV/atom\n"
"\n"
#: ../energyforces.py:86
msgid "Forces:\n"
msgstr "Forces:\n"
#: ../execute.py:23
msgid ""
"\n"
" Global commands work on all frames or only on the current frame\n"
" - Assignment of a global variable may not reference a local one\n"
" - use 'Current frame' switch to switch off application to all frames\n"
" e:\t\ttotal energy of one frame\n"
" fmax:\tmaximal force in one frame\n"
" A:\tunit cell\n"
" E:\t\ttotal energy array of all frames\n"
" F:\t\tall forces in one frame\n"
" M:\tall magnetic moments\n"
" R:\t\tall atomic positions\n"
" S:\tall selected atoms (boolean array)\n"
" D:\tall dynamic atoms (boolean array)\n"
" examples: frame = 1, A[0][1] += 4, e-E[-1]\n"
"\n"
" Atom commands work on each atom (or a selection) individually\n"
" - these can use global commands on the RHS of an equation\n"
" - use 'selected atoms only' to restrict application of command\n"
" x,y,z:\tatomic coordinates\n"
" r,g,b:\tatom display color, range is [0..1]\n"
" rad:\tatomic radius for display\n"
" s:\t\tatom is selected\n"
" d:\t\tatom is movable\n"
" f:\t\tforce\n"
" Z:\tatomic number\n"
" m:\tmagnetic moment\n"
" examples: x -= A[0][0], s = z > 5, Z = 6\n"
"\n"
" Special commands and objects:\n"
" sa,cf:\t(un)restrict to selected atoms/current frame\n"
" frame:\tframe number\n"
" center:\tcenters the system in its existing unit cell\n"
" del S:\tdelete selection\n"
" CM:\tcenter of mass\n"
" ans[-i]:\tith last calculated result\n"
" exec file: executes commands listed in file\n"
" cov[Z]:(read only): covalent radius of atomic number Z\n"
" gui:\tadvanced: ag window python object\n"
" img:\tadvanced: ag images object\n"
" "
msgstr ""
"\n"
" Global commands work on all frames or only on the current frame\n"
" - Assignment of a global variable may not reference a local one\n"
" - use 'Current frame' switch to switch off application to all frames\n"
" e:\t\ttotal energy of one frame\n"
" fmax:\tmaximal force in one frame\n"
" A:\tunit cell\n"
" E:\t\ttotal energy array of all frames\n"
" F:\t\tall forces in one frame\n"
" M:\tall magnetic moments\n"
" R:\t\tall atomic positions\n"
" S:\tall selected atoms (boolean array)\n"
" D:\tall dynamic atoms (boolean array)\n"
" examples: frame = 1, A[0][1] += 4, e-E[-1]\n"
"\n"
" Atom commands work on each atom (or a selection) individually\n"
" - these can use global commands on the RHS of an equation\n"
" - use 'selected atoms only' to restrict application of command\n"
" x,y,z:\tatomic coordinates\n"
" r,g,b:\tatom display colour, range is [0..1]\n"
" rad:\tatomic radius for display\n"
" s:\t\tatom is selected\n"
" d:\t\tatom is movable\n"
" f:\t\tforce\n"
" Z:\tatomic number\n"
" m:\tmagnetic moment\n"
" examples: x -= A[0][0], s = z > 5, Z = 6\n"
"\n"
" Special commands and objects:\n"
" sa,cf:\t(un)restrict to selected atoms/current frame\n"
" frame:\tframe number\n"
" center:\tcenters the system in its existing unit cell\n"
" del S:\tdelete selection\n"
" CM:\tcentre of mass\n"
" ans[-i]:\tith last calculated result\n"
" exec file: executes commands listed in file\n"
" cov[Z]:(read only): covalent radius of atomic number Z\n"
" gui:\tadvanced: ag window python object\n"
" img:\tadvanced: ag images object\n"
" "
#: ../execute.py:67
msgid "Expert user mode"
msgstr "Expert user mode"
#: ../execute.py:80
msgid "Welcome to the ASE Expert user mode"
msgstr "Welcome to the ASE Expert user mode"
#: ../execute.py:87
msgid "Only selected atoms (sa) "
msgstr "Only selected atoms (sa) "
#: ../execute.py:89
msgid "Only current frame (cf) "
msgstr "Only current frame (cf) "
#: ../execute.py:99
msgid ""
"Global: Use A, D, E, M, N, R, S, n, frame; Atoms: Use a, f, m, s, x, y, z, "
"Z "
msgstr ""
"Global: Use A, D, E, M, N, R, S, n, frame; Atoms: Use a, f, m, s, x, y, z, "
"Z "
#: ../execute.py:198
#, python-format
msgid "*** WARNING: file does not exist - %s"
msgstr "*** WARNING: file does not exist - %s"
#: ../execute.py:203
msgid "*** WARNING: No atoms selected to work with"
msgstr "*** WARNING: No atoms selected to work with"
#: ../execute.py:277
msgid "*** Only working on selected atoms"
msgstr "*** Only working on selected atoms"
#: ../execute.py:279
msgid "*** Working on all atoms"
msgstr "*** Working on all atoms"
#: ../execute.py:283
msgid "*** Only working on current image"
msgstr "*** Only working on current image"
#: ../execute.py:285
msgid "*** Working on all images"
msgstr "*** Working on all images"
#: ../execute.py:301
msgid "Save Terminal text ..."
msgstr "Save Terminal text ..."
#: ../graphene.py:15
msgid ""
"Set up a graphene sheet or a graphene nanoribbon. A nanoribbon may\n"
"optionally be saturated with hydrogen (or another element)."
msgstr ""
"Set up a graphene sheet or a graphene nanoribbon. A nanoribbon may\n"
"optionally be saturated with hydrogen (or another element)."
#: ../graphene.py:30 ../gui.py:298
msgid "Graphene"
msgstr "Graphene"
#. Choose structure
#. The structure and lattice constant
#. Choose the surface structure
#: ../graphene.py:37 ../nanoparticle.py:138 ../surfaceslab.py:78
msgid "Structure: "
msgstr "Structure: "
#: ../graphene.py:39
msgid "Infinite sheet"
msgstr "Infinite sheet"
#: ../graphene.py:39
msgid "Unsaturated ribbon"
msgstr "Unsaturated ribbon"
#: ../graphene.py:40
msgid "Saturated ribbon"
msgstr "Saturated ribbon"
#. Orientation
#: ../graphene.py:47
msgid "Orientation: "
msgstr "Orientation: "
#: ../graphene.py:50
msgid "zigzag"
msgstr "zigzag"
#: ../graphene.py:50
msgid "armchair"
msgstr "armchair"
#: ../graphene.py:66 ../graphene.py:78 ../nanotube.py:46
msgid " Bond length: "
msgstr " Bond length: "
#. Choose the saturation element and bond length
#: ../graphene.py:72
msgid "Saturation: "
msgstr "Saturation: "
#: ../graphene.py:75
msgid "H"
msgstr "H"
#. Size
#: ../graphene.py:91
msgid "Width: "
msgstr "Width: "
#: ../graphene.py:92 ../nanotube.py:65
msgid " Length: "
msgstr " Length: "
#. Vacuum
#: ../graphene.py:100
msgid "Vacuum: "
msgstr "Vacuum: "
#: ../graphene.py:138 ../nanotube.py:96 ../setupwindow.py:32
msgid " No element specified!"
msgstr " No element specified!"
#: ../graphene.py:231 ../nanoparticle.py:614 ../nanotube.py:140
#: ../pybutton.py:49 ../surfaceslab.py:249
msgid "You have not (yet) specified a consistent set of parameters."
msgstr "You have not (yet) specified a consistent set of parameters."
#: ../graphs.py:19
msgid "Help for plot ..."
msgstr "Help for plot ..."
#: ../graphs.py:30 ../graphs.py:33
msgid "Plot"
msgstr "Plot"
#: ../graphs.py:38
msgid "clear"
msgstr "clear"
#: ../graphs.py:92
msgid "Save data to file ... "
msgstr "Save data to file ... "
#: ../gtkexcepthook.py:117
msgid "Bug Detected"
msgstr "Bug Detected"
#: ../gtkexcepthook.py:121
msgid "A programming error has been detected."
msgstr "A programming error has been detected."
#: ../gtkexcepthook.py:124
msgid ""
"It probably isn't fatal, but the details should be reported to the "
"developers nonetheless."
msgstr ""
"It probably isn't fatal, but the details should be reported to the "
"developers nonetheless."
#: ../gtkexcepthook.py:140
msgid "Report..."
msgstr "Report..."
#: ../gtkexcepthook.py:144
msgid "Details..."
msgstr "Details..."
#: ../gtkexcepthook.py:160
#, python-format
msgid ""
"From: buggy_application\"\n"
"To: bad_programmer\n"
"Subject: Exception feedback\n"
"\n"
"%s"
msgstr ""
"From: buggy_application\"\n"
"To: bad_programmer\n"
"Subject: Exception feedback\n"
"\n"
"%s"
#. Show details...
#: ../gtkexcepthook.py:173
msgid "Bug Details"
msgstr "Bug Details"
#: ../gui.py:164
msgid "_File"
msgstr "_File"
#: ../gui.py:165
msgid "_Edit"
msgstr "_Edit"
#: ../gui.py:166
msgid "_View"
msgstr "_View"
#: ../gui.py:167
msgid "_Tools"
msgstr "_Tools"
#. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
#: ../gui.py:169
msgid "_Setup"
msgstr "_Setup"
#: ../gui.py:170
msgid "_Calculate"
msgstr "_Calculate"
#: ../gui.py:171
msgid "_Help"
msgstr "_Help"
#: ../gui.py:172
msgid "_Open"
msgstr "_Open"
#: ../gui.py:173
msgid "Create a new file"
msgstr "Create a new file"
#: ../gui.py:175
msgid "_New"
msgstr "_New"
#: ../gui.py:176
msgid "New ase.gui window"
msgstr "New ase.gui window"
#: ../gui.py:178
msgid "_Save"
msgstr "_Save"
#: ../gui.py:179
msgid "Save current file"
msgstr "Save current file"
#: ../gui.py:181
msgid "_Quit"
msgstr "_Quit"
#: ../gui.py:182
msgid "Quit"
msgstr "Quit"
#: ../gui.py:184
msgid "Select _all"
msgstr "Select _all"
#: ../gui.py:187
msgid "_Invert selection"
msgstr "_Invert selection"
#: ../gui.py:190
msgid "Select _constrained atoms"
msgstr "Select _constrained atoms"
#: ../gui.py:193
msgid "Select _immobile atoms"
msgstr "Select _immobile atoms"
#: ../gui.py:196
msgid "_Copy"
msgstr "_Copy"
#: ../gui.py:197
msgid "Copy current selection and its orientation to clipboard"
msgstr "Copy current selection and its orientation to clipboard"
#: ../gui.py:199
msgid "_Paste"
msgstr "_Paste"
#: ../gui.py:200
msgid "Insert current clipboard selection"
msgstr "Insert current clipboard selection"
#: ../gui.py:202
msgid "_Modify"
msgstr "_Modify"
#: ../gui.py:203
msgid "Change tags, moments and atom types of the selected atoms"
msgstr "Change tags, moments and atom types of the selected atoms"
#: ../gui.py:205
msgid "_Add atoms"
msgstr "_Add atoms"
#: ../gui.py:206
msgid "Insert or import atoms and molecules"
msgstr "Insert or import atoms and molecules"
#: ../gui.py:208
msgid "_Delete selected atoms"
msgstr "_Delete selected atoms"
#: ../gui.py:209
msgid "Delete the selected atoms"
msgstr "Delete the selected atoms"
#: ../gui.py:211
msgid "_First image"
msgstr "_First image"
#: ../gui.py:214
msgid "_Previous image"
msgstr "_Previous image"
#: ../gui.py:217
msgid "_Next image"
msgstr "_Next image"
#: ../gui.py:220
msgid "_Last image"
msgstr "_Last image"
#: ../gui.py:223
msgid "Quick Info ..."
msgstr "Quick Info ..."
#: ../gui.py:226
msgid "Repeat ..."
msgstr "Repeat ..."
#: ../gui.py:229
msgid "Rotate ..."
msgstr "Rotate ..."
#: ../gui.py:232
msgid "Colors ..."
msgstr "Colours ..."
#. TRANSLATORS: verb
#: ../gui.py:235
msgid "Focus"
msgstr "Focus"
#: ../gui.py:238
msgid "Zoom in"
msgstr "Zoom in"
#: ../gui.py:241
msgid "Zoom out"
msgstr "Zoom out"
#: ../gui.py:244
msgid "Reset View"
msgstr "Reset View"
#: ../gui.py:247
msgid "Settings ..."
msgstr "Settings ..."
#: ../gui.py:250
msgid "VMD"
msgstr "VMD"
#: ../gui.py:253
msgid "RasMol"
msgstr "RasMol"
#: ../gui.py:256
msgid "xmakemol"
msgstr "xmakemol"
#: ../gui.py:259
msgid "avogadro"
msgstr "avogadro"
#: ../gui.py:262
msgid "Graphs ..."
msgstr "Graphs ..."
#: ../gui.py:265
msgid "Movie ..."
msgstr "Movie ..."
#: ../gui.py:268
msgid "Expert mode ..."
msgstr "Expert mode ..."
#: ../gui.py:271
msgid "Constraints ..."
msgstr "Constraints ..."
#: ../gui.py:274
msgid "Render scene ..."
msgstr "Render scene ..."
#: ../gui.py:277
msgid "DFT ..."
msgstr "DFT ..."
#: ../gui.py:280
msgid "NE_B"
msgstr "NE_B"
#: ../gui.py:283
msgid "B_ulk Modulus"
msgstr "B_ulk Modulus"
#: ../gui.py:286
msgid "_Bulk Crystal"
msgstr "_Bulk Crystal"
#: ../gui.py:287
msgid "Create a bulk crystal with arbitrary orientation"
msgstr "Create a bulk crystal with arbitrary orientation"
#: ../gui.py:289
msgid "_Surface slab"
msgstr "_Surface slab"
#: ../gui.py:290
msgid "Create the most common surfaces"
msgstr "Create the most common surfaces"
#: ../gui.py:292
msgid "_Nanoparticle"
msgstr "_Nanoparticle"
#: ../gui.py:293
msgid "Create a crystalline nanoparticle"
msgstr "Create a crystalline nanoparticle"
#: ../gui.py:295
msgid "Nano_tube"
msgstr "Nano_tube"
#: ../gui.py:296
msgid "Create a nanotube"
msgstr "Create a nanotube"
#: ../gui.py:299
msgid "Create a graphene sheet or nanoribbon"
msgstr "Create a graphene sheet or nanoribbon"
#: ../gui.py:301
msgid "Set _Calculator"
msgstr "Set _Calculator"
#: ../gui.py:302
msgid "Set a calculator used in all calculation modules"
msgstr "Set a calculator used in all calculation modules"
#: ../gui.py:304
msgid "_Energy and Forces"
msgstr "_Energy and Forces"
#: ../gui.py:305
msgid "Calculate energy and forces"
msgstr "Calculate energy and forces"
#: ../gui.py:307
msgid "Energy _Minimization"
msgstr "Energy _Minimisation"
#: ../gui.py:308
msgid "Minimize the energy"
msgstr "Minimise the energy"
#: ../gui.py:310
msgid "Scale system"
msgstr "Scale system"
#: ../gui.py:311
msgid "Deform system by scaling it"
msgstr "Deform system by scaling it"
#: ../gui.py:313
msgid "_About"
msgstr "_About"
#: ../gui.py:316
msgid "Webpage ..."
msgstr "Webpage ..."
#: ../gui.py:317
msgid "Debug ..."
msgstr "Debug ..."
#: ../gui.py:319
msgid "Show _unit cell"
msgstr "Show _unit cell"
#: ../gui.py:323
msgid "Show _axes"
msgstr "Show _axes"
#: ../gui.py:327
msgid "Show _bonds"
msgstr "Show _bonds"
#: ../gui.py:331
msgid "_Move atoms"
msgstr "_Move atoms"
#: ../gui.py:335
msgid "_Rotate atoms"
msgstr "_Rotate atoms"
#: ../gui.py:339
msgid "Orien_t atoms"
msgstr "Orien_t atoms"
#: ../gui.py:351
#, python-format
msgid "building menus failed: %s"
msgstr "building menus failed: %s"
#: ../gui.py:620 ../gui.py:1016 ../gui.py:1076
msgid "Open ..."
msgstr "Open ..."
#: ../gui.py:624 ../gui.py:1019
msgid "<>"
msgstr "<>"
#: ../gui.py:756
msgid "Add atoms"
msgstr "Add atoms"
#: ../gui.py:759
msgid "Paste"
msgstr "Paste"
#: ../gui.py:765
msgid "Insert atom or molecule"
msgstr "Insert atom or molecule"
#: ../gui.py:766 ../gui.py:883
msgid "Tag"
msgstr "Tag"
#: ../gui.py:767 ../gui.py:884
msgid "Moment"
msgstr "Moment"
#: ../gui.py:768
msgid "Position"
msgstr "Position"
#: ../gui.py:793
msgid "_Load molecule"
msgstr "_Load molecule"
#: ../gui.py:797 ../gui.py:899
msgid "_OK"
msgstr "_OK"
#: ../gui.py:801 ../gui.py:903
msgid "_Cancel"
msgstr "_Cancel"
#: ../gui.py:876
msgid "Modify"
msgstr "Modify"
#: ../gui.py:882
msgid "Atom"
msgstr "Atom"
#: ../gui.py:927
msgid "Confirmation"
msgstr "Confirmation"
#: ../gui.py:931
msgid "Delete selected atom?"
msgid_plural "Delete selected atoms?"
msgstr[0] "Delete selected atom?"
msgstr[1] "Delete selected atoms?"
#: ../gui.py:938
msgid "Cancel"
msgstr "Cancel"
#: ../gui.py:1024 ../gui.py:1106
msgid "Automatic"
msgstr "Automatic"
#: ../gui.py:1025
msgid "Dacapo netCDF output file"
msgstr "Dacapo netCDF output file"
#: ../gui.py:1026
msgid "Virtual Nano Lab file"
msgstr "Virtual Nano Lab file"
#: ../gui.py:1027
msgid "ASE pickle trajectory"
msgstr "ASE pickle trajectory"
#: ../gui.py:1028 ../gui.py:1119
msgid "ASE bundle trajectory"
msgstr "ASE bundle trajectory"
#: ../gui.py:1029
msgid "GPAW text output"
msgstr "GPAW text output"
#: ../gui.py:1030
msgid "CUBE file"
msgstr "CUBE file"
#: ../gui.py:1031
msgid "XCrySDen Structure File"
msgstr "XCrySDen Structure File"
#: ../gui.py:1032
msgid "Dacapo text output"
msgstr "Dacapo text output"
#: ../gui.py:1033
msgid "XYZ-file"
msgstr "XYZ-file"
#: ../gui.py:1034
msgid "VASP POSCAR/CONTCAR file"
msgstr "VASP POSCAR/CONTCAR file"
#: ../gui.py:1035
msgid "VASP OUTCAR file"
msgstr "VASP OUTCAR file"
#: ../gui.py:1036
msgid "Protein Data Bank"
msgstr "Protein Data Bank"
#: ../gui.py:1037
msgid "CIF-file"
msgstr "CIF-file"
#: ../gui.py:1038
msgid "FHI-aims geometry file"
msgstr "FHI-aims geometry file"
#: ../gui.py:1039
msgid "FHI-aims output file"
msgstr "FHI-aims output file"
#: ../gui.py:1040
msgid "TURBOMOLE coord file"
msgstr "TURBOMOLE coord file"
#: ../gui.py:1041
msgid "exciting input"
msgstr "exciting input"
#: ../gui.py:1042
msgid "WIEN2k structure file"
msgstr "WIEN2k structure file"
#: ../gui.py:1043
msgid "DftbPlus input file"
msgstr "DftbPlus input file"
#: ../gui.py:1044
msgid "ETSF format"
msgstr "ETSF format"
#: ../gui.py:1045 ../gui.py:1117
msgid "CASTEP geom file"
msgstr "CASTEP geom file"
#: ../gui.py:1046
msgid "CASTEP output file"
msgstr "CASTEP output file"
#: ../gui.py:1047
msgid "CASTEP trajectory file"
msgstr "CASTEP trajectory file"
#: ../gui.py:1048
msgid "DFTBPlus GEN format"
msgstr "DFTBPlus GEN format"
#: ../gui.py:1054
msgid "File type:"
msgstr "File type:"
#: ../gui.py:1094
msgid "Save ..."
msgstr "Save ..."
#: ../gui.py:1107
msgid "XYZ file"
msgstr "XYZ file"
#: ../gui.py:1108
msgid "ASE trajectory"
msgstr "ASE trajectory"
#: ../gui.py:1109
msgid "PDB file"
msgstr "PDB file"
#: ../gui.py:1110
msgid "Gaussian cube file"
msgstr "Gaussian cube file"
#: ../gui.py:1111
msgid "Python script"
msgstr "Python script"
#: ../gui.py:1112
msgid "VNL file"
msgstr "VNL file"
#: ../gui.py:1113
msgid "Portable Network Graphics"
msgstr "Portable Network Graphics"
#: ../gui.py:1114
msgid "Persistence of Vision"
msgstr "Persistence of Vision"
#: ../gui.py:1115
msgid "Encapsulated PostScript"
msgstr "Encapsulated PostScript"
#: ../gui.py:1116
msgid "FHI-aims geometry input"
msgstr "FHI-aims geometry input"
#: ../gui.py:1118
msgid "VASP geometry input"
msgstr "VASP geometry input"
#: ../gui.py:1120
msgid "cif file"
msgstr "cif file"
#: ../gui.py:1142
#, python-format
msgid "Save current image only (#%d)"
msgstr "Save current image only (#%d)"
#: ../gui.py:1146
msgid "Slice: "
msgstr "Slice: "
#: ../gui.py:1147
msgid "Help for slice ..."
msgstr "Help for slice ..."
#: ../gui.py:1159
msgid "AG INTERNAL ERROR: strange response in Save,"
msgstr "AG INTERNAL ERROR: strange response in Save,"
#: ../gui.py:1178
msgid "Unknown output format!"
msgstr "Unknown output format!"
#: ../gui.py:1179
#, python-format
msgid "Use one of: %s"
msgstr "Use one of: %s"
#: ../gui.py:1284
msgid "Not implemented!"
msgstr "Not implemented!"
#: ../gui.py:1285
msgid "do you really need it?"
msgstr "do you really need it?"
#: ../minimize.py:20
msgid "Algorithm: "
msgstr "Algorithm: "
#: ../minimize.py:25 ../progress.py:67
msgid "Convergence criterion: Fmax = "
msgstr "Convergence criterion: Fmax = "
#: ../minimize.py:30 ../progress.py:70
msgid "Max. number of steps: "
msgstr "Max. number of steps: "
#. Special stuff for MDMin
#: ../minimize.py:33
msgid "Pseudo time step: "
msgstr "Pseudo time step: "
#: ../minimize.py:54
msgid "Energy minimization"
msgstr "Energy minimisation"
#: ../minimize.py:58
msgid "Minimize the energy with respect to the positions."
msgstr "Minimise the energy with respect to the positions."
#. Don't catch errors in the function.
#. Display status message
#: ../minimize.py:90 ../scaling.py:299
msgid "Running ..."
msgstr "Running ..."
#. Update display to reflect cancellation of simulation.
#: ../minimize.py:107
#, python-format
msgid "Minimization CANCELLED after %i steps."
msgstr "Minimisation CANCELLED after %i steps."
#: ../minimize.py:113 ../scaling.py:350
msgid "Out of memory, consider using LBFGS instead"
msgstr "Out of memory, consider using LBFGS instead"
#. Update display to reflect succesful end of simulation.
#: ../minimize.py:120
#, python-format
msgid "Minimization completed in %i steps."
msgstr "Minimisation completed in %i steps."
#. self.connect('delete_event', self.exit2)
#: ../movie.py:14
msgid "Movie"
msgstr "Movie"
#: ../movie.py:16
msgid "Image number:"
msgstr "Image number:"
#: ../movie.py:38
msgid "Play"
msgstr "Play"
#: ../movie.py:40
msgid "Stop"
msgstr "Stop"
#. TRANSLATORS: This function plays an animation forwards and backwards
#. alternatingly, e.g. for displaying vibrational movement
#: ../movie.py:44
msgid "Rock"
msgstr "Rock"
#: ../movie.py:60
msgid " Frame rate: "
msgstr " Frame rate: "
#: ../movie.py:61
msgid " Skip frames: "
msgstr " Skip frames: "
#: ../nanoparticle.py:19
msgid ""
"Create a nanoparticle either by specifying the number of layers, or using "
"the\n"
"Wulff construction. Please press the [Help] button for instructions on how "
"to\n"
"specify the directions.\n"
"WARNING: The Wulff construction currently only works with cubic crystals!\n"
msgstr ""
"Create a nanoparticle either by specifying the number of layers, or using "
"the\n"
"Wulff construction. Please press the [Help] button for instructions on how "
"to\n"
"specify the directions.\n"
"WARNING: The Wulff construction currently only works with cubic crystals!\n"
#: ../nanoparticle.py:26
msgid ""
"\n"
"The nanoparticle module sets up a nano-particle or a cluster with a given\n"
"crystal structure.\n"
"\n"
"1) Select the element, the crystal structure and the lattice constant(s).\n"
" The [Get structure] button will find the data for a given element.\n"
"\n"
"2) Choose if you want to specify the number of layers in each direction, or "
"if\n"
" you want to use the Wulff construction. In the latter case, you must "
"specify\n"
" surface energies in each direction, and the size of the cluster.\n"
"\n"
"How to specify the directions:\n"
"------------------------------\n"
"\n"
"First time a direction appears, it is interpreted as the entire family of\n"
"directions, i.e. (0,0,1) also covers (1,0,0), (-1,0,0) etc. If one of "
"these\n"
"directions is specified again, the second specification overrules that "
"specific\n"
"direction. For this reason, the order matters and you can rearrange the\n"
"directions with the [Up] and [Down] keys. You can also add a new "
"direction,\n"
"remember to press [Add] or it will not be included.\n"
"\n"
"Example: (1,0,0) (1,1,1), (0,0,1) would specify the {100} family of "
"directions,\n"
"the {111} family and then the (001) direction, overruling the value given "
"for\n"
"the whole family of directions.\n"
msgstr ""
"\n"
"The nanoparticle module sets up a nano-particle or a cluster with a given\n"
"crystal structure.\n"
"\n"
"1) Select the element, the crystal structure and the lattice constant(s).\n"
" The [Get structure] button will find the data for a given element.\n"
"\n"
"2) Choose if you want to specify the number of layers in each direction, or "
"if\n"
" you want to use the Wulff construction. In the latter case, you must "
"specify\n"
" surface energies in each direction, and the size of the cluster.\n"
"\n"
"How to specify the directions:\n"
"------------------------------\n"
"\n"
"First time a direction appears, it is interpreted as the entire family of\n"
"directions, i.e. (0,0,1) also covers (1,0,0), (-1,0,0) etc. If one of "
"these\n"
"directions is specified again, the second specification overrules that "
"specific\n"
"direction. For this reason, the order matters and you can rearrange the\n"
"directions with the [Up] and [Down] keys. You can also add a new "
"direction,\n"
"remember to press [Add] or it will not be included.\n"
"\n"
"Example: (1,0,0) (1,1,1), (0,0,1) would specify the {100} family of "
"directions,\n"
"the {111} family and then the (001) direction, overruling the value given "
"for\n"
"the whole family of directions.\n"
#. Structures: Abbreviation, name, 4-index (boolean), two lattice const (bool), factory
#: ../nanoparticle.py:83
msgid "Face centered cubic (fcc)"
msgstr "Face centered cubic (fcc)"
#: ../nanoparticle.py:84
msgid "Body centered cubic (bcc)"
msgstr "Body centered cubic (bcc)"
#: ../nanoparticle.py:85
msgid "Simple cubic (sc)"
msgstr "Simple cubic (sc)"
#: ../nanoparticle.py:86
msgid "Hexagonal closed-packed (hcp)"
msgstr "Hexagonal closed-packed (hcp)"
#: ../nanoparticle.py:87
msgid "Graphite"
msgstr "Graphite"
#: ../nanoparticle.py:116
msgid "Nanoparticle"
msgstr "Nanoparticle"
#. Choose the element
#. Choose the element and bond length
#. Choose the element
#: ../nanoparticle.py:126 ../nanotube.py:40 ../surfaceslab.py:69
msgid "Element: "
msgstr "Element: "
#: ../nanoparticle.py:130
msgid "Get structure"
msgstr "Get structure"
#: ../nanoparticle.py:154
msgid "Lattice constant: a ="
msgstr "Lattice constant: a ="
#. Choose specification method
#: ../nanoparticle.py:171
msgid "Method: "
msgstr "Method: "
#: ../nanoparticle.py:173
msgid "Layer specification"
msgstr "Layer specification"
#: ../nanoparticle.py:173
msgid "Wulff construction"
msgstr "Wulff construction"
#: ../nanoparticle.py:193
msgid "Dummy placeholder object"
msgstr "Dummy placeholder object"
#: ../nanoparticle.py:195
msgid "Add new direction:"
msgstr "Add new direction:"
#: ../nanoparticle.py:211
msgid "Add"
msgstr "Add"
#: ../nanoparticle.py:219
msgid "Set all directions to default values"
msgstr "Set all directions to default values"
#: ../nanoparticle.py:227
msgid "Particle size: "
msgstr "Particle size: "
#: ../nanoparticle.py:228 ../nanoparticle.py:265 ../progress.py:196
msgid "Number of atoms: "
msgstr "Number of atoms: "
#: ../nanoparticle.py:233
msgid "Volume: "
msgstr "Volume: "
#: ../nanoparticle.py:238
msgid "ų"
msgstr "ų"
#: ../nanoparticle.py:243
msgid "Rounding: If exact size is not possible, choose the size"
msgstr "Rounding: If exact size is not possible, choose the size"
#: ../nanoparticle.py:246
msgid "above "
msgstr "above "
#: ../nanoparticle.py:247
msgid "below "
msgstr "below "
#: ../nanoparticle.py:248
msgid "closest "
msgstr "closest "
#: ../nanoparticle.py:251
msgid "Smaller"
msgstr "Smaller"
#: ../nanoparticle.py:252
msgid "Larger"
msgstr "Larger"
#: ../nanoparticle.py:267
msgid " Approx. diameter: "
msgstr " Approx. diameter: "
#: ../nanoparticle.py:271
msgid "Information about the created cluster:"
msgstr "Information about the created cluster:"
#. Buttons
#: ../nanoparticle.py:277 ../nanotube.py:75
msgid "Creating a nanoparticle."
msgstr "Creating a nanoparticle."
#: ../nanoparticle.py:284
msgid "Automatic Apply"
msgstr "Automatic Apply"
#: ../nanoparticle.py:332
msgid "Up"
msgstr "Up"
#: ../nanoparticle.py:337
msgid "Down"
msgstr "Down"
#: ../nanoparticle.py:342
msgid "Delete"
msgstr "Delete"
#: ../nanoparticle.py:383
msgid "Surface energies (as energy/area, NOT per atom):"
msgstr "Surface energies (as energy/area, NOT per atom):"
#: ../nanoparticle.py:389
msgid "Number of layers:"
msgstr "Number of layers:"
#: ../nanoparticle.py:418
msgid "At least one index must be non-zero"
msgstr "At least one index must be non-zero"
#: ../nanoparticle.py:421
msgid "Invalid hexagonal indices"
msgstr "Invalid hexagonal indices"
#: ../nanoparticle.py:476 ../surfaceslab.py:218
msgid "Invalid element."
msgstr "Invalid element."
#: ../nanoparticle.py:486
msgid "Unsupported or unknown structure"
msgstr "Unsupported or unknown structure"
#: ../nanoparticle.py:603
#, python-format
msgid "%.1f Ã…"
msgstr "%.1f Ã…"
#: ../nanotube.py:14
msgid ""
"Set up a Carbon nanotube by specifying the (n,m) roll-up vector.\n"
"Please note that m <= n.\n"
"\n"
"Nanotubes of other elements can be made by specifying the element\n"
"and bond length."
msgstr ""
"Set up a Carbon nanotube by specifying the (n,m) roll-up vector.\n"
"Please note that m <= n.\n"
"\n"
"Nanotubes of other elements can be made by specifying the element\n"
"and bond length."
#: ../nanotube.py:33
msgid "Nanotube"
msgstr "Nanotube"
#. Choose the structure.
#: ../nanotube.py:57
msgid "Select roll-up vector (n,m) and tube length:"
msgstr "Select roll-up vector (n,m) and tube length:"
#: ../progress.py:25
msgid "Progress"
msgstr "Progress"
#: ../progress.py:32
msgid "Scaling deformation:"
msgstr "Scaling deformation:"
#: ../progress.py:38
#, python-format
msgid "Step number %s of %s."
msgstr "Step number %s of %s."
#. Minimization progress frame
#. Box containing frame and spacing
#: ../progress.py:53
msgid "Energy minimization:"
msgstr "Energy minimisation:"
#: ../progress.py:60
msgid "Step number: "
msgstr "Step number: "
#: ../progress.py:62
msgid "Fmax: "
msgstr "Fmax: "
#: ../progress.py:102
msgid "unknown"
msgstr "unknown"
#: ../progress.py:179
msgid "Status: "
msgstr "Status: "
#: ../progress.py:181
msgid "Iteration: "
msgstr "Iteration: "
#: ../progress.py:184
msgid "log10(change):"
msgstr "log10(change):"
#: ../progress.py:187
msgid "Wave functions: "
msgstr "Wave functions: "
#: ../progress.py:189
msgid "Density: "
msgstr "Density: "
#: ../progress.py:191
msgid "Energy: "
msgstr "Energy: "
#: ../progress.py:194
msgid "GPAW version: "
msgstr "GPAW version: "
#: ../progress.py:197
msgid "N/A"
msgstr "N/A"
#: ../progress.py:198
msgid "Memory estimate: "
msgstr "Memory estimate: "
#: ../progress.py:233
msgid "No info"
msgstr "No info"
#: ../progress.py:243
msgid "Initializing"
msgstr "Initializing"
#: ../progress.py:244
msgid "Positions:"
msgstr "Positions:"
#: ../progress.py:248
msgid "Starting calculation"
msgstr "Starting calculation"
#: ../progress.py:285
msgid "unchanged"
msgstr "unchanged"
#: ../progress.py:295
msgid "Self-consistency loop"
msgstr "Self-consistency loop"
#: ../progress.py:300
msgid "Calculating forces"
msgstr "Calculating forces"
#: ../progress.py:301
msgid " (converged)"
msgstr " (converged)"
#: ../pybutton.py:37
msgid "Python"
msgstr "Python"
#: ../pybutton.py:48
msgid "No Python code"
msgstr "No Python code"
#: ../pybutton.py:52
#, python-format
msgid ""
"\n"
"Title: %(title)s\n"
"Time: %(time)s\n"
msgstr ""
"\n"
"Title: %(title)s\n"
"Time: %(time)s\n"
#: ../pybutton.py:61
msgid "ag: Python code"
msgstr "ag: Python code"
#: ../pybutton.py:65
msgid "Information:"
msgstr "Information:"
#: ../pybutton.py:72
msgid "Python code:"
msgstr "Python code:"
#: ../quickinfo.py:9
msgid "Single image loaded."
msgstr "Single image loaded."
#: ../quickinfo.py:10
#, python-format
msgid "Image %d loaded (0 - %d)."
msgstr "Image %d loaded (0 - %d)."
#: ../quickinfo.py:11
msgid "Unit cell is fixed."
msgstr "Unit cell is fixed."
#: ../quickinfo.py:12
msgid "Unit cell varies."
msgstr "Unit cell varies."
#: ../quickinfo.py:14
#, python-format
msgid ""
"%s\n"
"\n"
"Number of atoms: %d.\n"
"\n"
"Unit cell:\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
"%s\n"
msgstr ""
"%s\n"
"\n"
"Number of atoms: %d.\n"
"\n"
"Unit cell:\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
"%s\n"
#: ../quickinfo.py:29
msgid "Quick Info"
msgstr "Quick Info"
#: ../quickinfo.py:33
msgid "No atoms loaded."
msgstr "No atoms loaded."
#: ../render.py:14
msgid ""
" Textures can be used to highlight different parts of\n"
" an atomic structure. This window applies the default\n"
" texture to the entire structure and optionally\n"
" applies a different texture to subsets of atoms that\n"
" can be selected using the mouse.\n"
" An alternative selection method is based on a boolean\n"
" expression in the entry box provided, using the\n"
" variables x, y, z, or Z. For example, the expression\n"
" Z == 11 and x > 10 and y > 10 \n"
" will mark all sodium atoms with x or coordinates \n"
" larger than 10. In either case, the button labeled\n"
" `Create new texture from selection` will enable\n"
" to change the attributes of the current selection. \n"
" "
msgstr ""
" Textures can be used to highlight different parts of\n"
" an atomic structure. This window applies the default\n"
" texture to the entire structure and optionally\n"
" applies a different texture to subsets of atoms that\n"
" can be selected using the mouse.\n"
" An alternative selection method is based on a boolean\n"
" expression in the entry box provided, using the\n"
" variables x, y, z, or Z. For example, the expression\n"
" Z == 11 and x > 10 and y > 10 \n"
" will mark all sodium atoms with x or coordinates \n"
" larger than 10. In either case, the button labeled\n"
" `Create new texture from selection` will enable\n"
" to change the attributes of the current selection. \n"
" "
#: ../render.py:32
msgid "Render current view in povray ... "
msgstr "Render current view in povray ... "
#: ../render.py:36
#, python-format
msgid "Rendering %d atoms."
msgstr "Rendering %d atoms."
#: ../render.py:41
msgid "Render constraints"
msgstr "Render constraints"
#: ../render.py:44
msgid "Width"
msgstr "Width"
#: ../render.py:45
msgid " Height"
msgstr " Height"
#: ../render.py:52
msgid "Render unit cell"
msgstr "Render unit cell"
#: ../render.py:61
msgid "Line width"
msgstr "Line width"
#: ../render.py:63
msgid "Angstrom "
msgstr "Angstrom "
#: ../render.py:73
msgid "Set"
msgstr "Set"
#: ../render.py:75
msgid "Output basename: "
msgstr "Output basename: "
#: ../render.py:77
msgid " Filename: "
msgstr " Filename: "
#: ../render.py:88
msgid " Default texture for atoms: "
msgstr " Default texture for atoms: "
#: ../render.py:89
msgid " transparency: "
msgstr " transparency: "
#: ../render.py:90
msgid "Define atom selection for new texture:"
msgstr "Define atom selection for new texture:"
#: ../render.py:92
msgid "Select"
msgstr "Select"
#: ../render.py:96
msgid "Create new texture from selection"
msgstr "Create new texture from selection"
#: ../render.py:98
msgid "Help on textures"
msgstr "Help on textures"
#: ../render.py:111
msgid "Camera type: "
msgstr "Camera type: "
#: ../render.py:112
msgid " Camera distance"
msgstr " Camera distance"
#: ../render.py:113
msgid "Render current frame"
msgstr "Render current frame"
#: ../render.py:117
#, python-format
msgid "Render all %d frames"
msgstr "Render all %d frames"
#: ../render.py:122
msgid "Transparent background"
msgstr "Transparent background"
#: ../render.py:125
msgid "Run povray "
msgstr "Run povray "
#: ../render.py:128
msgid "Keep povray files "
msgstr "Keep povray files "
#: ../render.py:131
msgid "Show output window"
msgstr "Show output window"
#: ../render.py:212
msgid " transparency: "
msgstr " transparency: "
#: ../render.py:218
msgid ""
"Can not create new texture! Must have some atoms selected to create a new "
"material!"
msgstr ""
"Can not create new texture! Must have some atoms selected to create a new "
"material!"
#: ../repeat.py:14
msgid "Repeat"
msgstr "Repeat"
#: ../repeat.py:21
msgid "Set unit cell"
msgstr "Set unit cell"
#: ../rotate.py:15
msgid "Rotate"
msgstr "Rotate"
#: ../rotate.py:17
msgid "Rotation angles:"
msgstr "Rotation angles:"
#: ../rotate.py:27
msgid ""
"Note:\n"
"You can rotate freely\n"
"with the mouse, by holding\n"
"down mouse button 2."
msgstr ""
"Note:\n"
"You can rotate freely\n"
"with the mouse, by holding\n"
"down mouse button 2."
#: ../scaling.py:49
msgid "Homogeneous scaling"
msgstr "Homogeneous scaling"
#: ../scaling.py:59
msgid "3D deformation "
msgstr "3D deformation "
#: ../scaling.py:60
msgid "2D deformation "
msgstr "2D deformation "
#: ../scaling.py:61
msgid "1D deformation "
msgstr "1D deformation "
#: ../scaling.py:64
msgid "Bulk"
msgstr "Bulk"
#: ../scaling.py:66
msgid "xy-plane"
msgstr "xy-plane"
#: ../scaling.py:68
msgid "xz-plane"
msgstr "xz-plane"
#: ../scaling.py:70
msgid "yz-plane"
msgstr "yz-plane"
#: ../scaling.py:72
msgid "x-axis"
msgstr "x-axis"
#: ../scaling.py:74
msgid "y-axis"
msgstr "y-axis"
#: ../scaling.py:76
msgid "z-axis"
msgstr "z-axis"
#: ../scaling.py:89
msgid "Allow deformation along non-periodic directions."
msgstr "Allow deformation along non-periodic directions."
#. Parameters for the deformation
#: ../scaling.py:94
msgid "Deformation:"
msgstr "Deformation:"
#: ../scaling.py:100
msgid "Maximal scale factor: "
msgstr "Maximal scale factor: "
#: ../scaling.py:103
msgid "Scale offset: "
msgstr "Scale offset: "
#: ../scaling.py:106
msgid "Number of steps: "
msgstr "Number of steps: "
#: ../scaling.py:107
msgid "Only positive deformation"
msgstr "Only positive deformation"
#. Atomic relaxations
#: ../scaling.py:112
msgid "Atomic relaxations:"
msgstr "Atomic relaxations:"
#: ../scaling.py:116
msgid "On "
msgstr "On "
#: ../scaling.py:117
msgid "Off"
msgstr "Off"
#. Results
#: ../scaling.py:128
msgid "Results:"
msgstr "Results:"
#: ../scaling.py:130
msgid "Keep original configuration"
msgstr "Keep original configuration"
#: ../scaling.py:132
msgid "Load optimal configuration"
msgstr "Load optimal configuration"
#: ../scaling.py:134
msgid "Load all configurations"
msgstr "Load all configurations"
#: ../scaling.py:143
msgid "Strain\t\tEnergy [eV]"
msgstr "Strain\t\tEnergy [eV]"
#: ../scaling.py:144
msgid "Fit:"
msgstr "Fit:"
#: ../scaling.py:148
msgid "2nd"
msgstr "2nd"
#: ../scaling.py:149
msgid "3rd"
msgstr "3rd"
#: ../scaling.py:153
msgid "Order of fit: "
msgstr "Order of fit: "
#. Update display to reflect cancellation of simulation.
#: ../scaling.py:346
msgid "Calculation CANCELLED."
msgstr "Calculation CANCELLED."
#. Update display to reflect succesful end of simulation.
#: ../scaling.py:357
msgid "Calculation completed."
msgstr "Calculation completed."
#: ../scaling.py:380
msgid "No trustworthy minimum: Old configuration kept."
msgstr "No trustworthy minimum: Old configuration kept."
#: ../scaling.py:420
#, python-format
msgid ""
"Insufficent data for a fit\n"
"(only %i data points)\n"
msgstr ""
"Insufficent data for a fit\n"
"(only %i data points)\n"
#: ../scaling.py:424
msgid ""
"REVERTING TO 2ND ORDER FIT\n"
"(only 3 data points)\n"
"\n"
msgstr ""
"REVERTING TO 2ND ORDER FIT\n"
"(only 3 data points)\n"
"\n"
#: ../scaling.py:440
msgid "No minimum found!"
msgstr "No minimum found!"
#: ../scaling.py:454
msgid ""
"\n"
"WARNING: Minimum is outside interval\n"
msgstr ""
"\n"
"WARNING: Minimum is outside interval\n"
#: ../scaling.py:455
msgid "It is UNRELIABLE!\n"
msgstr "It is UNRELIABLE!\n"
#: ../settings.py:16
msgid "Constraints:"
msgstr "Constraints:"
#: ../settings.py:19
msgid "release"
msgstr "release"
#: ../settings.py:23
msgid "Constrain immobile atoms"
msgstr "Constrain immobile atoms"
#: ../settings.py:25
msgid "Clear all constraints"
msgstr "Clear all constraints"
#: ../settings.py:31
msgid "Visibility:"
msgstr "Visibility:"
#: ../settings.py:32
msgid "Hide"
msgstr "Hide"
#: ../settings.py:34
msgid "show"
msgstr "show"
#: ../settings.py:38
msgid "View all atoms"
msgstr "View all atoms"
#: ../settings.py:44
msgid "Miscellaneous:"
msgstr "Miscellaneous:"
#: ../settings.py:47
msgid "Scale atomic radii:"
msgstr "Scale atomic radii:"
#. A close button
#: ../settings.py:52
msgid "\n"
msgstr "\n"
#: ../setupwindow.py:51
msgid "No crystal structure data"
msgstr "No crystal structure data"
#: ../setupwindow.py:62
msgid " ERROR: Invalid element!"
msgstr " ERROR: Invalid element!"
#: ../simulation.py:24
msgid " (rerun simulation)"
msgstr " (rerun simulation)"
#: ../simulation.py:25
msgid " (continue simulation)"
msgstr " (continue simulation)"
#: ../simulation.py:27
msgid "Select starting configuration:"
msgstr "Select starting configuration:"
#: ../simulation.py:32
#, python-format
msgid "There are currently %i configurations loaded."
msgstr "There are currently %i configurations loaded."
#: ../simulation.py:36
msgid "Choose which one to use as the initial configuration"
msgstr "Choose which one to use as the initial configuration"
#: ../simulation.py:40
#, python-format
msgid "The first configuration %s."
msgstr "The first configuration %s."
#: ../simulation.py:43
msgid "Configuration number "
msgstr "Configuration number "
#: ../simulation.py:49
#, python-format
msgid "The last configuration %s."
msgstr "The last configuration %s."
#: ../simulation.py:85
msgid "Run"
msgstr "Run"
#: ../simulation.py:105
msgid "No calculator: Use Calculate/Set Calculator on the menu."
msgstr "No calculator: Use Calculate/Set Calculator on the menu."
#: ../status.py:37 ../status.py:39
msgid "Tip for status box ..."
msgstr "Tip for status box ..."
#. TRANSLATORS: mom refers to magnetic moment
#: ../status.py:63
#, python-format
msgid " tag=%(tag)s mom=%(mom)1.2f"
msgstr " tag=%(tag)s mom=%(mom)1.2f"
#: ../status.py:104
msgid "dihedral"
msgstr "dihedral"
#: ../surfaceslab.py:14
msgid ""
" Use this dialog to create surface slabs. Select the element by\n"
"writing the chemical symbol or the atomic number in the box. Then\n"
"select the desired surface structure. Note that some structures can\n"
"be created with an othogonal or a non-orthogonal unit cell, in these\n"
"cases the non-orthogonal unit cell will contain fewer atoms.\n"
"\n"
" If the structure matches the experimental crystal structure, you can\n"
"look up the lattice constant, otherwise you have to specify it\n"
"yourself."
msgstr ""
" Use this dialog to create surface slabs. Select the element by\n"
"writing the chemical symbol or the atomic number in the box. Then\n"
"select the desired surface structure. Note that some structures can\n"
"be created with an othogonal or a non-orthogonal unit cell, in these\n"
"cases the non-orthogonal unit cell will contain fewer atoms.\n"
"\n"
" If the structure matches the experimental crystal structure, you can\n"
"look up the lattice constant, otherwise you have to specify it\n"
"yourself."
#. Name, structure, orthogonal, support-nonorthogonal, function
#: ../surfaceslab.py:26
msgid "FCC(100)"
msgstr "FCC(100)"
#: ../surfaceslab.py:26 ../surfaceslab.py:27 ../surfaceslab.py:28
#: ../surfaceslab.py:30
msgid "fcc"
msgstr "fcc"
#: ../surfaceslab.py:27
msgid "FCC(110)"
msgstr "FCC(110)"
#: ../surfaceslab.py:28
msgid "FCC(111) non-orthogonal"
msgstr "FCC(111) non-orthogonal"
#: ../surfaceslab.py:30
msgid "FCC(111) orthogonal"
msgstr "FCC(111) orthogonal"
#: ../surfaceslab.py:31
msgid "BCC(100)"
msgstr "BCC(100)"
#: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:34
#: ../surfaceslab.py:35 ../surfaceslab.py:37
msgid "bcc"
msgstr "bcc"
#: ../surfaceslab.py:32
msgid "BCC(110) non-orthogonal"
msgstr "BCC(110) non-orthogonal"
#: ../surfaceslab.py:34
msgid "BCC(110) orthogonal"
msgstr "BCC(110) orthogonal"
#: ../surfaceslab.py:35
msgid "BCC(111) non-orthogonal"
msgstr "BCC(111) non-orthogonal"
#: ../surfaceslab.py:37
msgid "BCC(111) orthogonal"
msgstr "BCC(111) orthogonal"
#: ../surfaceslab.py:38
msgid "HCP(0001) non-orthogonal"
msgstr "HCP(0001) non-orthogonal"
#: ../surfaceslab.py:38 ../surfaceslab.py:40 ../surfaceslab.py:41
msgid "hcp"
msgstr "hcp"
#: ../surfaceslab.py:40
msgid "HCP(0001) orthogonal"
msgstr "HCP(0001) orthogonal"
#: ../surfaceslab.py:41
msgid "HCP(10-10) orthogonal"
msgstr "HCP(10-10) orthogonal"
#: ../surfaceslab.py:43
msgid "DIAMOND(100) orthogonal"
msgstr "DIAMOND(100) orthogonal"
#: ../surfaceslab.py:43 ../surfaceslab.py:45
msgid "diamond"
msgstr "diamond"
#: ../surfaceslab.py:45
msgid "DIAMOND(111) non-orthogonal"
msgstr "DIAMOND(111) non-orthogonal"
#: ../surfaceslab.py:60
msgid "Surface"
msgstr "Surface"
#: ../surfaceslab.py:90
msgid "Lattice constant: "
msgstr "Lattice constant: "
#: ../surfaceslab.py:97
msgid "a:"
msgstr "a:"
#: ../surfaceslab.py:109
#, python-format
msgid "(%.1f %% of ideal)"
msgstr "(%.1f %% of ideal)"
#: ../surfaceslab.py:126
msgid "Size: \tx: "
msgstr "Size: \tx: "
#: ../surfaceslab.py:128
msgid "\t\ty: "
msgstr "\t\ty: "
#: ../surfaceslab.py:130
msgid " \t\tz: "
msgstr " \t\tz: "
#: ../surfaceslab.py:131
msgid " layers, "
msgstr " layers, "
#: ../surfaceslab.py:132
msgid " Ã… vacuum"
msgstr " Ã… vacuum"
#: ../surfaceslab.py:133
msgid "\t\tNo size information yet."
msgstr "\t\tNo size information yet."
#. Buttons
#: ../surfaceslab.py:142
msgid "Creating a surface slab."
msgstr "Creating a surface slab."
#: ../surfaceslab.py:212
#, python-format
msgid "%i atoms."
msgstr "%i atoms."
#: ../surfaceslab.py:224
msgid "No structure specified!"
msgstr "No structure specified!"
#: ../surfaceslab.py:233
#, python-format
msgid "%(struct)s lattice constant unknown for %(element)s."
msgstr "%(struct)s lattice constant unknown for %(element)s."
#: ../widgets.py:53 ../widgets.py:80
msgid "Help"
msgstr "Help"
#: ../widgets.py:97
msgid "Clear constraint"
msgstr "Clear constraint"
#~ msgid " %8.3f, %8.3f, %8.3f eV/Ã…\n"
#~ msgstr " %8.3f, %8.3f, %8.3f eV/Ã…\n"
#~ msgid "%s (a=%.3f Ã…)"
#~ msgstr "%s (a=%.3f Ã…)"
#~ msgid " %s: %s, Z=%i, %s"
#~ msgstr " %s: %s, Z=%i, %s"
#~ msgid " #%d %s (%s): %.3f Ã…, %.3f Ã…, %.3f Ã… "
#~ msgstr " #%d %s (%s): %.3f Ã…, %.3f Ã…, %.3f Ã… "
#~ msgid " %s-%s: %.3f Ã…"
#~ msgstr " %s-%s: %.3f Ã…"
#~ msgid " %s-%s-%s: %.1f°, %.1f°, %.1f°"
#~ msgstr " %s-%s-%s: %.1f°, %.1f°, %.1f°"
#~ msgid "dihedral %s->%s->%s->%s: %.1f°"
#~ msgstr "dihedral %s->%s->%s->%s: %.1f°"
#~ msgid "c:"
#~ msgstr "c:"
#~ msgid "\t\t%.2f Ã… x %.2f Ã… x %.2f Ã…, %i atoms."
#~ msgstr "\t\t%.2f Ã… x %.2f Ã… x %.2f Ã…, %i atoms."
#~ msgid "FILE"
#~ msgstr "FILE"
#~ msgid "%prog [options] [file[, file2, ...]]"
#~ msgstr "%prog [options] [file[, file2, ...]]"
#~ msgid "NUMBER"
#~ msgstr "NUMBER"
#~ msgid ""
#~ "Pick image(s) from trajectory. NUMBER can be a single number (use a "
#~ "negative number to count from the back) or a range: start:stop:step, "
#~ "where the \":step\" part can be left out - default values are 0:nimages:1."
#~ msgstr ""
#~ "Pick image(s) from trajectory. NUMBER can be a single number (use a "
#~ "negative number to count from the back) or a range: start:stop:step, "
#~ "where the \":step\" part can be left out - default values are 0:nimages:1."
#~ msgid "I"
#~ msgstr "I"
#~ msgid ""
#~ "0: Don't show unit cell. 1: Show unit cell. 2: Show all of unit cell."
#~ msgstr ""
#~ "0: Don't show unit cell. 1: Show unit cell. 2: Show all of unit cell."
#~ msgid "Repeat unit cell. Use \"-r 2\" or \"-r 2,3,1\"."
#~ msgstr "Repeat unit cell. Use \"-r 2\" or \"-r 2,3,1\"."
#~ msgid "Examples: \"-R -90x\", \"-R 90z,-30x\"."
#~ msgstr "Examples: \"-R -90x\", \"-R 90z,-30x\"."
#~ msgid "Write configurations to FILE."
#~ msgstr "Write configurations to FILE."
#~ msgid "EXPR"
#~ msgstr "EXPR"
#~ msgid ""
#~ "Plot x,y1,y2,... graph from configurations or write data to sdtout in "
#~ "terminal mode. Use the symbols: i, s, d, fmax, e, ekin, A, R, E and F. "
#~ "See https://wiki.fysik.dtu.dk/ase/ase/gui.html#plotting-data for more "
#~ "details."
#~ msgstr ""
#~ "Plot x,y1,y2,... graph from configurations or write data to sdtout in "
#~ "terminal mode. Use the symbols: i, s, d, fmax, e, ekin, A, R, E and F. "
#~ "See https://wiki.fysik.dtu.dk/ase/ase/gui.html#plotting-data for more "
#~ "details."
#~ msgid "Run in terminal window - no GUI."
#~ msgstr "Run in terminal window - no GUI."
#~ msgid "Read ANEB data."
#~ msgstr "Read ANEB data."
#~ msgid "N"
#~ msgstr "N"
#~ msgid "Interpolate N images between 2 given images."
#~ msgstr "Interpolate N images between 2 given images."
#~ msgid "Draw bonds between atoms."
#~ msgstr "Draw bonds between atoms."
python-ase-3.6.0.2515/ase/gui/po/makefile 0000644 0001754 0001754 00000003543 11711330540 016652 0 ustar askhl askhl # This makefile is used to update templates for internationalization ("i18n")
# of ag.
# INSTRUCTIONS
# ------------
#
# To update existing templates with strings from the latest python files,
# just run 'make'.
#
# To create a translation template for a new language (e.g. de_DE.UTF8), run:
# LANG=de_DE.UTF8 make init
#
# List of files calling gettext.
TRANSLATIONFILES=../ag.py ../calculator.py ../colors.py ../constraints.py ../crystal.py ../debug.py ../dft.py ../energyforces.py ../execute.py ../graphene.py ../graphs.py ../gtkexcepthook.py ../gui.py ../minimize.py ../movie.py ../nanoparticle.py ../nanotube.py ../progress.py ../pybutton.py ../quickinfo.py ../render.py ../repeat.py ../rotate.py ../scaling.py ../settings.py ../setupwindow.py ../simulation.py ../status.py ../surfaceslab.py ../widgets.py
i18n: ag.pot update-po compile
# This will update the English template (ag.pot) with English messages from
# the Python source code.
ag.pot: ${TRANSLATIONFILES}
xgettext --add-comments --language=Python --keyword=_ --output=ag.pot ${TRANSLATIONFILES}
# This will create an empty translation file ($LANG.po, where $LANG is
# an environment variable) from the English template ag.pot.
# The po-file header will have to be edited afterwards.
init: ag.pot
mkdir -p ${LANG}/LC_MESSAGES
msginit --locale=${LANG} --input=ag.pot --output-file=${LANG}/LC_MESSAGES/ag.po
# This will merge new/changed English strings from the template ag.pot
# into all existing translations (*.po), maximally
# reusing the existing translations.
update-po: ag.pot
for FILE in $(wildcard */LC_MESSAGES/ag.po); do \
msgmerge --update $$FILE ag.pot ;\
done
# This will compile all translations (*.po) into binary files in gettext's
# search directory.
compile: */LC_MESSAGES/ag.po
for DIR in $(wildcard */LC_MESSAGES/); do \
msgfmt -cv --output-file=$$DIR/ag.mo $$DIR/ag.po ;\
done
python-ase-3.6.0.2515/ase/gui/po/ag.pot 0000644 0001754 0001754 00000145550 11716573517 016314 0 ustar askhl askhl # SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR , YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-14 13:35+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
#: ../ag.py:130
msgid ""
"\n"
"An exception occurred! Please report the issue to\n"
"ase-developers@listserv.fysik.dtu.dk - thanks! Please also report this if\n"
"it was a user error, so that a better error message can be provided\n"
"next time."
msgstr ""
#. Asap and GPAW may be imported if selected.
#: ../calculator.py:18
msgid ""
"To make most calculations on the atoms, a Calculator object must first\n"
"be associated with it. ASE supports a number of calculators, supporting\n"
"different elements, and implementing different physical models for the\n"
"interatomic interactions."
msgstr ""
#. Informational text about the calculators
#: ../calculator.py:26
msgid ""
"The Lennard-Jones pair potential is one of the simplest\n"
"possible models for interatomic interactions, mostly\n"
"suitable for noble gasses and model systems.\n"
"\n"
"Interactions are described by an interaction length and an\n"
"interaction strength."
msgstr ""
#: ../calculator.py:35
msgid ""
"The EMT potential is a many-body potential, giving a\n"
"good description of the late transition metals crystalling\n"
"in the FCC crystal structure. The elements described by the\n"
"main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and\n"
"Au, the Al potential is however not suitable for materials\n"
"science application, as the stacking fault energy is wrong.\n"
"\n"
"A number of parameter sets are provided.\n"
"\n"
"Default parameters:\n"
"\n"
"The default EMT parameters, as published in K. W. Jacobsen,\n"
"P. Stoltze and J. K. Nørskov, Surf. Sci. 366, 394 (1996).\n"
"\n"
"Alternative Cu, Ag and Au:\n"
"\n"
"An alternative set of parameters for Cu, Ag and Au,\n"
"reoptimized to experimental data including the stacking\n"
"fault energies by Torben Rasmussen (partly unpublished).\n"
"\n"
"Ruthenium:\n"
"\n"
"Parameters for Ruthenium, as published in J. Gavnholt and\n"
"J. Schiøtz, Phys. Rev. B 77, 035404 (2008).\n"
"\n"
"Metallic glasses:\n"
"\n"
"Parameters for MgCu and CuZr metallic glasses. MgCu\n"
"parameters are in N. P. Bailey, J. Schiøtz and\n"
"K. W. Jacobsen, Phys. Rev. B 69, 144205 (2004).\n"
"CuZr in A. Paduraru, A. Kenoufi, N. P. Bailey and\n"
"J. Schiøtz, Adv. Eng. Mater. 9, 505 (2007).\n"
msgstr ""
#: ../calculator.py:70
msgid ""
"The EMT potential is a many-body potential, giving a\n"
"good description of the late transition metals crystalling\n"
"in the FCC crystal structure. The elements described by the\n"
"main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and\n"
"Au. In addition, this implementation allows for the use of\n"
"H, N, O and C adatoms, although the description of these is\n"
"most likely not very good.\n"
"\n"
"This is the ASE implementation of EMT. For large\n"
"simulations the ASAP implementation is more suitable; this\n"
"implementation is mainly to make EMT available when ASAP is\n"
"not installed.\n"
msgstr ""
#: ../calculator.py:85
msgid ""
"The Brenner potential is a reactive bond-order potential for\n"
"carbon and hydrocarbons. As a bond-order potential, it takes\n"
"into account that carbon orbitals can hybridize in different\n"
"ways, and that carbon can form single, double and triple\n"
"bonds. That the potential is reactive means that it can\n"
"handle gradual changes in the bond order as chemical bonds\n"
"are formed or broken.\n"
"\n"
"The Brenner potential is implemented in Asap, based on a\n"
"C implentation published at http://www.rahul.net/pcm/brenner/ .\n"
"\n"
"The potential is documented here:\n"
" Donald W Brenner, Olga A Shenderova, Judith A Harrison,\n"
" Steven J Stuart, Boris Ni and Susan B Sinnott:\n"
" \"A second-generation reactive empirical bond order (REBO)\n"
" potential energy expression for hydrocarbons\",\n"
" J. Phys.: Condens. Matter 14 (2002) 783-802.\n"
" doi: 10.1088/0953-8984/14/4/312\n"
msgstr ""
#: ../calculator.py:107
msgid ""
"GPAW implements Density Functional Theory using a\n"
"Grid-based real-space representation of the wave\n"
"functions, and the Projector Augmented Wave\n"
"method for handling the core regions. \n"
msgstr ""
#: ../calculator.py:114
msgid ""
"FHI-aims is an external package implementing density \n"
"functional theory and quantum chemical methods using \n"
"all-electron methods and a numeric local orbital basis set. \n"
"For full details, see http://www.fhi-berlin.mpg.de/aims/ \n"
"or Comp. Phys. Comm. v180 2175 (2009). The ASE \n"
"documentation contains information on the keywords and \n"
"functionalities available within this interface. \n"
msgstr ""
#: ../calculator.py:124
msgid ""
"WARNING:\n"
"Your system seems to have more than zero but less than \n"
"three periodic dimensions. Please check that this is \n"
"really what you want to compute. Assuming full \n"
"3D periodicity for this calculator."
msgstr ""
#: ../calculator.py:131
msgid ""
"VASP is an external package implementing density \n"
"functional functional theory using pseudopotentials \n"
"or the projector-augmented wave method together \n"
"with a plane wave basis set. For full details, see\n"
"http://cms.mpi.univie.ac.at/vasp/vasp/\n"
msgstr ""
#: ../calculator.py:140
msgid "Default (Al, Ni, Cu, Pd, Ag, Pt, Au)"
msgstr ""
#: ../calculator.py:141
msgid "Alternative Cu, Ag and Au"
msgstr ""
#: ../calculator.py:142
msgid "Ruthenium"
msgstr ""
#: ../calculator.py:143
msgid "CuMg and CuZr metallic glass"
msgstr ""
#: ../calculator.py:158
msgid "Select calculator"
msgstr ""
#: ../calculator.py:164
msgid "Calculator:"
msgstr ""
#. No calculator (the default)
#: ../calculator.py:167
msgid "None"
msgstr ""
#: ../calculator.py:172
msgid "Lennard-Jones (ASAP)"
msgstr ""
#: ../calculator.py:173 ../calculator.py:206 ../calculator.py:215
#: ../calculator.py:224
msgid "Setup"
msgstr ""
#: ../calculator.py:180
msgid "EMT - Effective Medium Theory (ASAP)"
msgstr ""
#: ../calculator.py:192
msgid "EMT - Effective Medium Theory (ASE)"
msgstr ""
#: ../calculator.py:198
msgid "Brenner Potential (ASAP)"
msgstr ""
#: ../calculator.py:204
msgid "Density Functional Theory (GPAW)"
msgstr ""
#: ../calculator.py:213
msgid "Density Functional Theory (FHI-aims)"
msgstr ""
#: ../calculator.py:222
msgid "Density Functional Theory (VASP)"
msgstr ""
#: ../calculator.py:235
msgid "Check that the calculator is reasonable."
msgstr ""
#: ../calculator.py:298 ../simulation.py:114
msgid "No atoms present"
msgstr ""
#: ../calculator.py:388 ../calculator.py:422 ../calculator.py:456
msgid "ASAP is not installed. (Failed to import asap3)"
msgstr ""
#: ../calculator.py:391
msgid "You must set up the Lennard-Jones parameters"
msgstr ""
#: ../calculator.py:396
msgid "Could not create useful Lennard-Jones calculator."
msgstr ""
#: ../calculator.py:430
msgid "Could not attach EMT calculator to the atoms."
msgstr ""
#: ../calculator.py:472 ../calculator.py:484
msgid "GPAW is not installed. (Failed to import gpaw)"
msgstr ""
#: ../calculator.py:475
msgid "You must set up the GPAW parameters"
msgstr ""
#: ../calculator.py:516
msgid "You must set up the FHI-aims parameters"
msgstr ""
#: ../calculator.py:530
msgid "You must set up the VASP parameters"
msgstr ""
#: ../calculator.py:554
#, python-format
msgid "Element %(sym)s not allowed by the '%(name)s' calculator"
msgstr ""
#: ../calculator.py:561
msgid "Info"
msgstr ""
#: ../calculator.py:577
msgid "Lennard-Jones parameters"
msgstr ""
#: ../calculator.py:589
msgid "Specify the Lennard-Jones parameters here"
msgstr ""
#: ../calculator.py:592
msgid "Epsilon (eV):"
msgstr ""
#: ../calculator.py:596
msgid "Sigma (Ã…):"
msgstr ""
#. TRANSLATORS: Shift roughly means adjust (about a potential)
#: ../calculator.py:600
msgid "Shift to make smooth at cutoff"
msgstr ""
#: ../calculator.py:681
msgid "GPAW parameters"
msgstr ""
#. label = gtk.Label("Specify the GPAW parameters here")
#. pack(vbox, [label])
#. Print some info
#: ../calculator.py:696 ../calculator.py:985 ../calculator.py:1473
#, python-format
msgid "%i atoms.\n"
msgstr ""
#: ../calculator.py:698
#, python-format
msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Ã…."
msgstr ""
#: ../calculator.py:700
msgid "Non-orthogonal unit cell:\n"
msgstr ""
#: ../calculator.py:710 ../calculator.py:1001 ../calculator.py:1488
msgid "Exchange-correlation functional: "
msgstr ""
#. Grid spacing
#: ../calculator.py:714
msgid "Grid spacing"
msgstr ""
#: ../calculator.py:718 ../graphene.py:67 ../graphene.py:79 ../graphene.py:102
#: ../nanotube.py:47 ../surfaceslab.py:97
msgid "Ã…"
msgstr ""
#: ../calculator.py:719
msgid "Grid points"
msgstr ""
#: ../calculator.py:728
#, python-format
msgid "heff = (%.3f, %.3f, %.3f) Ã…"
msgstr ""
#: ../calculator.py:754 ../calculator.py:1016 ../calculator.py:1524
msgid "k-points k = ("
msgstr ""
#: ../calculator.py:758 ../calculator.py:1020
#, python-format
msgid "k-points x size: (%.1f, %.1f, %.1f) Ã…"
msgstr ""
#. Spin polarized
#: ../calculator.py:763 ../calculator.py:1486
msgid "Spin polarized"
msgstr ""
#: ../calculator.py:769
msgid "FD - Finite Difference (grid) mode"
msgstr ""
#: ../calculator.py:770
msgid "LCAO - Linear Combination of Atomic Orbitals"
msgstr ""
#: ../calculator.py:773
msgid "Mode: "
msgstr ""
#: ../calculator.py:775
msgid "sz - Single Zeta"
msgstr ""
#: ../calculator.py:776
msgid "szp - Single Zeta polarized"
msgstr ""
#: ../calculator.py:777
msgid "dzp - Double Zeta polarized"
msgstr ""
#. dzp
#: ../calculator.py:779
msgid "Basis functions: "
msgstr ""
#. Mixer
#: ../calculator.py:785
msgid "Non-standard mixer parameters"
msgstr ""
#: ../calculator.py:981
msgid "FHI-aims parameters"
msgstr ""
#: ../calculator.py:988
msgid "Periodic geometry, unit cell is:\n"
msgstr ""
#: ../calculator.py:993
msgid "Non-periodic geometry.\n"
msgstr ""
#: ../calculator.py:1000
msgid "Hirshfeld-based dispersion correction"
msgstr ""
#. Spin polarized, charge, relativity
#: ../calculator.py:1026
msgid "Spin / initial moment "
msgstr ""
#: ../calculator.py:1044
msgid " Charge"
msgstr ""
#: ../calculator.py:1046
msgid " Relativity"
msgstr ""
#: ../calculator.py:1048
msgid " Threshold"
msgstr ""
#. self-consistency criteria
#: ../calculator.py:1053
msgid "Self-consistency convergence:"
msgstr ""
#: ../calculator.py:1066
msgid "Compute forces"
msgstr ""
#. XXX: use gtk table for layout. Spaces will not work well otherwise
#. (depend on fonts, widget style, ...)
#. TRANSLATORS: Don't care too much about these, just get approximately
#. the same string lengths
#: ../calculator.py:1077
msgid "Energy: "
msgstr ""
#: ../calculator.py:1079
msgid " eV Sum of eigenvalues: "
msgstr ""
#: ../calculator.py:1081 ../calculator.py:1559
msgid " eV"
msgstr ""
#: ../calculator.py:1082
msgid "Electron density: "
msgstr ""
#: ../calculator.py:1084
msgid " Force convergence: "
msgstr ""
#: ../calculator.py:1086
msgid " eV/Ang "
msgstr ""
#: ../calculator.py:1099 ../calculator.py:1570
msgid "Additional keywords: "
msgstr ""
#. run command and species defaults:
#: ../calculator.py:1113
msgid "FHI-aims execution command: "
msgstr ""
#: ../calculator.py:1115 ../calculator.py:1587
msgid "Directory for species defaults: "
msgstr ""
#: ../calculator.py:1127 ../calculator.py:1595
msgid "Set Defaults"
msgstr ""
#: ../calculator.py:1129
msgid "Import control.in"
msgstr ""
#: ../calculator.py:1131
msgid "Export control.in"
msgstr ""
#: ../calculator.py:1317
msgid "Export parameters ... "
msgstr ""
#: ../calculator.py:1337
msgid "Import control.in file ... "
msgstr ""
#: ../calculator.py:1393 ../calculator.py:1907
#, python-format
msgid ""
"Please use the facilities provided in this window to manipulate the keyword: "
"%s!"
msgstr ""
#: ../calculator.py:1396
#, python-format
msgid ""
"Don't know this keyword: %s\n"
"\n"
"Please check!\n"
"\n"
"If you really think it should be available, please add it to the top of ase/"
"calculators/aims.py."
msgstr ""
#: ../calculator.py:1469
msgid "VASP parameters"
msgstr ""
#: ../calculator.py:1475
msgid "Periodic geometry, unit cell is: \n"
msgstr ""
#: ../calculator.py:1527
msgid ") Cutoff: "
msgstr ""
#: ../calculator.py:1528
msgid " Precision: "
msgstr ""
#: ../calculator.py:1530
#, python-format
msgid "k-points x size: (%.1f, %.1f, %.1f) Ã… "
msgstr ""
#: ../calculator.py:1546
msgid "Smearing: "
msgstr ""
#: ../calculator.py:1548
msgid " order: "
msgstr ""
#: ../calculator.py:1550
msgid " width: "
msgstr ""
#: ../calculator.py:1557
msgid "Self-consistency convergence: "
msgstr ""
#. run command and location of POTCAR files:
#: ../calculator.py:1583
msgid "VASP execution command: "
msgstr ""
#: ../calculator.py:1597
msgid "Import VASP files"
msgstr ""
#: ../calculator.py:1599
msgid "Export VASP files"
msgstr ""
#: ../calculator.py:1810
msgid "WARNING: cutoff energy is lower than recommended minimum!"
msgstr ""
#: ../calculator.py:1862
msgid "Import VASP input files: choose directory ... "
msgstr ""
#: ../calculator.py:1877
msgid "Export VASP input files: choose directory ... "
msgstr ""
#: ../calculator.py:1910
#, python-format
msgid ""
"Don't know this keyword: %s\n"
"Please check!\n"
"\n"
"If you really think it should be available, please add it to the top of ase/"
"calculators/vasp.py."
msgstr ""
#: ../colors.py:24
msgid "Colors"
msgstr ""
#. Upper left: Choose how the atoms are colored.
#: ../colors.py:41
msgid "Choose how the atoms are colored:"
msgstr ""
#: ../colors.py:43
msgid "By atomic number, default \"jmol\" colors"
msgstr ""
#: ../colors.py:45
msgid "By atomic number, user specified"
msgstr ""
#: ../colors.py:46
msgid "By tag"
msgstr ""
#: ../colors.py:47
msgid "By force"
msgstr ""
#: ../colors.py:48
msgid "By velocity"
msgstr ""
#: ../colors.py:49
msgid "Manually specified"
msgstr ""
#: ../colors.py:50
msgid "All the same color"
msgstr ""
#. Now fill in the box for additional information in case the force is used.
#: ../colors.py:60
msgid "This should not be displayed!"
msgstr ""
#: ../colors.py:65 ../colors.py:82 ../rotate.py:25
msgid "Update"
msgstr ""
#: ../colors.py:67 ../colors.py:84
msgid "Min: "
msgstr ""
#: ../colors.py:69 ../colors.py:86
msgid " Max: "
msgstr ""
#: ../colors.py:71 ../colors.py:88
msgid " Steps: "
msgstr ""
#: ../colors.py:95
msgid "Create a color scale:"
msgstr ""
#: ../colors.py:98
msgid "Black - white"
msgstr ""
#: ../colors.py:99
msgid "Black - red - yellow - white"
msgstr ""
#: ../colors.py:100
msgid "Black - green - white"
msgstr ""
#: ../colors.py:101
msgid "Black - blue - cyan"
msgstr ""
#: ../colors.py:102
msgid "Hue"
msgstr ""
#: ../colors.py:103
msgid "Named colors"
msgstr ""
#: ../colors.py:109
msgid "Create"
msgstr ""
#: ../colors.py:367
#, python-format
msgid "Max force: %.2f (this frame), %.2f (all frames)"
msgstr ""
#: ../colors.py:369
#, python-format
msgid "Max force: %.2f."
msgstr ""
#: ../colors.py:383
#, python-format
msgid "Max velocity: %.2f (this frame), %.2f (all frames)"
msgstr ""
#: ../colors.py:385
#, python-format
msgid "Max velocity: %.2f."
msgstr ""
#: ../colors.py:426
msgid "ERROR"
msgstr ""
#: ../colors.py:455
msgid "ERR"
msgstr ""
#: ../colors.py:542
msgid "Incorrect color specification"
msgstr ""
#: ../constraints.py:13 ../widgets.py:89
msgid "Constraints"
msgstr ""
#: ../constraints.py:15 ../constraints.py:18 ../settings.py:17
#: ../widgets.py:91 ../widgets.py:94
msgid "Constrain"
msgstr ""
#: ../constraints.py:16 ../settings.py:20 ../settings.py:35 ../widgets.py:92
msgid " selected atoms"
msgstr ""
#: ../constraints.py:19 ../widgets.py:95
msgid " immobile atoms:"
msgstr ""
#: ../constraints.py:21
msgid "Unconstrain"
msgstr ""
#: ../constraints.py:22
msgid " selected atoms:"
msgstr ""
#: ../constraints.py:24
msgid "Clear constraints"
msgstr ""
#: ../constraints.py:26 ../dft.py:29 ../settings.py:53 ../widgets.py:60
#: ../widgets.py:99
msgid "Close"
msgstr ""
#: ../crystal.py:16
msgid ""
" Use this dialog to create crystal lattices. First select the structure,\n"
" either from a set of common crystal structures, or by space group "
"description.\n"
" Then add all other lattice parameters.\n"
"\n"
" If an experimental crystal structure is available for an atom, you can\n"
" look up the crystal type and lattice constant, otherwise you have to "
"specify it\n"
" yourself. "
msgstr ""
#: ../crystal.py:33
#, python-format
msgid " %(natoms)i atoms: %(symbols)s, Volume: %(volume).3f A3"
msgstr ""
#: ../crystal.py:58
msgid "Create Bulk Crystal by Spacegroup"
msgstr ""
#: ../crystal.py:72
msgid "Number: 1"
msgstr ""
#: ../crystal.py:73
msgid "Lattice: "
msgstr ""
#: ../crystal.py:73
msgid "\tSpace group: "
msgstr ""
#: ../crystal.py:77
msgid "Size: x: "
msgstr ""
#: ../crystal.py:78 ../crystal.py:138
msgid " y: "
msgstr ""
#: ../crystal.py:79 ../crystal.py:139
msgid " z: "
msgstr ""
#: ../crystal.py:80 ../surfaceslab.py:127 ../surfaceslab.py:129
msgid " unit cells"
msgstr ""
#: ../crystal.py:92 ../crystal.py:96 ../crystal.py:100 ../crystal.py:104
#: ../crystal.py:108 ../crystal.py:112
msgid "free"
msgstr ""
#: ../crystal.py:93 ../crystal.py:102
msgid "equals b"
msgstr ""
#: ../crystal.py:94 ../crystal.py:98
msgid "equals c"
msgstr ""
#: ../crystal.py:95 ../crystal.py:99 ../crystal.py:103 ../crystal.py:107
#: ../crystal.py:111 ../crystal.py:115
msgid "fixed"
msgstr ""
#: ../crystal.py:97 ../crystal.py:101
msgid "equals a"
msgstr ""
#: ../crystal.py:105 ../crystal.py:114
msgid "equals beta"
msgstr ""
#: ../crystal.py:106 ../crystal.py:110
msgid "equals gamma"
msgstr ""
#: ../crystal.py:109 ../crystal.py:113
msgid "equals alpha"
msgstr ""
#: ../crystal.py:119
msgid "Lattice parameters"
msgstr ""
#: ../crystal.py:120
msgid "\t\ta:\t"
msgstr ""
#: ../crystal.py:121
msgid "\talpha:\t"
msgstr ""
#: ../crystal.py:122
msgid "\t\tb:\t"
msgstr ""
#: ../crystal.py:123
msgid "\tbeta:\t"
msgstr ""
#: ../crystal.py:124
msgid "\t\tc:\t"
msgstr ""
#: ../crystal.py:125
msgid "\tgamma:\t"
msgstr ""
#: ../crystal.py:126 ../surfaceslab.py:99
msgid "Get from database"
msgstr ""
#: ../crystal.py:131
msgid "Basis: "
msgstr ""
#: ../crystal.py:137
msgid " Element:\t"
msgstr ""
#: ../crystal.py:137
msgid "\tx: "
msgstr ""
#: ../crystal.py:157
msgid "Creating a crystal."
msgstr ""
#: ../crystal.py:202
#, python-format
msgid "Symbol: %s"
msgstr ""
#: ../crystal.py:207
#, python-format
msgid "Number: %s"
msgstr ""
#: ../crystal.py:210
msgid "Invalid Spacegroup!"
msgstr ""
#: ../crystal.py:336 ../crystal.py:339
msgid "Please specify a consistent set of atoms."
msgstr ""
#: ../crystal.py:348 ../graphene.py:230 ../nanoparticle.py:613
#: ../nanotube.py:139 ../surfaceslab.py:248
msgid "No valid atoms."
msgstr ""
#: ../crystal.py:465
msgid "Can't find lattice definition!"
msgstr ""
#: ../debug.py:11
msgid "Debug"
msgstr ""
#: ../dft.py:13
msgid "DFT"
msgstr ""
#: ../dft.py:19
msgid "XC-functional: "
msgstr ""
#: ../dft.py:23 ../repeat.py:16
msgid "Repeat atoms:"
msgstr ""
#: ../energyforces.py:11
msgid "Output:"
msgstr ""
#: ../energyforces.py:41
msgid "Save output"
msgstr ""
#: ../energyforces.py:57
msgid "Potential energy and forces"
msgstr ""
#: ../energyforces.py:61
msgid "Calculate potential energy and the force on all atoms"
msgstr ""
#: ../energyforces.py:65
msgid "Write forces on the atoms"
msgstr ""
#: ../energyforces.py:82
msgid "Potential Energy:\n"
msgstr ""
#: ../energyforces.py:83
#, python-format
msgid " %8.2f eV\n"
msgstr ""
#: ../energyforces.py:84
#, python-format
msgid ""
" %8.4f eV/atom\n"
"\n"
msgstr ""
#: ../energyforces.py:86
msgid "Forces:\n"
msgstr ""
#: ../execute.py:23
msgid ""
"\n"
" Global commands work on all frames or only on the current frame\n"
" - Assignment of a global variable may not reference a local one\n"
" - use 'Current frame' switch to switch off application to all frames\n"
" e:\t\ttotal energy of one frame\n"
" fmax:\tmaximal force in one frame\n"
" A:\tunit cell\n"
" E:\t\ttotal energy array of all frames\n"
" F:\t\tall forces in one frame\n"
" M:\tall magnetic moments\n"
" R:\t\tall atomic positions\n"
" S:\tall selected atoms (boolean array)\n"
" D:\tall dynamic atoms (boolean array)\n"
" examples: frame = 1, A[0][1] += 4, e-E[-1]\n"
"\n"
" Atom commands work on each atom (or a selection) individually\n"
" - these can use global commands on the RHS of an equation\n"
" - use 'selected atoms only' to restrict application of command\n"
" x,y,z:\tatomic coordinates\n"
" r,g,b:\tatom display color, range is [0..1]\n"
" rad:\tatomic radius for display\n"
" s:\t\tatom is selected\n"
" d:\t\tatom is movable\n"
" f:\t\tforce\n"
" Z:\tatomic number\n"
" m:\tmagnetic moment\n"
" examples: x -= A[0][0], s = z > 5, Z = 6\n"
"\n"
" Special commands and objects:\n"
" sa,cf:\t(un)restrict to selected atoms/current frame\n"
" frame:\tframe number\n"
" center:\tcenters the system in its existing unit cell\n"
" del S:\tdelete selection\n"
" CM:\tcenter of mass\n"
" ans[-i]:\tith last calculated result\n"
" exec file: executes commands listed in file\n"
" cov[Z]:(read only): covalent radius of atomic number Z\n"
" gui:\tadvanced: ag window python object\n"
" img:\tadvanced: ag images object\n"
" "
msgstr ""
#: ../execute.py:67
msgid "Expert user mode"
msgstr ""
#: ../execute.py:80
msgid "Welcome to the ASE Expert user mode"
msgstr ""
#: ../execute.py:87
msgid "Only selected atoms (sa) "
msgstr ""
#: ../execute.py:89
msgid "Only current frame (cf) "
msgstr ""
#: ../execute.py:99
msgid ""
"Global: Use A, D, E, M, N, R, S, n, frame; Atoms: Use a, f, m, s, x, y, z, "
"Z "
msgstr ""
#: ../execute.py:198
#, python-format
msgid "*** WARNING: file does not exist - %s"
msgstr ""
#: ../execute.py:203
msgid "*** WARNING: No atoms selected to work with"
msgstr ""
#: ../execute.py:277
msgid "*** Only working on selected atoms"
msgstr ""
#: ../execute.py:279
msgid "*** Working on all atoms"
msgstr ""
#: ../execute.py:283
msgid "*** Only working on current image"
msgstr ""
#: ../execute.py:285
msgid "*** Working on all images"
msgstr ""
#: ../execute.py:301
msgid "Save Terminal text ..."
msgstr ""
#: ../graphene.py:15
msgid ""
"Set up a graphene sheet or a graphene nanoribbon. A nanoribbon may\n"
"optionally be saturated with hydrogen (or another element)."
msgstr ""
#: ../graphene.py:30 ../gui.py:298
msgid "Graphene"
msgstr ""
#. Choose structure
#. The structure and lattice constant
#. Choose the surface structure
#: ../graphene.py:37 ../nanoparticle.py:138 ../surfaceslab.py:78
msgid "Structure: "
msgstr ""
#: ../graphene.py:39
msgid "Infinite sheet"
msgstr ""
#: ../graphene.py:39
msgid "Unsaturated ribbon"
msgstr ""
#: ../graphene.py:40
msgid "Saturated ribbon"
msgstr ""
#. Orientation
#: ../graphene.py:47
msgid "Orientation: "
msgstr ""
#: ../graphene.py:50
msgid "zigzag"
msgstr ""
#: ../graphene.py:50
msgid "armchair"
msgstr ""
#: ../graphene.py:66 ../graphene.py:78 ../nanotube.py:46
msgid " Bond length: "
msgstr ""
#. Choose the saturation element and bond length
#: ../graphene.py:72
msgid "Saturation: "
msgstr ""
#: ../graphene.py:75
msgid "H"
msgstr ""
#. Size
#: ../graphene.py:91
msgid "Width: "
msgstr ""
#: ../graphene.py:92 ../nanotube.py:65
msgid " Length: "
msgstr ""
#. Vacuum
#: ../graphene.py:100
msgid "Vacuum: "
msgstr ""
#: ../graphene.py:138 ../nanotube.py:96 ../setupwindow.py:32
msgid " No element specified!"
msgstr ""
#: ../graphene.py:231 ../nanoparticle.py:614 ../nanotube.py:140
#: ../pybutton.py:49 ../surfaceslab.py:249
msgid "You have not (yet) specified a consistent set of parameters."
msgstr ""
#: ../graphs.py:19
msgid "Help for plot ..."
msgstr ""
#: ../graphs.py:30 ../graphs.py:33
msgid "Plot"
msgstr ""
#: ../graphs.py:38
msgid "clear"
msgstr ""
#: ../graphs.py:92
msgid "Save data to file ... "
msgstr ""
#: ../gtkexcepthook.py:117
msgid "Bug Detected"
msgstr ""
#: ../gtkexcepthook.py:121
msgid "A programming error has been detected."
msgstr ""
#: ../gtkexcepthook.py:124
msgid ""
"It probably isn't fatal, but the details should be reported to the "
"developers nonetheless."
msgstr ""
#: ../gtkexcepthook.py:140
msgid "Report..."
msgstr ""
#: ../gtkexcepthook.py:144
msgid "Details..."
msgstr ""
#: ../gtkexcepthook.py:160
#, python-format
msgid ""
"From: buggy_application\"\n"
"To: bad_programmer\n"
"Subject: Exception feedback\n"
"\n"
"%s"
msgstr ""
#. Show details...
#: ../gtkexcepthook.py:173
msgid "Bug Details"
msgstr ""
#: ../gui.py:164
msgid "_File"
msgstr ""
#: ../gui.py:165
msgid "_Edit"
msgstr ""
#: ../gui.py:166
msgid "_View"
msgstr ""
#: ../gui.py:167
msgid "_Tools"
msgstr ""
#. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ...
#: ../gui.py:169
msgid "_Setup"
msgstr ""
#: ../gui.py:170
msgid "_Calculate"
msgstr ""
#: ../gui.py:171
msgid "_Help"
msgstr ""
#: ../gui.py:172
msgid "_Open"
msgstr ""
#: ../gui.py:173
msgid "Create a new file"
msgstr ""
#: ../gui.py:175
msgid "_New"
msgstr ""
#: ../gui.py:176
msgid "New ase.gui window"
msgstr ""
#: ../gui.py:178
msgid "_Save"
msgstr ""
#: ../gui.py:179
msgid "Save current file"
msgstr ""
#: ../gui.py:181
msgid "_Quit"
msgstr ""
#: ../gui.py:182
msgid "Quit"
msgstr ""
#: ../gui.py:184
msgid "Select _all"
msgstr ""
#: ../gui.py:187
msgid "_Invert selection"
msgstr ""
#: ../gui.py:190
msgid "Select _constrained atoms"
msgstr ""
#: ../gui.py:193
msgid "Select _immobile atoms"
msgstr ""
#: ../gui.py:196
msgid "_Copy"
msgstr ""
#: ../gui.py:197
msgid "Copy current selection and its orientation to clipboard"
msgstr ""
#: ../gui.py:199
msgid "_Paste"
msgstr ""
#: ../gui.py:200
msgid "Insert current clipboard selection"
msgstr ""
#: ../gui.py:202
msgid "_Modify"
msgstr ""
#: ../gui.py:203
msgid "Change tags, moments and atom types of the selected atoms"
msgstr ""
#: ../gui.py:205
msgid "_Add atoms"
msgstr ""
#: ../gui.py:206
msgid "Insert or import atoms and molecules"
msgstr ""
#: ../gui.py:208
msgid "_Delete selected atoms"
msgstr ""
#: ../gui.py:209
msgid "Delete the selected atoms"
msgstr ""
#: ../gui.py:211
msgid "_First image"
msgstr ""
#: ../gui.py:214
msgid "_Previous image"
msgstr ""
#: ../gui.py:217
msgid "_Next image"
msgstr ""
#: ../gui.py:220
msgid "_Last image"
msgstr ""
#: ../gui.py:223
msgid "Quick Info ..."
msgstr ""
#: ../gui.py:226
msgid "Repeat ..."
msgstr ""
#: ../gui.py:229
msgid "Rotate ..."
msgstr ""
#: ../gui.py:232
msgid "Colors ..."
msgstr ""
#. TRANSLATORS: verb
#: ../gui.py:235
msgid "Focus"
msgstr ""
#: ../gui.py:238
msgid "Zoom in"
msgstr ""
#: ../gui.py:241
msgid "Zoom out"
msgstr ""
#: ../gui.py:244
msgid "Reset View"
msgstr ""
#: ../gui.py:247
msgid "Settings ..."
msgstr ""
#: ../gui.py:250
msgid "VMD"
msgstr ""
#: ../gui.py:253
msgid "RasMol"
msgstr ""
#: ../gui.py:256
msgid "xmakemol"
msgstr ""
#: ../gui.py:259
msgid "avogadro"
msgstr ""
#: ../gui.py:262
msgid "Graphs ..."
msgstr ""
#: ../gui.py:265
msgid "Movie ..."
msgstr ""
#: ../gui.py:268
msgid "Expert mode ..."
msgstr ""
#: ../gui.py:271
msgid "Constraints ..."
msgstr ""
#: ../gui.py:274
msgid "Render scene ..."
msgstr ""
#: ../gui.py:277
msgid "DFT ..."
msgstr ""
#: ../gui.py:280
msgid "NE_B"
msgstr ""
#: ../gui.py:283
msgid "B_ulk Modulus"
msgstr ""
#: ../gui.py:286
msgid "_Bulk Crystal"
msgstr ""
#: ../gui.py:287
msgid "Create a bulk crystal with arbitrary orientation"
msgstr ""
#: ../gui.py:289
msgid "_Surface slab"
msgstr ""
#: ../gui.py:290
msgid "Create the most common surfaces"
msgstr ""
#: ../gui.py:292
msgid "_Nanoparticle"
msgstr ""
#: ../gui.py:293
msgid "Create a crystalline nanoparticle"
msgstr ""
#: ../gui.py:295
msgid "Nano_tube"
msgstr ""
#: ../gui.py:296
msgid "Create a nanotube"
msgstr ""
#: ../gui.py:299
msgid "Create a graphene sheet or nanoribbon"
msgstr ""
#: ../gui.py:301
msgid "Set _Calculator"
msgstr ""
#: ../gui.py:302
msgid "Set a calculator used in all calculation modules"
msgstr ""
#: ../gui.py:304
msgid "_Energy and Forces"
msgstr ""
#: ../gui.py:305
msgid "Calculate energy and forces"
msgstr ""
#: ../gui.py:307
msgid "Energy _Minimization"
msgstr ""
#: ../gui.py:308
msgid "Minimize the energy"
msgstr ""
#: ../gui.py:310
msgid "Scale system"
msgstr ""
#: ../gui.py:311
msgid "Deform system by scaling it"
msgstr ""
#: ../gui.py:313
msgid "_About"
msgstr ""
#: ../gui.py:316
msgid "Webpage ..."
msgstr ""
#: ../gui.py:317
msgid "Debug ..."
msgstr ""
#: ../gui.py:319
msgid "Show _unit cell"
msgstr ""
#: ../gui.py:323
msgid "Show _axes"
msgstr ""
#: ../gui.py:327
msgid "Show _bonds"
msgstr ""
#: ../gui.py:331
msgid "_Move atoms"
msgstr ""
#: ../gui.py:335
msgid "_Rotate atoms"
msgstr ""
#: ../gui.py:339
msgid "Orien_t atoms"
msgstr ""
#: ../gui.py:351
#, python-format
msgid "building menus failed: %s"
msgstr ""
#: ../gui.py:620 ../gui.py:1016 ../gui.py:1076
msgid "Open ..."
msgstr ""
#: ../gui.py:624 ../gui.py:1019
msgid "<>"
msgstr ""
#: ../gui.py:756
msgid "Add atoms"
msgstr ""
#: ../gui.py:759
msgid "Paste"
msgstr ""
#: ../gui.py:765
msgid "Insert atom or molecule"
msgstr ""
#: ../gui.py:766 ../gui.py:883
msgid "Tag"
msgstr ""
#: ../gui.py:767 ../gui.py:884
msgid "Moment"
msgstr ""
#: ../gui.py:768
msgid "Position"
msgstr ""
#: ../gui.py:793
msgid "_Load molecule"
msgstr ""
#: ../gui.py:797 ../gui.py:899
msgid "_OK"
msgstr ""
#: ../gui.py:801 ../gui.py:903
msgid "_Cancel"
msgstr ""
#: ../gui.py:876
msgid "Modify"
msgstr ""
#: ../gui.py:882
msgid "Atom"
msgstr ""
#: ../gui.py:927
msgid "Confirmation"
msgstr ""
#: ../gui.py:931
msgid "Delete selected atom?"
msgid_plural "Delete selected atoms?"
msgstr[0] ""
msgstr[1] ""
#: ../gui.py:938
msgid "Cancel"
msgstr ""
#: ../gui.py:1024 ../gui.py:1106
msgid "Automatic"
msgstr ""
#: ../gui.py:1025
msgid "Dacapo netCDF output file"
msgstr ""
#: ../gui.py:1026
msgid "Virtual Nano Lab file"
msgstr ""
#: ../gui.py:1027
msgid "ASE pickle trajectory"
msgstr ""
#: ../gui.py:1028 ../gui.py:1119
msgid "ASE bundle trajectory"
msgstr ""
#: ../gui.py:1029
msgid "GPAW text output"
msgstr ""
#: ../gui.py:1030
msgid "CUBE file"
msgstr ""
#: ../gui.py:1031
msgid "XCrySDen Structure File"
msgstr ""
#: ../gui.py:1032
msgid "Dacapo text output"
msgstr ""
#: ../gui.py:1033
msgid "XYZ-file"
msgstr ""
#: ../gui.py:1034
msgid "VASP POSCAR/CONTCAR file"
msgstr ""
#: ../gui.py:1035
msgid "VASP OUTCAR file"
msgstr ""
#: ../gui.py:1036
msgid "Protein Data Bank"
msgstr ""
#: ../gui.py:1037
msgid "CIF-file"
msgstr ""
#: ../gui.py:1038
msgid "FHI-aims geometry file"
msgstr ""
#: ../gui.py:1039
msgid "FHI-aims output file"
msgstr ""
#: ../gui.py:1040
msgid "TURBOMOLE coord file"
msgstr ""
#: ../gui.py:1041
msgid "exciting input"
msgstr ""
#: ../gui.py:1042
msgid "WIEN2k structure file"
msgstr ""
#: ../gui.py:1043
msgid "DftbPlus input file"
msgstr ""
#: ../gui.py:1044
msgid "ETSF format"
msgstr ""
#: ../gui.py:1045 ../gui.py:1117
msgid "CASTEP geom file"
msgstr ""
#: ../gui.py:1046
msgid "CASTEP output file"
msgstr ""
#: ../gui.py:1047
msgid "CASTEP trajectory file"
msgstr ""
#: ../gui.py:1048
msgid "DFTBPlus GEN format"
msgstr ""
#: ../gui.py:1054
msgid "File type:"
msgstr ""
#: ../gui.py:1094
msgid "Save ..."
msgstr ""
#: ../gui.py:1107
msgid "XYZ file"
msgstr ""
#: ../gui.py:1108
msgid "ASE trajectory"
msgstr ""
#: ../gui.py:1109
msgid "PDB file"
msgstr ""
#: ../gui.py:1110
msgid "Gaussian cube file"
msgstr ""
#: ../gui.py:1111
msgid "Python script"
msgstr ""
#: ../gui.py:1112
msgid "VNL file"
msgstr ""
#: ../gui.py:1113
msgid "Portable Network Graphics"
msgstr ""
#: ../gui.py:1114
msgid "Persistence of Vision"
msgstr ""
#: ../gui.py:1115
msgid "Encapsulated PostScript"
msgstr ""
#: ../gui.py:1116
msgid "FHI-aims geometry input"
msgstr ""
#: ../gui.py:1118
msgid "VASP geometry input"
msgstr ""
#: ../gui.py:1120
msgid "cif file"
msgstr ""
#: ../gui.py:1142
#, python-format
msgid "Save current image only (#%d)"
msgstr ""
#: ../gui.py:1146
msgid "Slice: "
msgstr ""
#: ../gui.py:1147
msgid "Help for slice ..."
msgstr ""
#: ../gui.py:1159
msgid "AG INTERNAL ERROR: strange response in Save,"
msgstr ""
#: ../gui.py:1178
msgid "Unknown output format!"
msgstr ""
#: ../gui.py:1179
#, python-format
msgid "Use one of: %s"
msgstr ""
#: ../gui.py:1284
msgid "Not implemented!"
msgstr ""
#: ../gui.py:1285
msgid "do you really need it?"
msgstr ""
#: ../minimize.py:20
msgid "Algorithm: "
msgstr ""
#: ../minimize.py:25 ../progress.py:67
msgid "Convergence criterion: Fmax = "
msgstr ""
#: ../minimize.py:30 ../progress.py:70
msgid "Max. number of steps: "
msgstr ""
#. Special stuff for MDMin
#: ../minimize.py:33
msgid "Pseudo time step: "
msgstr ""
#: ../minimize.py:54
msgid "Energy minimization"
msgstr ""
#: ../minimize.py:58
msgid "Minimize the energy with respect to the positions."
msgstr ""
#. Don't catch errors in the function.
#. Display status message
#: ../minimize.py:90 ../scaling.py:299
msgid "Running ..."
msgstr ""
#. Update display to reflect cancellation of simulation.
#: ../minimize.py:107
#, python-format
msgid "Minimization CANCELLED after %i steps."
msgstr ""
#: ../minimize.py:113 ../scaling.py:350
msgid "Out of memory, consider using LBFGS instead"
msgstr ""
#. Update display to reflect succesful end of simulation.
#: ../minimize.py:120
#, python-format
msgid "Minimization completed in %i steps."
msgstr ""
#. self.connect('delete_event', self.exit2)
#: ../movie.py:14
msgid "Movie"
msgstr ""
#: ../movie.py:16
msgid "Image number:"
msgstr ""
#: ../movie.py:38
msgid "Play"
msgstr ""
#: ../movie.py:40
msgid "Stop"
msgstr ""
#. TRANSLATORS: This function plays an animation forwards and backwards
#. alternatingly, e.g. for displaying vibrational movement
#: ../movie.py:44
msgid "Rock"
msgstr ""
#: ../movie.py:60
msgid " Frame rate: "
msgstr ""
#: ../movie.py:61
msgid " Skip frames: "
msgstr ""
#: ../nanoparticle.py:19
msgid ""
"Create a nanoparticle either by specifying the number of layers, or using "
"the\n"
"Wulff construction. Please press the [Help] button for instructions on how "
"to\n"
"specify the directions.\n"
"WARNING: The Wulff construction currently only works with cubic crystals!\n"
msgstr ""
#: ../nanoparticle.py:26
msgid ""
"\n"
"The nanoparticle module sets up a nano-particle or a cluster with a given\n"
"crystal structure.\n"
"\n"
"1) Select the element, the crystal structure and the lattice constant(s).\n"
" The [Get structure] button will find the data for a given element.\n"
"\n"
"2) Choose if you want to specify the number of layers in each direction, or "
"if\n"
" you want to use the Wulff construction. In the latter case, you must "
"specify\n"
" surface energies in each direction, and the size of the cluster.\n"
"\n"
"How to specify the directions:\n"
"------------------------------\n"
"\n"
"First time a direction appears, it is interpreted as the entire family of\n"
"directions, i.e. (0,0,1) also covers (1,0,0), (-1,0,0) etc. If one of "
"these\n"
"directions is specified again, the second specification overrules that "
"specific\n"
"direction. For this reason, the order matters and you can rearrange the\n"
"directions with the [Up] and [Down] keys. You can also add a new "
"direction,\n"
"remember to press [Add] or it will not be included.\n"
"\n"
"Example: (1,0,0) (1,1,1), (0,0,1) would specify the {100} family of "
"directions,\n"
"the {111} family and then the (001) direction, overruling the value given "
"for\n"
"the whole family of directions.\n"
msgstr ""
#. Structures: Abbreviation, name, 4-index (boolean), two lattice const (bool), factory
#: ../nanoparticle.py:83
msgid "Face centered cubic (fcc)"
msgstr ""
#: ../nanoparticle.py:84
msgid "Body centered cubic (bcc)"
msgstr ""
#: ../nanoparticle.py:85
msgid "Simple cubic (sc)"
msgstr ""
#: ../nanoparticle.py:86
msgid "Hexagonal closed-packed (hcp)"
msgstr ""
#: ../nanoparticle.py:87
msgid "Graphite"
msgstr ""
#: ../nanoparticle.py:116
msgid "Nanoparticle"
msgstr ""
#. Choose the element
#. Choose the element and bond length
#. Choose the element
#: ../nanoparticle.py:126 ../nanotube.py:40 ../surfaceslab.py:69
msgid "Element: "
msgstr ""
#: ../nanoparticle.py:130
msgid "Get structure"
msgstr ""
#: ../nanoparticle.py:154
msgid "Lattice constant: a ="
msgstr ""
#. Choose specification method
#: ../nanoparticle.py:171
msgid "Method: "
msgstr ""
#: ../nanoparticle.py:173
msgid "Layer specification"
msgstr ""
#: ../nanoparticle.py:173
msgid "Wulff construction"
msgstr ""
#: ../nanoparticle.py:193
msgid "Dummy placeholder object"
msgstr ""
#: ../nanoparticle.py:195
msgid "Add new direction:"
msgstr ""
#: ../nanoparticle.py:211
msgid "Add"
msgstr ""
#: ../nanoparticle.py:219
msgid "Set all directions to default values"
msgstr ""
#: ../nanoparticle.py:227
msgid "Particle size: "
msgstr ""
#: ../nanoparticle.py:228 ../nanoparticle.py:265 ../progress.py:196
msgid "Number of atoms: "
msgstr ""
#: ../nanoparticle.py:233
msgid "Volume: "
msgstr ""
#: ../nanoparticle.py:238
msgid "ų"
msgstr ""
#: ../nanoparticle.py:243
msgid "Rounding: If exact size is not possible, choose the size"
msgstr ""
#: ../nanoparticle.py:246
msgid "above "
msgstr ""
#: ../nanoparticle.py:247
msgid "below "
msgstr ""
#: ../nanoparticle.py:248
msgid "closest "
msgstr ""
#: ../nanoparticle.py:251
msgid "Smaller"
msgstr ""
#: ../nanoparticle.py:252
msgid "Larger"
msgstr ""
#: ../nanoparticle.py:267
msgid " Approx. diameter: "
msgstr ""
#: ../nanoparticle.py:271
msgid "Information about the created cluster:"
msgstr ""
#. Buttons
#: ../nanoparticle.py:277 ../nanotube.py:75
msgid "Creating a nanoparticle."
msgstr ""
#: ../nanoparticle.py:284
msgid "Automatic Apply"
msgstr ""
#: ../nanoparticle.py:332
msgid "Up"
msgstr ""
#: ../nanoparticle.py:337
msgid "Down"
msgstr ""
#: ../nanoparticle.py:342
msgid "Delete"
msgstr ""
#: ../nanoparticle.py:383
msgid "Surface energies (as energy/area, NOT per atom):"
msgstr ""
#: ../nanoparticle.py:389
msgid "Number of layers:"
msgstr ""
#: ../nanoparticle.py:418
msgid "At least one index must be non-zero"
msgstr ""
#: ../nanoparticle.py:421
msgid "Invalid hexagonal indices"
msgstr ""
#: ../nanoparticle.py:476 ../surfaceslab.py:218
msgid "Invalid element."
msgstr ""
#: ../nanoparticle.py:486
msgid "Unsupported or unknown structure"
msgstr ""
#: ../nanoparticle.py:603
#, python-format
msgid "%.1f Ã…"
msgstr ""
#: ../nanotube.py:14
msgid ""
"Set up a Carbon nanotube by specifying the (n,m) roll-up vector.\n"
"Please note that m <= n.\n"
"\n"
"Nanotubes of other elements can be made by specifying the element\n"
"and bond length."
msgstr ""
#: ../nanotube.py:33
msgid "Nanotube"
msgstr ""
#. Choose the structure.
#: ../nanotube.py:57
msgid "Select roll-up vector (n,m) and tube length:"
msgstr ""
#: ../progress.py:25
msgid "Progress"
msgstr ""
#: ../progress.py:32
msgid "Scaling deformation:"
msgstr ""
#: ../progress.py:38
#, python-format
msgid "Step number %s of %s."
msgstr ""
#. Minimization progress frame
#. Box containing frame and spacing
#: ../progress.py:53
msgid "Energy minimization:"
msgstr ""
#: ../progress.py:60
msgid "Step number: "
msgstr ""
#: ../progress.py:62
msgid "Fmax: "
msgstr ""
#: ../progress.py:102
msgid "unknown"
msgstr ""
#: ../progress.py:179
msgid "Status: "
msgstr ""
#: ../progress.py:181
msgid "Iteration: "
msgstr ""
#: ../progress.py:184
msgid "log10(change):"
msgstr ""
#: ../progress.py:187
msgid "Wave functions: "
msgstr ""
#: ../progress.py:189
msgid "Density: "
msgstr ""
#: ../progress.py:191
msgid "Energy: "
msgstr ""
#: ../progress.py:194
msgid "GPAW version: "
msgstr ""
#: ../progress.py:197
msgid "N/A"
msgstr ""
#: ../progress.py:198
msgid "Memory estimate: "
msgstr ""
#: ../progress.py:233
msgid "No info"
msgstr ""
#: ../progress.py:243
msgid "Initializing"
msgstr ""
#: ../progress.py:244
msgid "Positions:"
msgstr ""
#: ../progress.py:248
msgid "Starting calculation"
msgstr ""
#: ../progress.py:285
msgid "unchanged"
msgstr ""
#: ../progress.py:295
msgid "Self-consistency loop"
msgstr ""
#: ../progress.py:300
msgid "Calculating forces"
msgstr ""
#: ../progress.py:301
msgid " (converged)"
msgstr ""
#: ../pybutton.py:37
msgid "Python"
msgstr ""
#: ../pybutton.py:48
msgid "No Python code"
msgstr ""
#: ../pybutton.py:52
#, python-format
msgid ""
"\n"
"Title: %(title)s\n"
"Time: %(time)s\n"
msgstr ""
#: ../pybutton.py:61
msgid "ag: Python code"
msgstr ""
#: ../pybutton.py:65
msgid "Information:"
msgstr ""
#: ../pybutton.py:72
msgid "Python code:"
msgstr ""
#: ../quickinfo.py:9
msgid "Single image loaded."
msgstr ""
#: ../quickinfo.py:10
#, python-format
msgid "Image %d loaded (0 - %d)."
msgstr ""
#: ../quickinfo.py:11
msgid "Unit cell is fixed."
msgstr ""
#: ../quickinfo.py:12
msgid "Unit cell varies."
msgstr ""
#: ../quickinfo.py:14
#, python-format
msgid ""
"%s\n"
"\n"
"Number of atoms: %d.\n"
"\n"
"Unit cell:\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
" %8.3f %8.3f %8.3f\n"
"%s\n"
msgstr ""
#: ../quickinfo.py:29
msgid "Quick Info"
msgstr ""
#: ../quickinfo.py:33
msgid "No atoms loaded."
msgstr ""
#: ../render.py:14
msgid ""
" Textures can be used to highlight different parts of\n"
" an atomic structure. This window applies the default\n"
" texture to the entire structure and optionally\n"
" applies a different texture to subsets of atoms that\n"
" can be selected using the mouse.\n"
" An alternative selection method is based on a boolean\n"
" expression in the entry box provided, using the\n"
" variables x, y, z, or Z. For example, the expression\n"
" Z == 11 and x > 10 and y > 10 \n"
" will mark all sodium atoms with x or coordinates \n"
" larger than 10. In either case, the button labeled\n"
" `Create new texture from selection` will enable\n"
" to change the attributes of the current selection. \n"
" "
msgstr ""
#: ../render.py:32
msgid "Render current view in povray ... "
msgstr ""
#: ../render.py:36
#, python-format
msgid "Rendering %d atoms."
msgstr ""
#: ../render.py:41
msgid "Render constraints"
msgstr ""
#: ../render.py:44
msgid "Width"
msgstr ""
#: ../render.py:45
msgid " Height"
msgstr ""
#: ../render.py:52
msgid "Render unit cell"
msgstr ""
#: ../render.py:61
msgid "Line width"
msgstr ""
#: ../render.py:63
msgid "Angstrom "
msgstr ""
#: ../render.py:73
msgid "Set"
msgstr ""
#: ../render.py:75
msgid "Output basename: "
msgstr ""
#: ../render.py:77
msgid " Filename: "
msgstr ""
#: ../render.py:88
msgid " Default texture for atoms: "
msgstr ""
#: ../render.py:89
msgid " transparency: "
msgstr ""
#: ../render.py:90
msgid "Define atom selection for new texture:"
msgstr ""
#: ../render.py:92
msgid "Select"
msgstr ""
#: ../render.py:96
msgid "Create new texture from selection"
msgstr ""
#: ../render.py:98
msgid "Help on textures"
msgstr ""
#: ../render.py:111
msgid "Camera type: "
msgstr ""
#: ../render.py:112
msgid " Camera distance"
msgstr ""
#: ../render.py:113
msgid "Render current frame"
msgstr ""
#: ../render.py:117
#, python-format
msgid "Render all %d frames"
msgstr ""
#: ../render.py:122
msgid "Transparent background"
msgstr ""
#: ../render.py:125
msgid "Run povray "
msgstr ""
#: ../render.py:128
msgid "Keep povray files "
msgstr ""
#: ../render.py:131
msgid "Show output window"
msgstr ""
#: ../render.py:212
msgid " transparency: "
msgstr ""
#: ../render.py:218
msgid ""
"Can not create new texture! Must have some atoms selected to create a new "
"material!"
msgstr ""
#: ../repeat.py:14
msgid "Repeat"
msgstr ""
#: ../repeat.py:21
msgid "Set unit cell"
msgstr ""
#: ../rotate.py:15
msgid "Rotate"
msgstr ""
#: ../rotate.py:17
msgid "Rotation angles:"
msgstr ""
#: ../rotate.py:27
msgid ""
"Note:\n"
"You can rotate freely\n"
"with the mouse, by holding\n"
"down mouse button 2."
msgstr ""
#: ../scaling.py:49
msgid "Homogeneous scaling"
msgstr ""
#: ../scaling.py:59
msgid "3D deformation "
msgstr ""
#: ../scaling.py:60
msgid "2D deformation "
msgstr ""
#: ../scaling.py:61
msgid "1D deformation "
msgstr ""
#: ../scaling.py:64
msgid "Bulk"
msgstr ""
#: ../scaling.py:66
msgid "xy-plane"
msgstr ""
#: ../scaling.py:68
msgid "xz-plane"
msgstr ""
#: ../scaling.py:70
msgid "yz-plane"
msgstr ""
#: ../scaling.py:72
msgid "x-axis"
msgstr ""
#: ../scaling.py:74
msgid "y-axis"
msgstr ""
#: ../scaling.py:76
msgid "z-axis"
msgstr ""
#: ../scaling.py:89
msgid "Allow deformation along non-periodic directions."
msgstr ""
#. Parameters for the deformation
#: ../scaling.py:94
msgid "Deformation:"
msgstr ""
#: ../scaling.py:100
msgid "Maximal scale factor: "
msgstr ""
#: ../scaling.py:103
msgid "Scale offset: "
msgstr ""
#: ../scaling.py:106
msgid "Number of steps: "
msgstr ""
#: ../scaling.py:107
msgid "Only positive deformation"
msgstr ""
#. Atomic relaxations
#: ../scaling.py:112
msgid "Atomic relaxations:"
msgstr ""
#: ../scaling.py:116
msgid "On "
msgstr ""
#: ../scaling.py:117
msgid "Off"
msgstr ""
#. Results
#: ../scaling.py:128
msgid "Results:"
msgstr ""
#: ../scaling.py:130
msgid "Keep original configuration"
msgstr ""
#: ../scaling.py:132
msgid "Load optimal configuration"
msgstr ""
#: ../scaling.py:134
msgid "Load all configurations"
msgstr ""
#: ../scaling.py:143
msgid "Strain\t\tEnergy [eV]"
msgstr ""
#: ../scaling.py:144
msgid "Fit:"
msgstr ""
#: ../scaling.py:148
msgid "2nd"
msgstr ""
#: ../scaling.py:149
msgid "3rd"
msgstr ""
#: ../scaling.py:153
msgid "Order of fit: "
msgstr ""
#. Update display to reflect cancellation of simulation.
#: ../scaling.py:346
msgid "Calculation CANCELLED."
msgstr ""
#. Update display to reflect succesful end of simulation.
#: ../scaling.py:357
msgid "Calculation completed."
msgstr ""
#: ../scaling.py:380
msgid "No trustworthy minimum: Old configuration kept."
msgstr ""
#: ../scaling.py:420
#, python-format
msgid ""
"Insufficent data for a fit\n"
"(only %i data points)\n"
msgstr ""
#: ../scaling.py:424
msgid ""
"REVERTING TO 2ND ORDER FIT\n"
"(only 3 data points)\n"
"\n"
msgstr ""
#: ../scaling.py:440
msgid "No minimum found!"
msgstr ""
#: ../scaling.py:454
msgid ""
"\n"
"WARNING: Minimum is outside interval\n"
msgstr ""
#: ../scaling.py:455
msgid "It is UNRELIABLE!\n"
msgstr ""
#: ../settings.py:16
msgid "Constraints:"
msgstr ""
#: ../settings.py:19
msgid "release"
msgstr ""
#: ../settings.py:23
msgid "Constrain immobile atoms"
msgstr ""
#: ../settings.py:25
msgid "Clear all constraints"
msgstr ""
#: ../settings.py:31
msgid "Visibility:"
msgstr ""
#: ../settings.py:32
msgid "Hide"
msgstr ""
#: ../settings.py:34
msgid "show"
msgstr ""
#: ../settings.py:38
msgid "View all atoms"
msgstr ""
#: ../settings.py:44
msgid "Miscellaneous:"
msgstr ""
#: ../settings.py:47
msgid "Scale atomic radii:"
msgstr ""
#. A close button
#: ../settings.py:52
msgid "\n"
msgstr ""
#: ../setupwindow.py:51
msgid "No crystal structure data"
msgstr ""
#: ../setupwindow.py:62
msgid " ERROR: Invalid element!"
msgstr ""
#: ../simulation.py:24
msgid " (rerun simulation)"
msgstr ""
#: ../simulation.py:25
msgid " (continue simulation)"
msgstr ""
#: ../simulation.py:27
msgid "Select starting configuration:"
msgstr ""
#: ../simulation.py:32
#, python-format
msgid "There are currently %i configurations loaded."
msgstr ""
#: ../simulation.py:36
msgid "Choose which one to use as the initial configuration"
msgstr ""
#: ../simulation.py:40
#, python-format
msgid "The first configuration %s."
msgstr ""
#: ../simulation.py:43
msgid "Configuration number "
msgstr ""
#: ../simulation.py:49
#, python-format
msgid "The last configuration %s."
msgstr ""
#: ../simulation.py:85
msgid "Run"
msgstr ""
#: ../simulation.py:105
msgid "No calculator: Use Calculate/Set Calculator on the menu."
msgstr ""
#: ../status.py:37 ../status.py:39
msgid "Tip for status box ..."
msgstr ""
#. TRANSLATORS: mom refers to magnetic moment
#: ../status.py:63
#, python-format
msgid " tag=%(tag)s mom=%(mom)1.2f"
msgstr ""
#: ../status.py:104
msgid "dihedral"
msgstr ""
#: ../surfaceslab.py:14
msgid ""
" Use this dialog to create surface slabs. Select the element by\n"
"writing the chemical symbol or the atomic number in the box. Then\n"
"select the desired surface structure. Note that some structures can\n"
"be created with an othogonal or a non-orthogonal unit cell, in these\n"
"cases the non-orthogonal unit cell will contain fewer atoms.\n"
"\n"
" If the structure matches the experimental crystal structure, you can\n"
"look up the lattice constant, otherwise you have to specify it\n"
"yourself."
msgstr ""
#. Name, structure, orthogonal, support-nonorthogonal, function
#: ../surfaceslab.py:26
msgid "FCC(100)"
msgstr ""
#: ../surfaceslab.py:26 ../surfaceslab.py:27 ../surfaceslab.py:28
#: ../surfaceslab.py:30
msgid "fcc"
msgstr ""
#: ../surfaceslab.py:27
msgid "FCC(110)"
msgstr ""
#: ../surfaceslab.py:28
msgid "FCC(111) non-orthogonal"
msgstr ""
#: ../surfaceslab.py:30
msgid "FCC(111) orthogonal"
msgstr ""
#: ../surfaceslab.py:31
msgid "BCC(100)"
msgstr ""
#: ../surfaceslab.py:31 ../surfaceslab.py:32 ../surfaceslab.py:34
#: ../surfaceslab.py:35 ../surfaceslab.py:37
msgid "bcc"
msgstr ""
#: ../surfaceslab.py:32
msgid "BCC(110) non-orthogonal"
msgstr ""
#: ../surfaceslab.py:34
msgid "BCC(110) orthogonal"
msgstr ""
#: ../surfaceslab.py:35
msgid "BCC(111) non-orthogonal"
msgstr ""
#: ../surfaceslab.py:37
msgid "BCC(111) orthogonal"
msgstr ""
#: ../surfaceslab.py:38
msgid "HCP(0001) non-orthogonal"
msgstr ""
#: ../surfaceslab.py:38 ../surfaceslab.py:40 ../surfaceslab.py:41
msgid "hcp"
msgstr ""
#: ../surfaceslab.py:40
msgid "HCP(0001) orthogonal"
msgstr ""
#: ../surfaceslab.py:41
msgid "HCP(10-10) orthogonal"
msgstr ""
#: ../surfaceslab.py:43
msgid "DIAMOND(100) orthogonal"
msgstr ""
#: ../surfaceslab.py:43 ../surfaceslab.py:45
msgid "diamond"
msgstr ""
#: ../surfaceslab.py:45
msgid "DIAMOND(111) non-orthogonal"
msgstr ""
#: ../surfaceslab.py:60
msgid "Surface"
msgstr ""
#: ../surfaceslab.py:90
msgid "Lattice constant: "
msgstr ""
#: ../surfaceslab.py:97
msgid "a:"
msgstr ""
#: ../surfaceslab.py:109
#, python-format
msgid "(%.1f %% of ideal)"
msgstr ""
#: ../surfaceslab.py:126
msgid "Size: \tx: "
msgstr ""
#: ../surfaceslab.py:128
msgid "\t\ty: "
msgstr ""
#: ../surfaceslab.py:130
msgid " \t\tz: "
msgstr ""
#: ../surfaceslab.py:131
msgid " layers, "
msgstr ""
#: ../surfaceslab.py:132
msgid " Ã… vacuum"
msgstr ""
#: ../surfaceslab.py:133
msgid "\t\tNo size information yet."
msgstr ""
#. Buttons
#: ../surfaceslab.py:142
msgid "Creating a surface slab."
msgstr ""
#: ../surfaceslab.py:212
#, python-format
msgid "%i atoms."
msgstr ""
#: ../surfaceslab.py:224
msgid "No structure specified!"
msgstr ""
#: ../surfaceslab.py:233
#, python-format
msgid "%(struct)s lattice constant unknown for %(element)s."
msgstr ""
#: ../widgets.py:53 ../widgets.py:80
msgid "Help"
msgstr ""
#: ../widgets.py:97
msgid "Clear constraint"
msgstr ""
python-ase-3.6.0.2515/ase/gui/render.py 0000644 0001754 0001754 00000036502 11706276516 016406 0 ustar askhl askhl #!/usr/bin/env python
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack, Help, oops
from ase.io.pov import write_pov
from ase.gui.status import formula
from os.path import basename
from os import system
import numpy as np
class Render(gtk.Window):
finish_list = ['ase2','ase3','glass','simple','pale','intermediate','vmd','jmol']
cameras = ['orthographic','perspective','ultra_wide_angle']
selection_info_txt = _("""\
Textures can be used to highlight different parts of
an atomic structure. This window applies the default
texture to the entire structure and optionally
applies a different texture to subsets of atoms that
can be selected using the mouse.
An alternative selection method is based on a boolean
expression in the entry box provided, using the
variables x, y, z, or Z. For example, the expression
Z == 11 and x > 10 and y > 10
will mark all sodium atoms with x or coordinates
larger than 10. In either case, the button labeled
`Create new texture from selection` will enable
to change the attributes of the current selection.
""")
def __init__(self, gui):
self.gui = gui
gtk.Window.__init__(self)
self.set_title(_('Render current view in povray ... '))
vbox = gtk.VBox()
vbox.set_border_width(5)
self.natoms = self.gui.images.natoms
pack(vbox, [gtk.Label(_("Rendering %d atoms.") % self.natoms)])
self.size = [gtk.Adjustment(self.gui.width, 1, 9999, 50),
gtk.Adjustment(self.gui.height, 1, 9999, 50)]
self.width = gtk.SpinButton(self.size[0], 0, 0)
self.height = gtk.SpinButton(self.size[1], 0, 0)
self.render_constraints = gtk.CheckButton(_("Render constraints"))
self.render_constraints.set_sensitive(not self.gui.images.dynamic.all())
self.render_constraints.connect("toggled",self.toggle_render_lines)
pack(vbox, [gtk.Label(_("Width")), self.width,
gtk.Label(_(" Height")), self.height,
gtk.Label(" "),self.render_constraints])
self.width.connect('value-changed',self.change_width,"")
self.height.connect('value-changed',self.change_height,"")
self.sizeratio = gui.width/float(gui.height)
self.line_width = gtk.SpinButton(gtk.Adjustment(0.07,0.01,9.99,0.01), 0, 0)
self.line_width.set_digits(3)
self.render_cell = gtk.CheckButton(_("Render unit cell"))
if self.gui.ui.get_widget('/MenuBar/ViewMenu/ShowUnitCell').get_active():
self.render_cell.set_active(True)
else:
self.render_cell.set_active(False)
self.render_cell.set_sensitive(False)
self.render_cell.connect("toggled",self.toggle_render_lines)
have_lines = (not self.gui.images.dynamic.all()) or self.render_cell.get_active()
self.line_width.set_sensitive(have_lines)
pack(vbox, [gtk.Label(_("Line width")),
self.line_width,
gtk.Label(_("Angstrom ")),
self.render_cell])
pack(vbox, [gtk.Label("")])
filename = gui.window.get_title()
len_suffix = len(filename.split('.')[-1])+1
if len(filename) > len_suffix:
filename = filename[:-len_suffix]
self.basename = gtk.Entry(max = 30)
self.basename.connect("activate",self.set_outputname,"")
self.basename.set_text(basename(filename))
set_name = gtk.Button(_("Set"))
set_name.connect("clicked",self.set_outputname,"")
pack(vbox,[gtk.Label(_("Output basename: ")), self.basename,set_name])
self.outputname = gtk.Label("")
pack(vbox,[gtk.Label(_(" Filename: ")),self.outputname])
pack(vbox,[gtk.Label("")])
self.tbox = gtk.VBox()
self.tbox.set_border_width(10)
self.default_texture = gtk.combo_box_new_text()
for t in self.finish_list:
self.default_texture.append_text(t)
self.default_texture.set_active(1)
self.default_transparency = gtk.Adjustment(0,0.0,1.0,0.01)
self.transparency = gtk.SpinButton(self.default_transparency, 0, 0)
self.transparency.set_digits(2)
pack(self.tbox,[gtk.Label(_(" Default texture for atoms: ")), self.default_texture,
gtk.Label(_(" transparency: ")),self.transparency])
pack(self.tbox,[gtk.Label(_("Define atom selection for new texture:"))])
self.texture_selection = gtk.Entry(max = 50)
self.texture_select_but = gtk.Button(_("Select"))
self.texture_selection.connect("activate",self.select_texture,"")
self.texture_select_but.connect("clicked",self.select_texture,"")
pack(self.tbox,[self.texture_selection, self.texture_select_but])
self.create_texture = gtk.Button(_("Create new texture from selection"))
self.create_texture.connect("clicked",self.material_from_selection,"")
self.selection_help_but = gtk.Button(_("Help on textures"))
self.selection_help_but.connect("clicked",self.selection_help,"")
self.materials = []
pack(self.tbox,[self.create_texture,
gtk.Label(" "), self.selection_help_but])
pack(vbox,[self.tbox])
pack(vbox,[gtk.Label("")])
self.camera_style = gtk.combo_box_new_text()
for c in self.cameras:
self.camera_style.append_text(c)
self.camera_style.set_active(0)
self.camera_distance = gtk.SpinButton(gtk.Adjustment(50.0,-99.0,99.0,1.0), 0, 0)
self.camera_distance.set_digits(1)
pack(vbox,[gtk.Label(_("Camera type: ")),self.camera_style,
gtk.Label(_(" Camera distance")),self.camera_distance])
self.single_frame = gtk.RadioButton(None,_("Render current frame"))
self.nimages = self.gui.images.nimages
self.iframe = self.gui.frame
self.movie = gtk.RadioButton(self.single_frame,
_("Render all %d frames") % self.nimages)
self.movie.connect("toggled",self.set_movie)
self.movie.set_sensitive(self.nimages > 1)
self.set_outputname()
pack(vbox,[self.single_frame,gtk.Label(" "),self.movie])
self.transparent = gtk.CheckButton(_("Transparent background"))
self.transparent.set_active(True)
pack(vbox,[self.transparent])
self.run_povray = gtk.CheckButton(_("Run povray "))
self.run_povray.set_active(True)
self.run_povray.connect("toggled",self.toggle_run_povray,"")
self.keep_files = gtk.CheckButton(_("Keep povray files "))
self.keep_files.set_active(False)
self.keep_files_status = True
self.window_open = gtk.CheckButton(_("Show output window"))
self.window_open.set_active(True)
self.window_open_status = True
pack(vbox,[self.run_povray,self.keep_files,self.window_open])
pack(vbox,[gtk.Label("")])
cancel_but = gtk.Button(stock=gtk.STOCK_CANCEL)
cancel_but.connect('clicked', lambda widget: self.destroy())
ok_but = gtk.Button(stock=gtk.STOCK_OK)
ok_but.connect('clicked', self.ok)
close_but = gtk.Button(stock=gtk.STOCK_CLOSE)
close_but.connect('clicked', lambda widget: self.destroy())
butbox = gtk.HButtonBox()
butbox.pack_start(cancel_but, 0, 0)
butbox.pack_start(ok_but, 0, 0)
butbox.pack_start(close_but, 0, 0)
butbox.show_all()
pack(vbox, [butbox], end=True, bottom=True)
self.add(vbox)
vbox.show()
self.show()
def change_width(self, *args):
self.height.set_value(self.width.get_value()*self.gui.height/float(self.gui.width))
def change_height(self, *args):
self.width.set_value(self.height.get_value()*self.gui.width/float(self.gui.height))
def toggle_render_lines(self, *args):
self.line_width.set_sensitive(self.render_cell.get_active()
or self.render_constraints.get_active())
def set_outputname(self, *args):
movie_index = ''
self.iframe = self.gui.frame
if self.movie.get_active():
while len(movie_index) + len(str(self.iframe)) < len(str(self.nimages)):
movie_index += '0'
movie_index = '.' + movie_index + str(self.iframe)
name = self.basename.get_text() + movie_index + '.pov'
self.outputname.set_text(name)
def get_selection(self):
selection = np.zeros(self.natoms, bool)
text = self.texture_selection.get_text()
if len(self.texture_selection.get_text()) == 0:
text = 'False'
code = compile(text,'render.py', 'eval')
for n in range(self.natoms):
Z = self.gui.images.Z[n]
x, y, z = self.gui.images.P[self.iframe][n]
selection[n] = eval(code)
return selection
def select_texture(self,*args):
self.iframe = self.gui.frame
self.gui.images.selected = self.get_selection()
self.gui.set_frame(self.iframe)
def material_from_selection(self,*args):
box_selection = self.get_selection()
selection = self.gui.images.selected.copy()
if selection.any():
Z = []
for n in range(len(selection)):
if selection[n]:
Z += [self.gui.images.Z[n]]
name = formula(Z)
if (box_selection == selection).all():
name += ': ' + self.texture_selection.get_text()
texture_button = gtk.combo_box_new_text()
for t in self.finish_list:
texture_button.append_text(t)
texture_button.set_active(1)
transparency = gtk.Adjustment(0,0.0,1.0,0.01)
transparency_spin = gtk.SpinButton(transparency, 0, 0)
transparency_spin.set_digits(2)
delete_button = gtk.Button(stock=gtk.STOCK_DELETE)
alignment = delete_button.get_children()[0]
index = len(self.materials)
delete_button.connect("clicked",self.delete_material,{"n":index})
self.materials += [[True,selection,texture_button,
gtk.Label(_(" transparency: ")),transparency_spin,
gtk.Label(" "),delete_button,gtk.Label()]]
self.materials[-1][-1].set_markup(" "+name)
pack(self.tbox,[self.materials[-1][2],self.materials[-1][3],self.materials[-1][4],
self.materials[-1][5],self.materials[-1][6],self.materials[-1][7]])
else:
oops(_("Can not create new texture! Must have some atoms selected to create a new material!"))
def delete_material(self, button, index, *args):
n = index["n"]
self.materials[n][0] = False
self.materials[n][1] = np.zeros(self.natoms, bool)
self.materials[n][2].destroy()
self.materials[n][3].destroy()
self.materials[n][4].destroy()
self.materials[n][5].destroy()
self.materials[n][6].destroy()
self.materials[n][7].destroy()
def set_movie(self, *args):
if self.single_frame.get_active() and self.run_povray.get_active():
self.window_open.set_active(self.window_open_status)
self.window_open.set_sensitive(True)
else:
if self.run_povray.get_active():
self.window_open_status = self.window_open.get_active()
self.window_open.set_active(False)
self.window_open.set_sensitive(False)
self.set_outputname()
def toggle_run_povray(self, *args):
if self.run_povray.get_active():
self.keep_files.set_active(self.keep_files_status)
self.keep_files.set_sensitive(True)
if self.single_frame.get_active():
self.window_open.set_active(self.window_open_status)
self.window_open.set_sensitive(True)
else:
self.keep_files_status = self.keep_files.get_active()
self.keep_files.set_active(True)
self.keep_files.set_sensitive(False)
if self.single_frame.get_active():
self.window_open_status = self.window_open.get_active()
self.window_open.set_active(False)
self.window_open.set_sensitive(False)
def selection_help(self,*args):
Help(self.selection_info_txt)
def set_textures(self):
textures = self.natoms*[self.finish_list[self.default_texture.get_active()]]
for mat in self.materials:
sel = mat[1]
t = self.finish_list[mat[2].get_active()]
if mat[0]:
for n, val in enumerate(sel):
if val:
textures[n] = t
return textures
def get_colors(self):
colors = self.gui.get_colors(rgb = True)
for n in range(self.natoms):
colors[n] = list(colors[n]) + [0,self.default_transparency.value]
for mat in self.materials:
sel = mat[1]
trans = mat[4].get_value()
for n, val in enumerate(sel):
if val:
colors[n][4] = trans
return colors
def ok(self, *args):
print "Rendering povray image(s): "
scale = self.gui.scale*self.height.get_value()/self.gui.height
bbox = np.empty(4)
size = np.array([self.width.get_value(), self.height.get_value()]) / scale
bbox[0:2] = np.dot(self.gui.center, self.gui.axes[:, :2]) - size / 2
bbox[2:] = bbox[:2] + size
povray_settings = {'run_povray' : self.run_povray.get_active(),
'bbox' : bbox,
'rotation' : self.gui.axes,
'show_unit_cell' : self.render_cell.get_active(),
'display' : self.window_open.get_active(),
'transparent' : self.transparent.get_active(),
'camera_type' : self.cameras[self.camera_style.get_active()],
'camera_dist' : self.camera_distance.get_value(),
'canvas_width' : self.width.get_value(),
'celllinewidth' : self.line_width.get_value(),
'textures' : self.set_textures(),
'exportconstraints' : self.render_constraints.get_active()}
if self.single_frame.get_active():
frames = [self.gui.frame]
else:
frames = range(self.nimages)
initial_frame = self.gui.frame
for frame in frames:
self.gui.set_frame(frame)
povray_settings['colors'] = self.get_colors()
atoms = self.gui.images.get_atoms(frame)
self.set_outputname()
filename = self.outputname.get_text()
print " | Writing files for image", filename, "..."
write_pov(filename,
atoms,
radii = self.gui.images.r,
**povray_settings)
if not self.keep_files.get_active():
print " | Deleting temporary file ", filename
system("rm "+filename)
filename = filename[:-4] + '.ini'
print " | Deleting temporary file ", filename
system("rm "+filename)
self.gui.set_frame(initial_frame)
self.set_outputname()
python-ase-3.6.0.2515/ase/gui/graphs.py 0000644 0001754 0001754 00000007231 11706276516 016410 0 ustar askhl askhl #!/usr/bin/env python
from math import sqrt
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack, help
class Graphs(gtk.Window):
def __init__(self, gui):
gtk.Window.__init__(self)
#self.window.set_position(gtk.WIN_POS_CENTER)
#self.window.connect("destroy", lambda w: gtk.main_quit())
#self.window.connect('delete_event', self.exit)
self.set_title('Graphs')
vbox = gtk.VBox()
self.expr = pack(vbox, [gtk.Entry(64),
help(_('Help for plot ...'))])[0]
self.expr.connect('activate', self.plot)
completion = gtk.EntryCompletion()
self.liststore = gtk.ListStore(str)
for s in ['fmax', 's, e-E[0]', 'i, d(0,1)']:
self.liststore.append([s])
completion.set_model(self.liststore)
self.expr.set_completion(completion)
completion.set_text_column(0)
button = pack(vbox, [gtk.Button(_('Plot')),
gtk.Label(' x, y1, y2, ...')])[0]
button.connect('clicked', self.plot, 'xy')
button = pack(vbox, [gtk.Button(_('Plot')),
gtk.Label(' y1, y2, ...')])[0]
button.connect('clicked', self.plot, 'y')
save_button = gtk.Button(stock=gtk.STOCK_SAVE)
save_button.connect('clicked',self.save)
clear_button = gtk.Button(_('clear'))
clear_button.connect('clicked', self.clear)
pack(vbox, [save_button,clear_button])
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
def plot(self, button=None, type=None, expr=None):
if expr is None:
expr = self.expr.get_text()
else:
self.expr.set_text(expr)
if expr not in [row[0] for row in self.liststore]:
self.liststore.append([expr])
data = self.gui.images.graph(expr)
import matplotlib
matplotlib.interactive(True)
matplotlib.use('GTK')
#matplotlib.use('GTK', warn=False)# Not avail. in 0.91 (it is in 0.98)
import pylab
pylab.ion()
x = 2.5
self.gui.graphs.append(pylab.figure(figsize=(x * 2.5**0.5, x)))
i = self.gui.frame
m = len(data)
if type is None:
if m == 1:
type = 'y'
else:
type = 'xy'
if type == 'y':
for j in range(m):
pylab.plot(data[j])
pylab.plot([i], [data[j, i]], 'o')
else:
for j in range(1, m):
pylab.plot(data[0], data[j])
pylab.plot([data[0, i]], [data[j, i]], 'o')
pylab.title(expr)
#pylab.show()
python = plot
def save(self, filename):
chooser = gtk.FileChooserDialog(
_('Save data to file ... '), None, gtk.FILE_CHOOSER_ACTION_SAVE,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
save = chooser.run()
if save == gtk.RESPONSE_OK:
filename = chooser.get_filename()
expr = self.expr.get_text()
data = self.gui.images.graph(expr)
expr = '# '+expr
fd = open(filename,'w')
fd.write("%s \n" % (expr))
for s in range(len(data[0])):
for i in range(len(data)):
val = data[i,s]
fd.write("%12.8e\t" % (val))
fd.write("\n")
fd.close()
chooser.destroy()
def clear(self, button):
import pylab
for graph in self.gui.graphs:
pylab.close(graph)
self.gui.graphs = []
python-ase-3.6.0.2515/ase/gui/languages/ 0000755 0001754 0001754 00000000000 11757245036 016514 5 ustar askhl askhl python-ase-3.6.0.2515/ase/gui/languages/__init__.py 0000644 0001754 0001754 00000001317 10713161602 020612 0 ustar askhl askhl import locale
from ase.gui.languages.en import translation as default_translation
def translate(text):
return default_translation.get(text, text)
language_code = locale.getdefaultlocale()[0]
if language_code is None:
language_code = 'en'
else:
language_code = language_code[:2]
if language_code != 'en':
try:
module = __import__(language_code, globals(), locals())
except ImportError:
pass
else:
translation = module.translation
def translate(text):
translated_text = translation.get(text)
if translated_text is None:
return default_translation.get(text, text)
else:
return translated_text
python-ase-3.6.0.2515/ase/gui/languages/en.py 0000644 0001754 0001754 00000002366 11672656022 017474 0 ustar askhl askhl translation = {
'Tip for status box ...':
"""Show information about selected atoms (type, position, bondlengths and angles). Use left mouse button to select atoms - possibly combined with the [ctrl] key.""",
'Help for plot ...':
"""Symbols:
e:\t\t\ttotal energy
epot:\t\tpotential energy
ekin:\t\tkinetic energy
fmax:\t\tmaximum force
fave:\t\taverage force
R[n,0-2]:\t\tposition of atom number n
d(n1,n2):\t\tdistance between two atoms n1 and n2
i:\t\t\tcurrent image number
E[i]:\t\t\tenergy of image number i
F[n,0-2]:\t\tforce on atom number n
V[n,0-2]:\t\tvelocity of atom number n
M[n]:\t\tmagnetic moment of atom number n
A[0-2,0-2]:\tunit-cell basis vectors
s:\t\t\tpath length
a(n1,n2,n3):\tangle between atoms n1, n2 and n3, centered on n2
dih(n1,n2,n3,n4):\tdihedral angle between n1, n2, n3, and n4
T:\t\t\tTemperature (K)""",
'Help for slice ...':
"""Use Python slice syntax: "start:stop:step" or "start:stop":
2:5\tsecond, third and fourth
:3\tfirst three
-3:\tlast three
::3\tevery third
0\tfirst
6\tseventh
-1\tlast
"""
}
python-ase-3.6.0.2515/ase/gui/languages/da.py 0000644 0001754 0001754 00000002277 11672656022 017457 0 ustar askhl askhl # -*- coding: utf-8 -*-
"""Danish translation."""
translation = {
'Select': u'Vælg',
'Invert selection': 'Inverter valg',
'Select all': u'Vælg alle',
'View': 'Vis',
'Focus': u'Fokusér',
'Settings': 'Indstillinger',
'Plugins': 'Indstik',
'Help': u'Hjælp',
'Edit': u'Redigér',
'File': 'Fil',
'Exit': 'Afslut',
'Open': u'Ã…ben',
'Play': 'Afspil',
'Adjust play time.': 'Indstil afspilningstid',
'Image number:': 'Billede nummer:',
'Tip for status box ...':
"""Vis informationer om valgte atomer (type, position, bindingslængder
og vinkler) ved at vælge atomer med musen (venstre knap) evt. i
kombination med [ctrl] tasten""",
'Help for plot ...':
u"""Symboler:
e:\t\ttotal energi
epot:\tpotentiel energi
ekin:\tkinetisk energi
fmax:\tmaximum kræft
fave:\tmiddel kræft
R[n,0-2]:\tposition af atom nummer n
d(n1,n1):\tafstand mellem to atomer
i:\t\tnuværende billede nummer
E[i]:\t\tenergi af billede nummer i
F[n,0-2]:\tkræft på atom nummer n
V[n,0-2]:\thastighed af atom nummer n
A[0-2,0-2]:\tEnhedscelle vektorer
s:\t\tvejlængde""",
'Slice: ': 'Udsnit: '
}
python-ase-3.6.0.2515/ase/gui/nanoparticle.py 0000644 0001754 0001754 00000062500 11706276516 017603 0 ustar askhl askhl # encoding: utf-8
"""nanoparticle.py - Window for setting up crystalline nanoparticles.
"""
import gtk
from gettext import gettext as _
from copy import copy
from ase.gui.widgets import pack, cancel_apply_ok, oops, help
from ase.gui.setupwindow import SetupWindow
from ase.gui.pybutton import PyButton
import ase
import numpy as np
# Delayed imports:
# ase.cluster.data
from ase.cluster.cubic import FaceCenteredCubic, BodyCenteredCubic, SimpleCubic
from ase.cluster.hexagonal import HexagonalClosedPacked, Graphite
from ase.cluster import wulff_construction
introtext = _("""\
Create a nanoparticle either by specifying the number of layers, or using the
Wulff construction. Please press the [Help] button for instructions on how to
specify the directions.
WARNING: The Wulff construction currently only works with cubic crystals!
""")
helptext = _("""
The nanoparticle module sets up a nano-particle or a cluster with a given
crystal structure.
1) Select the element, the crystal structure and the lattice constant(s).
The [Get structure] button will find the data for a given element.
2) Choose if you want to specify the number of layers in each direction, or if
you want to use the Wulff construction. In the latter case, you must specify
surface energies in each direction, and the size of the cluster.
How to specify the directions:
------------------------------
First time a direction appears, it is interpreted as the entire family of
directions, i.e. (0,0,1) also covers (1,0,0), (-1,0,0) etc. If one of these
directions is specified again, the second specification overrules that specific
direction. For this reason, the order matters and you can rearrange the
directions with the [Up] and [Down] keys. You can also add a new direction,
remember to press [Add] or it will not be included.
Example: (1,0,0) (1,1,1), (0,0,1) would specify the {100} family of directions,
the {111} family and then the (001) direction, overruling the value given for
the whole family of directions.
""")
py_template_layers = """
import ase
%(import)s
surfaces = %(surfaces)s
layers = %(layers)s
lc = %(latconst)s
atoms = %(factory)s('%(element)s', surfaces, layers, latticeconstant=lc)
# OPTIONAL: Cast to ase.Atoms object, discarding extra information:
# atoms = ase.Atoms(atoms)
"""
py_template_wulff = """
import ase
from ase.cluster import wulff_construction
surfaces = %(surfaces)s
esurf = %(energies)s
lc = %(latconst)s
size = %(natoms)s # Number of atoms
atoms = wulff_construction('%(element)s', surfaces, esurf, size, '%(structure)s',
rounding='%(rounding)s', latticeconstant=lc)
# OPTIONAL: Cast to ase.Atoms object, discarding extra information:
# atoms = ase.Atoms(atoms)
"""
class SetupNanoparticle(SetupWindow):
"Window for setting up a nanoparticle."
# Structures: Abbreviation, name, 4-index (boolean), two lattice const (bool), factory
structure_data = (('fcc', _('Face centered cubic (fcc)'), False, False, FaceCenteredCubic),
('bcc', _('Body centered cubic (bcc)'), False, False, BodyCenteredCubic),
('sc', _('Simple cubic (sc)'), False, False, SimpleCubic),
('hcp', _('Hexagonal closed-packed (hcp)'), True, True, HexagonalClosedPacked),
('graphite', _('Graphite'), True, True, Graphite),
)
#NB: HCP is broken!
# A list of import statements for the Python window.
import_names = {'fcc': 'from ase.cluster.cubic import FaceCenteredCubic',
'bcc': 'from ase.cluster.cubic import BodyCenteredCubic',
'sc': 'from ase.cluster.cubic import SimpleCubic',
'hcp': 'from ase.cluster.hexagonal import HexagonalClosedPacked',
'graphite': 'from ase.cluster.hexagonal import Graphite',
}
# Default layer specifications for the different structures.
default_layers = {'fcc': [( (1,0,0), 6),
( (1,1,0), 9),
( (1,1,1), 5)],
'bcc': [( (1,0,0), 6),
( (1,1,0), 9),
( (1,1,1), 5)],
'sc': [( (1,0,0), 6),
( (1,1,0), 9),
( (1,1,1), 5)],
'hcp': [( (0,0,0,1), 5),
( (1,0,-1,0), 5)],
'graphite': [( (0,0,0,1), 5),
( (1,0,-1,0), 5)]
}
def __init__(self, gui):
SetupWindow.__init__(self)
self.set_title(_("Nanoparticle"))
self.atoms = None
self.no_update = True
vbox = gtk.VBox()
# Intoductory text
self.packtext(vbox, introtext)
# Choose the element
label = gtk.Label(_("Element: "))
label.set_alignment(0.0, 0.2)
element = gtk.Entry(max=3)
self.element = element
lattice_button = gtk.Button(_("Get structure"))
lattice_button.connect('clicked', self.set_structure_data)
self.elementinfo = gtk.Label(" ")
pack(vbox, [label, element, self.elementinfo, lattice_button], end=True)
self.element.connect('activate', self.update)
self.legal_element = False
# The structure and lattice constant
label = gtk.Label(_("Structure: "))
self.structure = gtk.combo_box_new_text()
self.list_of_structures = []
self.needs_4index = {}
self.needs_2lat = {}
self.factory = {}
for abbrev, name, n4, c, factory in self.structure_data:
self.structure.append_text(name)
self.list_of_structures.append(abbrev)
self.needs_4index[abbrev] = n4
self.needs_2lat[abbrev] = c
self.factory[abbrev] = factory
self.structure.set_active(0)
self.fourindex = self.needs_4index[self.list_of_structures[0]]
self.structure.connect('changed', self.update_structure)
label2 = gtk.Label(_("Lattice constant: a ="))
self.lattice_const_a = gtk.Adjustment(3.0, 0.0, 1000.0, 0.01)
self.lattice_const_c = gtk.Adjustment(5.0, 0.0, 1000.0, 0.01)
self.lattice_box_a = gtk.SpinButton(self.lattice_const_a, 10.0, 3)
self.lattice_box_c = gtk.SpinButton(self.lattice_const_c, 10.0, 3)
self.lattice_box_a.numeric = True
self.lattice_box_c.numeric = True
self.lattice_label_c = gtk.Label(" c =")
pack(vbox, [label, self.structure])
pack(vbox, [label2, self.lattice_box_a,
self.lattice_label_c, self.lattice_box_c])
self.lattice_label_c.hide()
self.lattice_box_c.hide()
self.lattice_const_a.connect('value-changed', self.update)
self.lattice_const_c.connect('value-changed', self.update)
# Choose specification method
label = gtk.Label(_("Method: "))
self.method = gtk.combo_box_new_text()
for meth in (_("Layer specification"), _("Wulff construction")):
self.method.append_text(meth)
self.method.set_active(0)
self.method.connect('changed', self.update_gui_method)
pack(vbox, [label, self.method])
pack(vbox, gtk.Label(""))
self.old_structure = None
frame = gtk.Frame()
pack(vbox, frame)
framebox = gtk.VBox()
frame.add(framebox)
framebox.show()
self.layerlabel = gtk.Label("Missing text") # Filled in later
pack(framebox, [self.layerlabel])
# This box will contain a single table that is replaced when
# the list of directions is changed.
self.direction_table_box = gtk.VBox()
pack(framebox, self.direction_table_box)
pack(self.direction_table_box,
gtk.Label(_("Dummy placeholder object")))
pack(framebox, gtk.Label(""))
pack(framebox, [gtk.Label(_("Add new direction:"))])
self.newdir_label = []
self.newdir_box = []
self.newdir_index = []
packlist = []
for txt in ('(', ', ', ', ', ', '):
self.newdir_label.append(gtk.Label(txt))
adj = gtk.Adjustment(0, -100, 100, 1)
self.newdir_box.append(gtk.SpinButton(adj, 1, 0))
self.newdir_index.append(adj)
packlist.append(self.newdir_label[-1])
packlist.append(self.newdir_box[-1])
self.newdir_layers = gtk.Adjustment(5, 0, 100, 1)
self.newdir_layers_box = gtk.SpinButton(self.newdir_layers, 1, 0)
self.newdir_esurf = gtk.Adjustment(1.0, 0, 1000.0, 0.1)
self.newdir_esurf_box = gtk.SpinButton(self.newdir_esurf, 10, 3)
addbutton = gtk.Button(_("Add"))
addbutton.connect('clicked', self.row_add)
packlist.extend([gtk.Label("): "),
self.newdir_layers_box,
self.newdir_esurf_box,
gtk.Label(" "),
addbutton])
pack(framebox, packlist)
self.defaultbutton = gtk.Button(_("Set all directions to default "
"values"))
self.defaultbutton.connect('clicked', self.default_direction_table)
self.default_direction_table()
# Extra widgets for the Wulff construction
self.wulffbox = gtk.VBox()
pack(vbox, self.wulffbox)
label = gtk.Label(_("Particle size: "))
self.size_n_radio = gtk.RadioButton(None, _("Number of atoms: "))
self.size_n_radio.set_active(True)
self.size_n_adj = gtk.Adjustment(100, 1, 100000, 1)
self.size_n_spin = gtk.SpinButton(self.size_n_adj, 0, 0)
self.size_dia_radio = gtk.RadioButton(self.size_n_radio,
_("Volume: "))
self.size_dia_adj = gtk.Adjustment(1.0, 0, 100.0, 0.1)
self.size_dia_spin = gtk.SpinButton(self.size_dia_adj, 10.0, 2)
pack(self.wulffbox, [label, self.size_n_radio, self.size_n_spin,
gtk.Label(" "), self.size_dia_radio, self.size_dia_spin,
gtk.Label(_("ų"))])
self.size_n_radio.connect("toggled", self.update_gui_size)
self.size_dia_radio.connect("toggled", self.update_gui_size)
self.size_n_adj.connect("value-changed", self.update_size_n)
self.size_dia_adj.connect("value-changed", self.update_size_dia)
label = gtk.Label(_("Rounding: If exact size is not possible, "
"choose the size"))
pack(self.wulffbox, [label])
self.round_above = gtk.RadioButton(None, _("above "))
self.round_below = gtk.RadioButton(self.round_above, _("below "))
self.round_closest = gtk.RadioButton(self.round_above, _("closest "))
self.round_closest.set_active(True)
butbox = gtk.HButtonBox()
self.smaller_button = gtk.Button(_("Smaller"))
self.larger_button = gtk.Button(_("Larger"))
self.smaller_button.connect('clicked', self.wulff_smaller)
self.larger_button.connect('clicked', self.wulff_larger)
pack(butbox, [self.smaller_button, self.larger_button])
buts = [self.round_above, self.round_below, self.round_closest]
for b in buts:
b.connect("toggled", self.update)
buts.append(butbox)
pack(self.wulffbox, buts, end=True)
# Information
pack(vbox, gtk.Label(""))
infobox = gtk.VBox()
label1 = gtk.Label(_("Number of atoms: "))
self.natoms_label = gtk.Label("-")
label2 = gtk.Label(_(" Approx. diameter: "))
self.dia1_label = gtk.Label("-")
pack(infobox, [label1, self.natoms_label, label2, self.dia1_label])
pack(infobox, gtk.Label(""))
infoframe = gtk.Frame(_("Information about the created cluster:"))
infoframe.add(infobox)
infobox.show()
pack(vbox, infoframe)
# Buttons
self.pybut = PyButton(_("Creating a nanoparticle."))
self.pybut.connect('clicked', self.makeatoms)
helpbut = help(helptext)
buts = cancel_apply_ok(cancel=lambda widget: self.destroy(),
apply=self.apply,
ok=self.ok)
pack(vbox, [self.pybut, helpbut, buts], end=True, bottom=True)
self.auto = gtk.CheckButton(_("Automatic Apply"))
fr = gtk.Frame()
fr.add(self.auto)
fr.show_all()
pack(vbox, [fr], end=True, bottom=True)
# Finalize setup
self.update_structure()
self.update_gui_method()
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
self.no_update = False
def default_direction_table(self, widget=None):
"Set default directions and values for the current crystal structure."
self.direction_table = []
struct = self.get_structure()
for direction, layers in self.default_layers[struct]:
adj1 = gtk.Adjustment(layers, -100, 100, 1)
adj2 = gtk.Adjustment(1.0, -1000.0, 1000.0, 0.1)
adj1.connect("value-changed", self.update)
adj2.connect("value-changed", self.update)
self.direction_table.append([direction, adj1, adj2])
self.update_direction_table()
def update_direction_table(self):
"Update the part of the GUI containing the table of directions."
#Discard old table
oldwidgets = self.direction_table_box.get_children()
assert len(oldwidgets) == 1
oldwidgets[0].hide()
self.direction_table_box.remove(oldwidgets[0])
del oldwidgets # It should now be gone
tbl = gtk.Table(len(self.direction_table)+1, 7)
pack(self.direction_table_box, [tbl])
for i, data in enumerate(self.direction_table):
tbl.attach(gtk.Label("%s: " % (str(data[0]),)),
0, 1, i, i+1)
if self.method.get_active():
# Wulff construction
spin = gtk.SpinButton(data[2], 1.0, 3)
else:
# Layers
spin = gtk.SpinButton(data[1], 1, 0)
tbl.attach(spin, 1, 2, i, i+1)
tbl.attach(gtk.Label(" "), 2, 3, i, i+1)
but = gtk.Button(_("Up"))
but.connect("clicked", self.row_swap_next, i-1)
if i == 0:
but.set_sensitive(False)
tbl.attach(but, 3, 4, i, i+1)
but = gtk.Button(_("Down"))
but.connect("clicked", self.row_swap_next, i)
if i == len(self.direction_table)-1:
but.set_sensitive(False)
tbl.attach(but, 4, 5, i, i+1)
but = gtk.Button(_("Delete"))
but.connect("clicked", self.row_delete, i)
if len(self.direction_table) == 1:
but.set_sensitive(False)
tbl.attach(but, 5, 6, i, i+1)
tbl.show_all()
self.update()
def get_structure(self):
"Returns the crystal structure chosen by the user."
return self.list_of_structures[self.structure.get_active()]
def update_structure(self, widget=None):
"Called when the user changes the structure."
s = self.get_structure()
if s != self.old_structure:
old4 = self.fourindex
self.fourindex = self.needs_4index[s]
if self.fourindex != old4:
# The table of directions is invalid.
self.default_direction_table()
self.old_structure = s
if self.needs_2lat[s]:
self.lattice_label_c.show()
self.lattice_box_c.show()
else:
self.lattice_label_c.hide()
self.lattice_box_c.hide()
if self.fourindex:
self.newdir_label[3].show()
self.newdir_box[3].show()
else:
self.newdir_label[3].hide()
self.newdir_box[3].hide()
self.update()
def update_gui_method(self, widget=None):
"Switch between layer specification and Wulff construction."
self.update_direction_table()
if self.method.get_active():
self.wulffbox.show()
self.layerlabel.set_text(_("Surface energies (as energy/area, "
"NOT per atom):"))
self.newdir_layers_box.hide()
self.newdir_esurf_box.show()
else:
self.wulffbox.hide()
self.layerlabel.set_text(_("Number of layers:"))
self.newdir_layers_box.show()
self.newdir_esurf_box.hide()
self.update()
def wulff_smaller(self, widget=None):
"Make a smaller Wulff construction."
n = len(self.atoms)
self.size_n_radio.set_active(True)
self.size_n_adj.value = n-1
self.round_below.set_active(True)
self.apply()
def wulff_larger(self, widget=None):
"Make a larger Wulff construction."
n = len(self.atoms)
self.size_n_radio.set_active(True)
self.size_n_adj.value = n+1
self.round_above.set_active(True)
self.apply()
def row_add(self, widget=None):
"Add a row to the list of directions."
if self.fourindex:
n = 4
else:
n = 3
idx = tuple( [int(a.value) for a in self.newdir_index[:n]] )
if not np.array(idx).any():
oops(_("At least one index must be non-zero"))
return
if n == 4 and np.array(idx)[:3].sum() != 0:
oops(_("Invalid hexagonal indices",
"The sum of the first three numbers must be zero"))
return
adj1 = gtk.Adjustment(self.newdir_layers.value, -100, 100, 1)
adj2 = gtk.Adjustment(self.newdir_esurf.value, -1000.0, 1000.0, 0.1)
adj1.connect("value-changed", self.update)
adj2.connect("value-changed", self.update)
self.direction_table.append([idx, adj1, adj2])
self.update_direction_table()
def row_delete(self, widget, row):
del self.direction_table[row]
self.update_direction_table()
def row_swap_next(self, widget, row):
dt = self.direction_table
dt[row], dt[row+1] = dt[row+1], dt[row]
self.update_direction_table()
def update_gui_size(self, widget=None):
"Update gui when the cluster size specification changes."
self.size_n_spin.set_sensitive(self.size_n_radio.get_active())
self.size_dia_spin.set_sensitive(self.size_dia_radio.get_active())
def update_size_n(self, widget=None):
if not self.size_n_radio.get_active():
return
at_vol = self.get_atomic_volume()
dia = 2.0 * (3 * self.size_n_adj.value * at_vol / (4 * np.pi))**(1.0/3)
self.size_dia_adj.value = dia
self.update()
def update_size_dia(self, widget=None):
if not self.size_dia_radio.get_active():
return
at_vol = self.get_atomic_volume()
n = round(np.pi / 6 * self.size_dia_adj.value**3 / at_vol)
self.size_n_adj.value = n
self.update()
def update(self, *args):
if self.no_update:
return
self.update_element()
if self.auto.get_active():
self.makeatoms()
if self.atoms is not None:
self.gui.new_atoms(self.atoms)
else:
self.clearatoms()
self.makeinfo()
def set_structure_data(self, *args):
"Called when the user presses [Get structure]."
if not self.update_element():
oops(_("Invalid element."))
return
z = ase.atomic_numbers[self.legal_element]
ref = ase.data.reference_states[z]
if ref is None:
structure = None
else:
structure = ref['symmetry']
if ref is None or not structure in self.list_of_structures:
oops(_("Unsupported or unknown structure",
"Element = %s, structure = %s" % (self.legal_element,
structure)))
return
for i, s in enumerate(self.list_of_structures):
if structure == s:
self.structure.set_active(i)
a = ref['a']
self.lattice_const_a.set_value(a)
self.fourindex = self.needs_4index[structure]
if self.fourindex:
try:
c = ref['c']
except KeyError:
c = ref['c/a'] * a
self.lattice_const_c.set_value(c)
self.lattice_label_c.show()
self.lattice_box_c.show()
else:
self.lattice_label_c.hide()
self.lattice_box_c.hide()
def makeatoms(self, *args):
"Make the atoms according to the current specification."
if not self.update_element():
self.clearatoms()
self.makeinfo()
return False
assert self.legal_element is not None
struct = self.list_of_structures[self.structure.get_active()]
if self.needs_2lat[struct]:
# a and c lattice constants
lc = {'a': self.lattice_const_a.value,
'c': self.lattice_const_c.value}
lc_str = str(lc)
else:
lc = self.lattice_const_a.value
lc_str = "%.5f" % (lc,)
if self.method.get_active() == 0:
# Layer-by-layer specification
surfaces = [x[0] for x in self.direction_table]
layers = [int(x[1].value) for x in self.direction_table]
self.atoms = self.factory[struct](self.legal_element, copy(surfaces),
layers, latticeconstant=lc)
imp = self.import_names[struct]
self.pybut.python = py_template_layers % {'import': imp,
'element': self.legal_element,
'surfaces': str(surfaces),
'layers': str(layers),
'latconst': lc_str,
'factory': imp.split()[-1]
}
else:
# Wulff construction
assert self.method.get_active() == 1
surfaces = [x[0] for x in self.direction_table]
surfaceenergies = [x[2].value for x in self.direction_table]
self.update_size_dia()
if self.round_above.get_active():
rounding = "above"
elif self.round_below.get_active():
rounding = "below"
elif self.round_closest.get_active():
rounding = "closest"
else:
raise RuntimeError("No rounding!")
self.atoms = wulff_construction(self.legal_element, surfaces,
surfaceenergies,
self.size_n_adj.value,
self.factory[struct],
rounding, lc)
self.pybut.python = py_template_wulff % {'element': self.legal_element,
'surfaces': str(surfaces),
'energies': str(surfaceenergies),
'latconst': lc_str,
'natoms': self.size_n_adj.value,
'structure': struct,
'rounding': rounding
}
self.makeinfo()
def clearatoms(self):
self.atoms = None
self.pybut.python = None
def get_atomic_volume(self):
s = self.list_of_structures[self.structure.get_active()]
a = self.lattice_const_a.value
c = self.lattice_const_c.value
if s == 'fcc':
return a**3 / 4
elif s == 'bcc':
return a**3 / 2
elif s == 'sc':
return a**3
elif s == 'hcp':
return np.sqrt(3.0)/2 * a * a * c / 2
elif s == 'graphite':
return np.sqrt(3.0)/2 * a * a * c / 4
else:
raise RuntimeError("Unknown structure: "+s)
def makeinfo(self):
"""Fill in information field about the atoms.
Also turns the Wulff construction buttons [Larger] and
[Smaller] on and off.
"""
if self.atoms is None:
self.natoms_label.set_label("-")
self.dia1_label.set_label("-")
self.smaller_button.set_sensitive(False)
self.larger_button.set_sensitive(False)
else:
self.natoms_label.set_label(str(len(self.atoms)))
at_vol = self.get_atomic_volume()
dia = 2 * (3 * len(self.atoms) * at_vol / (4 * np.pi))**(1.0/3.0)
self.dia1_label.set_label(_("%.1f Ã…") % (dia,))
self.smaller_button.set_sensitive(True)
self.larger_button.set_sensitive(True)
def apply(self, *args):
self.makeatoms()
if self.atoms is not None:
self.gui.new_atoms(self.atoms)
return True
else:
oops(_("No valid atoms."),
_("You have not (yet) specified a consistent set of "
"parameters."))
return False
def ok(self, *args):
if self.apply():
self.destroy()
python-ase-3.6.0.2515/ase/gui/setupwindow.py 0000644 0001754 0001754 00000004131 11711330540 017470 0 ustar askhl askhl # encoding: utf-8
"""setupwindow.py - Window base class for setup modules.
"""
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack, cancel_apply_ok, oops
import ase
class SetupWindow(gtk.Window):
"Base class for ase.gui setup windows."
# __init__ inherited from gtk.Window
def packtext(self, vbox, text, label=None):
"Pack an text frame into the window."
pack(vbox, gtk.Label(""))
txtframe = gtk.Frame(label)
txtlbl = gtk.Label(text)
txtframe.add(txtlbl)
txtlbl.show()
pack(vbox, txtframe)
pack(vbox, gtk.Label(""))
def update_element(self, *args):
"Called when a new element may have been entered."
# Assumes the element widget is self.element and that a label
# to keep updated is self.elementinfo. The chemical symbol is
# placed in self.legalelement - or None if the element is
# invalid.
elem = self.element.get_text()
if not elem:
self.invalid_element(_(" No element specified!"))
return False
try:
z = int(elem)
except ValueError:
# Probably a symbol
try:
z = ase.data.atomic_numbers[elem]
except KeyError:
self.invalid_element()
return False
try:
symb = ase.data.chemical_symbols[z]
except KeyError:
self.invalid_element()
return False
name = ase.data.atomic_names[z]
ref = ase.data.reference_states[z]
if ref is None:
struct = _("No crystal structure data")
else:
struct = ref['symmetry']
if struct == 'fcc' or struct == 'bcc':
struct = "%s (a=%.3f Ã…)" % (struct, ref['a'])
txt = " %s: %s, Z=%i, %s" % (name, symb, z, struct)
self.elementinfo.set_text(txt)
self.legal_element = symb
return True
def invalid_element(self, txt=_(" ERROR: Invalid element!")):
self.legal_element = False
self.elementinfo.set_text(txt)
python-ase-3.6.0.2515/ase/gui/quickinfo.py 0000644 0001754 0001754 00000003247 11706276516 017117 0 ustar askhl askhl # encoding: utf-8
"Module for displaying information about the system."
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack
singleimage = _("Single image loaded.")
multiimage = _("Image %d loaded (0 - %d).")
ucconst = _("Unit cell is fixed.")
ucvaries = _("Unit cell varies.")
format = _("""\
%s
Number of atoms: %d.
Unit cell:
%8.3f %8.3f %8.3f
%8.3f %8.3f %8.3f
%8.3f %8.3f %8.3f
%s
""")
class QuickInfo(gtk.Window):
def __init__(self, gui):
gtk.Window.__init__(self)
self.set_title(_("Quick Info"))
vbox = gtk.VBox()
images = gui.images
if images.natoms < 1:
txt = _("No atoms loaded.")
else:
(nimg, natoms, three) = images.P.shape
assert three == 3
img = gui.frame
uc = images.A[img]
if nimg > 1:
equal = True
for i in range(nimg):
equal = equal and (uc == images.A[i]).all()
if equal:
uctxt = ucconst
else:
uctxt = ucvaries
else:
uctxt = ""
if nimg == 1:
imgtxt = singleimage
else:
imgtxt = multiimage % (img, nimg-1)
txt = format % ((imgtxt, natoms) + tuple(uc.flat) + (uctxt,))
label = gtk.Label(txt)
pack(vbox, [label])
but = gtk.Button(stock=gtk.STOCK_CLOSE)
but.connect('clicked', self.close)
pack(vbox, [but], end=True)
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
def close(self, *args):
self.destroy()
python-ase-3.6.0.2515/ase/gui/rotate.py 0000644 0001754 0001754 00000003064 11706276516 016422 0 ustar askhl askhl import numpy as np
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack
from ase.utils import rotate, irotate
class Rotate(gtk.Window):
update = True
def __init__(self, gui):
gtk.Window.__init__(self)
angles = irotate(gui.axes)
self.set_title(_('Rotate'))
vbox = gtk.VBox()
pack(vbox, gtk.Label(_('Rotation angles:')))
self.rotate = [gtk.Adjustment(value=a, lower=-360, upper=360,
step_incr=1, page_incr=10)
for a in angles]
pack(vbox, [gtk.SpinButton(a, climb_rate=0, digits=1)
for a in self.rotate])
for r in self.rotate:
r.connect('value-changed', self.change)
button = pack(vbox, gtk.Button(_('Update')))
button.connect('clicked', self.update_angles)
pack(vbox, gtk.Label(_('Note:\nYou can rotate freely\n'
'with the mouse, by holding\n'
'down mouse button 2.')))
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
def change(self, adjustment):
if self.update:
x, y, z = [float(a.value) for a in self.rotate]
self.gui.axes = rotate('%fx,%fy,%fz' % (x, y, z))
self.gui.set_coordinates()
return True
def update_angles(self, button):
angles = irotate(self.gui.axes)
self.update = False
for r, a in zip(self.rotate, angles):
r.value = a
self.update = True
python-ase-3.6.0.2515/ase/gui/scaling.py 0000644 0001754 0001754 00000046460 11706276516 016553 0 ustar askhl askhl # encoding: utf-8
"Module for homogeneous deformation and calculations of elastic constants."
import gtk
from gettext import gettext as _
from ase.gui.simulation import Simulation
from ase.gui.minimize import MinimizeMixin
from ase.gui.energyforces import OutputFieldMixin
from ase.gui.widgets import oops, pack, AseGuiCancelException
import ase
import numpy as np
scaling_txt = """\
This module is intended for calculating elastic constants by homogeneously
deforming a system."""
help_txt = """
The homogeneous scaling module changes the size of a system by stretching it
along on or more directions. Small amounts of deformation can be used to
calculate elastic constants, large amounts to simulate plastic deformation.
You will have to choose along which axis/axes the deformation is done. Usually,
it only makes sense to deform along axes with periodic boundary conditions. The
amount of deformation is set in the Deformation frame. A scale factor of
e.g. 0.01 means that the system is changed incrementally from being 1% smaller
than the initial configuration to 1% larger. The offset alters this so it is
not symmetric around 0% deformation. A check-box can disable the negative
deformation (compression).
'Atomic relaxations' means that the individual atoms are allowed to move
relative to the unit cell. This is done by performing an energy minimization
for each configuration. You will have to choose the algorithm and minimization
parameters.
During the deformation, a number of steps is taken, with different system sizes.
You can choose to load all configurations into the main window as a movie, to
only load the configuration with the lowest energy, or to keep the original
configuration loaded. Important: If you repeat the calculation by
pressing [Run] a second time, the starting configuration will have changed
unless you keep the original configuration.
"""
class HomogeneousDeformation(Simulation, MinimizeMixin, OutputFieldMixin):
"Window for homogeneous deformation and elastic constants."
use_scrollbar = True
def __init__(self, gui):
Simulation.__init__(self, gui)
self.set_title(_("Homogeneous scaling"))
self.scaling_is_ready = False
vbox = gtk.VBox()
self.packtext(vbox, scaling_txt)
self.packimageselection(vbox, txt1="", txt2="")
self.start_radio_nth.set_active(True)
pack(vbox, gtk.Label(""))
# Radio buttons for choosing deformation mode.
tbl = gtk.Table(4,3)
for i, l in enumerate([_('3D deformation '),
_('2D deformation '),
_('1D deformation ')]):
lbl = gtk.Label(l)
tbl.attach(lbl, i, i+1, 0, 1)
self.radio_bulk = gtk.RadioButton(None, _("Bulk"))
tbl.attach(self.radio_bulk, 0, 1, 1, 2)
self.radio_xy = gtk.RadioButton(self.radio_bulk, _("xy-plane"))
tbl.attach(self.radio_xy, 1, 2, 1, 2)
self.radio_xz = gtk.RadioButton(self.radio_bulk, _("xz-plane"))
tbl.attach(self.radio_xz, 1, 2, 2, 3)
self.radio_yz = gtk.RadioButton(self.radio_bulk, _("yz-plane"))
tbl.attach(self.radio_yz, 1, 2, 3, 4)
self.radio_x = gtk.RadioButton(self.radio_bulk, _("x-axis"))
tbl.attach(self.radio_x, 2, 3, 1, 2)
self.radio_y = gtk.RadioButton(self.radio_bulk, _("y-axis"))
tbl.attach(self.radio_y, 2, 3, 2, 3)
self.radio_z = gtk.RadioButton(self.radio_bulk, _("z-axis"))
tbl.attach(self.radio_z, 2, 3, 3, 4)
tbl.show_all()
pack(vbox, [tbl])
self.deformtable = [
(self.radio_bulk, (1,1,1)),
(self.radio_xy, (1,1,0)),
(self.radio_xz, (1,0,1)),
(self.radio_yz, (0,1,1)),
(self.radio_x, (1,0,0)),
(self.radio_y, (0,1,0)),
(self.radio_z, (0,0,1))]
self.allow_non_pbc = gtk.CheckButton(
_("Allow deformation along non-periodic directions."))
pack(vbox, [self.allow_non_pbc])
self.allow_non_pbc.connect('toggled', self.choose_possible_deformations)
# Parameters for the deformation
framedef = gtk.Frame(_("Deformation:"))
vbox2 = gtk.VBox()
vbox2.show()
framedef.add(vbox2)
self.max_scale = gtk.Adjustment(0.010, 0.001, 10.0, 0.001)
max_scale_spin = gtk.SpinButton(self.max_scale, 10.0, 3)
pack(vbox2, [gtk.Label(_("Maximal scale factor: ")), max_scale_spin])
self.scale_offset = gtk.Adjustment(0.0, -10.0, 10.0, 0.001)
self.scale_offset_spin = gtk.SpinButton(self.scale_offset, 10.0, 3)
pack(vbox2, [gtk.Label(_("Scale offset: ")), self.scale_offset_spin])
self.nsteps = gtk.Adjustment(5, 3, 1000, 1)
nsteps_spin = gtk.SpinButton(self.nsteps, 1, 0)
pack(vbox2, [gtk.Label(_("Number of steps: ")), nsteps_spin])
self.pull = gtk.CheckButton(_("Only positive deformation"))
pack(vbox2, [self.pull])
self.pull.connect('toggled', self.pull_toggled)
# Atomic relaxations
framerel = gtk.Frame(_("Atomic relaxations:"))
vbox2 = gtk.VBox()
vbox2.show()
framerel.add(vbox2)
self.radio_relax_on = gtk.RadioButton(None, _("On "))
self.radio_relax_off = gtk.RadioButton(self.radio_relax_on, _("Off"))
self.radio_relax_off.set_active(True)
pack(vbox2, [self.radio_relax_on, self.radio_relax_off])
self.make_minimize_gui(vbox2)
for r in (self.radio_relax_on, self.radio_relax_off):
r.connect("toggled", self.relax_toggled)
self.relax_toggled()
pack(vbox, [framedef, gtk.Label(" "), framerel])
pack(vbox, gtk.Label(""))
# Results
pack(vbox, [gtk.Label(_("Results:"))])
self.radio_results_keep = gtk.RadioButton(
None, _("Keep original configuration"))
self.radio_results_optimal = gtk.RadioButton(
self.radio_results_keep, _("Load optimal configuration"))
self.radio_results_all = gtk.RadioButton(
self.radio_results_optimal, _("Load all configurations"))
self.radio_results_keep.set_active(True)
pack(vbox, [self.radio_results_keep])
pack(vbox, [self.radio_results_optimal])
pack(vbox, [self.radio_results_all])
# Output field
#label = gtk.Label("Strain\t\tEnergy [eV]\n")
outframe = self.makeoutputfield(None,
heading=_("Strain\t\tEnergy [eV]"))
fitframe = gtk.Frame(_("Fit:"))
vbox2 = gtk.VBox()
vbox2.show()
fitframe.add(vbox2)
self.radio_fit_2 = gtk.RadioButton(None, _("2nd"))
self.radio_fit_3 = gtk.RadioButton(self.radio_fit_2, _("3rd"))
self.radio_fit_2.connect("toggled", self.change_fit)
self.radio_fit_3.connect("toggled", self.change_fit)
self.radio_fit_3.set_active(True)
pack(vbox2, [gtk.Label(_("Order of fit: ")), self.radio_fit_2,
self.radio_fit_3])
pack(vbox2, [gtk.Label("")])
scrwin = gtk.ScrolledWindow()
scrwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.fit_output = gtk.TextBuffer()
txtview = gtk.TextView(self.fit_output)
txtview.set_editable(False)
scrwin.add(txtview)
scrwin.show_all()
self.fit_win = scrwin
vbox2.pack_start(scrwin, True, True, 0)
hbox = gtk.HBox(homogeneous=True)
for w in [outframe, fitframe]:
hbox.pack_start(w)
w.show()
pack(vbox, hbox)
pack(vbox, gtk.Label(""))
# Status field
self.status_label = gtk.Label("")
pack(vbox, [self.status_label])
# Activate the right deformation buttons
self.choose_possible_deformations(first=True)
# Run buttons etc.
self.makebutbox(vbox, helptext=help_txt)
vbox.show()
if self.use_scrollbar:
self.scrwin = gtk.ScrolledWindow()
self.scrwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.scrwin.add_with_viewport(vbox)
self.scrwin.show()
self.add(self.scrwin)
self.scaling_is_ready = True
self.set_reasonable_size()
else:
self.add(vbox)
self.show()
self.gui.register_vulnerable(self)
def set_reasonable_size(self, resize=False):
if not self.use_scrollbar or not self.scaling_is_ready:
return
x, y = self.scrwin.get_children()[0].size_request()
x += self.scrwin.get_vscrollbar().size_request()[0] + 5
y += self.scrwin.get_hscrollbar().size_request()[1] + 5
print x,y
if resize:
xdef, ydef = self.get_default_size()
xnow, ynow = self.get_size()
if xdef == xnow and ydef == ynow:
# The user has not changed the size. Resize should be OK
self.resize(x,y)
self.set_default_size(x,y)
else:
self.set_default_size(x,y)
def min_algo_specific(self, *args):
MinimizeMixin.min_algo_specific(self, *args)
self.set_reasonable_size(resize=True)
def choose_possible_deformations(self, widget=None, first=False):
"""Turn on sensible radio buttons.
Only radio buttons corresponding to deformations in directions
with periodic boundary conditions should be turned on.
"""
if self.setup_atoms():
pbc = self.atoms.get_pbc()
else:
pbc = np.array([False, False, False], bool)
if (pbc == [True, True, True]).all():
self.allow_non_pbc.set_active(False)
self.allow_non_pbc.set_sensitive(False)
else:
self.allow_non_pbc.set_sensitive(True)
if self.allow_non_pbc.get_active():
pbc = [True, True, True] #All is allowed
self.radio_relax_off.set_active(True)
self.radio_relax_on.set_sensitive(False)
else:
self.radio_relax_on.set_sensitive(True)
for radio, requirement in self.deformtable:
ok = True
for i in range(3):
if requirement[i] and not pbc[i]:
ok = False
radio.set_sensitive(ok)
if first and ok:
# The first acceptable choice, choose it to prevent
# inconsistent state.
radio.set_active(True)
first = False
def relax_toggled(self, *args):
"Turn minimization widgets on or off."
state = self.radio_relax_on.get_active()
for widget in (self.algo, self.fmax_spin, self.steps_spin):
widget.set_sensitive(state)
def pull_toggled(self, *args):
"When positive def. only, the scale offset is turned off."
self.scale_offset_spin.set_sensitive(not self.pull.get_active())
def notify_atoms_changed(self):
"When atoms have changed, check for the number of images."
self.setupimageselection()
self.choose_possible_deformations()
self.set_reasonable_size(resize=True)
def get_deformation_axes(self):
"""Return which axes the user wants to deform along."""
for but, deform in self.deformtable:
if but.get_active():
return np.array(deform)
# No deformation chosen!
oops("No deformation chosen: Please choose a deformation mode.")
return False
def run(self, *args):
"""Make the deformation."""
self.output.set_text("")
if not self.setup_atoms():
return
deform_axes = self.get_deformation_axes()
if deform_axes is False:
return #Nothing to do!
# Prepare progress bar
if self.radio_relax_on.get_active():
fmax = self.fmax.value
mininame = self.minimizers[self.algo.get_active()]
self.begin(mode="scale/min", algo=mininame, fmax=fmax,
steps=self.steps.value, scalesteps=self.nsteps.value)
else:
self.begin(mode="scale", scalesteps=self.nsteps.value)
try:
logger_func = self.gui.simulation['progress'].get_logger_stream
except (KeyError, AttributeError):
logger = None
else:
logger = logger_func() # Don't catch errors in the function.
# Display status message
self.status_label.set_text(_("Running ..."))
self.status_label.modify_fg(gtk.STATE_NORMAL,
gtk.gdk.color_parse('#AA0000'))
while gtk.events_pending():
gtk.main_iteration()
# Do the scaling
scale = self.max_scale.value
if self.pull.get_active():
steps = np.linspace(0, scale, self.nsteps.value)
else:
steps = np.linspace(-scale, scale, self.nsteps.value)
steps += self.scale_offset.value
undef_cell = self.atoms.get_cell()
results = []
#txt = "Strain\t\tEnergy [eV]\n"
txt = ""
# If we load all configurations, prepare it.
if self.radio_results_all.get_active():
self.prepare_store_atoms()
stored_atoms = False
try:
# Now, do the deformation
for i, d in enumerate(steps):
deformation = np.diag(1.0 + d * deform_axes)
self.atoms.set_cell(np.dot(undef_cell, deformation),
scale_atoms=True)
if self.gui.simulation.has_key('progress'):
self.gui.simulation['progress'].set_scale_progress(i)
if self.radio_relax_on.get_active():
algo = getattr(ase.optimize, mininame)
if mininame == "MDMin":
minimizer = algo(self.atoms, logfile=logger,
dt=self.mdmin_dt.value)
else:
minimizer = algo(self.atoms, logfile=logger)
minimizer.run(fmax=fmax, steps=self.steps.value)
e = self.atoms.get_potential_energy()
results.append((d, e))
txt = txt + ("%.5f\t\t%.5f\n" % (d, e))
self.output.set_text(txt)
if self.radio_results_all.get_active():
self.store_atoms()
stored_atoms = True
except AseGuiCancelException:
# Update display to reflect cancellation of simulation.
self.status_label.set_text(_("Calculation CANCELLED."))
self.status_label.modify_fg(gtk.STATE_NORMAL,
gtk.gdk.color_parse('#AA4000'))
except MemoryError:
self.status_label.set_text(_("Out of memory, consider using "
"LBFGS instead"))
self.status_label.modify_fg(gtk.STATE_NORMAL,
gtk.gdk.color_parse('#AA4000'))
else:
# Update display to reflect succesful end of simulation.
self.status_label.set_text(_("Calculation completed."))
self.status_label.modify_fg(gtk.STATE_NORMAL,
gtk.gdk.color_parse('#007700'))
if results:
self.do_fit(np.array(results))
if self.radio_results_optimal.get_active():
if self.minimum_ok:
deformation = np.diag(1.0 + self.x0 * deform_axes)
self.atoms.set_cell(np.dot(undef_cell, deformation),
scale_atoms=True)
if self.radio_relax_on.get_active():
if self.gui.simulation.has_key('progress'):
self.gui.simulation['progress'].set_scale_progress(
len(steps))
algo = getattr(ase.optimize, mininame)
minimizer = algo(self.atoms, logfile=logger)
minimizer.run(fmax=fmax, steps=self.steps.value)
# Store the optimal configuration.
self.prepare_store_atoms()
self.store_atoms()
stored_atoms = True
else:
oops(_("No trustworthy minimum: Old configuration kept."))
self.activate_output()
if stored_atoms:
self.gui.notify_vulnerable()
self.end()
# If we store all configurations: Open movie window and energy graph
if stored_atoms and self.gui.images.nimages > 1:
self.gui.movie()
assert not np.isnan(self.gui.images.E[0])
if not self.gui.plot_graphs_newatoms():
expr = 'i, e - E[-1]'
self.gui.plot_graphs(expr=expr)
# Continuations should use the best image
nbest = np.argmin(np.array(results)[:,1])
self.start_nth_adj.value = nbest
def change_fit(self, widget):
"Repeat the fitting if the order is changed."
# It may be called both for the button being turned on and the
# one being turned off. But we only want to call do_fit once.
# And only if there are already cached results (ie. if the
# order is changed AFTER the calculation is done).
if widget.get_active() and getattr(self, "results", None) is not None:
self.do_fit(None)
def do_fit(self, results):
"Fit the results to a polynomial"
if results is None:
results = self.results # Use cached results
else:
self.results = results # Keep for next time
self.minimum_ok = False
if self.radio_fit_3.get_active():
order = 3
else:
order = 2
if len(results) < 3:
txt = (_("Insufficent data for a fit\n(only %i data points)\n")
% (len(results),) )
order = 0
elif len(results) == 3 and order == 3:
txt = _("REVERTING TO 2ND ORDER FIT\n(only 3 data points)\n\n")
order = 2
else:
txt = ""
if order > 0:
fit0 = np.poly1d(np.polyfit(results[:,0], results[:,1], order))
fit1 = np.polyder(fit0, 1)
fit2 = np.polyder(fit1, 1)
x0 = None
for t in np.roots(fit1):
if fit2(t) > 0:
x0 = t
break
if x0 is None:
txt = txt + _("No minimum found!")
else:
e0 = fit0(x0)
e2 = fit2(x0)
txt += "E = "
if order == 3:
txt += "A(x - x0)³ + "
txt += "B(x - x0)² + C\n\n"
txt += "B = %.5g eV\n" % (e2,)
txt += "C = %.5g eV\n" % (e0,)
txt += "x0 = %.5g\n" % (x0,)
lowest = self.scale_offset.value - self.max_scale.value
highest = self.scale_offset.value + self.max_scale.value
if x0 < lowest or x0 > highest:
txt += _("\nWARNING: Minimum is outside interval\n")
txt += _("It is UNRELIABLE!\n")
else:
self.minimum_ok = True
self.x0 = x0
self.fit_output.set_text(txt)
python-ase-3.6.0.2515/ase/gui/graphene.py 0000644 0001754 0001754 00000021522 11706276516 016714 0 ustar askhl askhl # encoding: utf-8
"""nanotube.py - Window for setting up Graphene sheets and ribbons.
"""
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack, cancel_apply_ok, oops
from ase.gui.setupwindow import SetupWindow
from ase.gui.pybutton import PyButton
from ase.structure import graphene_nanoribbon
import ase
import numpy as np
introtext = _("""\
Set up a graphene sheet or a graphene nanoribbon. A nanoribbon may
optionally be saturated with hydrogen (or another element).\
""")
py_template = """
from ase.structure import nanotube
atoms = nanotube(%(n)i, %(m)i, length=%(length)i, bond=%(bl).3f, symbol=%(symb)s)
"""
class SetupGraphene(SetupWindow):
"Window for setting up a graphene sheet or nanoribbon."
def __init__(self, gui):
SetupWindow.__init__(self)
self.set_title(_("Graphene"))
vbox = gtk.VBox()
# Intoductory text
self.packtext(vbox, introtext)
# Choose structure
label = gtk.Label(_("Structure: "))
self.struct = gtk.combo_box_new_text()
for s in (_("Infinite sheet"), _("Unsaturated ribbon"),
_("Saturated ribbon")):
self.struct.append_text(s)
self.struct.set_active(0)
self.struct.connect('changed', self.update_gui)
pack(vbox, [label, self.struct])
# Orientation
label = gtk.Label(_("Orientation: "))
self.orient = gtk.combo_box_new_text()
self.orient_text = []
for s in (_("zigzag"), _("armchair")):
self.orient.append_text(s)
self.orient_text.append(s)
self.orient.set_active(0)
self.orient.connect('changed', self.update_gui)
pack(vbox, [label, self.orient])
pack(vbox, gtk.Label(""))
# Choose the element and bond length
label1 = gtk.Label("Element: ")
#label.set_alignment(0.0, 0.2)
self.element = gtk.Entry(max=3)
self.element.set_text("C")
self.element.connect('activate', self.update_element)
self.bondlength = gtk.Adjustment(1.42, 0.0, 1000.0, 0.01)
label2 = gtk.Label(_(" Bond length: "))
label3 = gtk.Label(_("Ã…"))
bond_box = gtk.SpinButton(self.bondlength, 10.0, 3)
pack(vbox, [label1, self.element, label2, bond_box, label3])
# Choose the saturation element and bond length
self.sat_label1 = gtk.Label(_("Saturation: "))
#label.set_alignment(0.0, 0.2)
self.element2 = gtk.Entry(max=3)
self.element2.set_text(_("H"))
self.element2.connect('activate', self.update_element)
self.bondlength2 = gtk.Adjustment(1.12, 0.0, 1000.0, 0.01)
self.sat_label2 = gtk.Label(_(" Bond length: "))
self.sat_label3 = gtk.Label(_("Ã…"))
self.bond_box = gtk.SpinButton(self.bondlength2, 10.0, 3)
pack(vbox, [self.sat_label1, self.element2, self.sat_label2,
self.bond_box, self.sat_label3])
self.elementinfo = gtk.Label("")
self.elementinfo.modify_fg(gtk.STATE_NORMAL,
gtk.gdk.color_parse('#FF0000'))
pack(vbox, [self.elementinfo])
pack(vbox, gtk.Label(""))
# Size
label1 = gtk.Label(_("Width: "))
label2 = gtk.Label(_(" Length: "))
self.n = gtk.Adjustment(1, 1, 100, 1)
self.m = gtk.Adjustment(1, 1, 100, 1)
spinn = gtk.SpinButton(self.n, 0, 0)
spinm = gtk.SpinButton(self.m, 0, 0)
pack(vbox, [label1, spinn, label2, spinm])
# Vacuum
label1 = gtk.Label(_("Vacuum: "))
self.vacuum = gtk.Adjustment(5.0, 0.0, 1000.0, 0.1)
label2 = gtk.Label(_("Ã…"))
vac_box = gtk.SpinButton(self.vacuum, 10.0, 2)
pack(vbox, [label1, vac_box, label2])
pack(vbox, gtk.Label(""))
# Buttons
#self.pybut = PyButton("Creating a nanoparticle.")
#self.pybut.connect('clicked', self.makeatoms)
buts = cancel_apply_ok(cancel=lambda widget: self.destroy(),
apply=self.apply,
ok=self.ok)
pack(vbox, [buts], end=True, bottom=True)
# Finalize setup
self.update_gui()
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
def update_element(self, *args):
"Called when a new element may have been entered."
# Assumes the element widget is self.element and that a label
# for errors is self.elementinfo. The chemical symbol is
# placed in self.legalelement - or None if the element is
# invalid.
symb = []
if self.struct.get_active() == 2:
# Saturated nanoribbon
elements = (self.element.get_text(), self.element2.get_text())
else:
elements = (self.element.get_text(), )
for elem in elements:
if not elem:
self.invalid_element(_(" No element specified!"))
return False
try:
z = int(elem)
except ValueError:
# Probably a symbol
try:
z = ase.data.atomic_numbers[elem]
except KeyError:
self.invalid_element()
return False
try:
symb.append(ase.data.chemical_symbols[z])
except KeyError:
self.invalid_element()
return False
self.elementinfo.set_text("")
self.legal_element = symb[0]
if len(symb) == 2:
self.legal_element2 = symb[1]
else:
self.legal_element2 = None
return True
def update_gui(self, *args):
# Saturation element is only relevant for saturated nanoribbons
satur = self.struct.get_active() == 2
for w in (self.element2, self.bond_box):
w.set_sensitive(satur)
# Infinite zigzag sheets must have even width
if self.struct.get_active() == 0 and self.orient.get_active() == 0:
if self.n.value % 2 == 1:
self.n.value += 1
self.n.lower = 2
self.n.step_increment = 2
else:
self.n.lower = 1
self.n.step_increment = 1
def makeatoms(self, *args):
self.update_element()
if self.legal_element is None or (self.struct.get_active() == 2 and
self.legal_element2 is None):
self.atoms = None
self.pybut.python = None
else:
n = int(self.n.value)
m = int(self.m.value)
CC = self.bondlength.value
vacuum = self.vacuum.value
orient = self.orient_text[self.orient.get_active()]
elem = self.legal_element
if self.struct.get_active() == 0:
# Extended sheet
self.atoms = graphene_nanoribbon(n, m, type=orient, C_C=CC,
vacc=vacuum, sheet=True,
main_element=elem)
elif self.struct.get_active() == 1:
# Unsaturated nanoribbon
self.atoms = graphene_nanoribbon(n, m, type=orient, C_C=CC,
vacc=vacuum,
main_element=elem)
elif self.struct.get_active() == 2:
# Saturated nanoribbon
elem2 = self.legal_element2
self.atoms = graphene_nanoribbon(n, m, type=orient, C_C=CC,
C_H=self.bondlength2.value,
vacuum=vacuum,
saturated=True,
main_element=elem,
saturate_element=elem2)
else:
raise RuntimeError("Unknown structure in SetupGraphene!")
# Now, rotate into the xy plane (ase.gui's default view plane)
pos = self.atoms.get_positions()
cell = self.atoms.get_cell()
pbc = self.atoms.get_pbc()
cell[1,1], cell[2,2] = cell[2,2], cell[1,1]
x = pos[:,1].copy()
z = pos[:,2].copy()
pos[:,1] = z
pos[:,2] = x
self.atoms.set_cell(cell)
self.atoms.set_positions(pos)
self.atoms.set_pbc([pbc[0], pbc[2], pbc[1]])
def apply(self, *args):
self.makeatoms()
if self.atoms is not None:
self.gui.new_atoms(self.atoms)
return True
else:
oops(_("No valid atoms."),
_("You have not (yet) specified a consistent set of "
"parameters."))
return False
def ok(self, *args):
if self.apply():
self.destroy()
python-ase-3.6.0.2515/ase/gui/progress.py 0000644 0001754 0001754 00000031577 11706276516 017002 0 ustar askhl askhl # encoding: utf-8
import gtk
from gettext import gettext as _
import numpy as np
from ase.gui.widgets import pack, oops, AseGuiCancelException
import sys
import re
import time
class DummyProgressIndicator:
def begin(self, **kwargs):
pass
def end(self):
pass
class DefaultProgressIndicator(gtk.Window):
"Window for reporting progress."
waittime = 3 # Time (in sec) after which a progress bar appears.
updatetime = 0.1 # Minimum time (in sec) between updates of the progress bars.
def __init__(self):
gtk.Window.__init__(self)
self.set_title(_("Progress"))
self.globalbox = gtk.VBox()
self.nextupdate = 0
self.fmax_max = 1.0
# Scaling deformation progress frame
self.scalebox = gtk.VBox()
self.scaleframe = gtk.Frame(_("Scaling deformation:"))
vbox = gtk.VBox()
self.scaleframe.add(vbox)
pack(self.scalebox, [self.scaleframe])
pack(self.scalebox, gtk.Label(""))
self.label_scale_stepno_format = _("Step number %s of %s.")
self.label_scale_stepno = gtk.Label(
self.label_scale_stepno_format % ("-" , "-"))
pack(vbox, [self.label_scale_stepno])
self.scale_progress = gtk.ProgressBar()
self.scale_progress.modify_bg(gtk.STATE_PRELIGHT,
gtk.gdk.color_parse('#00AA00'))
pack(vbox, [self.scale_progress])
vbox.show()
self.scaleframe.show()
self.globalbox.pack_start(self.scalebox)
# Minimization progress frame
self.minbox = gtk.VBox() # Box containing frame and spacing
self.minframe = gtk.Frame(_("Energy minimization:"))
vbox = gtk.VBox() # Box containing the frames content.
self.minframe.add(vbox)
pack(self.minbox, [self.minframe])
pack(self.minbox, gtk.Label(""))
self.label_min_stepno = gtk.Label("-")
pack(vbox, [gtk.Label(_("Step number: ")), self.label_min_stepno])
lbl = gtk.Label()
lbl.set_markup(_("Fmax: "))
self.minimize_progress = gtk.ProgressBar()
pack(vbox, [lbl, self.minimize_progress])
self.label_min_fmax = gtk.Label("-")
lbl = gtk.Label()
lbl.set_markup(_("Convergence criterion: Fmax = "))
pack(vbox, [lbl, self.label_min_fmax])
self.label_min_maxsteps = gtk.Label("-")
pack(vbox, [gtk.Label(_("Max. number of steps: ")),
self.label_min_maxsteps])
vbox.show()
self.minframe.show()
self.globalbox.pack_start(self.minbox)
self.globalbox.show()
self.add(self.globalbox)
# Make the cancel button
self.cancelbut = gtk.Button(stock=gtk.STOCK_CANCEL)
self.cancelbut.connect('clicked', self.cancel)
pack(self.globalbox, [self.cancelbut], end=True, bottom=True)
def begin(self, mode=None, algo=None, fmax=None, steps=None,
scalesteps=None):
self.mode = mode
# Hide all mode-specific boxes
self.scalebox.hide()
self.minbox.hide()
# Activate any relevant box
if mode == "scale" or mode == "scale/min":
self.scalesteps = int(scalesteps)
self.scalebox.show()
self.set_scale_progress(0, init=True)
if mode == "min" or mode == "scale/min":
# It is a minimization.
self.minbox.show()
self.label_min_stepno.set_text("-")
self.label_min_fmax.set_text("%.3f" % (fmax,))
self.label_min_maxsteps.set_text(str(int(steps)))
self.minimize_progress.set_fraction(0)
self.minimize_progress.set_text(_("unknown"))
# Record starting time
self.starttime = time.time()
self.active = None # Becoming active
self.raisecancelexception = False
def end(self):
self.hide()
self.active = False
def activity(self):
"Register that activity occurred."
if self.active is None and time.time() > self.starttime + self.waittime:
# This has taken so long that a progress bar is needed.
self.show()
self.active = True
# Allow GTK to update display
if self.active:
while gtk.events_pending():
gtk.main_iteration()
if self.raisecancelexception:
self.cancelbut.set_sensitive(True)
raise AseGuiCancelException
def cancel(self, widget):
print "CANCEL pressed."
# We cannot raise the exception here, as this function is
# called by the GTK main loop.
self.raisecancelexception = True
self.cancelbut.set_sensitive(False)
def set_scale_progress(self, step, init=False):
"Set the step number in scaling deformation."
self.label_scale_stepno.set_text(
self.label_scale_stepno_format % (step, self.scalesteps))
percent = 1.0 * step / self.scalesteps
self.scale_progress.set_fraction(percent)
self.scale_progress.set_text("%i%%" % (round(100*percent),))
if not init:
self.activity()
def logger_write(self, line):
if time.time() > self.nextupdate:
if self.mode == "min" or self.mode == "scale/min":
# Update the minimization progress bar.
w = line.split()
fmax = float(w[-1])
step = w[1]
if fmax > self.fmax_max:
self.fmax_max = np.ceil(fmax)
self.minimize_progress.set_fraction(fmax / self.fmax_max)
self.minimize_progress.set_text(w[-1])
self.label_min_stepno.set_text(step)
else:
raise RuntimeError(
"ProgressIndicator.logger_write called unexpectedly")
self.activity()
self.nextupdate = time.time() + self.updatetime
def get_logger_stream(self):
return LoggerStream(self)
class GpawProgressIndicator(DefaultProgressIndicator):
"Window for reporting GPAW progress."
def __init__(self):
DefaultProgressIndicator.__init__(self)
# GPAW progress frame
self.gpawframe = gtk.Frame("GPAW progress:")
vbox = self.gpawvbox = gtk.VBox()
self.gpawframe.add(vbox)
self.table = gtk.Table(1, 2)
self.tablerows = 0
pack(vbox, self.table)
self.status = gtk.Label("-")
self.tablepack([gtk.Label(_("Status: ")), self.status])
self.iteration = gtk.Label("-")
self.tablepack([gtk.Label(_("Iteration: ")), self.iteration])
self.tablepack([gtk.Label("")])
lbl = gtk.Label()
lbl.set_markup(_("log10(change):"))
self.tablepack([gtk.Label(""), lbl])
self.wfs_progress = gtk.ProgressBar()
self.tablepack([gtk.Label(_("Wave functions: ")), self.wfs_progress])
self.dens_progress = gtk.ProgressBar()
self.tablepack([gtk.Label(_("Density: ")), self.dens_progress])
self.energy_progress = gtk.ProgressBar()
self.tablepack([gtk.Label(_("Energy: ")), self.energy_progress])
self.tablepack([gtk.Label("")])
self.versionlabel = gtk.Label("")
self.tablepack([gtk.Label(_("GPAW version: ")), self.versionlabel])
self.natomslabel = gtk.Label("")
self.tablepack([gtk.Label(_("Number of atoms: ")), self.natomslabel])
self.memorylabel = gtk.Label(_("N/A"))
self.tablepack([gtk.Label(_("Memory estimate: ")), self.memorylabel])
self.globalbox.pack_start(self.gpawframe)
self.gpawframe.show()
vbox.show()
self.active = False
def tablepack(self, widgets):
self.tablerows += 1
self.table.resize(self.tablerows, 2)
for i, w in enumerate(widgets):
self.table.attach(w, i, i+1, self.tablerows-1, self.tablerows)
if hasattr(w, "set_alignment"):
w.set_alignment(0, 0.5)
w.show()
def begin(self, **kwargs):
DefaultProgressIndicator.begin(self, **kwargs)
# Set GPAW specific stuff.
self.active = True
self.oldenergy = None
self.poscount = None
self.reset_gpaw_bars()
# With GPAW, all calculations are slow: Show progress window
# immediately.
self.show()
while gtk.events_pending():
gtk.main_iteration()
def reset_gpaw_bars(self):
for lbl in (self.status, self.iteration):
lbl.set_text("-")
for bar in (self.wfs_progress, self.dens_progress,
self.energy_progress):
bar.set_fraction(0.0)
bar.set_text(_("No info"))
def gpaw_write(self, txt):
#if not self.active:
# self.begin()
sys.stdout.write(txt)
versearch = re.search("\|[ |_.]+([0-9]+\.[0-9]+\.[0-9]+)", txt)
if versearch:
# Starting a gpaw calculation.
self.versionlabel.set_text(versearch.group(1))
self.status.set_text(_("Initializing"))
elif txt.startswith(_("Positions:")):
# Start counting atoms
self.poscount = True
self.reset_gpaw_bars()
self.status.set_text(_("Starting calculation"))
self.oldenergy = None
elif txt.strip() == "":
# Stop counting atoms
self.poscount = False
elif self.poscount:
# Count atoms.
w = txt.split()
assert(len(w) == 5)
self.natoms = int(w[0]) + 1
self.natomslabel.set_text(str(self.natoms))
elif txt.startswith("iter:"):
# Found iteration line.
wfs = txt[self.wfs_idx:self.density_idx].strip()
dens = txt[self.density_idx:self.energy_idx].strip()
energy = txt[self.energy_idx:self.fermi_idx].strip()
if wfs:
p = fraction(float(wfs), -9.0)
self.wfs_progress.set_fraction(p)
self.wfs_progress.set_text(wfs)
if dens:
p = fraction(float(dens), -4.0)
self.dens_progress.set_fraction(p)
self.dens_progress.set_text(dens)
if energy:
if self.oldenergy is None:
self.oldenergy = float(energy)
else:
de = abs(self.oldenergy - float(energy))
self.oldenergy = float(energy)
if de > 1e-10:
de = np.log10(de/self.natoms)
p = fraction(de, -3.0)
self.energy_progress.set_fraction(p)
self.energy_progress.set_text("%.1f" % de)
else:
self.energy_progress.set_fraction(1)
self.energy_progress.set_text(_("unchanged"))
words = txt.split()
self.iteration.set_text(words[1])
elif (-1 < txt.find("WFS") < txt.find("Density") < txt.find("Energy")
< txt.find("Fermi")):
# Found header of convergence table
self.wfs_idx = txt.find("WFS")
self.density_idx = txt.find("Density")
self.energy_idx = txt.find("Energy")
self.fermi_idx = txt.find("Fermi")
self.status.set_text(_("Self-consistency loop"))
self.iteration.set_text("0")
elif txt.find("Converged After") != -1:
# SCF loop has converged.
words = txt.split()
self.status.set_text(_("Calculating forces"))
self.iteration.set_text(words[2] + _(" (converged)"))
elif -1 < txt.find("Calculator") < txt.find("MiB"):
# Memory estimate
words = txt.split()
self.memorylabel.set_text(words[1]+" "+words[2])
self.activity()
def get_gpaw_stream(self):
return GpawStream(self)
class LoggerStream:
"A file-like object feeding minimizer logs to GpawProgressWindow."
def __init__(self, progresswindow):
self.window = progresswindow
def write(self, txt):
self.window.logger_write(txt)
def flush(self):
pass
class GpawStream:
"A file-like object feeding GPAWs txt file to GpawProgressWindow."
def __init__(self, progresswindow):
self.window = progresswindow
def write(self, txt):
if txt == "":
return
endline = txt[-1] == '\n'
if endline:
txt = txt[:-1]
lines = txt.split("\n")
if endline:
for l in lines:
self.window.gpaw_write(l+'\n')
else:
for l in lines[:-1]:
self.window.gpaw_write(l+'\n')
self.window.gpaw_write(lines[-1])
def flush(self):
pass
def fraction(value, maximum):
p = value/maximum
if p < 0.0:
return 0.0
elif p > 1.0:
return 1.0
else:
return p
python-ase-3.6.0.2515/ase/gui/surfaceslab.py 0000644 0001754 0001754 00000024077 11711330540 017405 0 ustar askhl askhl # encoding: utf-8
"""surfaceslab.py - Window for setting up surfaces
"""
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack, cancel_apply_ok, oops
from ase.gui.pybutton import PyButton
from ase.gui.setupwindow import SetupWindow
import ase.lattice.surface as _surf
import ase
import numpy as np
introtext = _("""\
Use this dialog to create surface slabs. Select the element by
writing the chemical symbol or the atomic number in the box. Then
select the desired surface structure. Note that some structures can
be created with an othogonal or a non-orthogonal unit cell, in these
cases the non-orthogonal unit cell will contain fewer atoms.
If the structure matches the experimental crystal structure, you can
look up the lattice constant, otherwise you have to specify it
yourself.""")
# Name, structure, orthogonal, support-nonorthogonal, function
surfaces = [(_('FCC(100)'), _('fcc'), True, False, _surf.fcc100),
(_('FCC(110)'), _('fcc'), True, False, _surf.fcc110),
(_('FCC(111) non-orthogonal'), _('fcc'), False, True,
_surf.fcc111),
(_('FCC(111) orthogonal'), _('fcc'), True, True, _surf.fcc111),
(_('BCC(100)'), _('bcc'), True, False, _surf.bcc100),
(_('BCC(110) non-orthogonal'), _('bcc'), False, True,
_surf.bcc110),
(_('BCC(110) orthogonal'), _('bcc'), True, True, _surf.bcc110),
(_('BCC(111) non-orthogonal'), _('bcc'), False, True,
_surf.bcc111),
(_('BCC(111) orthogonal'), _('bcc'), True, True, _surf.bcc111),
(_('HCP(0001) non-orthogonal'), _('hcp'), False, True,
_surf.hcp0001),
(_('HCP(0001) orthogonal'), _('hcp'), True, True, _surf.hcp0001),
(_('HCP(10-10) orthogonal'), _('hcp'), True, False,
_surf.hcp10m10),
(_('DIAMOND(100) orthogonal'), _('diamond'), True, False,
_surf.diamond100),
(_('DIAMOND(111) non-orthogonal'), _('diamond'), False, True,
_surf.diamond111),
]
py_template = """
from ase.lattice.surface import %(func)s
atoms = %(func)s(symbol='%(symbol)s', size=%(size)s,
a=%(a).3f, vacuum=%(vacuum).3f%(orthoarg)s)
"""
class SetupSurfaceSlab(SetupWindow):
"""Window for setting up a surface."""
def __init__(self, gui):
SetupWindow.__init__(self)
self.set_title(_("Surface"))
self.atoms = None
vbox = gtk.VBox()
# Intoductory text
self.packtext(vbox, introtext)
# Choose the element
label = gtk.Label(_("Element: "))
element = gtk.Entry(max=3)
self.element = element
self.elementinfo = gtk.Label("")
pack(vbox, [label, element, self.elementinfo])
self.element.connect('activate', self.update)
self.legal_element = False
# Choose the surface structure
label = gtk.Label(_("Structure: "))
self.structchoice = gtk.combo_box_new_text()
self.surfinfo = {}
for s in surfaces:
assert len(s) == 5
self.structchoice.append_text(s[0])
self.surfinfo[s[0]] = s
pack(vbox, [label, self.structchoice])
self.structchoice.connect('changed', self.update)
# Choose the lattice constant
tbl = gtk.Table(2, 3)
label = gtk.Label(_("Lattice constant: "))
tbl.attach(label, 0, 1, 0, 1)
vbox2 = gtk.VBox() # For the non-HCP stuff
self.vbox_hcp = gtk.VBox() # For the HCP stuff.
self.lattice_const = gtk.Adjustment(3.0, 0.0, 1000.0, 0.01)
lattice_box = gtk.SpinButton(self.lattice_const, 10.0, 3)
lattice_box.numeric = True
pack(vbox2, [gtk.Label(_("a:")), lattice_box, gtk.Label(_("Ã…"))])
tbl.attach(vbox2, 1, 2, 0, 1)
lattice_button = gtk.Button(_("Get from database"))
tbl.attach(lattice_button, 2, 3, 0, 1)
# HCP stuff
self.hcp_ideal = (8.0/3)**(1.0/3)
self.lattice_const_c = gtk.Adjustment(self.lattice_const.value * self.hcp_ideal,
0.0, 1000.0, 0.01)
lattice_box_c = gtk.SpinButton(self.lattice_const_c, 10.0, 3)
lattice_box_c.numeric = True
pack(self.vbox_hcp, [gtk.Label("c:"),
lattice_box_c, gtk.Label("Ã…")])
self.hcp_c_over_a_format = "c/a: %.3f " + _("(%.1f %% of ideal)")
self.hcp_c_over_a_label = gtk.Label(self.hcp_c_over_a_format % \
(self.hcp_ideal, 100.0))
pack(self.vbox_hcp, [self.hcp_c_over_a_label])
tbl.attach(self.vbox_hcp, 1, 2, 1, 2)
tbl.show_all()
pack(vbox, [tbl])
self.lattice_const.connect('value-changed', self.update)
self.lattice_const_c.connect('value-changed', self.update)
lattice_button.connect('clicked', self.get_lattice_const)
pack(vbox, gtk.Label(""))
# System size
self.size = [gtk.Adjustment(1, 1, 100, 1) for i in range(3)]
buttons = [gtk.SpinButton(s, 0, 0) for s in self.size]
self.vacuum = gtk.Adjustment(10.0, 0, 100.0, 0.1)
vacuum_box = gtk.SpinButton(self.vacuum, 0.0, 1)
pack(vbox, [gtk.Label(_("Size: \tx: ")), buttons[0],
gtk.Label(_(" unit cells"))])
pack(vbox, [gtk.Label(_("\t\ty: ")), buttons[1],
gtk.Label(_(" unit cells"))])
pack(vbox, [gtk.Label(_(" \t\tz: ")), buttons[2],
gtk.Label(_(" layers, ")),
vacuum_box, gtk.Label(_(" Ã… vacuum"))])
self.nosize = _("\t\tNo size information yet.")
self.sizelabel = gtk.Label(self.nosize)
pack(vbox, [self.sizelabel])
for s in self.size:
s.connect('value-changed', self.update)
self.vacuum.connect('value-changed', self.update)
pack(vbox, gtk.Label(""))
# Buttons
self.pybut = PyButton(_("Creating a surface slab."))
self.pybut.connect('clicked', self.update)
buts = cancel_apply_ok(cancel=lambda widget: self.destroy(),
apply=self.apply,
ok=self.ok)
pack(vbox, [self.pybut, buts], end=True, bottom=True)
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
# Hide the HCP stuff to begin with.
self.vbox_hcp.hide_all()
# update_element inherited from SetupWindow
def update(self, *args):
"Called when something has changed."
struct = self.structchoice.get_active_text()
if struct:
structinfo = self.surfinfo[struct]
if structinfo[1] == 'hcp':
self.vbox_hcp.show_all()
ca = self.lattice_const_c.value / self.lattice_const.value
self.hcp_c_over_a_label.set_text(self.hcp_c_over_a_format %
(ca, 100 * ca / self.hcp_ideal))
else:
self.vbox_hcp.hide_all()
# Abort if element or structure is invalid
if not (self.update_element() and struct):
self.sizelabel.set_text(self.nosize)
self.atoms = None
self.pybut.python = None
return False
# Make the atoms
assert self.legal_element
kw = {}
kw2 = {}
if structinfo[3]: # Support othogonal keyword?
kw['orthogonal'] = structinfo[2]
kw2['orthoarg'] = ', orthogonal=' + str(kw['orthogonal'])
else:
kw2['orthoarg'] = ''
kw2['func'] = structinfo[4].__name__
kw['symbol'] = self.legal_element
kw['size'] = [int(s.value) for s in self.size]
kw['a'] = self.lattice_const.value
kw['vacuum'] = self.vacuum.value
# Now create the atoms
try:
self.atoms = structinfo[4](**kw)
except ValueError, e:
# The values were illegal - for example some size
# constants must be even for some structures.
self.pybut.python = None
self.atoms = None
self.sizelabel.set_text(str(e).replace(". ", ".\n"))
return False
kw2.update(kw)
self.pybut.python = py_template % kw2
# Find the heights of the unit cell
h = np.zeros(3)
uc = self.atoms.get_cell()
for i in range(3):
norm = np.cross(uc[i-1], uc[i-2])
norm /= np.sqrt(np.dot(norm, norm))
h[i] = np.abs(np.dot(norm, uc[i]))
natoms = len(self.atoms)
txt = ("\t\t%.2f Ã… x %.2f Ã… x %.2f Ã…, %s"
% (h[0], h[1], h[2], _('%i atoms.') % natoms))
self.sizelabel.set_text(txt)
return True
def get_lattice_const(self, *args):
if not self.update_element():
oops(_("Invalid element."))
return
z = ase.atomic_numbers[self.legal_element]
ref = ase.data.reference_states[z]
surface = self.structchoice.get_active_text()
if not surface:
oops(_("No structure specified!"))
return
struct = self.surfinfo[surface][1]
if ref is None or ref['symmetry'] != struct:
from ase.data.alternatives import alternative_structures
alt = alternative_structures[z]
if alt and alt['symmetry'] == struct:
ref = alt
else:
oops(_('%(struct)s lattice constant unknown for %(element)s.')
% dict(struct=struct.upper(), element=self.legal_element))
a = ref['a']
self.lattice_const.set_value(a)
if struct == 'hcp':
c = ref['c/a'] * a
self.lattice_const_c.set_value(c)
def apply(self, *args):
self.update()
if self.atoms is not None:
self.gui.new_atoms(self.atoms)
return True
else:
oops(_("No valid atoms."),
_("You have not (yet) specified "
"a consistent set of parameters."))
return False
def ok(self, *args):
if self.apply():
self.destroy()
python-ase-3.6.0.2515/ase/gui/gtkexcepthook.py 0000644 0001754 0001754 00000015067 11706276516 020011 0 ustar askhl askhl # vim: sw=4 ts=4:
#
# (c) 2003 Gustavo J A M Carneiro gjc at inescporto.pt
# 2004-2005 Filip Van Raemdonck
#
# http://www.daa.com.au/pipermail/pygtk/2003-August/005775.html
# Message-ID: <1062087716.1196.5.camel@emperor.homelinux.net>
# "The license is whatever you want."
#
# This file was downloaded from http://www.sysfs.be/downloads/
# Minor adaptions 2009 by Martin Renold:
# - let KeyboardInterrupt through
# - print traceback to stderr before showing the dialog
# - nonzero exit code when hitting the "quit" button
# - suppress more dialogs while one is already active
# see also http://faq.pygtk.org/index.py?req=show&file=faq20.010.htp
# (The license is still whatever you want.)
import inspect, linecache, pydoc, sys, traceback
from cStringIO import StringIO
from gettext import gettext as _
from smtplib import SMTP
import pygtk
pygtk.require ('2.0')
import gtk, pango
def analyse_simple (exctyp, value, tb):
trace = StringIO()
traceback.print_exception (exctyp, value, tb, None, trace)
return trace
def lookup (name, frame, lcls):
'''Find the value for a given name in the given frame'''
if name in lcls:
return 'local', lcls[name]
elif name in frame.f_globals:
return 'global', frame.f_globals[name]
elif '__builtins__' in frame.f_globals:
builtins = frame.f_globals['__builtins__']
if type (builtins) is dict:
if name in builtins:
return 'builtin', builtins[name]
else:
if hasattr (builtins, name):
return 'builtin', getattr (builtins, name)
return None, []
def analyse (exctyp, value, tb):
import tokenize, keyword
trace = StringIO()
nlines = 3
frecs = inspect.getinnerframes (tb, nlines)
trace.write ('Traceback (most recent call last):\n')
for frame, fname, lineno, funcname, context, cindex in frecs:
trace.write (' File "%s", line %d, ' % (fname, lineno))
args, varargs, varkw, lcls = inspect.getargvalues (frame)
def readline (lno=[lineno], *args):
if args: print args
try: return linecache.getline (fname, lno[0])
finally: lno[0] += 1
all, prev, name, scope = {}, None, '', None
for ttype, tstr, stup, etup, line in tokenize.generate_tokens (readline):
if ttype == tokenize.NAME and tstr not in keyword.kwlist:
if name:
if name[-1] == '.':
try:
val = getattr (prev, tstr)
except AttributeError:
# XXX skip the rest of this identifier only
break
name += tstr
else:
assert not name and not scope
scope, val = lookup (tstr, frame, lcls)
name = tstr
if hasattr(val, "shape") and len(val):
prev = val
elif val:
prev = val
#print ' found', scope, 'name', name, 'val', val, 'in', prev, 'for token', tstr
elif tstr == '.':
if prev:
name += '.'
else:
if name:
all[name] = (scope, prev)
prev, name, scope = None, '', None
if ttype == tokenize.NEWLINE:
break
trace.write (funcname +
inspect.formatargvalues (args, varargs, varkw, lcls, formatvalue=lambda v: '=' + pydoc.text.repr (v)) + '\n')
trace.write (''.join ([' ' + x.replace ('\t', ' ') for x in filter (lambda a: a.strip(), context)]))
if len (all):
trace.write (' variables: %s\n' % str (all))
trace.write ('%s: %s' % (exctyp.__name__, value))
return trace
def _info (exctyp, value, tb):
global exception_dialog_active
if exctyp is KeyboardInterrupt:
return original_excepthook(exctyp, value, tb)
sys.stderr.write(analyse_simple (exctyp, value, tb).getvalue())
if exception_dialog_active:
return
gtk.gdk.pointer_ungrab()
gtk.gdk.keyboard_ungrab()
exception_dialog_active = True
trace = None
dialog = gtk.MessageDialog (parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_NONE)
dialog.set_title(_("Bug Detected"))
if gtk.check_version (2, 4, 0) is not None:
dialog.set_has_separator (False)
primary = "%s" % _("A programming error has been "
"detected.")
primary += '\n\n'+str(value)+''
secondary = _("It probably isn't fatal, but the details should be "
"reported to the developers nonetheless.")
try:
setsec = dialog.format_secondary_text
except AttributeError:
raise
dialog.vbox.get_children()[0].get_children()[1].set_markup ('%s\n\n%s' % (primary, secondary))
#lbl.set_property ("use-markup", True)
else:
del setsec
dialog.set_markup (primary)
dialog.format_secondary_text (secondary)
try:
email = feedback
dialog.add_button(_("Report..."), 3)
except NameError:
# could ask for an email address instead...
pass
dialog.add_button (_("Details..."), 2)
dialog.add_button (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
dialog.add_button (gtk.STOCK_QUIT, 1)
while True:
resp = dialog.run()
if resp == 3:
if trace == None:
trace = analyse (exctyp, value, tb)
# TODO: prettyprint, deal with problems in sending feedback, &tc
try:
server = smtphost
except NameError:
server = 'localhost'
message = _('From: buggy_application"\nTo: bad_programmer\nSubject: Exception feedback\n\n%s') % trace.getvalue()
s = SMTP()
s.connect (server)
s.sendmail (email, (email,), message)
s.quit()
break
elif resp == 2:
if trace == None:
trace = analyse (exctyp, value, tb)
# Show details...
details = gtk.Dialog (_("Bug Details"), dialog,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE, ))
details.set_property ("has-separator", False)
textview = gtk.TextView(); textview.show()
textview.set_editable (False)
textview.modify_font (pango.FontDescription ("Monospace"))
sw = gtk.ScrolledWindow(); sw.show()
sw.set_policy (gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
sw.add (textview)
details.vbox.add (sw)
textbuffer = textview.get_buffer()
textbuffer.set_text (trace.getvalue())
monitor = gtk.gdk.screen_get_default ().get_monitor_at_window (dialog.window)
area = gtk.gdk.screen_get_default ().get_monitor_geometry (monitor)
try:
w = area.width // 1.6
h = area.height // 1.6
except SyntaxError:
# python < 2.2
w = area.width / 1.6
h = area.height / 1.6
details.set_default_size (int (w), int (h))
details.run()
details.destroy()
elif resp == 1 and gtk.main_level() > 0:
#gtk.main_quit() - why...? Exit code 0 is bad for IDEs.
sys.exit(1)
break
else:
break
dialog.destroy()
exception_dialog_active = False
original_excepthook = sys.excepthook
sys.excepthook = _info
exception_dialog_active = False
if __name__ == '__main__':
class X (object):
pass
x = X()
x.y = 'Test'
x.z = x
w = ' e'
#feedback = 'developer@bigcorp.comp'
#smtphost = 'mx.bigcorp.comp'
1, x.z.y, f, w
raise Exception (x.z.y + w)
python-ase-3.6.0.2515/ase/gui/neb.py 0000644 0001754 0001754 00000001257 11207220276 015656 0 ustar askhl askhl # -*- coding: utf-8 -*-
from math import sqrt
import numpy as np
from ase.neb import fit0
def NudgedElasticBand(images):
N = images.repeat.prod()
natoms = images.natoms // N
R = images.P[:, :natoms]
E = images.E
F = images.F[:, :natoms]
s, E, Sfit, Efit, lines = fit0(E, F, R)
import pylab
import matplotlib
#matplotlib.use('GTK')
pylab.ion()
x = 2.95
pylab.figure(figsize=(x * 2.5**0.5, x))
pylab.plot(s, E, 'o')
for x, y in lines:
pylab.plot(x, y, '-g')
pylab.plot(Sfit, Efit, 'k-')
pylab.xlabel(u'path [Ã…]')
pylab.ylabel(u'energy [eV]')
pylab.title('Maximum: %.3f eV' % max(Efit))
pylab.show()
python-ase-3.6.0.2515/ase/gui/movie.py 0000644 0001754 0001754 00000011000 11712043160 016210 0 ustar askhl askhl #!/usr/bin/env python
import gtk
from gettext import gettext as _
import gobject
from ase.gui.widgets import pack
class Movie(gtk.Window):
def __init__(self, gui):
gtk.Window.__init__(self)
self.set_position(gtk.WIN_POS_NONE)
self.connect('destroy', self.close)
#self.connect('delete_event', self.exit2)
self.set_title(_('Movie'))
vbox = gtk.VBox()
pack(vbox, gtk.Label(_('Image number:')))
self.frame_number = gtk.Adjustment(gui.frame, 0,
gui.images.nimages - 1,
1.0, 5.0)
self.frame_number.connect('value-changed', self.new_frame)
hscale = pack(vbox, gtk.HScale(self.frame_number))
hscale.set_update_policy(gtk.UPDATE_CONTINUOUS)
hscale.set_digits(0)
buttons = [gtk.Button(stock=gtk.STOCK_GOTO_FIRST),
gtk.Button(stock=gtk.STOCK_GO_BACK),
gtk.Button(stock=gtk.STOCK_GO_FORWARD),
gtk.Button(stock=gtk.STOCK_GOTO_LAST)]
buttons[0].connect('clicked', self.click, -1, True)
buttons[1].connect('clicked', self.click, -1)
buttons[2].connect('clicked', self.click, 1)
buttons[3].connect('clicked', self.click, 1, True)
pack(vbox, buttons)
play = gtk.Button(_('Play'))
play.connect('clicked', self.play)
stop = gtk.Button(_('Stop'))
stop.connect('clicked', self.stop)
# TRANSLATORS: This function plays an animation forwards and backwards
# alternatingly, e.g. for displaying vibrational movement
self.rock = gtk.CheckButton(_('Rock'))
pack(vbox, [play, stop, gtk.Label(' '), self.rock])
if gui.images.nimages > 150:
skipdefault = gui.images.nimages/150
tdefault = min(max(gui.images.nimages/(skipdefault*5.0), 1.0), 30)
else:
skipdefault = 0
tdefault = min(max(gui.images.nimages/5.0, 1.0), 30)
self.time = gtk.Adjustment(tdefault, 1.0, 99, 0.1)
self.time_spin = gtk.SpinButton(self.time, 0, 0)
self.time_spin.set_digits(1)
self.time.connect("value-changed",self.frame_rate_changed)
self.skip = gtk.Adjustment(skipdefault, 0, 99, 1)
self.skip_spin = gtk.SpinButton(self.skip, 0, 0)
pack(vbox, [gtk.Label(_(' Frame rate: ')), self.time_spin,
gtk.Label(_(' Skip frames: ')), self.skip_spin,
gtk.Label(' ')])
self.add(vbox)
vbox.show()
self.show()
self.gui = gui
#gui.m=self
self.direction = 1
self.id = None
gui.register_vulnerable(self)
def notify_atoms_changed(self):
"Called by gui object when the atoms have changed."
self.destroy()
def close(self, event):
self.stop()
def click(self, button, step, firstlast=False):
if firstlast and step < 0:
i = 0
elif firstlast:
i = self.gui.images.nimages - 1
else:
i = max(0, min(self.gui.images.nimages - 1, self.gui.frame + step))
self.gui.set_frame(i)
self.frame_number.value = i
if firstlast:
self.direction = cmp(-step, 0)
else:
self.direction = cmp(step, 0)
def new_frame(self, widget):
self.gui.set_frame(int(self.frame_number.value))
def play(self, widget=None):
if self.id is not None:
gobject.source_remove(self.id)
t = int(1000.0 / float(self.time.value))
self.id = gobject.timeout_add(t, self.step)
def stop(self, widget=None):
if self.id is not None:
gobject.source_remove(self.id)
self.id = None
def frame_rate_changed(self,widget=None):
if self.id is not None:
self.play()
def step(self):
i = self.gui.frame
nimages = self.gui.images.nimages
delta = int(self.skip.value + 1)
if self.rock.get_active():
if i <= self.skip.value:
self.direction = 1
elif i >= nimages - delta:
self.direction = -1
i += self.direction * delta
else:
i = (i + self.direction * delta + nimages) % nimages
self.gui.set_frame(i)
self.frame_number.value = i
return True
def new_time(self, widget):
if self.id is not None:
self.play()
if __name__ == '__main__':
import os
os.system('python gui.py')
python-ase-3.6.0.2515/ase/gui/crystal.py 0000644 0001754 0001754 00000054453 11706276516 016615 0 ustar askhl askhl # encoding: utf-8
"""crystal.py - Window for setting up arbitrary crystal lattices
"""
import gtk
from gettext import gettext as _
from ase.gui.widgets import pack, cancel_apply_ok, oops
from ase.gui.pybutton import PyButton
from ase.gui.setupwindow import SetupWindow
from ase.gui.status import formula
from ase.lattice.spacegroup import crystal, Spacegroup
import ase
import numpy as np
introtext = _("""\
Use this dialog to create crystal lattices. First select the structure,
either from a set of common crystal structures, or by space group description.
Then add all other lattice parameters.
If an experimental crystal structure is available for an atom, you can
look up the crystal type and lattice constant, otherwise you have to specify it
yourself. """)
py_template = """
from ase.lattice.spacegroup.crystal import crystal
atoms = crystal(spacegroup=%(spacegroup)d,
symbols=%(symbols)s,
basis=%(basis)s,
cellpar=%(cellpar)s)
"""
label_template = _(""" %(natoms)i atoms: %(symbols)s, Volume: %(volume).3f A3""")
# all predefined crystals go into tuples here:
# (selection name, spacegroup, group_active, [repeats], [a,b,c,alpha,beta,gamma],[lattice constraints],[constraints_active],basis)
crystal_definitions = [('Spacegroup', 1, True, [1,1,1], [3.0, 3.0, 3.0, 90.0, 90.0, 90.0],
[0,0,0,0,0,0], [ True, True, True, True, True, True], [['','','','']]),
('fcc', 225, False, [1,1,1], [3.0, 3.0, 3.0, 90.0, 90.0, 90.0],
[0,1,1,3,3,3], [False,False,False,False,False,False], [['','','','']]),
('bcc', 229, False, [1,1,1], [3.0, 3.0, 3.0, 90.0, 90.0, 90.0],
[0,1,1,3,3,3], [False,False,False,False,False,False], [['','','','']]),
('diamond', 227, False, [1,1,1], [3.0, 3.0, 3.0, 90.0, 90.0, 90.0],
[0,1,1,3,3,3], [False,False,False,False,False,False], [['','','','']]),
('hcp', 194, False, [1,1,1], [3.0, 3.0, 3.0, 90.0, 90.0, 120.0],
[0,1,0,3,3,3], [False,False,False,False,False,False], [['','1./3.','2./3.','3./4.']]),
('graphite', 186, False, [1,1,1], [3.0, 3.0, 3.0, 90.0, 90.0, 120.0],
[0,1,0,3,3,3], [False,False,False,False,False,False], [['','0','0','0'],['','1./3.','2./3.','0']]),
('rocksalt', 225, False, [1,1,1], [3.0, 3.0, 3.0, 90.0, 90.0, 90.0],
[0,1,1,3,3,3], [False,False,False,False,False,False], [['','0','0','0'],['','0.5','0.5','0.5']]),
('rutile', 136, False, [1,1,1], [3.0, 3.0, 3.0, 90.0, 90.0, 90.0],
[0,1,0,3,3,3], [False,False,False,False,False,False], [['','0','0','0'],['O','0.3','0.3','0' ]])]
class SetupBulkCrystal(SetupWindow):
"""Window for setting up a surface."""
def __init__(self, gui):
SetupWindow.__init__(self)
self.set_title(_("Create Bulk Crystal by Spacegroup"))
self.atoms = None
vbox = gtk.VBox()
self.packtext(vbox, introtext)
self.structinfo = gtk.combo_box_new_text()
self.structures = {}
for c in crystal_definitions:
self.structinfo.append_text(c[0])
self.structures[c[0]] = c
self.structinfo.set_active(0)
self.structinfo.connect("changed",self.set_lattice_type)
self.spacegroup = gtk.Entry(max=14)
self.spacegroup.set_text('P 1')
self.elementinfo = gtk.Label("")
self.spacegroupinfo = gtk.Label(_('Number: 1'))
pack(vbox,[gtk.Label(_("Lattice: ")),self.structinfo,gtk.Label(_("\tSpace group: ")),self.spacegroup,gtk.Label(' '),self.spacegroupinfo,gtk.Label(' '),self.elementinfo])
pack(vbox,[gtk.Label("")])
self.size = [gtk.Adjustment(1, 1, 100, 1) for i in range(3)]
buttons = [gtk.SpinButton(s, 0, 0) for s in self.size]
pack(vbox, [gtk.Label(_("Size: x: ")), buttons[0],
gtk.Label(_(" y: ")), buttons[1],
gtk.Label(_(" z: ")), buttons[2],
gtk.Label(_(" unit cells"))])
pack(vbox,[gtk.Label("")])
self.lattice_lengths = [gtk.Adjustment(3.0, 0.0, 1000.0, 0.01) for i in range(3)]
self.lattice_angles = [gtk.Adjustment(90.0,0.0, 180.0, 1) for i in range(3)]
self.lattice_lbuts = [gtk.SpinButton(self.lattice_lengths[i], 0, 0) for i in range(3)]
self.lattice_abuts = [gtk.SpinButton(self.lattice_angles[i] , 0, 0) for i in range(3)]
for i in self.lattice_lbuts:
i.set_digits(5)
for i in self.lattice_abuts:
i.set_digits(3)
self.lattice_lequals = [gtk.combo_box_new_text() for i in range(3)]
self.lattice_aequals = [gtk.combo_box_new_text() for i in range(3)]
self.lattice_lequals[0].append_text(_('free'))
self.lattice_lequals[0].append_text(_('equals b'))
self.lattice_lequals[0].append_text(_('equals c'))
self.lattice_lequals[0].append_text(_('fixed'))
self.lattice_lequals[1].append_text(_('free'))
self.lattice_lequals[1].append_text(_('equals a'))
self.lattice_lequals[1].append_text(_('equals c'))
self.lattice_lequals[1].append_text(_('fixed'))
self.lattice_lequals[2].append_text(_('free'))
self.lattice_lequals[2].append_text(_('equals a'))
self.lattice_lequals[2].append_text(_('equals b'))
self.lattice_lequals[2].append_text(_('fixed'))
self.lattice_aequals[0].append_text(_('free'))
self.lattice_aequals[0].append_text(_('equals beta'))
self.lattice_aequals[0].append_text(_('equals gamma'))
self.lattice_aequals[0].append_text(_('fixed'))
self.lattice_aequals[1].append_text(_('free'))
self.lattice_aequals[1].append_text(_('equals alpha'))
self.lattice_aequals[1].append_text(_('equals gamma'))
self.lattice_aequals[1].append_text(_('fixed'))
self.lattice_aequals[2].append_text(_('free'))
self.lattice_aequals[2].append_text(_('equals alpha'))
self.lattice_aequals[2].append_text(_('equals beta'))
self.lattice_aequals[2].append_text(_('fixed'))
for i in range(3):
self.lattice_lequals[i].set_active(0)
self.lattice_aequals[i].set_active(0)
pack(vbox,[gtk.Label(_('Lattice parameters'))])
pack(vbox,[gtk.Label(_('\t\ta:\t')) , self.lattice_lbuts[0],gtk.Label(' '),self.lattice_lequals[0],
gtk.Label(_('\talpha:\t')), self.lattice_abuts[0],gtk.Label(' '),self.lattice_aequals[0]])
pack(vbox,[gtk.Label(_('\t\tb:\t')) , self.lattice_lbuts[1],gtk.Label(' '),self.lattice_lequals[1],
gtk.Label(_('\tbeta:\t')) , self.lattice_abuts[1],gtk.Label(' '),self.lattice_aequals[1]])
pack(vbox,[gtk.Label(_('\t\tc:\t')) , self.lattice_lbuts[2],gtk.Label(' '),self.lattice_lequals[2],
gtk.Label(_('\tgamma:\t')), self.lattice_abuts[2],gtk.Label(' '),self.lattice_aequals[2]])
self.get_data = gtk.Button(_("Get from database"))
self.get_data.connect("clicked", self.get_from_database)
self.get_data.set_sensitive(False)
pack(vbox,[gtk.Label(" "),self.get_data])
pack(vbox,[gtk.Label("")])
pack(vbox,[gtk.Label(_("Basis: "))])
self.elements = [[gtk.Entry(max=3),gtk.Entry(max=8),gtk.Entry(max=8),gtk.Entry(max=8),True]]
self.element = self.elements[0][0]
add_atom = gtk.Button(stock = gtk.STOCK_ADD)
add_atom.connect("clicked",self.add_basis_atom)
add_atom.connect("activate",self.add_basis_atom)
pack(vbox,[gtk.Label(_(' Element:\t')),self.elements[0][0],gtk.Label(_('\tx: ')),
self.elements[0][1],gtk.Label(_(' y: ')),self.elements[0][2],
gtk.Label(_(' z: ')),self.elements[0][3],gtk.Label('\t'),add_atom])
self.vbox_basis = gtk.VBox()
swin = gtk.ScrolledWindow()
swin.set_border_width(0)
swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
vbox.pack_start(swin, True, True, 0)
swin.add_with_viewport(self.vbox_basis)
self.vbox_basis.get_parent().set_shadow_type(gtk.SHADOW_NONE)
self.vbox_basis.get_parent().set_size_request(-1, 100)
swin.show()
pack(self.vbox_basis,[gtk.Label('')])
pack(vbox,[self.vbox_basis])
self.vbox_basis.show()
pack(vbox,[gtk.Label("")])
self.status = gtk.Label("")
pack(vbox,[self.status])
pack(vbox,[gtk.Label("")])
self.pybut = PyButton(_("Creating a crystal."))
self.pybut.connect('clicked', self.update)
clear = gtk.Button(stock = gtk.STOCK_CLEAR)
clear.connect("clicked", self.clear)
buts = cancel_apply_ok(cancel=lambda widget: self.destroy(),
apply=self.apply,
ok=self.ok)
pack(vbox, [self.pybut, clear, buts], end=True, bottom=True)
self.structinfo.connect("changed", self.update)
self.spacegroup.connect("activate", self.update)
for s in self.size:
s.connect("value-changed",self.update)
for el in self.elements:
if el[-1]:
for i in el[:-1]:
i.connect("activate", self.update)
i.connect("changed", self.update)
for i in range(3):
self.lattice_lbuts[i].connect("value-changed", self.update)
self.lattice_abuts[i].connect("value-changed", self.update)
self.lattice_lequals[i].connect("changed", self.update)
self.lattice_aequals[i].connect("changed", self.update)
self.clearing_in_process = False
self.gui = gui
self.add(vbox)
vbox.show()
self.show()
def update(self, *args):
""" all changes of physical constants are handled here, atoms are set up"""
if self.clearing_in_process:
return True
self.update_element()
a_equals = self.lattice_lequals[0].get_active()
b_equals = self.lattice_lequals[1].get_active()
c_equals = self.lattice_lequals[2].get_active()
alpha_equals = self.lattice_aequals[0].get_active()
beta_equals = self.lattice_aequals[1].get_active()
gamma_equals = self.lattice_aequals[2].get_active()
sym = self.spacegroup.get_text()
valid = True
try:
no = int(sym)
spg = Spacegroup(no).symbol
self.spacegroupinfo.set_label(_('Symbol: %s') % str(spg))
spg = no
except:
try:
no = Spacegroup(sym).no
self.spacegroupinfo.set_label(_('Number: %s') % str(no))
spg = no
except:
self.spacegroupinfo.set_label(_('Invalid Spacegroup!'))
valid = False
if a_equals == 0:
self.lattice_lbuts[0].set_sensitive(True)
elif a_equals == 1:
self.lattice_lbuts[0].set_sensitive(False)
self.lattice_lbuts[0].set_value(self.lattice_lbuts[1].get_value())
elif a_equals == 2:
self.lattice_lbuts[0].set_sensitive(False)
self.lattice_lbuts[0].set_value(self.lattice_lbuts[2].get_value())
else:
self.lattice_lbuts[0].set_sensitive(False)
if b_equals == 0:
self.lattice_lbuts[1].set_sensitive(True)
elif b_equals == 1:
self.lattice_lbuts[1].set_sensitive(False)
self.lattice_lbuts[1].set_value(self.lattice_lbuts[0].get_value())
elif b_equals == 2:
self.lattice_lbuts[1].set_sensitive(False)
self.lattice_lbuts[1].set_value(self.lattice_lbuts[2].get_value())
else:
self.lattice_lbuts[1].set_sensitive(False)
if c_equals == 0:
self.lattice_lbuts[2].set_sensitive(True)
elif c_equals == 1:
self.lattice_lbuts[2].set_sensitive(False)
self.lattice_lbuts[2].set_value(self.lattice_lbuts[0].get_value())
elif c_equals == 2:
self.lattice_lbuts[2].set_sensitive(False)
self.lattice_lbuts[2].set_value(self.lattice_lbuts[1].get_value())
else:
self.lattice_lbuts[2].set_sensitive(False)
if alpha_equals == 0:
self.lattice_abuts[0].set_sensitive(True)
elif alpha_equals == 1:
self.lattice_abuts[0].set_sensitive(False)
self.lattice_abuts[0].set_value(self.lattice_abuts[1].get_value())
elif alpha_equals == 2:
self.lattice_abuts[0].set_sensitive(False)
self.lattice_abuts[0].set_value(self.lattice_abuts[2].get_value())
else:
self.lattice_abuts[0].set_sensitive(False)
if beta_equals == 0:
self.lattice_abuts[1].set_sensitive(True)
elif beta_equals == 1:
self.lattice_abuts[1].set_sensitive(False)
self.lattice_abuts[1].set_value(self.lattice_abuts[0].get_value())
elif beta_equals == 2:
self.lattice_abuts[1].set_sensitive(False)
self.lattice_abuts[1].set_value(self.lattice_abuts[2].get_value())
else:
self.lattice_abuts[1].set_sensitive(False)
if gamma_equals == 0:
self.lattice_abuts[2].set_sensitive(True)
elif gamma_equals == 1:
self.lattice_abuts[2].set_sensitive(False)
self.lattice_abuts[2].set_value(self.lattice_abuts[0].get_value())
elif gamma_equals == 2:
self.lattice_abuts[2].set_sensitive(False)
self.lattice_abuts[2].set_value(self.lattice_abuts[1].get_value())
else:
self.lattice_abuts[2].set_sensitive(False)
valid = len(self.elements[0][0].get_text()) and valid
self.get_data.set_sensitive(valid and self.get_n_elements() == 1 and self.update_element())
self.atoms = None
if valid:
basis_count = -1
for el in self.elements:
if el[-1]:
basis_count += 1
if basis_count:
symbol_str = '['
basis_str = "["
symbol = []
basis = []
else:
symbol_str = ''
basis_str = ''
basis = None
for el in self.elements:
if el[-1]:
symbol_str += "'"+el[0].get_text()+"'"
if basis_count:
symbol_str += ','
symbol += [el[0].get_text()]
exec 'basis += [[float('+el[1].get_text()+'),float('+el[2].get_text()+'),float('+el[3].get_text()+')]]'
else:
symbol = el[0].get_text()
exec 'basis = [[float('+el[1].get_text()+'),float('+el[2].get_text()+'),float('+el[3].get_text()+')]]'
basis_str += '['+el[1].get_text()+','+el[2].get_text()+','+el[3].get_text()+'],'
basis_str = basis_str[:-1]
if basis_count:
symbol_str = symbol_str[:-1]+']'
basis_str += ']'
size_str = '('+str(int(self.size[0].get_value()))+','+str(int(self.size[1].get_value()))+','+str(int(self.size[2].get_value()))+')'
size = (int(self.size[0].get_value()),int(self.size[1].get_value()),int(self.size[2].get_value()))
cellpar_str = ''
cellpar = []
for i in self.lattice_lbuts:
cellpar_str += str(i.get_value())+','
cellpar += [i.get_value()]
for i in self.lattice_abuts:
cellpar_str += str(i.get_value())+','
cellpar += [i.get_value()]
cellpar_str = '['+cellpar_str[:-1]+']'
args = {'symbols' : symbol,
'basis' : basis,
'size' : size,
'spacegroup' : spg,
'cellpar' : cellpar}
args_str = {'symbols' : symbol_str,
'basis' : basis_str,
'size' : size_str,
'spacegroup' : spg,
'cellpar' : cellpar_str}
self.pybut.python = py_template % args_str
try:
self.atoms = crystal(**args)
label = label_template % {'natoms' : self.atoms.get_number_of_atoms(),
'symbols' : formula(self.atoms.get_atomic_numbers()),
'volume' : self.atoms.get_volume()}
self.status.set_label(label)
except:
self.atoms = None
self.status.set_markup(_("Please specify a consistent set of atoms."))
else:
self.atoms = None
self.status.set_markup(_("Please specify a consistent set of atoms."))
def apply(self, *args):
""" create gui atoms from currently active atoms"""
self.update()
if self.atoms is not None:
self.gui.new_atoms(self.atoms)
return True
else:
oops(_("No valid atoms.",
"You have not (yet) specified a consistent set of "
"parameters."))
return False
def ok(self, *args):
if self.apply():
self.destroy()
def add_basis_atom(self,*args):
""" add an atom to the customizable basis """
n = len(self.elements)
self.elements += [[gtk.Entry(max=3),gtk.Entry(max=8),gtk.Entry(max=8),gtk.Entry(max=8),
gtk.Label('\t\t\t'),gtk.Label('\tx: '),gtk.Label(' y: '),
gtk.Label(' z: '),gtk.Label(' '),
gtk.Button(stock=gtk.STOCK_DELETE),True]]
self.elements[n][-2].connect("clicked",self.delete_basis_atom,{'n':n})
pack(self.vbox_basis,[self.elements[n][4],self.elements[n][0],self.elements[n][5],
self.elements[n][1],self.elements[n][6],self.elements[n][2],
self.elements[n][7],self.elements[n][3],self.elements[n][8],
self.elements[n][9]])
self.update()
def delete_basis_atom(self, button, index, *args):
""" delete atom index from customizable basis"""
n = index['n']
self.elements[n][-1] = False
for i in range(10):
self.elements[n][i].destroy()
self.update()
def get_n_elements(self):
""" counts how many basis atoms are actually active """
n = 0
for el in self.elements:
if el[-1]:
n += 1
return n
def clear(self, *args):
""" reset to original state """
self.clearing_in_process = True
self.clear_lattice()
self.structinfo.set_active(0)
self.set_lattice_type()
self.clearing_in_process = False
self.update()
def clear_lattice(self, *args):
""" delete all custom settings """
self.atoms = None
if len(self.elements) > 1:
for n, el in enumerate(self.elements[1:]):
self.elements[n+1][-1] = False
for i in range(10):
self.elements[n+1][i].destroy()
for i in range(4):
self.elements[0][i].set_text("")
self.spacegroup.set_sensitive(True)
for i in self.lattice_lbuts:
i.set_sensitive(True)
for i in self.lattice_abuts:
i.set_sensitive(True)
for i in range(3):
self.lattice_lequals[i].set_sensitive(True)
self.lattice_aequals[i].set_sensitive(True)
self.lattice_lequals[i].set_active(0)
self.lattice_aequals[i].set_active(0)
for s in self.size:
s.set_value(1)
def set_lattice_type(self, *args):
""" set defaults from original """
self.clearing_in_process = True
self.clear_lattice()
lattice = crystal_definitions[self.structinfo.get_active()]
self.spacegroup.set_text(str(lattice[1]))
self.spacegroup.set_sensitive(lattice[2])
for s, i in zip(self.size,lattice[3]):
s.set_value(i)
self.lattice_lbuts[0].set_value(lattice[4][0])
self.lattice_lbuts[1].set_value(lattice[4][1])
self.lattice_lbuts[2].set_value(lattice[4][2])
self.lattice_abuts[0].set_value(lattice[4][3])
self.lattice_abuts[1].set_value(lattice[4][4])
self.lattice_abuts[2].set_value(lattice[4][5])
self.lattice_lequals[0].set_active(lattice[5][0])
self.lattice_lequals[1].set_active(lattice[5][1])
self.lattice_lequals[2].set_active(lattice[5][2])
self.lattice_aequals[0].set_active(lattice[5][3])
self.lattice_aequals[1].set_active(lattice[5][4])
self.lattice_aequals[2].set_active(lattice[5][5])
self.lattice_lequals[0].set_sensitive(lattice[6][0])
self.lattice_lequals[1].set_sensitive(lattice[6][1])
self.lattice_lequals[2].set_sensitive(lattice[6][2])
self.lattice_aequals[0].set_sensitive(lattice[6][3])
self.lattice_aequals[1].set_sensitive(lattice[6][4])
self.lattice_aequals[2].set_sensitive(lattice[6][5])
for n, at in enumerate(lattice[7]):
l = 0
if n > 0:
l = len(self.elements)
self.add_basis_atom()
for i, s in enumerate(at):
self.elements[l][i].set_text(s)
self.clearing_in_process = False
self.update()
def get_from_database(self, *args):
element = self.elements[0][0].get_text()
z = ase.atomic_numbers[self.legal_element]
ref = ase.data.reference_states[z]
lattice = ref['symmetry']
index = 0
while index < len(crystal_definitions) and crystal_definitions[index][0] != lattice:
index += 1
if index == len(crystal_definitions) or not self.legal_element:
oops(_("Can't find lattice definition!"))
return False
self.structinfo.set_active(index)
self.lattice_lbuts[0].set_value(ref['a'])
if lattice == 'hcp':
self.lattice_lbuts[2].set_value(ref['c/a']*ref['a'])
self.elements[0][0].set_text(element)
if lattice in ['fcc', 'bcc', 'diamond']:
self.elements[0][1].set_text('0')
self.elements[0][2].set_text('0')
self.elements[0][3].set_text('0')
python-ase-3.6.0.2515/ase/gui/ag.py 0000644 0001754 0001754 00000011515 11711330540 015473 0 ustar askhl askhl #!/usr/bin/env python
# Copyright 2008, 2009
# CAMd (see accompanying license files for details).
import os
from optparse import OptionParser, SUPPRESS_HELP
import ase.gui.i18n
from gettext import gettext as _
# Grrr, older versions (pre-python2.7) of optparse have a bug
# which prevents non-ascii descriptions. How do we circumvent this?
# For now, we'll have to use English in the command line options then.
def build_parser():
parser = OptionParser(usage='%prog [options] [file[, file2, ...]]',
version='%prog 0.1',
description='See the online manual ' +
'(https://wiki.fysik.dtu.dk/ase/ase/gui.html) ' +
'for more information.')
parser.add_option('-n', '--image-number',
default=':', metavar='NUMBER',
help='Pick image(s) from trajectory. NUMBER can be a '
'single number (use a negative number to count from '
'the back) or a range: start:stop:step, where the '
'":step" part can be left out - default values are '
'0:nimages:1.')
parser.add_option('-u', '--show-unit-cell', type='int',
default=1, metavar='I',
help="0: Don't show unit cell. 1: Show unit cell. "
'2: Show all of unit cell.')
parser.add_option('-r', '--repeat',
default='1',
help='Repeat unit cell. Use "-r 2" or "-r 2,3,1".')
parser.add_option('-R', '--rotations', default='',
help='Examples: "-R -90x", "-R 90z,-30x".')
parser.add_option('-o', '--output', metavar='FILE',
help='Write configurations to FILE.')
parser.add_option('-g', '--graph',
# TRANSLATORS: EXPR abbreviates 'expression'
metavar='EXPR',
help='Plot x,y1,y2,... graph from configurations or '
'write data to sdtout in terminal mode. Use the '
'symbols: i, s, d, fmax, e, ekin, A, R, E and F. See '
'https://wiki.fysik.dtu.dk/ase/ase/gui.html'
'#plotting-data for more details.')
parser.add_option('-t', '--terminal',
action='store_true',
default=False,
help='Run in terminal window - no GUI.')
parser.add_option('--aneb',
action='store_true',
default=False,
help='Read ANEB data.')
parser.add_option('--interpolate',
type='int', metavar='N',
help='Interpolate N images between 2 given images.')
parser.add_option('-b', '--bonds',
action='store_true',
default=False,
help='Draw bonds between atoms.')
return parser
def main():
parser = build_parser()
opt, args = parser.parse_args()
try:
import ase
except ImportError:
import sys
from os.path import dirname, join, pardir
sys.path.append(join(dirname(__file__), pardir))
from ase.gui.images import Images
from ase.atoms import Atoms
def run(opt, args):
images = Images()
if opt.aneb:
opt.image_number = '-1'
if len(args) > 0:
from ase.io import string2index
images.read(args, string2index(opt.image_number))
else:
images.initialize([Atoms()])
if opt.interpolate:
images.interpolate(opt.interpolate)
if opt.aneb:
images.aneb()
if opt.repeat != '1':
r = opt.repeat.split(',')
if len(r) == 1:
r = 3 * r
images.repeat_images([int(c) for c in r])
if opt.output is not None:
images.write(opt.output, rotations=opt.rotations,
show_unit_cell=opt.show_unit_cell)
opt.terminal = True
if opt.terminal:
if opt.graph is not None:
data = images.graph(opt.graph)
for line in data.T:
for x in line:
print x,
print
else:
from ase.gui.gui import GUI
import ase.gui.gtkexcepthook
gui = GUI(images, opt.rotations, opt.show_unit_cell, opt.bonds)
gui.run(opt.graph)
import traceback
try:
run(opt, args)
except KeyboardInterrupt:
pass
except Exception:
traceback.print_exc()
print(_("""
An exception occurred! Please report the issue to
ase-developers@listserv.fysik.dtu.dk - thanks! Please also report this if
it was a user error, so that a better error message can be provided
next time."""))
python-ase-3.6.0.2515/ase/transport/ 0000755 0001754 0001754 00000000000 11757245036 016016 5 ustar askhl askhl python-ase-3.6.0.2515/ase/transport/tools.py 0000644 0001754 0001754 00000034117 11257142403 017523 0 ustar askhl askhl import numpy as np
from math import sqrt, exp
def tri2full(H_nn, UL='L'):
"""Fill in values of hermitian matrix.
Fill values in lower or upper triangle of H_nn based on the opposite
triangle, such that the resulting matrix is symmetric/hermitian.
UL='U' will copy (conjugated) values from upper triangle into the
lower triangle.
UL='L' will copy (conjugated) values from lower triangle into the
upper triangle.
"""
N, tmp = H_nn.shape
assert N == tmp, 'Matrix must be square'
#assert np.isreal(H_nn.diagonal()).all(), 'Diagonal should be real'
if UL != 'L':
H_nn = H_nn.T
for n in range(N - 1):
H_nn[n, n + 1:] = H_nn[n + 1:, n].conj()
def dagger(matrix):
return np.conj(matrix.T)
def rotate_matrix(h, u):
return np.dot(u.T.conj(), np.dot(h, u))
def get_subspace(matrix, index):
"""Get the subspace spanned by the basis function listed in index"""
assert matrix.ndim == 2 and matrix.shape[0] == matrix.shape[1]
return matrix.take(index, 0).take(index, 1)
permute_matrix = get_subspace
def normalize(matrix, S=None):
"""Normalize column vectors.
::
= 1
"""
for col in matrix.T:
if S is None:
col /= np.linalg.norm(col)
else:
col /= np.sqrt(np.dot(col.conj(), np.dot(S, col)))
def subdiagonalize(h_ii, s_ii, index_j):
nb = h_ii.shape[0]
nb_sub = len(index_j)
h_sub_jj = get_subspace(h_ii, index_j)
s_sub_jj = get_subspace(s_ii, index_j)
e_j, v_jj = np.linalg.eig(np.linalg.solve(s_sub_jj, h_sub_jj))
normalize(v_jj, s_sub_jj) # normalize: = 1
permute_list = np.argsort(e_j.real)
e_j = np.take(e_j, permute_list)
v_jj = np.take(v_jj, permute_list, axis=1)
#setup transformation matrix
c_ii = np.identity(nb, complex)
for i in xrange(nb_sub):
for j in xrange(nb_sub):
c_ii[index_j[i], index_j[j]] = v_jj[i, j]
h1_ii = rotate_matrix(h_ii, c_ii)
s1_ii = rotate_matrix(s_ii, c_ii)
return h1_ii, s1_ii, c_ii, e_j
def cutcoupling(h, s, index_n):
for i in index_n:
s[:, i] = 0.0
s[i, :] = 0.0
s[i, i] = 1.0
Ei = h[i, i]
h[:, i] = 0.0
h[i, :] = 0.0
h[i, i] = Ei
def fermidistribution(energy, kt):
#fermi level is fixed to zero
return 1.0 / (1.0 + np.exp(energy / kt) )
def fliplr(a):
length=len(a)
b = [0] * length
for i in range(length):
b[i] = a[length - i - 1]
return b
def plot_path(energy):
import pylab
pylab.plot(np.real(energy), np.imag(energy), 'b--o')
pylab.show()
def function_integral(function, calcutype):
#return the integral of the 'function' on 'intrange'
#the function can be a value or a matrix, arg1,arg2 are the possible
#parameters of the function
intctrl = function.intctrl
if calcutype == 'eqInt':
intrange = intctrl.eqintpath
tol = intctrl.eqinttol
if hasattr(function.intctrl, 'eqpath_radius'):
radius = function.intctrl.eqpath_radius
else:
radius = -1
if hasattr(function.intctrl, 'eqpath_origin'):
origin = function.intctrl.eqpath_origin
else:
origin = 1000
elif calcutype == 'neInt':
intrange = intctrl.neintpath
tol = intctrl.neinttol
radius = -1
origin = 1000
elif calcutype == 'locInt':
intrange = intctrl.locintpath
tol = intctrl.locinttol
if hasattr(function.intctrl, 'locpath_radius'):
radius = function.intctrl.locpath_radius
else:
radius = -1
if hasattr(function.intctrl, 'locpath_origin'):
origin = function.intctrl.locpath_origin
else:
origin = 1000
trace = 0
a = 0.
b = 1.
#Initialize with 13 function evaluations.
c = (a + b) / 2
h = (b - a) / 2
realmin = 2e-17
s = [.942882415695480, sqrt(2.0/3),
.641853342345781, 1/sqrt(5.0), .236383199662150]
s1 = [0] * len(s)
s2 = [0] * len(s)
for i in range(len(s)):
s1[i] = c - s[i] * h
s2[i] = c + fliplr(s)[i] * h
x0 = [a] + s1 + [c] + s2 + [b]
s0 = [.0158271919734802, .094273840218850, .155071987336585,
.188821573960182, .199773405226859, .224926465333340]
w0 = s0 + [.242611071901408] + fliplr(s0)
w1 = [1, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 1]
w2 = [77, 0, 432, 0, 625, 0, 672, 0, 625, 0, 432, 0, 77]
for i in range(len(w1)):
w1[i] = w1[i] / 6.0
w2[i] = w2[i] / 1470.0
dZ = [intrange[:len(intrange) - 1], intrange[1:]]
hmin = [0] * len(dZ[1])
path_type = []
for i in range(len(intrange) - 1):
rs = np.abs(dZ[0][i] - origin)
re = np.abs(dZ[1][i] - origin)
if abs(rs - radius) < 1.0e-8 and abs(re - radius) < 1.0e-8:
path_type.append('half_circle')
else:
path_type.append('line')
for i in range(len(dZ[1])):
if path_type[i] == 'half_circle':
dZ[0][i] = 0
dZ[1][i] = np.pi
for i in range(len(dZ[1])):
dZ[1][i] = dZ[1][i] - dZ[0][i]
hmin[i] = realmin / 1024 * abs(dZ[1][i])
temp = np.array([[1] * 13, x0]).transpose()
Zx = np.dot(temp, np.array(dZ))
Zxx = []
for i in range(len(intrange) - 1):
for j in range(13):
Zxx.append(Zx[j][i])
ns = 0
ne = 12
if path_type[0] == 'line':
yns = function.calgfunc(Zxx[ns], calcutype)
elif path_type[0] == 'half_circle':
energy = origin + radius * np.exp((np.pi - Zxx[ns + i]) * 1.j)
yns = -1.j * radius * np.exp(-1.j* Zxx[ns +i])* function.calgfunc(energy, calcutype)
fcnt = 0
for n in range(len(intrange)-1):
# below evaluate the integral and adjust the tolerance
Q1pQ0 = yns * (w1[0] - w0[0])
Q2pQ0 = yns * (w2[0] - w0[0])
fcnt = fcnt + 12
for i in range(1,12):
if path_type[n] == 'line':
yne = function.calgfunc(Zxx[ns + i], calcutype)
elif path_type[n] == 'half_circle':
energy = origin + radius * np.exp((np.pi -Zxx[ns + i]) * 1.j)
yne = -1.j * radius * np.exp(-1.j * Zxx[ns + i])* function.calgfunc(energy, calcutype)
Q1pQ0 += yne * (w1[i] - w0[i])
Q2pQ0 += yne * (w2[i] - w0[i])
# Increase the tolerance if refinement appears to be effective
r = np.abs(Q2pQ0) / (np.abs(Q1pQ0) + np.abs(realmin))
dim = np.product(r.shape)
r = np.sum(r) / dim
if r > 0 and r < 1:
thistol = tol / r
else:
thistol = tol
if path_type[n] == 'line':
yne = function.calgfunc(Zxx[ne], calcutype)
elif path_type[n] == 'half_circle':
energy = origin + radius * np.exp((np.pi -Zxx[ne]) * 1.j)
yne = -1.j * radius * np.exp(-1.j * Zxx[ne])* function.calgfunc(energy, calcutype)
#Call the recursive core integrator
Qk, xpk, wpk, fcnt, warn = quadlstep(function, Zxx[ns],
Zxx[ne], yns, yne,
thistol, trace, fcnt,
hmin[n], calcutype, path_type[n],
origin, radius)
if n == 0:
Q = np.copy(Qk)
Xp = xpk[:]
Wp = wpk[:]
else:
Q += Qk
Xp = Xp[:-1] + xpk
Wp = Wp[:-1] + [Wp[-1] + wpk[0]] + wpk[1:]
if warn == 1:
print 'warning: Minimum step size reached,singularity possible'
elif warn == 2:
print 'warning: Maximum function count excced; singularity likely'
elif warn == 3:
print 'warning: Infinite or Not-a-Number function value encountered'
else:
pass
ns += 13
ne += 13
yns = np.copy(yne)
return Q,Xp,Wp,fcnt
def quadlstep(f, Za, Zb, fa, fb, tol, trace, fcnt, hmin, calcutype,
path_type, origin, radius):
#Gaussian-Lobatto and Kronrod method
#QUADLSTEP Recursive core routine for integral
#input parameters:
# f ---------- function, here we just use the module calgfunc
# to return the value, if wanna use it for
# another one, change it
# Za, Zb ---------- the start and end point of the integral
# fa, fb ---------- the function value on Za and Zb
# fcnt ---------- the number of the funtion recalled till now
#output parameters:
# Q ---------- integral
# Xp ---------- selected points
# Wp ---------- weight
# fcnt ---------- the number of the function recalled till now
maxfcnt = 10000
# Evaluate integrand five times in interior of subintrval [a,b]
Zh = (Zb - Za) / 2.0
if abs(Zh) < hmin:
# Minimun step size reached; singularity possible
Q = Zh * (fa + fb)
if path_type == 'line':
Xp = [Za, Zb]
elif path_type == 'half_circle':
Xp = [origin + radius * np.exp((np.pi - Za) * 1.j),
origin + radius * np.exp((np.pi - Zb) * 1.j)]
Wp = [Zh, Zh]
warn = 1
return Q, Xp, Wp, fcnt, warn
fcnt += 5
if fcnt > maxfcnt:
#Maximum function count exceed; singularity likely
Q = Zh * (fa + fb)
if path_type == 'line':
Xp = [Za, Zb]
elif path_type == 'half_circle':
Xp = [origin + radius * np.exp((np.pi - Za) * 1.j),
origin + radius * np.exp((np.pi - Zb) * 1.j)]
Wp = [Zh, Zh]
warn = 2
return Q, Xp, Wp, fcnt, warn
x = [0.18350341907227, 0.55278640450004, 1.0,
1.44721359549996, 1.81649658092773];
Zx = [0] * len(x)
y = [0] * len(x)
for i in range(len(x)):
x[i] *= 0.5
Zx[i] = Za + (Zb - Za) * x[i]
if path_type == 'line':
y[i] = f.calgfunc(Zx[i], calcutype)
elif path_type == 'half_circle':
energy = origin + radius * np.exp((np.pi - Zx[i]) * 1.j)
y[i] = f.calgfunc(energy, calcutype)
#Four point Lobatto quadrature
s1 = [1.0, 0.0, 5.0, 0.0, 5.0, 0.0, 1.0]
s2 = [77.0, 432.0, 625.0, 672.0, 625.0, 432.0, 77.0]
Wk = [0] * 7
Wp = [0] * 7
for i in range(7):
Wk[i] = (Zh / 6.0) * s1[i]
Wp[i] = (Zh / 1470.0) * s2[i]
if path_type == 'line':
Xp = [Za] + Zx + [Zb]
elif path_type == 'half_circle':
Xp = [Za] + Zx + [Zb]
for i in range(7):
factor = -1.j * radius * np.exp(1.j * (np.pi - Xp[i]))
Wk[i] *= factor
Wp[i] *= factor
Xp[i] = origin + radius * np.exp((np.pi - Xp[i]) * 1.j)
Qk = fa * Wk[0] + fb * Wk[6]
Q = fa * Wp[0] + fb * Wp[6]
for i in range(1, 6):
Qk += y[i-1] * Wk[i]
Q += y[i-1] * Wp[i]
if np.isinf(np.max(np.abs(Q))):
Q = Zh * (fa + fb)
if path_type == 'line':
Xp = [Za, Zb]
elif path_type == 'half_circle':
Xp = [origin + radius * np.exp((np.pi - Za) * 1.j),
origin + radius * np.exp((np.pi - Zb) * 1.j)]
Wp = [Zh, Zh]
warn = 3
return Qk, Xp, Wp, fcnt, warn
else:
pass
if trace:
print fcnt, real(Za), imag(Za), abs(Zh)
#Check accurancy of integral over this subinterval
XXk = [Xp[0], Xp[2], Xp[4], Xp[6]]
WWk = [Wk[0], Wk[2], Wk[4], Wk[6]]
YYk = [fa, y[1], y[3], fb]
if np.max(np.abs(Qk - Q)) <= tol:
warn = 0
return Q, XXk, WWk, fcnt, warn
#Subdivide into six subintevals
else:
Q, Xk, Wk, fcnt, warn = quadlstep(f, Za, Zx[1], fa, YYk[1],
tol, trace, fcnt, hmin,
calcutype, path_type,
origin, radius)
Qk, xkk, wkk, fcnt, warnk = quadlstep(f, Zx[1],
Zx[3], YYk[1], YYk[2], tol, trace, fcnt, hmin,
calcutype, path_type,
origin, radius)
Q += Qk
Xk = Xk[:-1] + xkk
Wk = Wk[:-1] + [Wk[-1] + wkk[0]] + wkk[1:]
warn = max(warn, warnk)
Qk, xkk, wkk, fcnt, warnk = quadlstep(f, Zx[3], Zb, YYk[2], fb,
tol, trace, fcnt, hmin,
calcutype, path_type,
origin, radius)
Q += Qk
Xk = Xk[:-1] + xkk
Wk = Wk[:-1] + [Wk[-1] + wkk[0]] + wkk[1:]
warn = max(warn, warnk)
return Q, Xk, Wk, fcnt, warn
def mytextread0(filename):
num = 0
df = file(filename)
df.seek(0)
for line in df:
if num == 0:
dim = line.strip().split(' ')
row = int(dim[0])
col = int(dim[1])
mat = np.empty([row, col])
else:
data = line.strip().split(' ')
if len(data) == 0 or len(data)== 1:
break
else:
for i in range(len(data)):
mat[num - 1, i] = float(data[i])
num += 1
return mat
def mytextread1(filename):
num = 0
df = file(filename)
df.seek(0)
data = []
for line in df:
tmp = line.strip()
if len(tmp) != 0:
data.append(float(tmp))
else:
break
dim = int(sqrt(len(data)))
mat = np.empty([dim, dim])
for i in range(dim):
for j in range(dim):
mat[i, j] = data[num]
num += 1
return mat
def mytextwrite1(filename, mat):
num = 0
df = open(filename,'w')
df.seek(0)
dim = mat.shape[0]
if dim != mat.shape[1]:
print 'matwirte, matrix is not square'
for i in range(dim):
for j in range(dim):
df.write('%20.20e\n'% mat[i, j])
df.close()
python-ase-3.6.0.2515/ase/transport/__init__.py 0000644 0001754 0001754 00000000054 11051026546 020114 0 ustar askhl askhl from calculators import TransportCalculator
python-ase-3.6.0.2515/ase/transport/greenfunction.py 0000644 0001754 0001754 00000004077 11200232074 021223 0 ustar askhl askhl import numpy as np
class GreenFunction:
"""Equilibrium retarded Green function."""
def __init__(self, H, S=None, selfenergies=[], eta=1e-4):
self.H = H
self.S = S
self.selfenergies = selfenergies
self.eta = eta
self.energy = None
self.Ginv = np.empty(H.shape, complex)
def retarded(self, energy, inverse=False):
"""Get retarded Green function at specified energy.
If 'inverse' is True, the inverse Green function is returned (faster).
"""
if energy != self.energy:
self.energy = energy
z = energy + self.eta * 1.j
if self.S is None:
self.Ginv[:] = 0.0
self.Ginv.flat[:: len(self.S) + 1] = z
else:
self.Ginv[:] = z
self.Ginv *= self.S
self.Ginv -= self.H
for selfenergy in self.selfenergies:
self.Ginv -= selfenergy.retarded(energy)
if inverse:
return self.Ginv
else:
return np.linalg.inv(self.Ginv)
def calculate(self, energy, sigma):
"""XXX is this really needed"""
ginv = energy * self.S - self.H - sigma
return np.linalg.inv(ginv)
def apply_retarded(self, energy, X):
"""Apply retarded Green function to X.
Returns the matrix product G^r(e) . X
"""
return np.linalg.solve(self.retarded(energy, inverse=True), X)
def dos(self, energy):
"""Total density of states -1/pi Im(Tr(GS))"""
if self.S is None:
return -self(energy).imag.trace() / np.pi
else:
GS = self.apply_retarded(energy, self.S)
return -GS.imag.trace() / np.pi
def pdos(self, energy):
"""Projected density of states -1/pi Im(SGS/S)"""
if self.S is None:
return -self.retarded(energy).imag.diagonal() / np.pi
else:
S = self.S
SGS = np.dot(S, self.apply_retarded(energy, S))
return -(SGS.diagonal() / S.diagonal()).imag / np.pi
python-ase-3.6.0.2515/ase/transport/stm.py 0000644 0001754 0001754 00000016545 11564503727 017206 0 ustar askhl askhl import time
import numpy as np
from ase.transport.tools import dagger
from ase.transport.selfenergy import LeadSelfEnergy
from ase.transport.greenfunction import GreenFunction
from ase.parallel import world
class STM:
def __init__(self, h1, s1, h2, s2 ,h10, s10, h20, s20, eta1, eta2, w=0.5, pdos=[], logfile = None):
"""XXX
1. Tip
2. Surface
h1: ndarray
Hamiltonian and overlap matrix for the isolated tip
calculation. Note, h1 should contain (at least) one
principal layer.
h2: ndarray
Same as h1 but for the surface.
h10: ndarray
periodic part of the tip. must include two and only
two principal layers.
h20: ndarray
same as h10, but for the surface
The s* are the corresponding overlap matrices. eta1, and eta
2 are (finite) infinitesimals. """
self.pl1 = len(h10) // 2 #principal layer size for the tip
self.pl2 = len(h20) // 2 #principal layer size for the surface
self.h1 = h1
self.s1 = s1
self.h2 = h2
self.s2 = s2
self.h10 = h10
self.s10 = s10
self.h20 = h20
self.s20 = s20
self.eta1 = eta1
self.eta2 = eta2
self.w = w #asymmetry of the applied bias (0.5=>symmetric)
self.pdos = []
self.log = logfile
def initialize(self, energies, bias=0):
"""
energies: list of energies
for which the transmission function should be evaluated.
bias.
Will precalculate the surface greenfunctions of the tip and
surface.
"""
self.bias = bias
self.energies = energies
nenergies = len(energies)
pl1, pl2 = self.pl1, self.pl2
nbf1, nbf2 = len(self.h1), len(self.h2)
#periodic part of the tip
hs1_dii = self.h10[:pl1, :pl1], self.s10[:pl1, :pl1]
hs1_dij = self.h10[:pl1, pl1:2*pl1], self.s10[:pl1, pl1:2*pl1]
#coupling betwen per. and non. per part of the tip
h1_im = np.zeros((pl1, nbf1), complex)
s1_im = np.zeros((pl1, nbf1), complex)
h1_im[:pl1, :pl1], s1_im[:pl1, :pl1] = hs1_dij
hs1_dim = [h1_im, s1_im]
#periodic part the surface
hs2_dii = self.h20[:pl2, :pl2], self.s20[:pl2, :pl2]
hs2_dij = self.h20[pl2:2*pl2, :pl2], self.s20[pl2:2*pl2, :pl2]
#coupling betwen per. and non. per part of the surface
h2_im = np.zeros((pl2, nbf2), complex)
s2_im = np.zeros((pl2, nbf2), complex)
h2_im[-pl2:, -pl2:], s2_im[-pl2:, -pl2:] = hs2_dij
hs2_dim = [h2_im, s2_im]
#tip and surface greenfunction
self.selfenergy1 = LeadSelfEnergy(hs1_dii, hs1_dij, hs1_dim, self.eta1)
self.selfenergy2 = LeadSelfEnergy(hs2_dii, hs2_dij, hs2_dim, self.eta2)
self.greenfunction1 = GreenFunction(self.h1-self.bias*self.w*self.s1, self.s1,
[self.selfenergy1], self.eta1)
self.greenfunction2 = GreenFunction(self.h2-self.bias*(self.w-1)*self.s2, self.s2,
[self.selfenergy2], self.eta2)
#Shift the bands due to the bias.
bias_shift1 = -bias * self.w
bias_shift2 = -bias * (self.w - 1)
self.selfenergy1.set_bias(bias_shift1)
self.selfenergy2.set_bias(bias_shift2)
#tip and surface greenfunction matrices.
nbf1_small = nbf1 #XXX Change this for efficiency in the future
nbf2_small = nbf2 #XXX -||-
coupling_list1 = range(nbf1_small)# XXX -||-
coupling_list2 = range(nbf2_small)# XXX -||-
self.gft1_emm = np.zeros((nenergies, nbf1_small, nbf1_small), complex)
self.gft2_emm = np.zeros((nenergies, nbf2_small, nbf2_small), complex)
for e, energy in enumerate(self.energies):
if self.log != None: # and world.rank == 0:
T = time.localtime()
self.log.write(' %d:%02d:%02d, ' % (T[3], T[4], T[5]) +
'%d, %d, %02f\n' % (world.rank, e, energy))
gft1_mm = self.greenfunction1.retarded(energy)[coupling_list1]
gft1_mm = np.take(gft1_mm, coupling_list1, axis=1)
gft2_mm = self.greenfunction2.retarded(energy)[coupling_list2]
gft2_mm = np.take(gft2_mm, coupling_list2, axis=1)
self.gft1_emm[e] = gft1_mm
self.gft2_emm[e] = gft2_mm
if self.log != None and world.rank == 0:
self.log.flush()
def get_transmission(self, v_12, v_11_2=None, v_22_1=None):
"""XXX
v_12:
coupling between tip and surface
v_11_2:
correction to "on-site" tip elements due to the
surface (eq.16). Is only included to first order.
v_22_1:
corretion to "on-site" surface elements due to he
tip (eq.17). Is only included to first order.
"""
dim0 = v_12.shape[0]
dim1 = v_12.shape[1]
nenergies = len(self.energies)
T_e = np.empty(nenergies,float)
v_21 = dagger(v_12)
for e, energy in enumerate(self.energies):
gft1 = self.gft1_emm[e]
if v_11_2!=None:
gf1 = np.dot(v_11_2, np.dot(gft1, v_11_2))
gf1 += gft1 #eq. 16
else:
gf1 = gft1
gft2 = self.gft2_emm[e]
if v_22_1!=None:
gf2 = np.dot(v_22_1,np.dot(gft2, v_22_1))
gf2 += gft2 #eq. 17
else:
gf2 = gft2
a1 = (gf1 - dagger(gf1))
a2 = (gf2 - dagger(gf2))
self.v_12 = v_12
self.a2 = a2
self.v_21 = v_21
self.a1 = a1
v12_a2 = np.dot(v_12, a2[:dim1])
v21_a1 = np.dot(v_21, a1[-dim0:])
self.v12_a2 = v12_a2
self.v21_a1 = v21_a1
T = -np.trace(np.dot(v12_a2[:,:dim1], v21_a1[:,-dim0:])) #eq. 11
assert abs(T.imag).max() < 1e-14
T_e[e] = T.real
self.T_e = T_e
return T_e
def get_current(self, bias, v_12, v_11_2=None, v_22_1=None):
"""Very simple function to calculate the current.
Asummes zero temperature.
bias: type? XXX
bias voltage (V)
v_12: XXX
coupling between tip and surface.
v_11_2:
correction to onsite elements of the tip
due to the potential of the surface.
v_22_1:
correction to onsite elements of the surface
due to the potential of the tip.
"""
energies = self.energies
T_e = self.get_transmission(v_12, v_11_2, v_22_1)
bias_window = -np.array([bias * self.w, bias * (self.w - 1)])
bias_window.sort()
self.bias_window = bias_window
#print 'bias window', np.around(bias_window,3)
#print 'Shift of tip lead do to the bias:', self.selfenergy1.bias
#print 'Shift of surface lead do to the bias:', self.selfenergy2.bias
i1 = sum(energies < bias_window[0])
i2 = sum(energies < bias_window[1])
step = 1
if i2 < i1:
step = -1
return np.sign(bias)*np.trapz(x=energies[i1:i2:step], y=T_e[i1:i2:step])
python-ase-3.6.0.2515/ase/transport/selfenergy.py 0000644 0001754 0001754 00000005455 11177755457 020555 0 ustar askhl askhl import numpy as np
class LeadSelfEnergy:
conv = 1e-8 # Convergence criteria for surface Green function
def __init__(self, hs_dii, hs_dij, hs_dim, eta=1e-4):
self.h_ii, self.s_ii = hs_dii # onsite principal layer
self.h_ij, self.s_ij = hs_dij # coupling between principal layers
self.h_im, self.s_im = hs_dim # coupling to the central region
self.nbf = self.h_im.shape[1] # nbf for the scattering region
self.eta = eta
self.energy = None
self.bias = 0
self.sigma_mm = np.empty((self.nbf, self.nbf), complex)
def retarded(self, energy):
"""Return self-energy (sigma) evaluated at specified energy."""
if energy != self.energy:
self.energy = energy
z = energy - self.bias + self.eta * 1.j
tau_im = z * self.s_im - self.h_im
a_im = np.linalg.solve(self.get_sgfinv(energy), tau_im)
tau_mi = z * self.s_im.T.conj() - self.h_im.T.conj()
self.sigma_mm[:] = np.dot(tau_mi, a_im)
return self.sigma_mm
def set_bias(self, bias):
self.bias = bias
def get_lambda(self, energy):
"""Return the lambda (aka Gamma) defined by i(S-S^d).
Here S is the retarded selfenergy, and d denotes the hermitian
conjugate.
"""
sigma_mm = self.retarded(energy)
return 1.j * (sigma_mm - sigma_mm.T.conj())
def get_sgfinv(self, energy):
"""The inverse of the retarded surface Green function"""
z = energy - self.bias + self.eta * 1.j
v_00 = z * self.s_ii.T.conj() - self.h_ii.T.conj()
v_11 = v_00.copy()
v_10 = z * self.s_ij - self.h_ij
v_01 = z * self.s_ij.T.conj() - self.h_ij.T.conj()
delta = self.conv + 1
while delta > self.conv:
a = np.linalg.solve(v_11, v_01)
b = np.linalg.solve(v_11, v_10)
v_01_dot_b = np.dot(v_01, b)
v_00 -= v_01_dot_b
v_11 -= np.dot(v_10, a)
v_11 -= v_01_dot_b
v_01 = -np.dot(v_01, a)
v_10 = -np.dot(v_10, b)
delta = abs(v_01).max()
return v_00
class BoxProbe:
"""Box shaped Buttinger probe.
Kramers-kroning: real = H(imag); imag = -H(real)
"""
def __init__(self, eta, a, b, energies, S, T=0.3):
from Transport.Hilbert import hilbert
se = np.empty(len(energies), complex)
se.imag = .5 * (np.tanh(.5 * (energies - a) / T) -
np.tanh(.5 * (energies - b) / T))
se.real = hilbert(se.imag)
se.imag -= 1
self.selfenergy_e = eta * se
self.energies = energies
self.S = S
def retarded(self, energy):
return self.selfenergy_e[self.energies.searchsorted(energy)] * self.S
python-ase-3.6.0.2515/ase/transport/calculators.py 0000644 0001754 0001754 00000036231 11306725071 020701 0 ustar askhl askhl import numpy as np
from numpy import linalg
from ase.transport.selfenergy import LeadSelfEnergy, BoxProbe
from ase.transport.greenfunction import GreenFunction
from ase.transport.tools import subdiagonalize, cutcoupling, tri2full, dagger,\
rotate_matrix
class TransportCalculator:
"""Determine transport properties of a device sandwiched between
two semi-infinite leads using a Green function method.
"""
def __init__(self, **kwargs):
"""Create the transport calculator.
Parameters
==========
h : (N, N) ndarray
Hamiltonian matrix for the central region.
s : {None, (N, N) ndarray}, optional
Overlap matrix for the central region.
Use None for an orthonormal basis.
h1 : (N1, N1) ndarray
Hamiltonian matrix for lead1.
h2 : {None, (N2, N2) ndarray}, optional
Hamiltonian matrix for lead2. You may use None if lead1 and lead2
are identical.
s1 : {None, (N1, N1) ndarray}, optional
Overlap matrix for lead1. Use None for an orthonomormal basis.
hc1 : {None, (N1, N) ndarray}, optional
Hamiltonian coupling matrix between the first principal
layer in lead1 and the central region.
hc2 : {None, (N2, N} ndarray), optional
Hamiltonian coupling matrix between the first principal
layer in lead2 and the central region.
sc1 : {None, (N1, N) ndarray}, optional
Overlap coupling matrix between the first principal
layer in lead1 and the central region.
sc2 : {None, (N2, N) ndarray}, optional
Overlap coupling matrix between the first principal
layer in lead2 and the central region.
energies : {None, array_like}, optional
Energy points for which calculated transport properties are
evaluated.
eta : {1.0e-5, float}, optional
Infinitesimal for the central region Green function.
eta1/eta2 : {1.0e-5, float}, optional
Infinitesimal for lead1/lead2 Green function.
align_bf : {None, int}, optional
Use align_bf=m to shift the central region
by a constant potential such that the m'th onsite element
in the central region is aligned to the m'th onsite element
in lead1 principal layer.
logfile : {None, str}, optional
Write a logfile to file with name `logfile`.
Use '-' to write to std out.
eigenchannels: {0, int}, optional
Number of eigenchannel transmission coefficients to
calculate.
pdos : {None, (N,) array_like}, optional
Specify which basis functions to calculate the
projected density of states for.
dos : {False, bool}, optional
The total density of states of the central region.
box: XXX
YYY
If hc1/hc2 are None, they are assumed to be identical to
the coupling matrix elements between neareste neighbor
principal layers in lead1/lead2.
Examples
========
>>> import numpy as np
>>> h = np.array((0,)).reshape((1,1))
>>> h1 = np.array((0, -1, -1, 0)).reshape(2,2)
>>> energies = np.arange(-3, 3, 0.1)
>>> calc = TransportCalculator(h=h, h1=h1, energies=energies)
>>> T = calc.get_transmission()
"""
# The default values for all extra keywords
self.input_parameters = {'energies': None,
'h': None,
'h1': None,
'h2': None,
's': None,
's1': None,
's2': None,
'hc1': None,
'hc2': None,
'sc1': None,
'sc2': None,
'box': None,
'align_bf': None,
'eta1': 1e-5,
'eta2': 1e-5,
'eta': 1e-5,
'logfile': None, # '-',
'eigenchannels': 0,
'dos': False,
'pdos': [],
}
self.initialized = False # Changed Hamiltonians?
self.uptodate = False # Changed energy grid?
self.set(**kwargs)
def set(self, **kwargs):
for key in kwargs:
if key in ['h', 'h1', 'h2', 'hc1', 'hc2',
's', 's1', 's2', 'sc1', 'sc2',
'eta', 'eta1', 'eta2', 'align_bf', 'box']:
self.initialized = False
self.uptodate = False
break
elif key in ['energies', 'eigenchannels', 'dos', 'pdos']:
self.uptodate = False
elif key not in self.input_parameters:
raise KeyError, '\'%s\' not a vaild keyword' % key
self.input_parameters.update(kwargs)
log = self.input_parameters['logfile']
if log is None:
class Trash:
def write(self, s):
pass
def flush(self):
pass
self.log = Trash()
elif log == '-':
from sys import stdout
self.log = stdout
elif 'logfile' in kwargs:
self.log = open(log, 'w')
def initialize(self):
if self.initialized:
return
print >> self.log, '# Initializing calculator...'
p = self.input_parameters
if p['s'] == None:
p['s'] = np.identity(len(p['h']))
identical_leads = False
if p['h2'] == None:
p['h2'] = p['h1'] # Lead2 is idendical to lead1
identical_leads = True
if p['s1'] == None:
p['s1'] = np.identity(len(p['h1']))
if p['s2'] == None and not identical_leads:
p['s2'] = np.identity(len(p['h2'])) # Orthonormal basis for lead 2
else: # Lead2 is idendical to lead1
p['s2'] = p['s1']
h_mm = p['h']
s_mm = p['s']
pl1 = len(p['h1']) / 2
pl2 = len(p['h2']) / 2
h1_ii = p['h1'][:pl1, :pl1]
h1_ij = p['h1'][:pl1, pl1:2 * pl1]
s1_ii = p['s1'][:pl1, :pl1]
s1_ij = p['s1'][:pl1, pl1:2 * pl1]
h2_ii = p['h2'][:pl2, :pl2]
h2_ij = p['h2'][pl2: 2 * pl2, :pl2]
s2_ii = p['s2'][:pl2, :pl2]
s2_ij = p['s2'][pl2: 2 * pl2, :pl2]
if p['hc1'] is None:
nbf = len(h_mm)
h1_im = np.zeros((pl1, nbf), complex)
s1_im = np.zeros((pl1, nbf), complex)
h1_im[:pl1, :pl1] = h1_ij
s1_im[:pl1, :pl1] = s1_ij
p['hc1'] = h1_im
p['sc1'] = s1_im
else:
h1_im = p['hc1']
if p['sc1'] is not None:
s1_im = p['sc1']
else:
s1_im = np.zeros(h1_im.shape, complex)
p['sc1'] = s1_im
if p['hc2'] is None:
h2_im = np.zeros((pl2, nbf), complex)
s2_im = np.zeros((pl2, nbf), complex)
h2_im[-pl2:, -pl2:] = h2_ij
s2_im[-pl2:, -pl2:] = s2_ij
p['hc2'] = h2_im
p['sc2'] = s2_im
else:
h2_im = p['hc2']
if p['sc2'] is not None:
s2_im = p['sc2']
else:
s2_im = np.zeros(h2_im.shape, complex)
p['sc2'] = s2_im
align_bf = p['align_bf']
if align_bf != None:
diff = (h_mm[align_bf, align_bf] - h1_ii[align_bf, align_bf]) \
/ s_mm[align_bf, align_bf]
print >> self.log, '# Aligning scat. H to left lead H. diff=', diff
h_mm -= diff * s_mm
# Setup lead self-energies
# All infinitesimals must be > 0
assert np.all(np.array((p['eta'], p['eta1'], p['eta2'])) > 0.0)
self.selfenergies = [LeadSelfEnergy((h1_ii, s1_ii),
(h1_ij, s1_ij),
(h1_im, s1_im),
p['eta1']),
LeadSelfEnergy((h2_ii, s2_ii),
(h2_ij, s2_ij),
(h2_im, s2_im),
p['eta2'])]
box = p['box']
if box is not None:
print 'Using box probe!'
self.selfenergies.append(
BoxProbe(eta=box[0], a=box[1], b=box[2], energies=box[3],
S=s_mm, T=0.3))
#setup scattering green function
self.greenfunction = GreenFunction(selfenergies=self.selfenergies,
H=h_mm,
S=s_mm,
eta=p['eta'])
self.initialized = True
def update(self):
if self.uptodate:
return
p = self.input_parameters
self.energies = p['energies']
nepts = len(self.energies)
nchan = p['eigenchannels']
pdos = p['pdos']
self.T_e = np.empty(nepts)
if p['dos']:
self.dos_e = np.empty(nepts)
if pdos != []:
self.pdos_ne = np.empty((len(pdos), nepts))
if nchan > 0:
self.eigenchannels_ne = np.empty((nchan, nepts))
for e, energy in enumerate(self.energies):
Ginv_mm = self.greenfunction.retarded(energy, inverse=True)
lambda1_mm = self.selfenergies[0].get_lambda(energy)
lambda2_mm = self.selfenergies[1].get_lambda(energy)
a_mm = linalg.solve(Ginv_mm, lambda1_mm)
b_mm = linalg.solve(dagger(Ginv_mm), lambda2_mm)
T_mm = np.dot(a_mm, b_mm)
if nchan > 0:
t_n = linalg.eigvals(T_mm).real
self.eigenchannels_ne[:, e] = np.sort(t_n)[-nchan:]
self.T_e[e] = np.sum(t_n)
else:
self.T_e[e] = np.trace(T_mm).real
print >> self.log, energy, self.T_e[e]
self.log.flush()
if p['dos']:
self.dos_e[e] = self.greenfunction.dos(energy)
if pdos != []:
self.pdos_ne[:, e] = np.take(self.greenfunction.pdos(energy),
pdos)
self.uptodate = True
def print_pl_convergence(self):
self.initialize()
pl1 = len(self.input_parameters['h1']) / 2
h_ii = self.selfenergies[0].h_ii
s_ii = self.selfenergies[0].s_ii
ha_ii = self.greenfunction.H[:pl1, :pl1]
sa_ii = self.greenfunction.S[:pl1, :pl1]
c1 = np.abs(h_ii - ha_ii).max()
c2 = np.abs(s_ii - sa_ii).max()
print 'Conv (h,s)=%.2e, %2.e' % (c1, c2)
def plot_pl_convergence(self):
self.initialize()
pl1 = len(self.input_parameters['h1']) / 2
hlead = self.selfenergies[0].h_ii.real.diagonal()
hprincipal = self.greenfunction.H.real.diagonal[:pl1]
import pylab as pl
pl.plot(hlead, label='lead')
pl.plot(hprincipal, label='principal layer')
pl.axis('tight')
pl.show()
def get_transmission(self):
self.initialize()
self.update()
return self.T_e
def get_dos(self):
self.initialize()
self.update()
return self.dos_e
def get_eigenchannels(self, n=None):
"""Get ``n`` first eigenchannels."""
self.initialize()
self.update()
if n is None:
n = self.input_parameters['eigenchannels']
return self.eigenchannels_ne[:n]
def get_pdos(self):
self.initialize()
self.update()
return self.pdos_ne
def subdiagonalize_bfs(self, bfs, apply=False):
self.initialize()
bfs = np.array(bfs)
p = self.input_parameters
h_mm = p['h']
s_mm = p['s']
ht_mm, st_mm, c_mm, e_m = subdiagonalize(h_mm, s_mm, bfs)
if apply:
self.uptodate = False
h_mm[:] = ht_mm
s_mm[:] = st_mm
# Rotate coupling between lead and central region
for alpha, sigma in enumerate(self.selfenergies):
sigma.h_im[:] = np.dot(sigma.h_im, c_mm)
sigma.s_im[:] = np.dot(sigma.s_im, c_mm)
c_mm = np.take(c_mm, bfs, axis=0)
c_mm = np.take(c_mm, bfs, axis=1)
return ht_mm, st_mm, e_m, c_mm
def cutcoupling_bfs(self, bfs, apply=False):
self.initialize()
bfs = np.array(bfs)
p = self.input_parameters
h_pp = p['h'].copy()
s_pp = p['s'].copy()
cutcoupling(h_pp, s_pp, bfs)
if apply:
self.uptodate = False
p['h'][:] = h_pp
p['s'][:] = s_pp
for alpha, sigma in enumerate(self.selfenergies):
for m in bfs:
sigma.h_im[:, m] = 0.0
sigma.s_im[:, m] = 0.0
return h_pp, s_pp
def lowdin_rotation(self, apply=False):
p = self.input_parameters
h_mm = p['h']
s_mm = p['s']
eig, rot_mm = linalg.eigh(s_mm)
eig = np.abs(eig)
rot_mm = np.dot(rot_mm / np.sqrt(eig), dagger(rot_mm))
if apply:
self.uptodate = False
h_mm[:] = rotate_matrix(h_mm, rot_mm) # rotate C region
s_mm[:] = rotate_matrix(s_mm, rot_mm)
for alpha, sigma in enumerate(self.selfenergies):
sigma.h_im[:] = np.dot(sigma.h_im, rot_mm) # rotate L-C coupl.
sigma.s_im[:] = np.dot(sigma.s_im, rot_mm)
return rot_mm
def get_left_channels(self, energy, nchan=1):
self.initialize()
g_s_ii = self.greenfunction.retarded(energy)
lambda_l_ii = self.selfenergies[0].get_lambda(energy)
lambda_r_ii = self.selfenergies[1].get_lambda(energy)
if self.greenfunction.S is None:
s_s_qsrt_ii = s_s_isqrt = np.identity(len(g_s_ii))
else:
s_mm = self.greenfunction.S
s_s_i, s_s_ii = linalg.eig(s_mm)
s_s_i = np.abs(s_s_i)
s_s_sqrt_i = np.sqrt(s_s_i) # sqrt of eigenvalues
s_s_sqrt_ii = np.dot(s_s_ii * s_s_sqrt_i, dagger(s_s_ii))
s_s_isqrt_ii = np.dot(s_s_ii / s_s_sqrt_i, dagger(s_s_ii))
lambdab_r_ii = np.dot(np.dot(s_s_isqrt_ii, lambda_r_ii),s_s_isqrt_ii)
a_l_ii = np.dot(np.dot(g_s_ii, lambda_l_ii), dagger(g_s_ii))
ab_l_ii = np.dot(np.dot(s_s_sqrt_ii, a_l_ii), s_s_sqrt_ii)
lambda_i, u_ii = linalg.eig(ab_l_ii)
ut_ii = np.sqrt(lambda_i / (2.0 * np.pi)) * u_ii
m_ii = 2 * np.pi * np.dot(np.dot(dagger(ut_ii), lambdab_r_ii),ut_ii)
T_i,c_in = linalg.eig(m_ii)
T_i = np.abs(T_i)
channels = np.argsort(-T_i)[:nchan]
c_in = np.take(c_in, channels, axis=1)
T_n = np.take(T_i, channels)
v_in = np.dot(np.dot(s_s_isqrt_ii, ut_ii), c_in)
return T_n, v_in
python-ase-3.6.0.2515/ase/transport/test_transport_calulator.py 0000644 0001754 0001754 00000004162 11311137675 023527 0 ustar askhl askhl from ase.transport.calculators import TransportCalculator
import numpy as np
#Aux. function to write data to a text file.
def write(fname,xs,ys):
fd = open(fname,'w')
for x,y in zip(xs,ys):
print >> fd, x, y
fd.close()
H_lead = np.zeros([4,4])
# On-site energies are zero
for i in range(4):
H_lead[i,i] = 0.0
# Nearest neighbor hopping is -1.0
for i in range(3):
H_lead[i,i+1] = -1.0
H_lead[i+1,i] = -1.0
# Next-nearest neighbor hopping is 0.2
for i in range(2):
H_lead[i,i+2] = 0.2
H_lead[i+2,i] = 0.2
H_scat = np.zeros([6,6])
# Principal layers on either side of S
H_scat[:2,:2] = H_lead[:2,:2]
H_scat[-2:,-2:] = H_lead[:2,:2]
# Scattering region
H_scat[2,2] = 0.0
H_scat[3,3] = 0.0
H_scat[2,3] = -0.8
H_scat[3,2] = -0.8
# External coupling
H_scat[1,2] = 0.2
H_scat[2,1] = 0.2
H_scat[3,4] = 0.2
H_scat[4,3] = 0.2
energies = np.arange(-3,3,0.02)
tcalc = TransportCalculator(h=H_scat,
h1=H_lead,
eta=0.02,
energies=energies)
T = tcalc.get_transmission()
tcalc.set(pdos=[2, 3])
pdos = tcalc.get_pdos()
tcalc.set(dos=True)
dos = tcalc.get_dos()
write('T.dat',tcalc.energies,T)
write('pdos0.dat', tcalc.energies,pdos[0])
write('pdos1.dat', tcalc.energies,pdos[1])
#subdiagonalize
h_rot, s_rot, eps, u = tcalc.subdiagonalize_bfs([2, 3], apply=True)
T_rot = tcalc.get_transmission()
dos_rot = tcalc.get_dos()
pdos_rot = tcalc.get_pdos()
write('T_rot.dat', tcalc.energies,T_rot)
write('pdos0_rot.dat', tcalc.energies, pdos_rot[0])
write('pdos1_rot.dat', tcalc.energies, pdos_rot[1])
print 'Subspace eigenvalues:', eps
assert sum(abs(eps-(-0.8, 0.8))) < 2.0e-15, 'Subdiagonalization. error'
print 'Max deviation of T after the rotation:', np.abs(T-T_rot).max()
assert max(abs(T-T_rot)) < 2.0e-15, 'Subdiagonalization. error'
#remove coupling
h_cut, s_cut = tcalc.cutcoupling_bfs([2], apply=True)
T_cut = tcalc.get_transmission()
dos_cut = tcalc.get_dos()
pdos_cut = tcalc.get_pdos()
write('T_cut.dat', tcalc.energies, T_cut)
write('pdos0_cut.dat', tcalc.energies,pdos_cut[0])
write('pdos1_cut.dat', tcalc.energies,pdos_cut[1])
python-ase-3.6.0.2515/ase/transport/stm_test.py 0000644 0001754 0001754 00000003263 11143035723 020223 0 ustar askhl askhl import numpy as np
import pylab
import ase.transport.stm as stm
# Parameters for a simple model.
#
#
# * eps_a
# v_ts / \ v_a2
# ... * * * * * * * * * ...
# \/ \/
# t1 t2
#
# Tip Surface
# ----------------| |-----------------------
t1 = -1.0
t2 = -2.0
eps_a = 0.4
v_ts = 0.05
v_a2 = 1.0
#Tip
h1 = np.zeros([2, 2])
h1[0, 1] = t1
h1[1, 0] = t1
s1 = np.identity(2)
h10 = np.zeros([2,2])
h10[0, 1] = t1
h10[1, 0] = t1
s10 = np.identity(2)
#Surface with "molecule" a.
h2 = np.zeros([2,2])
h2[0, 1] = v_a2
h2[1, 0] = v_a2
h1[0, 0] = eps_a
s2 = np.identity(2)
h20 = np.zeros([2,2])
h20[0, 1] = t2
h20[1, 0] = t2
s20 = np.identity(2)
#Tip Surface coupling
V_ts = np.zeros([2,2])
V_ts[1, 0] = v_ts
eta1 = 0.0001
eta2 = 0.0001
stm = reload(stm)
stm_calc = stm.STM(h1, s1, h2, s2, h10, s10, h20, s20, eta1, eta2)
energies = np.arange(-3.0, 3.0, 0.01)
stm_calc.initialize(energies)
T_stm = stm_calc.get_transmission(V_ts)
#Perform the full calculation and compare
from ase.transport.calculators import TransportCalculator as TC
h = np.zeros([4,4])
h[:2, :2] = h1
h[-2:, -2:] = h2
h[:2, -2:] = V_ts
h[-2:, :2] = V_ts.T
tc = TC(energies=energies,
h=h,
h1=h10,
h2=h20,
eta=eta1, eta1=eta1, eta2=eta2)
T_full = tc.get_transmission()
pylab.plot(stm_calc.energies, T_stm, 'b')
pylab.plot(tc.energies, T_full, 'r--')
pylab.show()
#bias stuff
biass = np.arange(-2.0, 2.0, 0.2)
Is = [stm_calc.get_current(bias, V_ts) for bias in biass]
pylab.plot(biass, Is, '+')
pylab.show()
python-ase-3.6.0.2515/ase/constraints.py 0000644 0001754 0001754 00000120572 11712217646 016707 0 ustar askhl askhl from math import sqrt
import numpy as np
__all__ = ['FixCartesian', 'FixBondLength', 'FixedMode', 'FixConstraintSingle',
'FixAtoms', 'UnitCellFilter', 'FixScaled', 'StrainFilter',
'FixedPlane', 'Filter', 'FixConstraint', 'FixedLine',
'FixBondLengths', 'FixInternals']
def slice2enlist(s):
"""Convert a slice object into a list of (new, old) tuples."""
if isinstance(s, (list, tuple)):
return enumerate(s)
if s.step == None:
step = 1
else:
step = s.step
if s.start == None:
start = 0
else:
start = s.start
return enumerate(range(start, s.stop, step))
class FixConstraint:
"""Base class for classes that fix one or more atoms in some way."""
def index_shuffle(self, ind):
"""Change the indices.
When the ordering of the atoms in the Atoms object changes,
this method can be called to shuffle the indices of the
constraints.
ind -- List or tuple of indices.
"""
raise NotImplementedError
def repeat(self, m, n):
""" basic method to multiply by m, needs to know the length
of the underlying atoms object for the assignment of
multiplied constraints to work.
"""
raise NotImplementedError
class FixConstraintSingle(FixConstraint):
"""Base class for classes that fix a single atom."""
def index_shuffle(self, ind):
"""The atom index must be stored as self.a."""
newa = -1 # Signal error
for new, old in slice2enlist(ind):
if old == self.a:
newa = new
break
if newa == -1:
raise IndexError('Constraint not part of slice')
self.a = newa
class FixAtoms(FixConstraint):
"""Constraint object for fixing some chosen atoms."""
def __init__(self, indices=None, mask=None):
"""Constrain chosen atoms.
Parameters
----------
indices : list of int
Indices for those atoms that should be constrained.
mask : list of bool
One boolean per atom indicating if the atom should be
constrained or not.
Examples
--------
Fix all Copper atoms:
>>> c = FixAtoms(mask=[s == 'Cu' for s in atoms.get_chemical_symbols()])
>>> atoms.set_constraint(c)
Fix all atoms with z-coordinate less than 1.0 Angstrom:
>>> c = FixAtoms(mask=atoms.positions[:, 2] < 1.0)
>>> atoms.set_constraint(c)
"""
if indices is None and mask is None:
raise ValueError('Use "indices" or "mask".')
if indices is not None and mask is not None:
raise ValueError('Use only one of "indices" and "mask".')
if mask is not None:
self.index = np.asarray(mask, bool)
else:
# Check for duplicates
srt = np.sort(indices)
for i in range(len(indices) - 1):
if srt[i] == srt[i+1]:
raise ValueError(
'FixAtoms: The indices array contained duplicates. '
'Perhaps you wanted to specify a mask instead, but '
'forgot the mask= keyword.')
self.index = np.asarray(indices, int)
if self.index.ndim != 1:
raise ValueError('Wrong argument to FixAtoms class!')
def adjust_positions(self, old, new):
new[self.index] = old[self.index]
def adjust_forces(self, positions, forces):
forces[self.index] = 0.0
def index_shuffle(self, ind):
# See docstring of superclass
if self.index.dtype == bool:
self.index = self.index[ind]
else:
index = []
for new, old in slice2enlist(ind):
if old in self.index:
index.append(new)
if len(index) == 0:
raise IndexError('All indices in FixAtoms not part of slice')
self.index = np.asarray(index, int)
def copy(self):
if self.index.dtype == bool:
return FixAtoms(mask=self.index.copy())
else:
return FixAtoms(indices=self.index.copy())
def __repr__(self):
if self.index.dtype == bool:
return 'FixAtoms(mask=%s)' % ints2string(self.index.astype(int))
return 'FixAtoms(indices=%s)' % ints2string(self.index)
def repeat(self, m, n):
i0 = 0
l = len(self.index)
natoms = 0
if isinstance(m, int):
m = (m, m, m)
index_new = []
for m2 in range(m[2]):
for m1 in range(m[1]):
for m0 in range(m[0]):
i1 = i0 + n
if self.index.dtype == bool:
index_new.extend(self.index)
else:
index_new += [i+natoms for i in self.index]
i0 = i1
natoms += n
if self.index.dtype == bool:
self.index = np.asarray(index_new, bool)
else:
self.index = np.asarray(index_new, int)
return self
def delete_atom(self, ind):
""" Removes atom number ind from the index array, if present.
Required for removing atoms with existing FixAtoms constraints.
"""
if self.index.dtype == bool:
self.index = np.delete(self.index, ind)
else:
if ind in self.index:
i = list(self.index).index(ind)
self.index = np.delete(self.index, i)
for i in range(len(self.index)):
if self.index[i] >= ind:
self.index[i] -= 1
def ints2string(x, threshold=10):
"""Convert ndarray of ints to string."""
if len(x) <= threshold:
return str(x.tolist())
return str(x[:threshold].tolist())[:-1] + ', ...]'
class FixBondLengths(FixConstraint):
def __init__(self, pairs, iterations=10):
self.constraints = [FixBondLength(a1, a2)
for a1, a2 in pairs]
self.iterations = iterations
def adjust_positions(self, old, new):
for i in range(self.iterations):
for constraint in self.constraints:
constraint.adjust_positions(old, new)
def adjust_forces(self, positions, forces):
for i in range(self.iterations):
for constraint in self.constraints:
constraint.adjust_forces(positions, forces)
def copy(self):
return FixBondLengths([constraint.indices
for constraint in self.constraints])
class FixBondLength(FixConstraint):
"""Constraint object for fixing a bond length."""
def __init__(self, a1, a2):
"""Fix distance between atoms with indices a1 and a2."""
self.indices = [a1, a2]
def adjust_positions(self, old, new):
p1, p2 = old[self.indices]
d = p2 - p1
p = sqrt(np.dot(d, d))
q1, q2 = new[self.indices]
d = q2 - q1
q = sqrt(np.dot(d, d))
d *= 0.5 * (p - q) / q
new[self.indices] = (q1 - d, q2 + d)
def adjust_forces(self, positions, forces):
d = np.subtract.reduce(positions[self.indices])
d2 = np.dot(d, d)
d *= 0.5 * np.dot(np.subtract.reduce(forces[self.indices]), d) / d2
forces[self.indices] += (-d, d)
def index_shuffle(self, ind):
'Shuffle the indices of the two atoms in this constraint'
newa = [-1, -1] # Signal error
for new, old in slice2enlist(ind):
for i, a in enumerate(self.indices):
if old == a:
newa[i] = new
if newa[0] == -1 or newa[1] == -1:
raise IndexError('Constraint not part of slice')
self.indices = newa
def copy(self):
return FixBondLength(*self.indices)
def __repr__(self):
return 'FixBondLength(%d, %d)' % tuple(self.indices)
class FixedMode(FixConstraint):
"""Constrain atoms to move along directions orthogonal to
a given mode only."""
def __init__(self, indices, mode):
if indices is None:
raise ValueError('Use "indices".')
if indices is not None:
self.index = np.asarray(indices, int)
self.mode = (np.asarray(mode) / np.sqrt((mode **2).sum())).reshape(-1)
def adjust_positions(self, oldpositions, newpositions):
newpositions = newpositions.ravel()
oldpositions = oldpositions.ravel()
step = newpositions - oldpositions
newpositions -= self.mode * np.dot(step, self.mode)
newpositions = newpositions.reshape(-1, 3)
oldpositions = oldpositions.reshape(-1, 3)
def adjust_forces(self, positions, forces):
forces = forces.ravel()
forces -= self.mode * np.dot(forces, self.mode)
forces = forces.reshape(-1, 3)
def copy(self):
return FixedMode(self.index.copy(), self.mode)
def __repr__(self):
return 'FixedMode(%s, %s)' % (ints2string(self.index),
self.mode.tolist())
class FixedPlane(FixConstraintSingle):
"""Constrain an atom *a* to move in a given plane only.
The plane is defined by its normal: *direction*."""
def __init__(self, a, direction):
self.a = a
self.dir = np.asarray(direction) / sqrt(np.dot(direction, direction))
def adjust_positions(self, oldpositions, newpositions):
step = newpositions[self.a] - oldpositions[self.a]
newpositions[self.a] -= self.dir * np.dot(step, self.dir)
def adjust_forces(self, positions, forces):
forces[self.a] -= self.dir * np.dot(forces[self.a], self.dir)
def copy(self):
return FixedPlane(self.a, self.dir)
def __repr__(self):
return 'FixedPlane(%d, %s)' % (self.a, self.dir.tolist())
class FixedLine(FixConstraintSingle):
"""Constrain an atom *a* to move on a given line only.
The line is defined by its *direction*."""
def __init__(self, a, direction):
self.a = a
self.dir = np.asarray(direction) / sqrt(np.dot(direction, direction))
def adjust_positions(self, oldpositions, newpositions):
step = newpositions[self.a] - oldpositions[self.a]
x = np.dot(step, self.dir)
newpositions[self.a] = oldpositions[self.a] + x * self.dir
def adjust_forces(self, positions, forces):
forces[self.a] = self.dir * np.dot(forces[self.a], self.dir)
def copy(self):
return FixedLine(self.a, self.dir)
def __repr__(self):
return 'FixedLine(%d, %s)' % (self.a, self.dir.tolist())
class FixCartesian(FixConstraintSingle):
"Fix an atom in the directions of the cartesian coordinates."
def __init__(self, a, mask=(1, 1, 1)):
self.a = a
self.mask = -(np.array(mask) - 1)
def adjust_positions(self, old, new):
step = new[self.a] - old[self.a]
step *= self.mask
new[self.a] = old[self.a] + step
def adjust_forces(self, positions, forces):
forces[self.a] *= self.mask
def copy(self):
return FixCartesian(self.a, 1 - self.mask)
def __repr__(self):
return 'FixCartesian(indice=%s mask=%s)' % (self.a, self.mask)
class fix_cartesian(FixCartesian):
"Backwards compatibility for FixCartesian."
def __init__(self, a, mask=(1, 1, 1)):
import warnings
super(fix_cartesian, self).__init__(a, mask)
warnings.warn('fix_cartesian is deprecated. Please use FixCartesian'
' instead.', DeprecationWarning, stacklevel=2)
class FixScaled(FixConstraintSingle):
"Fix an atom in the directions of the unit vectors."
def __init__(self, cell, a, mask=(1, 1, 1)):
self.cell = cell
self.a = a
self.mask = np.array(mask)
def adjust_positions(self, old, new):
scaled_old = np.linalg.solve(self.cell.T, old.T).T
scaled_new = np.linalg.solve(self.cell.T, new.T).T
for n in range(3):
if self.mask[n]:
scaled_new[self.a, n] = scaled_old[self.a, n]
new[self.a] = np.dot(scaled_new, self.cell)[self.a]
def adjust_forces(self, positions, forces):
scaled_forces = np.linalg.solve(self.cell.T, forces.T).T
scaled_forces[self.a] *= -(self.mask - 1)
forces[self.a] = np.dot(scaled_forces, self.cell)[self.a]
def copy(self):
return FixScaled(self.cell, self.a, self.mask)
def __repr__(self):
return 'FixScaled(%s, %d, %s)' % (repr(self.cell),
self.a,
repr(self.mask))
class fix_scaled(FixScaled):
"Backwards compatibility for FixScaled."
def __init__(self, cell, a, mask=(1, 1, 1)):
import warnings
super(fix_scaled, self).__init__(cell, a, mask)
warnings.warn('fix_scaled is deprecated. Please use FixScaled '
'instead.', DeprecationWarning, stacklevel=2)
class FixInternals(FixConstraint):
"""Constraint object for fixing multiple internal coordinates.
Allows fixing bonds, angles, and dihedrals."""
def __init__(self, atoms=None, bonds=None, angles=None, dihedrals=None,
epsilon=1.e-7, _copy_init=None):
if _copy_init is None:
if atoms is None:
raise ValueError('Atoms object has to be defined.')
masses = atoms.get_masses()
if bonds is None:
bonds = []
if angles is None:
angles = []
if dihedrals is None:
dihedrals = []
self.n = len(bonds) + len(angles) + len(dihedrals)
self.constraints = []
for bond in bonds:
masses_bond = masses[bond[1]]
self.constraints.append(self.FixBondLengthAlt(bond[0], bond[1],
masses_bond))
for angle in angles:
masses_angle = masses[angle[1]]
self.constraints.append(self.FixAngle(angle[0], angle[1],
masses_angle))
for dihedral in dihedrals:
masses_dihedral = masses[dihedral[1]]
self.constraints.append(self.FixDihedral(dihedral[0],
dihedral[1],
masses_dihedral))
self.epsilon = epsilon
#copy case for __init__
else:
self.constraints = _copy_init
self.n = len(self.constraints)
self.epsilon = epsilon
def adjust_positions(self, old, new):
for constraint in self.constraints:
constraint.set_h_vectors(old)
for j in range(50):
maxerr = 0.0
for constraint in self.constraints:
constraint.adjust_positions(old, new)
maxerr = max(abs(constraint.sigma), maxerr)
if maxerr < self.epsilon:
return
raise ValueError('Shake did not converge.')
def adjust_forces(self, positions, forces):
#Project out translations and rotations and all other constraints
N = len(forces)
list2_constraints = list(np.zeros((6, N, 3)))
tx, ty, tz, rx, ry, rz = list2_constraints
list_constraints = [r.ravel() for r in list2_constraints]
tx[:, 0] = 1.0
ty[:, 1] = 1.0
tz[:, 2] = 1.0
ff = forces.ravel()
#Calculate the center of mass
center = positions.sum(axis=0) / N
rx[:, 1] = -(positions[:, 2] - center[2])
rx[:, 2] = positions[:, 1] - center[1]
ry[:, 0] = positions[:, 2] - center[2]
ry[:, 2] = -(positions[:, 0] - center[0])
rz[:, 0] = -(positions[:, 1] - center[1])
rz[:, 1] = positions[:, 0] - center[0]
#Normalizing transl., rotat. constraints
for r in list2_constraints:
r /= np.linalg.norm(r.ravel())
#Add all angle, etc. constraint vectors
for constraint in self.constraints:
constraint.adjust_forces(positions, forces)
list_constraints.insert(0, constraint.h)
#QR DECOMPOSITION - GRAM SCHMIDT
list_constraints = [r.ravel() for r in list_constraints]
aa = np.column_stack(list_constraints)
(aa, bb) = np.linalg.qr(aa, mode = 'full')
#Projektion
hh = []
for i, constraint in enumerate(self.constraints):
hh.append(aa[:, i] * np.row_stack(aa[:, i]))
txx = aa[:, self.n] * np.row_stack(aa[:, self.n])
tyy = aa[:, self.n+1] * np.row_stack(aa[:, self.n+1])
tzz = aa[:, self.n+2] * np.row_stack(aa[:, self.n+2])
rxx = aa[:, self.n+3] * np.row_stack(aa[:, self.n+3])
ryy = aa[:, self.n+4] * np.row_stack(aa[:, self.n+4])
rzz = aa[:, self.n+5] * np.row_stack(aa[:, self.n+5])
T = txx + tyy + tzz + rxx + ryy + rzz
for vec in hh:
T += vec
ff = np.dot(T, np.row_stack(ff))
forces[:, :] -= np.dot(T, np.row_stack(ff)).reshape(-1, 3)
def copy(self):
return FixInternals(epsilon=self.epsilon, _copy_init=self.constraints)
def __repr__(self):
constraints = repr(self.constraints)
return 'FixInternals(_copy_init=%s, epsilon=%s)' % (constraints,
repr(self.epsilon))
def __str__(self):
return '\n'.join([repr(c) for c in self.constraints])
#Classes for internal use in FixInternals
class FixBondLengthAlt:
"""Constraint subobject for fixing bond length within FixInternals."""
def __init__(self, bond, indices, masses, maxstep=0.01):
"""Fix distance between atoms with indices a1, a2."""
self.indices = indices
self.bond = bond
self.h1, self.h2 = None
self.masses = masses
self.h = []
self.sigma = 1.
def set_h_vectors(self, pos):
dist1 = pos[self.indices[0]] - pos[self.indices[1]]
self.h1 = 2 * dist1
self.h2 = -self.h1
def adjust_positions(self, old, new):
h1 = self.h1 / self.masses[0]
h2 = self.h2 / self.masses[1]
dist1 = new[self.indices[0]] - new[self.indices[1]]
dist = np.dot(dist1, dist1)
self.sigma = dist - self.bond**2
lamda = -self.sigma / (2 * np.dot(dist1, (h1 - h2)))
new[self.indices[0]] += lamda * h1
new[self.indices[1]] += lamda * h2
def adjust_forces(self, positions, forces):
self.h1 = 2 * (positions[self.indices[0]] -
positions[self.indices[1]])
self.h2 = -self.h1
self.h = np.zeros([len(forces)*3])
self.h[(self.indices[0])*3] = self.h1[0]
self.h[(self.indices[0])*3+1] = self.h1[1]
self.h[(self.indices[0])*3+2] = self.h1[2]
self.h[(self.indices[1])*3] = self.h2[0]
self.h[(self.indices[1])*3+1] = self.h2[1]
self.h[(self.indices[1])*3+2] = self.h2[2]
self.h /= np.linalg.norm(self.h)
def __repr__(self):
return 'FixBondLengthAlt(%d, %d, %d)' % \
tuple(self.bond, self.indices)
class FixAngle:
"""Constraint object for fixing an angle within
FixInternals."""
def __init__(self, angle, indices, masses):
"""Fix atom movement to construct a constant angle."""
self.indices = indices
self.a1m, self.a2m, self.a3m = masses
self.angle = np.cos(angle)
self.h1 = self.h2 = self.h3 = None
self.h = []
self.sigma = 1.
def set_h_vectors(self, pos):
r21 = pos[self.indices[0]] - pos[self.indices[1]]
r21_len = np.linalg.norm(r21)
e21 = r21 / r21_len
r23 = pos[self.indices[2]] - pos[self.indices[1]]
r23_len = np.linalg.norm(r23)
e23 = r23 / r23_len
angle = np.dot(e21, e23)
self.h1 = -2 * angle * ((angle * e21 - e23) / (r21_len))
self.h3 = -2 * angle * ((angle * e23 - e21) / (r23_len))
self.h2 = -(self.h1 + self.h3)
def adjust_positions(self, oldpositions, newpositions):
r21 = newpositions[self.indices[0]] - newpositions[self.indices[1]]
r21_len = np.linalg.norm(r21)
e21 = r21 / r21_len
r23 = newpositions[self.indices[2]] - newpositions[self.indices[1]]
r23_len = np.linalg.norm(r23)
e23 = r23 / r23_len
angle = np.dot(e21, e23)
self.sigma = (angle - self.angle) * (angle + self.angle)
h1 = self.h1 / self.a1m
h3 = self.h3 / self.a3m
h2 = self.h2 / self.a2m
h21 = h1 - h2
h23 = h3 - h2
# Calculating new positions
deriv = (((np.dot(r21, h23) + np.dot(r23, h21))
/ (r21_len * r23_len))
- (np.dot(r21, h21) / (r21_len * r21_len)
+ np.dot(r23, h23) / (r23_len * r23_len)) * angle)
deriv *= 2 * angle
lamda = -self.sigma / deriv
newpositions[self.indices[0]] += lamda * h1
newpositions[self.indices[1]] += lamda * h2
newpositions[self.indices[2]] += lamda * h3
def adjust_forces(self, positions, forces):
r21 = positions[self.indices[0]] - positions[self.indices[1]]
r21_len = np.linalg.norm(r21)
e21 = r21 / r21_len
r23 = positions[self.indices[2]] - positions[self.indices[1]]
r23_len = np.linalg.norm(r23)
e23 = r23 / r23_len
angle = np.dot(e21, e23)
self.h1 = -2 * angle * (angle * e21 - e23) / r21_len
self.h3 = -2 * angle * (angle * e23 - e21) / r23_len
self.h2 = -(self.h1 + self.h3)
self.h = np.zeros([len(positions)*3])
self.h[(self.indices[0])*3] = self.h1[0]
self.h[(self.indices[0])*3+1] = self.h1[1]
self.h[(self.indices[0])*3+2] = self.h1[2]
self.h[(self.indices[1])*3] = self.h2[0]
self.h[(self.indices[1])*3+1] = self.h2[1]
self.h[(self.indices[1])*3+2] = self.h2[2]
self.h[(self.indices[2])*3] = self.h3[0]
self.h[(self.indices[2])*3+1] = self.h3[1]
self.h[(self.indices[2])*3+2] = self.h3[2]
self.h /= np.linalg.norm(self.h)
def __repr__(self):
return 'FixAngle(%s, %f)' % (tuple(self.indices),
np.arccos(self.angle))
class FixDihedral:
"""Constraint object for fixing an dihedral using
the shake algorithm. This one allows also other constraints."""
def __init__(self, angle, indices, masses):
"""Fix atom movement to construct a constant dihedral angle."""
self.indices = indices
self.a1m, self.a2m, self.a3m, self.a4m = masses
self.angle = np.cos(angle)
self.h1 = self.h2 = self.h3 = self.h4 = None
self.h = []
self.sigma = 1.
def set_h_vectors(self, pos):
r12 = pos[self.indices[1]] - pos[self.indices[0]]
r12_len = np.linalg.norm(r12)
e12 = r12 / r12_len
r23 = pos[self.indices[2]] - pos[self.indices[1]]
r23_len = np.linalg.norm(r23)
e23 = r23 / r23_len
r34 = pos[self.indices[3]] - pos[self.indices[2]]
r34_len = np.linalg.norm(r34)
e34 = r34 / r34_len
a = -r12 - np.dot(-r12, e23) * e23
a_len = np.linalg.norm(a)
ea = a / a_len
b = r34 - np.dot(r34, e23) * e23
b_len = np.linalg.norm(b)
eb = b / b_len
angle = np.dot(ea, eb).clip(-1.0, 1.0)
self.h1 = (eb - angle * ea) / a_len
self.h4 = (ea - angle * eb) / b_len
self.h2 = self.h1 * (np.dot(-r12, e23) / r23_len -1)
self.h2 += np.dot(r34, e23) / r23_len * self.h4
self.h3 = -self.h4 * (np.dot(r34, e23) / r23_len + 1)
self.h3 += np.dot(r12, e23) / r23_len * self.h1
def adjust_positions(self, oldpositions, newpositions):
r12 = newpositions[self.indices[1]] - newpositions[self.indices[0]]
r12_len = np.linalg.norm(r12)
e12 = r12 / r12_len
r23 = newpositions[self.indices[2]] - newpositions[self.indices[1]]
r23_len = np.linalg.norm(r23)
e23 = r23 / r23_len
r34 = newpositions[self.indices[3]] - newpositions[self.indices[2]]
r34_len = np.linalg.norm(r34)
e34 = r34 / r34_len
n1 = np.cross(r12, r23)
n1_len = np.linalg.norm(n1)
n1e = n1 / n1_len
n2 = np.cross(r23, r34)
n2_len = np.linalg.norm(n2)
n2e = n2 / n2_len
angle = np.dot(n1e, n2e).clip(-1.0, 1.0)
self.sigma = (angle - self.angle) * (angle + self.angle)
h1 = self.h1 / self.a1m
h2 = self.h2 / self.a2m
h3 = self.h3 / self.a3m
h4 = self.h4 / self.a4m
h12 = h2 - h1
h23 = h3 - h2
h34 = h4 - h3
deriv = ((np.dot(n1, np.cross(r34, h23) + np.cross(h34, r23))
+ np.dot(n2, np.cross(r23, h12) + np.cross(h23, r12)))
/ (n1_len * n2_len))
deriv -= (((np.dot(n1, np.cross(r23, h12) + np.cross(h23, r12))
/ n1_len**2)
+ (np.dot(n2, np.cross(r34, h23) + np.cross(h34, r23))
/ n2_len**2)) * angle)
deriv *= -2 * angle
lamda = -self.sigma / deriv
newpositions[self.indices[0]] += lamda * h1
newpositions[self.indices[1]] += lamda * h2
newpositions[self.indices[2]] += lamda * h3
newpositions[self.indices[3]] += lamda * h4
def adjust_forces(self, positions, forces):
r12 = positions[self.indices[1]] - positions[self.indices[0]]
r12_len = np.linalg.norm(r12)
e12 = r12 / r12_len
r23 = positions[self.indices[2]] - positions[self.indices[1]]
r23_len = np.linalg.norm(r23)
e23 = r23 / r23_len
r34 = positions[self.indices[3]] - positions[self.indices[2]]
r34_len = np.linalg.norm(r34)
e34 = r34 / r34_len
a = -r12 - np.dot(-r12, e23) * e23
a_len = np.linalg.norm(a)
ea = a / a_len
b = r34 - np.dot(r34, e23) * e23
b_len = np.linalg.norm(b)
eb = b / b_len
angle = np.dot(ea, eb).clip(-1.0, 1.0)
self.h1 = (eb - angle * ea) / a_len
self.h4 = (ea - angle * eb) / b_len
self.h2 = self.h1 * (np.dot(-r12, e23) / r23_len - 1)
self.h2 += np.dot(r34, e23) / r23_len * self.h4
self.h3 = -self.h4 * (np.dot(r34, e23) / r23_len + 1)
self.h3 -= np.dot(-r12, e23) / r23_len * self.h1
self.h = np.zeros([len(positions)*3])
self.h[(self.indices[0])*3] = self.h1[0]
self.h[(self.indices[0])*3+1] = self.h1[1]
self.h[(self.indices[0])*3+2] = self.h1[2]
self.h[(self.indices[1])*3] = self.h2[0]
self.h[(self.indices[1])*3+1] = self.h2[1]
self.h[(self.indices[1])*3+2] = self.h2[2]
self.h[(self.indices[2])*3] = self.h3[0]
self.h[(self.indices[2])*3+1] = self.h3[1]
self.h[(self.indices[2])*3+2] = self.h3[2]
self.h[(self.indices[3])*3] = self.h4[0]
self.h[(self.indices[3])*3+1] = self.h4[1]
self.h[(self.indices[3])*3+2] = self.h4[2]
self.h /= np.linalg.norm(self.h)
def __repr__(self):
return 'FixDihedral(%s, %f)' % (tuple(self.indices), self.angle)
class BondSpring(FixConstraint):
"""Forces two atoms to stay close together by applying no force if they
are below threshhold_length, and applying a Hookian force when the
distance between them exceeds the thresshhold_length.
a1, a2 : indices of atoms 1 and 2
a2 can alternately be a position in space to tether a1 to
threshhold_length (float) : the length below which there is no force
springconstant (integer) : Hook's law constant to apply when distance
between the two atoms exceeds threshhold_length, dimensions of
(force / length)
"""
def __init__(self, a1, a2, threshhold_length, springconstant):
if type(a2) == int:
self._type = 2 # two atoms tethered together
self.indices = [a1, a2]
else:
self._type = 1 # one atom tethered to a point in space
self.index = a1
self.origin = np.array(a2)
self.threshhold = threshhold_length
self.spring = springconstant
def adjust_positions(self, oldpositions, newpositions):
pass
def adjust_forces(self, positions, forces):
if self._type == 2:
p1, p2 = positions[self.indices]
else:
p1 = positions[self.index]
p2 = self.origin
displace = p2 - p1
bondlength = np.linalg.norm(displace)
if bondlength > self.threshhold:
magnitude = self.spring * (bondlength - self.threshhold)
direction = displace / np.linalg.norm(displace)
if self._type == 2:
forces[self.indices[0]] += direction * magnitude / 2.
forces[self.indices[1]] -= direction * magnitude / 2.
else:
forces[self.index] += direction * magnitude
def __repr__(self):
if self._type == 2:
return 'BondSpring(%d, %d)' % tuple(self.indices)
else:
return 'BondSpring(%d) to cartesian' % self.index
def copy(self):
if self._type == 2:
return BondSpring(a1=self.indices[0], a2=self.indices[1],
threshhold_length=self.threshhold,
springconstant=self.spring)
else:
return BondSpring(a1=self.index, a2=self.origin,
threshhold_length=self.threshhold,
springconstant=self.spring)
class Filter:
"""Subset filter class."""
def __init__(self, atoms, indices=None, mask=None):
"""Filter atoms.
This filter can be used to hide degrees of freedom in an Atoms
object.
Parameters
----------
indices : list of int
Indices for those atoms that should remain visible.
mask : list of bool
One boolean per atom indicating if the atom should remain
visible or not.
"""
self.atoms = atoms
self.constraints = []
if indices is None and mask is None:
raise ValueError('Use "indices" or "mask".')
if indices is not None and mask is not None:
raise ValueError('Use only one of "indices" and "mask".')
if mask is not None:
self.index = np.asarray(mask, bool)
self.n = self.index.sum()
else:
self.index = np.asarray(indices, int)
self.n = len(self.index)
def get_cell(self):
"""Returns the computational cell.
The computational cell is the same as for the original system.
"""
return self.atoms.get_cell()
def get_pbc(self):
"""Returns the periodic boundary conditions.
The boundary conditions are the same as for the original system.
"""
return self.atoms.get_pbc()
def get_positions(self):
"Return the positions of the visible atoms."
return self.atoms.get_positions()[self.index]
def set_positions(self, positions):
"Set the positions of the visible atoms."
pos = self.atoms.get_positions()
pos[self.index] = positions
self.atoms.set_positions(pos)
positions = property(get_positions, set_positions,
doc='Positions of the atoms')
def get_momenta(self):
"Return the momenta of the visible atoms."
return self.atoms.get_momenta()[self.index]
def set_momenta(self, momenta):
"Set the momenta of the visible atoms."
mom = self.atoms.get_momenta()
mom[self.index] = momenta
self.atoms.set_momenta(mom)
def get_atomic_numbers(self):
"Return the atomic numbers of the visible atoms."
return self.atoms.get_atomic_numbers()[self.index]
def set_atomic_numbers(self, atomic_numbers):
"Set the atomic numbers of the visible atoms."
z = self.atoms.get_atomic_numbers()
z[self.index] = atomic_numbers
self.atoms.set_atomic_numbers(z)
def get_tags(self):
"Return the tags of the visible atoms."
return self.atoms.get_tags()[self.index]
def set_tags(self, tags):
"Set the tags of the visible atoms."
tg = self.atoms.get_tags()
tg[self.index] = tags
self.atoms.set_tags(tg)
def get_forces(self, *args, **kwargs):
return self.atoms.get_forces(*args, **kwargs)[self.index]
def get_stress(self):
return self.atoms.get_stress()
def get_stresses(self):
return self.atoms.get_stresses()[self.index]
def get_masses(self):
return self.atoms.get_masses()[self.index]
def get_potential_energy(self):
"""Calculate potential energy.
Returns the potential energy of the full system.
"""
return self.atoms.get_potential_energy()
def get_chemical_symbols(self):
return self.atoms.get_chemical_symbols()
def get_initial_magnetic_moments(self):
return self.atoms.get_initial_magnetic_moments()
def get_calculator(self):
"""Returns the calculator.
WARNING: The calculator is unaware of this filter, and sees a
different number of atoms.
"""
return self.atoms.get_calculator()
def has(self, name):
"""Check for existance of array."""
return self.atoms.has(name)
def __len__(self):
"Return the number of movable atoms."
return self.n
def __getitem__(self, i):
"Return an atom."
return self.atoms[self.index[i]]
class StrainFilter(Filter):
"""Modify the supercell while keeping the scaled positions fixed.
Presents the strain of the supercell as the generalized positions,
and the global stress tensor (times the volume) as the generalized
force.
This filter can be used to relax the unit cell until the stress is
zero. If MDMin is used for this, the timestep (dt) to be used
depends on the system size. 0.01/x where x is a typical dimension
seems like a good choice.
The stress and strain are presented as 6-vectors, the order of the
components follow the standard engingeering practice: xx, yy, zz,
yz, xz, xy.
"""
def __init__(self, atoms, mask=None):
"""Create a filter applying a homogeneous strain to a list of atoms.
The first argument, atoms, is the atoms object.
The optional second argument, mask, is a list of six booleans,
indicating which of the six independent components of the
strain that are allowed to become non-zero. It defaults to
[1,1,1,1,1,1].
"""
self.atoms = atoms
self.strain = np.zeros(6)
if mask is None:
self.mask = np.ones(6)
else:
self.mask = np.array(mask)
self.index = np.arange(len(atoms))
self.n = self.index.sum()
self.origcell = atoms.get_cell()
def get_positions(self):
return self.strain.reshape((2, 3))
def set_positions(self, new):
new = new.ravel() * self.mask
eps = np.array([[1.0 + new[0], 0.5 * new[5], 0.5 * new[4]],
[0.5 * new[5], 1.0 + new[1], 0.5 * new[3]],
[0.5 * new[4], 0.5 * new[3], 1.0 + new[2]]])
self.atoms.set_cell(np.dot(self.origcell, eps), scale_atoms=True)
self.strain[:] = new
def get_forces(self):
stress = self.atoms.get_stress()
return -self.atoms.get_volume() * (stress * self.mask).reshape((2, 3))
def get_potential_energy(self):
return self.atoms.get_potential_energy()
def has(self, x):
return self.atoms.has(x)
def __len__(self):
return 2
class UnitCellFilter(Filter):
"""Modify the supercell and the atom positions. """
def __init__(self, atoms, mask=None):
"""Create a filter that returns the atomic forces and unit
cell stresses together, so they can simultaneously be
minimized.
The first argument, atoms, is the atoms object.
The optional second argument, mask, is a list of booleans,
indicating which of the six independent
components of the strain are relaxed.
1, True = relax to zero
0, False = fixed, ignore this component
use atom Constraints, e.g. FixAtoms, to control relaxation of
the atoms.
#this should be equivalent to the StrainFilter
>>> atoms = Atoms(...)
>>> atoms.set_constraint(FixAtoms(mask=[True for atom in atoms]))
>>> ucf = UCFilter(atoms)
You should not attach this UCFilter object to a
trajectory. Instead, create a trajectory for the atoms, and
attach it to an optimizer like this:
>>> atoms = Atoms(...)
>>> ucf = UCFilter(atoms)
>>> qn = QuasiNewton(ucf)
>>> traj = PickleTrajectory('TiO2.traj','w',atoms)
>>> qn.attach(traj)
>>> qn.run(fmax=0.05)
Helpful conversion table
========================
0.05 eV/A^3 = 8 GPA
0.003 eV/A^3 = 0.48 GPa
0.0006 eV/A^3 = 0.096 GPa
0.0003 eV/A^3 = 0.048 GPa
0.0001 eV/A^3 = 0.02 GPa
"""
Filter.__init__(self, atoms, indices=range(len(atoms)))
self.atoms = atoms
self.strain = np.zeros(6)
if mask is None:
self.mask = np.ones(6)
else:
self.mask = np.array(mask)
self.origcell = atoms.get_cell()
def get_positions(self):
'''
this returns an array with shape (natoms + 2,3).
the first natoms rows are the positions of the atoms, the last
two rows are the strains associated with the unit cell
'''
atom_positions = self.atoms.get_positions()
strains = self.strain.reshape((2, 3))
natoms = len(self.atoms)
all_pos = np.zeros((natoms + 2, 3), np.float)
all_pos[0:natoms, :] = atom_positions
all_pos[natoms:, :] = strains
return all_pos
def set_positions(self, new):
'''
new is an array with shape (natoms+2,3).
the first natoms rows are the positions of the atoms, the last
two rows are the strains used to change the cell shape.
The atom positions are set first, then the unit cell is
changed keeping the atoms in their scaled positions.
'''
natoms = len(self.atoms)
atom_positions = new[0:natoms, :]
self.atoms.set_positions(atom_positions)
new = new[natoms:, :] #this is only the strains
new = new.ravel() * self.mask
eps = np.array([[1.0 + new[0], 0.5 * new[5], 0.5 * new[4]],
[0.5 * new[5], 1.0 + new[1], 0.5 * new[3]],
[0.5 * new[4], 0.5 * new[3], 1.0 + new[2]]])
self.atoms.set_cell(np.dot(self.origcell, eps), scale_atoms=True)
self.strain[:] = new
def get_forces(self, apply_constraint=False):
'''
returns an array with shape (natoms+2,3) of the atomic forces
and unit cell stresses.
the first natoms rows are the forces on the atoms, the last
two rows are the stresses on the unit cell, which have been
reshaped to look like "atomic forces". i.e.,
f[-2] = -vol*[sxx,syy,szz]*mask[0:3]
f[-1] = -vol*[syz, sxz, sxy]*mask[3:]
apply_constraint is an argument expected by ase
'''
stress = self.atoms.get_stress()
atom_forces = self.atoms.get_forces()
natoms = len(self.atoms)
all_forces = np.zeros((natoms+2, 3), np.float)
all_forces[0:natoms, :] = atom_forces
vol = self.atoms.get_volume()
stress_forces = -vol * (stress * self.mask).reshape((2, 3))
all_forces[natoms:, :] = stress_forces
return all_forces
def get_potential_energy(self):
return self.atoms.get_potential_energy()
def has(self, x):
return self.atoms.has(x)
def __len__(self):
return (2 + len(self.atoms))
python-ase-3.6.0.2515/ase/__init__.py 0000644 0001754 0001754 00000000252 11721407205 016057 0 ustar askhl askhl # Copyright 2008, 2009 CAMd
# (see accompanying license files for details).
"""Atomic Simulation Environment."""
from ase.atom import Atom
from ase.atoms import Atoms
python-ase-3.6.0.2515/ase/infrared.py 0000644 0001754 0001754 00000027354 11652336117 016134 0 ustar askhl askhl
# -*- coding: utf-8 -*-
"""Infrared intensities"""
import pickle
from math import sin, pi, sqrt, exp, log
import numpy as np
import ase.units as units
from ase.io.trajectory import PickleTrajectory
from ase.parallel import rank, barrier, parprint
from ase.vibrations import Vibrations
class InfraRed(Vibrations):
"""Class for calculating vibrational modes and infrared intensities
using finite difference.
The vibrational modes are calculated from a finite difference
approximation of the Dynamical matrix and the IR intensities from
a finite difference approximation of the gradient of the dipole
moment. The method is described in:
D. Porezag, M. R. Pederson:
"Infrared intensities and Raman-scattering activities within
density-functional theory",
Phys. Rev. B 54, 7830 (1996)
The calculator object (calc) linked to the Atoms object (atoms) must
have the attribute:
>>> calc.get_dipole_moment(atoms)
In addition to the methods included in the ``Vibrations`` class
the ``InfraRed`` class introduces two new methods;
*get_spectrum()* and *write_spectra()*. The *summary()*, *get_energies()*,
*get_frequencies()*, *get_spectrum()* and *write_spectra()*
methods all take an optional *method* keyword. Use
method='Frederiksen' to use the method described in:
T. Frederiksen, M. Paulsson, M. Brandbyge, A. P. Jauho:
"Inelastic transport theory from first-principles: methodology
and applications for nanoscale devices",
Phys. Rev. B 75, 205413 (2007)
atoms: Atoms object
The atoms to work on.
indices: list of int
List of indices of atoms to vibrate. Default behavior is
to vibrate all atoms.
name: str
Name to use for files.
delta: float
Magnitude of displacements.
nfree: int
Number of displacements per degree of freedom, 2 or 4 are
supported. Default is 2 which will displace each atom +delta
and -delta in each cartesian direction.
directions: list of int
Cartesian coordinates to calculate the gradient of the dipole moment in.
For example directions = 2 only dipole moment in the z-direction will
be considered, whereas for directions = [0, 1] only the dipole
moment in the xy-plane will be considered. Default behavior is to
use the dipole moment in all directions.
Example:
>>> from ase.io import read
>>> from ase.calculators.vasp import Vasp
>>> from ase.infrared import InfraRed
>>> water = read('water.traj') # read pre-relaxed structure of water molecule
>>> calc = Vasp(prec='Accurate',
... ediff=1E-8,
... isym=0,
... idipol=4, # calculate the total dipole moment
... dipol=water.get_center_of_mass(scaled=True),
... ldipol=True)
>>> water.set_calculator(calc)
>>> ir = InfraRed(water)
>>> ir.run()
>>> ir.summary()
-------------------------------------
Mode Frequency Intensity
# meV cm^-1 (D/Ã…)^2 amu^-1
-------------------------------------
0 16.9i 136.2i 1.6108
1 10.5i 84.9i 2.1682
2 5.1i 41.1i 1.7327
3 0.3i 2.2i 0.0080
4 2.4 19.0 0.1186
5 15.3 123.5 1.4956
6 195.5 1576.7 1.6437
7 458.9 3701.3 0.0284
8 473.0 3814.6 1.1812
-------------------------------------
Zero-point energy: 0.573 eV
Static dipole moment: 1.833 D
Maximum force on atom in `equilibrium`: 0.0026 eV/Ã…
This interface now also works for calculator 'siesta',
(added get_dipole_moment for siesta).
Example:
>>> #!/usr/bin/env python
>>> from ase.io import read
>>> from ase.calculators.siesta import Siesta
>>> from ase.infrared import InfraRed
>>> bud = read('bud1.xyz')
>>> calc = Siesta(label='bud',
... meshcutoff=250 * Ry,
... basis='DZP',
... kpts=[1, 1, 1])
>>> calc.set_fdf('DM.MixingWeight', 0.08)
>>> calc.set_fdf('DM.NumberPulay', 3)
>>> calc.set_fdf('DM.NumberKick', 20)
>>> calc.set_fdf('DM.KickMixingWeight', 0.15)
>>> calc.set_fdf('SolutionMethod', 'Diagon')
>>> calc.set_fdf('MaxSCFIterations', 500)
>>> calc.set_fdf('PAO.BasisType', 'split')
>>> #50 meV = 0.003674931 * Ry
>>> calc.set_fdf('PAO.EnergyShift', 0.003674931 * Ry )
>>> calc.set_fdf('LatticeConstant', 1.000000 * Ang)
>>> calc.set_fdf('WriteCoorXmol', 'T')
>>> bud.set_calculator(calc)
>>> ir = InfraRed(bud)
>>> ir.run()
>>> ir.summary()
"""
def __init__(self, atoms, indices=None, name='ir', delta=0.01, nfree=2, directions=None):
assert nfree in [2, 4]
self.atoms = atoms
if atoms.constraints:
print "WARNING! \n Your Atoms object is constrained. Some forces may be unintended set to zero. \n"
self.calc = atoms.get_calculator()
if indices is None:
indices = range(len(atoms))
self.indices = np.asarray(indices)
self.nfree = nfree
self.name = name+'-d%.3f' % delta
self.delta = delta
self.H = None
if directions is None:
self.directions = np.asarray([0, 1, 2])
else:
self.directions = np.asarray(directions)
self.ir = True
def read(self, method='standard', direction='central'):
self.method = method.lower()
self.direction = direction.lower()
assert self.method in ['standard', 'frederiksen']
if direction != 'central':
raise NotImplementedError('Only central difference is implemented at the moment.')
# Get "static" dipole moment and forces
name = '%s.eq.pckl' % self.name
[forces_zero, dipole_zero] = pickle.load(open(name))
self.dipole_zero = (sum(dipole_zero**2)**0.5)*units.Debye
self.force_zero = max([sum((forces_zero[j])**2)**0.5 for j in self.indices])
ndof = 3 * len(self.indices)
H = np.empty((ndof, ndof))
dpdx = np.empty((ndof, 3))
r = 0
for a in self.indices:
for i in 'xyz':
name = '%s.%d%s' % (self.name, a, i)
[fminus, dminus] = pickle.load(open(name + '-.pckl'))
[fplus, dplus] = pickle.load(open(name + '+.pckl'))
if self.nfree == 4:
[fminusminus, dminusminus] = pickle.load(open(name + '--.pckl'))
[fplusplus, dplusplus] = pickle.load(open(name + '++.pckl'))
if self.method == 'frederiksen':
fminus[a] += -fminus.sum(0)
fplus[a] += -fplus.sum(0)
if self.nfree == 4:
fminusminus[a] += -fminus.sum(0)
fplusplus[a] += -fplus.sum(0)
if self.nfree == 2:
H[r] = (fminus - fplus)[self.indices].ravel() / 2.0
dpdx[r] = (dminus - dplus)
if self.nfree == 4:
H[r] = (-fminusminus+8*fminus-8*fplus+fplusplus)[self.indices].ravel() / 12.0
dpdx[r] = (-dplusplus + 8*dplus - 8*dminus +dminusminus) / 6.0
H[r] /= 2 * self.delta
dpdx[r] /= 2 * self.delta
for n in range(3):
if n not in self.directions:
dpdx[r][n] = 0
dpdx[r][n] = 0
r += 1
# Calculate eigenfrequencies and eigenvectors
m = self.atoms.get_masses()
H += H.copy().T
self.H = H
m = self.atoms.get_masses()
self.im = np.repeat(m[self.indices]**-0.5, 3)
omega2, modes = np.linalg.eigh(self.im[:, None] * H * self.im)
self.modes = modes.T.copy()
# Calculate intensities
dpdq = np.array([dpdx[j]/sqrt(m[self.indices[j/3]]*units._amu/units._me) for j in range(ndof)])
dpdQ = np.dot(dpdq.T, modes)
dpdQ = dpdQ.T
intensities = np.array([sum(dpdQ[j]**2) for j in range(ndof)])
# Conversion factor:
s = units._hbar * 1e10 / sqrt(units._e * units._amu)
self.hnu = s * omega2.astype(complex)**0.5
# Conversion factor from atomic units to (D/Angstrom)^2/amu.
conv = units.Debye**2*units._amu/units._me
self.intensities = intensities*conv
def summary(self, method='standard', direction='central'):
hnu = self.get_energies(method, direction)
s = 0.01 * units._e / units._c / units._hplanck
parprint('-------------------------------------')
parprint(' Mode Frequency Intensity')
parprint(' # meV cm^-1 (D/Ã…)^2 amu^-1')
parprint('-------------------------------------')
for n, e in enumerate(hnu):
if e.imag != 0:
c = 'i'
e = e.imag
else:
c = ' '
parprint('%3d %6.1f%s %7.1f%s %9.4f' %
(n, 1000 * e, c, s * e, c, self.intensities[n]))
parprint('-------------------------------------')
parprint('Zero-point energy: %.3f eV' % self.get_zero_point_energy())
parprint('Static dipole moment: %.3f D' % self.dipole_zero)
parprint('Maximum force on atom in `equilibrium`: %.4f eV/Ã…' %
self.force_zero)
parprint()
def get_spectrum(self, start=800, end=4000, npts=None, width=4, type='Gaussian', method='standard', direction='central'):
"""Get infrared spectrum.
The method returns wavenumbers in cm^-1 with corresonding absolute infrared intensity.
Start and end point, and width of the Gaussian/Lorentzian should be given in cm^-1."""
self.type = type.lower()
assert self.type in ['gaussian', 'lorentzian']
if not npts:
npts = (end-start)/width*10+1
frequencies = self.get_frequencies(method, direction).real
intensities=self.intensities
if type == 'lorentzian':
intensities = intensities*width*pi/2.
else:
sigma = width/2./sqrt(2.*log(2.))
#Make array with spectrum data
spectrum = np.empty(npts,np.float)
energies = np.empty(npts,np.float)
ediff = (end-start)/float(npts-1)
energies = np.arange(start, end+ediff/2, ediff)
for i, energy in enumerate(energies):
energies[i] = energy
if type == 'lorentzian':
spectrum[i] = (intensities*0.5*width/pi/((frequencies-energy)**2+0.25*width**2)).sum()
else:
spectrum[i] = (intensities*np.exp(-(frequencies - energy)**2/2./sigma**2)).sum()
return [energies, spectrum]
def write_spectra(self, out='ir-spectra.dat', start=800, end=4000, npts=None, width=10, type='Gaussian', method='standard', direction='central'):
"""Write out infrared spectrum to file.
First column is the wavenumber in cm^-1, the second column the absolute infrared intensities, and
the third column the absorbance scaled so that data runs from 1 to 0. Start and end
point, and width of the Gaussian/Lorentzian should be given in cm^-1."""
energies, spectrum = self.get_spectrum(start, end, npts, width, type, method, direction)
#Write out spectrum in file. First column is absolute intensities.
#Second column is absorbance scaled so that data runs from 1 to 0
spectrum2 = 1. - spectrum/spectrum.max()
outdata = np.empty([len(energies), 3])
outdata.T[0] = energies
outdata.T[1] = spectrum
outdata.T[2] = spectrum2
fd = open(out, 'w')
for row in outdata:
fd.write('%.3f %15.5e %15.5e \n' % (row[0], row[1], row[2]) )
fd.close()
#np.savetxt(out, outdata, fmt='%.3f %15.5e %15.5e')
python-ase-3.6.0.2515/ase/version.py 0000644 0001754 0001754 00000000412 11721673546 016020 0 ustar askhl askhl # Copyright (C) 2003 CAMP
# Please see the accompanying LICENSE file for further information.
version_base = '3.6.0'
try:
from ase.svnversion import svnversion
except ImportError:
version = version_base
else:
version = version_base + '.' + svnversion
python-ase-3.6.0.2515/ase/visualize/ 0000755 0001754 0001754 00000000000 11757245034 015773 5 ustar askhl askhl python-ase-3.6.0.2515/ase/visualize/__init__.py 0000644 0001754 0001754 00000003241 11623435042 020074 0 ustar askhl askhl import os
import tempfile
from ase.io import write
import ase.parallel as parallel
from ase.old import OldASEListOfAtomsWrapper
def view(atoms, data=None, viewer='ag', repeat=None, block=False):
# Ignore for parallel calculations:
if parallel.size != 1:
return
if hasattr(atoms, 'GetUnitCell'):
# Convert old ASE ListOfAtoms to new style.
atoms = OldASEListOfAtomsWrapper(atoms).copy()
vwr = viewer.lower()
if vwr == 'ag':
format = 'traj'
if repeat is None:
command = 'ag'
else:
command = 'ag --repeat=%d,%d,%d' % tuple(repeat)
repeat = None
elif vwr == 'vmd':
format = 'cube'
command = 'vmd'
elif vwr == 'rasmol':
format = 'pdb'
command = 'rasmol -pdb'
elif vwr == 'xmakemol':
format = 'xyz'
command = 'xmakemol -f'
elif vwr == 'gopenmol':
format = 'xyz'
command = 'rungOpenMol'
elif vwr == 'avogadro':
format = 'cube'
command = 'avogadro'
elif vwr == 'sage':
from ase.visualize.sage import view_sage_jmol
view_sage_jmol(atoms)
return
else:
raise RuntimeError('Unknown viewer: ' + viewer)
fd, filename = tempfile.mkstemp('.' + format, 'ase-')
fd = os.fdopen(fd, 'w')
if repeat is not None:
atoms = atoms.repeat()
if data is None:
write(fd, atoms, format=format)
else:
write(fd, atoms, format=format, data=data)
fd.close()
if block:
os.system('%s %s' % (command, filename))
else:
os.system('%s %s &' % (command, filename))
os.system('(sleep 60; rm %s) &' % filename)
python-ase-3.6.0.2515/ase/visualize/primiplotter.py 0000644 0001754 0001754 00000105404 11575617122 021102 0 ustar askhl askhl """An experimental package for making plots during a simulation.
A PrimiPlotter can plot a list of atoms on one or more output devices.
"""
from numpy import *
from ase.visualize.colortable import color_table
import ase.data
import sys, os, time, weakref
class PrimiPlotterBase:
"Base class for PrimiPlotter and Povrayplotter."
#def set_dimensions(self, dims):
# "Set the size of the canvas (a 2-tuple)."
# self.dims = dims
def set_rotation(self, rotation):
"Set the rotation angles (in degrees)."
self.angles[:] = array(rotation) * (pi/180)
def set_radii(self, radii):
"""Set the atomic radii. Give an array or a single number."""
self.radius = radii
def set_colors(self, colors):
"""Explicitly set the colors of the atoms."""
self.colors = colors
def set_color_function(self, colors):
"""Set a color function, to be used to color the atoms."""
if callable(colors):
self.colorfunction = colors
else:
raise TypeError, "The color function is not callable."
def set_invisible(self, inv):
"""Choose invisible atoms."""
self.invisible = inv
def set_invisibility_function(self, invfunc):
"""Set an invisibility function."""
if callable(invfunc):
self.invisibilityfunction = invfunc
else:
raise TypeError, "The invisibility function is not callable."
def set_cut(self, xmin=None, xmax=None, ymin=None, ymax=None,
zmin=None, zmax=None):
self.cut = {"xmin":xmin, "xmax":xmax, "ymin":ymin, "ymax":ymax,
"zmin":zmin, "zmax":zmax}
def update(self, newatoms = None):
"""Cause a plot (respecting the interval setting).
update causes a plot to be made. If the interval variable was
specified when the plotter was create, it will only produce a
plot with that interval. update takes an optional argument,
newatoms, which can be used to replace the list of atoms with
a new one.
"""
if newatoms is not None:
self.atoms = newatoms
if self.skipnext <= 0:
self.plot()
self.skipnext = self.interval
self.skipnext -= 1
def set_log(self, log):
"""Sets a file for logging.
log may be an open file or a filename.
"""
if hasattr(log, "write"):
self.logfile = log
self.ownlogfile = False
else:
self.logfile = open(log, "w")
self.ownlogfile = True
def log(self, message):
"""logs a message to the file set by set_log."""
if self.logfile is not None:
self.logfile.write(message+"\n")
self.logfile.flush()
self._verb(message)
def _verb(self, txt):
if self.verbose:
sys.stderr.write(txt+"\n")
def _starttimer(self):
self.starttime = time.time()
def _stoptimer(self):
elapsedtime = time.time() - self.starttime
self.totaltime = self.totaltime + elapsedtime
print "plotting time %s sec (total %s sec)" % (elapsedtime,
self.totaltime)
def _getpositions(self):
return self.atoms.get_positions()
def _getradii(self):
if self.radius is not None:
if hasattr(self.radius, "shape"):
return self.radius # User has specified an array
else:
return self.radius * ones(len(self.atoms), float)
# No radii specified. Try getting them from the atoms.
try:
return self.atoms.get_atomic_radii()
except AttributeError:
try:
z = self._getatomicnumbers()
except AttributeError:
pass
else:
return ase.data.covalent_radii[z]
# No radius available. Defaulting to 1.0
return ones(len(self.atoms), float)
def _getatomicnumbers(self):
return self.atoms.get_atomic_numbers()
def _getcolors(self):
# Try any explicitly given colors
if self.colors is not None:
if type(self.colors) == type({}):
self.log("Explicit colors dictionary")
return _colorsfromdict(self.colors,
asarray(self.atoms.get_tags(),int))
else:
self.log("Explicit colors")
return self.colors
# Try the color function, if given
if self.colorfunction is not None:
self.log("Calling color function.")
return self.colorfunction(self.atoms)
# Maybe the atoms know their own colors
try:
c = self.atoms.get_colors()
except AttributeError:
c = None
if c is not None:
if type(c) == type({}):
self.log("Color dictionary from atoms.get_colors()")
return _colorsfromdict(c, asarray(self.atoms.get_tags(),int))
else:
self.log("Colors from atoms.get_colors()")
return c
# Default to white atoms
self.log("No colors: using white")
return ones(len(self.atoms), float)
def _getinvisible(self):
if self.invisible is not None:
inv = self.invisible
else:
inv = zeros(len(self.atoms))
if self.invisibilityfunction:
inv = logical_or(inv, self.invisibilityfunction(self.atoms))
r = self._getpositions()
if len(r) > len(inv):
# This will happen in parallel simulations due to ghost atoms.
# They are invisible. Hmm, this may cause trouble.
i2 = ones(len(r))
i2[:len(inv)] = inv
inv = i2
del i2
if self.cut["xmin"] is not None:
inv = logical_or(inv, less(r[:,0], self.cut["xmin"]))
if self.cut["xmax"] is not None:
inv = logical_or(inv, greater(r[:,0], self.cut["xmax"]))
if self.cut["ymin"] is not None:
inv = logical_or(inv, less(r[:,1], self.cut["ymin"]))
if self.cut["ymax"] is not None:
inv = logical_or(inv, greater(r[:,1], self.cut["ymax"]))
if self.cut["zmin"] is not None:
inv = logical_or(inv, less(r[:,2], self.cut["zmin"]))
if self.cut["zmax"] is not None:
inv = logical_or(inv, greater(r[:,2], self.cut["zmax"]))
return inv
def __del__(self):
if self.ownlogfile:
self.logfile.close()
class PrimiPlotter(PrimiPlotterBase):
"""Primitive PostScript-based plots during a simulation.
The PrimiPlotter plots atoms during simulations, extracting the
relevant information from the list of atoms. It is created using
the list of atoms as an argument to the constructor. Then one or
more output devices must be attached using set_output(device). The
list of supported output devices is at the end.
The atoms are plotted as circles. The system is first rotated
using the angles specified by set_rotation([vx, vy, vz]). The
rotation is vx degrees around the x axis (positive from the y
toward the z axis), then vy degrees around the y axis (from x
toward z), then vz degrees around the z axis (from x toward y).
The rotation matrix is the same as the one used by RasMol.
Per default, the system is scaled so it fits within the canvas
(autoscale mode). Autoscale mode is enabled and disables using
autoscale("on") or autoscale("off"). A manual scale factor can be
set with set_scale(scale), this implies autoscale("off"). The
scale factor (from the last autoscale event or from set_scale) can
be obtained with get_scale(). Finally, an explicit autoscaling can
be triggered with autoscale("now"), this is mainly useful before
calling get_scale or before disabling further autoscaling.
Finally, a relative scaling factor can be set with
SetRelativeScaling(), it is multiplied to the usual scale factor
(from autoscale or from set_scale). This is probably only useful in
connection with autoscaling.
The radii of the atoms are obtained from the first of the following
methods which work:
1. If the radii are specified using PrimiPlotter.set_radii(r),
they are used. Must be an array, or a single number.
2. If the atoms has a get_atomic_radii() method, it is used. This is
unlikely.
3. If the atoms has a get_atomic_numbers() method, the
corresponding covalent radii are extracted from the
ASE.ChemicalElements module.
4. If all else fails, the radius is set to 1.0 Angstrom.
The atoms are colored using the first of the following methods
which work.
1. If colors are explicitly set using PrimiPlotter.set_colors(),
they are used.
2. If these colors are specified as a dictionary, the tags
(from atoms.get_tags()) are used as an index into the
dictionary to get the actual colors of the atoms.
3. If a color function has been set using
PrimiPlotter.set_color_function(), it is called with the atoms
as an argument, and is expected to return an array of colors.
4. If the atoms have a get_colors() method, it is used to get the
colors.
5. If these colors are specified as a dictionary, the tags
(from atoms.get_tags()) are used as an index into the
dictionary to get the actual colors of the atoms.
6. If all else fails, the atoms will be white.
The colors are specified as an array of colors, one color per
atom. Each color is either a real number from 0.0 to 1.0,
specifying a grayscale (0.0 = black, 1.0 = white), or an array of
three numbers from 0.0 to 1.0, specifying RGB values. The colors
of all atoms are thus a Numerical Python N-vector or a 3xN matrix.
In cases 1a and 3a above, the keys of the dictionary are integers,
and the values are either numbers (grayscales) or 3-vectors (RGB
values), or strings with X11 color names, which are then
translated to RGB values. Only in case 1a and 3a are strings
recognized as colors.
Some atoms may be invisible, and thus left out of the plot.
Invisible atoms are determined from the following algorithm.
Unlike the radius or the coloring, all points below are tried and
if an atom is invisible by any criterion, it is left out of the plot.
1. All atoms are visible.
2. If PrimiPlotter.set_invisible() has be used to specify invisible
atoms, any atoms for which the value is non-zero becomes invisible.
3. If an invisiblility function has been set with
PrimiPlotter.set_invisibility_function(), it is called with the
atoms as argument. It is expected to return an integer per
atom, any non-zero value makes that atom invisible.
4. If a cut has been specified using set_cut, any atom outside the
cut is made invisible.
Note that invisible atoms are still included in the algorithm for
positioning and scaling the plot.
The following output devices are implemented.
PostScriptFile(prefix): Create PS files names prefix0000.ps etc.
PnmFile(prefix): Similar, but makes PNM files.
GifFile(prefix): Similar, but makes GIF files.
JpegFile(prefix): Similar, but makes JPEG files.
X11Window(): Show the plot in an X11 window using ghostscript.
Output devices writing to files take an extra optional argument to
the constructor, compress, specifying if the output file should be
gzipped. This is not allowed for some (already compressed) file
formats.
Instead of a filename prefix, a filename containing a % can be
used. In that case the filename is expected to expand to a real
filename when used with the Python string formatting operator (%)
with the frame number as argument. Avoid generating spaces in the
file names: use e.g. %03d instead of %3d.
"""
def __init__(self, atoms, verbose=0, timing=0, interval=1, initframe=0):
"""
Parameters to the constructor:
atoms: The atoms to be plottet.
verbose = 0: Write progress information to stderr.
timing = 0: Collect timing information.
interval = 1: If specified, a plot is only made every
interval'th time update() is called. Deprecated, normally you
should use the interval argument when attaching the plotter to
e.g. the dynamics.
initframe = 0: Initial frame number, i.e. the number of the
first plot.
"""
self.atoms = atoms
self.outputdevice = []
self.angles = zeros(3, float)
self.dims = (512, 512)
self.verbose = verbose
self.timing = timing
self.totaltime = 0.0
self.radius = None
self.colors = None
self.colorfunction = None
self.n = initframe
self.interval = interval
self.skipnext = 0 # Number of calls to update before anything happens.
self.a_scale = 1
self.relativescale = 1.0
self.invisible = None
self.invisibilityfunction = None
self.set_cut() # No cut
self.isparallel = 0
self.logfile = None
self.ownlogfile = False
def set_output(self, device):
self.outputdevice.append(device)
device.set_dimensions(self.dims)
device.set_owner(weakref.proxy(self))
def set_dimensions(self, dims):
"Set the size of the canvas (a 2-tuple)."
if self.outputdevice:
raise RuntimeError("Cannot set dimensions after an output device has been specified.")
self.dims = dims
def autoscale(self, mode):
if mode == "on":
self.a_scale = 1
elif mode == "off":
self.a_scale = 0
elif mode == "now":
coords = self._rotate(self.atoms.get_positions())
radii = self._getradii()
self._autoscale(coords, radii)
else:
raise ValueError, "Unknown autoscale mode: ",+str(mode)
def set_scale(self, scale):
self.autoscale("off")
self.scale = scale
def get_scale(self):
return self.scale
def set_relative_scale(self, rscale = 1.0):
self.relativescale = rscale
def plot(self):
"""Create a plot now. Does not respect the interval timer.
This method makes a plot unconditionally. It does not look at
the interval variable, nor is this plot taken into account in
the counting done by the update() method if an interval
variable was specified.
"""
if self.timing:
self._starttimer()
self.log("PrimiPlotter: Starting plot at "
+ time.strftime("%a, %d %b %Y %H:%M:%S"))
colors = self._getcolors()
invisible = self._getinvisible()
coords = self._rotate(self._getpositions())
radii = self._getradii()
if self.a_scale:
self._autoscale(coords,radii)
scale = self.scale * self.relativescale
coords = scale * coords
center = self._getcenter(coords)
offset = array(self.dims + (0.0,))/2.0 - center
coords = coords + offset
self.log("Scale is %f and size is (%d, %d)"
% (scale, self.dims[0], self.dims[1]))
self.log("Physical size of plot is %f Angstrom times %f Angstrom"
% (self.dims[0] / scale, self.dims[1] / scale))
self._verb("Sorting.")
order = argsort(coords[:,2])
coords = coords[order] ### take(coords, order)
radii = radii[order] ### take(radii, order)
colors = colors[order] ### take(colors, order)
invisible = invisible[order] ### take(invisible, order)
if self.isparallel:
id = arange(len(coords))[order] ### take(arange(len(coords)), order)
else:
id = None
radii = radii * scale
selector = self._computevisibility(coords, radii, invisible, id)
coords = compress(selector, coords, 0)
radii = compress(selector, radii)
colors = compress(selector, colors, 0)
self._makeoutput(scale, coords, radii, colors)
self.log("PrimiPlotter: Finished plotting at "
+ time.strftime("%a, %d %b %Y %H:%M:%S"))
self.log("\n\n")
if self.timing:
self._stoptimer()
def _computevisibility(self, coords, rad, invisible, id, zoom = 1):
xy = coords[:,:2]
typradius = sum(rad) / len(rad)
if typradius < 4.0:
self.log("Refining visibility check.")
if zoom >= 16:
raise RuntimeError, "Cannot check visibility - too deep recursion."
return self._computevisibility(xy*2, rad*2, invisible, id, zoom*2)
else:
self.log("Visibility(r_typ = %.1f pixels)" % (typradius,))
dims = array(self.dims) * zoom
maxr = int(ceil(max(rad))) + 2
canvas = zeros((dims[0] + 4*maxr, dims[1] + 4*maxr), int8)
# Atoms are only invisible if they are within the canvas, or closer
# to its edge than their radius
visible = (greater(xy[:,0], -rad) * less(xy[:,0], dims[0]+rad)
* greater(xy[:,1], -rad) * less(xy[:,1], dims[1]+rad)
* logical_not(invisible))
# Atoms are visible if not hidden behind other atoms
xy = floor(xy + 2*maxr + 0.5).astype(int)
masks = {}
for i in xrange(len(rad)-1, -1, -1):
if (i % 100000) == 0 and i:
self._verb(str(i))
if not visible[i]:
continue
x, y = xy[i]
r = rad[i]
try:
mask, invmask, rn = masks[r]
except KeyError:
rn = int(ceil(r))
nmask = 2*rn+1
mask = (arange(nmask) - rn)**2
mask = less(mask[:,newaxis]+mask[newaxis,:], r*r).astype(int8)
invmask = equal(mask, 0).astype(int8)
masks[r] = (mask, invmask, rn)
window = logical_or(canvas[x-rn:x+rn+1, y-rn:y+rn+1], invmask)
hidden = alltrue(window.flat)
if hidden:
visible[i] = 0
else:
canvas[x-rn:x+rn+1, y-rn:y+rn+1] = logical_or(canvas[x-rn:x+rn+1, y-rn:y+rn+1], mask)
self.log("%d visible, %d hidden out of %d" %
(sum(visible), len(visible) - sum(visible), len(visible)))
return visible
def _rotate(self, positions):
self.log("Rotation angles: %f %f %f" % tuple(self.angles))
mat = dot(dot(_rot(self.angles[2], 2),
_rot(self.angles[1], 1)),
_rot(self.angles[0]+pi, 0))
return dot(positions, mat)
def _getcenter(self, coords):
return array((max(coords[:,0]) + min(coords[:,0]),
max(coords[:,1]) + min(coords[:,1]), 0.0)) / 2.0
def _autoscale(self, coords, radii):
x = coords[:,0]
y = coords[:,1]
maxradius = max(radii)
deltax = max(x) - min(x) + 2*maxradius
deltay = max(y) - min(y) + 2*maxradius
scalex = self.dims[0] / deltax
scaley = self.dims[1] / deltay
self.scale = 0.95 * min(scalex, scaley)
self.log("Autoscale: %f" % self.scale)
def _makeoutput(self, scale, coords, radii, colors):
for device in self.outputdevice:
device.inform_about_scale(scale)
device.plot(self.n, coords, radii, colors)
self.n = self.n + 1
class ParallelPrimiPlotter(PrimiPlotter):
"""A version of PrimiPlotter for parallel ASAP simulations.
Used like PrimiPlotter, but only the output devices on the master
node are used. Most of the processing is distributed on the
nodes, but the actual output is only done on the master. See the
PrimiPlotter docstring for details.
"""
def __init__(self, *args, **kwargs):
apply(PrimiPlotter.__init__, (self,)+args, kwargs)
self.isparallel = 1
import Scientific.MPI
self.MPI = Scientific.MPI
self.mpi = Scientific.MPI.world
if self.mpi is None:
raise RuntimeError, "MPI is not available."
self.master = self.mpi.rank == 0
self.mpitag = 42 # Reduce chance of collision with other modules.
def set_output(self, device):
if self.master:
PrimiPlotter.set_output(self, device)
def set_log(self, log):
if self.master:
PrimiPlotter.set_log(self, log)
def _getpositions(self):
realpos = self.atoms.get_positions()
ghostpos = self.atoms.GetGhostCartesianPositions()
self.numberofrealatoms = len(realpos)
self.numberofghostatoms = len(ghostpos)
return concatenate((realpos, ghostpos))
def _getatomicnumbers(self):
realz = self.atoms.get_atomic_numbers()
ghostz = self.atoms.GetGhostAtomicNumbers()
return concatenate((realz, ghostz))
def _getradius(self):
r = PrimiPlotter._getradius(self)
if len(r) == self.numberofrealatoms + self.numberofghostatoms:
# Must have calculated radii from atomic numbers
return r
else:
assert len(r) == self.numberofrealatoms
# Heuristic: use minimum r for the ghosts
ghostr = min(r) * ones(self.numberofghostatoms, float)
return concatenate((r, ghostr))
def _getcenter(self, coords):
# max(x) and min(x) only works for rank-1 arrays in Numeric version 17.
maximal = maximum.reduce(coords[:,0:2])
minimal = minimum.reduce(coords[:,0:2])
recvmax = zeros(2, maximal.typecode())
recvmin = zeros(2, minimal.typecode())
self.mpi.allreduce(maximal, recvmax, self.MPI.max)
self.mpi.allreduce(minimal, recvmin, self.MPI.min)
maxx, maxy = recvmax
minx, miny = recvmin
return array([maxx + minx, maxy + miny, 0.0]) / 2.0
def _computevisibility(self, xy, rad, invisible, id, zoom = 1):
# Find visible atoms, allowing ghost atoms to hide real atoms.
v = PrimiPlotter._computevisibility(self, xy, rad, invisible, id, zoom)
# Then remove ghost atoms
return v * less(id, self.numberofrealatoms)
def _autoscale(self, coords, radii):
self._verb("Autoscale")
n = len(self.atoms)
x = coords[:n,0]
y = coords[:n,1]
assert len(x) == len(self.atoms)
maximal = array([max(x), max(y), max(radii[:n])])
minimal = array([min(x), min(y)])
recvmax = zeros(3, maximal.typecode())
recvmin = zeros(2, minimal.typecode())
self.mpi.allreduce(maximal, recvmax, self.MPI.max)
self.mpi.allreduce(minimal, recvmin, self.MPI.min)
maxx, maxy, maxradius = recvmax
minx, miny = recvmin
deltax = maxx - minx + 2*maxradius
deltay = maxy - miny + 2*maxradius
scalex = self.dims[0] / deltax
scaley = self.dims[1] / deltay
self.scale = 0.95 * min(scalex, scaley)
self.log("Autoscale: %f" % self.scale)
def _getcolors(self):
col = PrimiPlotter._getcolors(self)
nghost = len(self.atoms.GetGhostCartesianPositions())
newcolshape = (nghost + col.shape[0],) + col.shape[1:]
newcol = zeros(newcolshape, col.typecode())
newcol[:len(col)] = col
return newcol
def _makeoutput(self, scale, coords, radii, colors):
if len(colors.shape) == 1:
# Greyscales
ncol = 1
else:
ncol = colors.shape[1] # 1 or 3.
assert ncol == 3 # RGB values
# If one processor says RGB, all must convert
ncolthis = array([ncol])
ncolmax = zeros((1,), ncolthis.typecode())
self.mpi.allreduce(ncolthis, ncolmax, self.MPI.max)
ncolmax = ncolmax[0]
if ncolmax > ncol:
assert ncol == 1
colors = colors[:,newaxis] + zeros(ncolmax)[newaxis,:]
ncol = ncolmax
assert colors.shape == (len(coords), ncol)
# Now send data from slaves to master
data = zeros((len(coords)+1, 4+ncol), float)
data[:-1,:3] = coords
data[:-1,3] = radii
data[-1,-1] = 4+ncol # Used to communicate shape
if ncol == 1:
data[:-1,4] = colors
else:
data[:-1,4:] = colors
if not self.master:
self.mpi.send(data, 0, self.mpitag)
else:
total = [data[:-1]] # Last row is the dimensions.
n = len(coords)
colsmin = colsmax = 4+ncol
for proc in range(1, self.mpi.size):
self._verb("Receiving from processor "+str(proc))
fdat = self.mpi.receive(float, proc, self.mpitag)[0]
fdat.shape = (-1, fdat[-1])
fdat = fdat[:-1] # Last row is the dimensions.
total.append(fdat)
n = n + len(fdat)
if fdat.shape[1] < colsmin:
colsmin = fdat.shape[1]
if fdat.shape[1] > colsmax:
colsmax = fdat.shape[1]
self._verb("Merging data")
# Some processors may have only greyscales whereas others
# may have RGB. That will cause difficulties.
trouble = colsmax != colsmin
data = zeros((n, colsmax), float)
if trouble:
assert data.shape[1] == 7
else:
assert data.shape[1] == 7 or data.shape[1] == 5
i = 0
for d in total:
if not trouble or d.shape[1] == 7:
data[i:i+len(d)] = d
else:
assert d.shape[1] == 5
data[i:i+len(d), :5] = d
data[i:i+len(d), 5] = d[4]
data[i:i+len(d), 6] = d[4]
i = i + len(d)
assert i == len(data)
# Now all data is on the master
self._verb("Sorting merged data")
order = argsort(data[:,2])
data = data[order] ### take(data, order)
coords = data[:,:3]
radii = data[:,3]
if data.shape[1] == 5:
colors = data[:,4]
else:
colors = data[:,4:]
PrimiPlotter._makeoutput(self, scale, coords, radii, colors)
class _PostScriptDevice:
"""PostScript based output device."""
offset = (0,0) # Will be changed by some classes
def __init__(self):
self.scale = 1
self.linewidth = 1
self.outline = 1
def set_dimensions(self, dims):
self.dims = dims
def set_owner(self, owner):
self.owner = owner
def inform_about_scale(self, scale):
self.linewidth = 0.1 * scale
def set_outline(self, value):
self.outline = value
return self # Can chain these calls in set_output()
def plot(self, *args, **kargs):
self.Doplot(self.PSplot, *args, **kargs)
def plotArray(self, *args, **kargs):
self.Doplot(self.PSplotArray, *args, **kargs)
def PSplot(self, file, n, coords, r, colors, noshowpage=0):
xy = coords[:,:2]
assert(len(xy) == len(r) and len(xy) == len(colors))
if len(colors.shape) == 1:
gray = 1
else:
gray = 0
assert(colors.shape[1] == 3)
file.write("%!PS-Adobe-2.0\n")
file.write("%%Creator: Primiplot\n")
file.write("%%Pages: 1\n")
file.write("%%%%BoundingBox: %d %d %d %d\n" %
(self.offset + (self.offset[0] + self.dims[0],
self.offset[1] + self.dims[1])))
file.write("%%EndComments\n")
file.write("\n")
file.write("% Enforce BoundingBox\n")
file.write("%d %d moveto %d 0 rlineto 0 %d rlineto -%d 0 rlineto\n" %
((self.offset + self.dims + (self.dims[0],))))
file.write("closepath clip newpath\n\n")
file.write("%f %f scale\n" % (2*(1.0/self.scale,)))
file.write("%d %d translate\n" % (self.scale * self.offset[0],
self.scale * self.offset[1]))
file.write("\n")
if gray:
if self.outline:
file.write("/circ { 0 360 arc gsave setgray fill grestore stroke } def\n")
else:
file.write("/circ { 0 360 arc setgray fill } def\n")
else:
if self.outline:
file.write("/circ { 0 360 arc gsave setrgbcolor fill grestore stroke } def\n")
else:
file.write("/circ { 0 360 arc setrgbcolor fill } def\n")
file.write("%f setlinewidth 0.0 setgray\n" %
(self.linewidth * self.scale,))
if gray:
data = zeros((len(xy), 4), float)
data[:,0] = colors
data[:,1:3] = (self.scale * xy)
data[:,3] = (self.scale * r)
for point in data:
file.write("%.3f %.2f %.2f %.2f circ\n" % tuple(point))
else:
data = zeros((len(xy), 6), float)
data[:,0:3] = colors
data[:,3:5] = (self.scale * xy)
data[:,5] = (self.scale * r)
for point in data:
file.write("%.3f %.3f %.3f %.2f %.2f %.2f circ\n" % tuple(point))
if not noshowpage:
file.write("showpage\n")
def PSplotArray(self, file, n, data, noshowpage=0):
assert(len(data.shape) == 3)
assert(data.shape[0] == self.dims[1] and data.shape[1] == self.dims[0])
data = clip((256*data).astype(int), 0, 255)
file.write("%!PS-Adobe-2.0\n")
file.write("%%Creator: Fieldplotter\n")
file.write("%%Pages: 1\n")
file.write("%%%%BoundingBox: %d %d %d %d\n" %
(self.offset + (self.offset[0] + self.dims[0],
self.offset[1] + self.dims[1])))
file.write("%%EndComments\n")
file.write("\n")
file.write("%d %d translate\n" % self.offset)
file.write("%f %f scale\n" % self.dims)
file.write("\n")
file.write("% String holding a single line\n")
file.write("/pictline %d string def\n" %(data.shape[1]*data.shape[2],))
file.write("\n")
file.write("%d %d 8\n" % self.dims)
file.write("[%d 0 0 %d 0 0]\n" % self.dims)
file.write("{currentfile pictline readhexstring pop}\n")
file.write("false %d colorimage\n" % (data.shape[2],))
file.write("\n")
s = ""
for d in data.flat:
s += ("%02X" % d)
if len(s) >= 72:
file.write(s+"\n")
s = ""
file.write(s+"\n")
file.write("\n")
if not noshowpage:
file.write("showpage\n")
class _PostScriptToFile(_PostScriptDevice):
"""Output device for PS files."""
compr_suffix = None
def __init__(self, prefix, compress = 0):
self.compress = compress
if "'" in prefix:
raise ValueError, "Filename may not contain a quote ('): "+prefix
if "%" in prefix:
# Assume the user knows what (s)he is doing
self.filenames = prefix
else:
self.filenames = prefix + "%04d" + self.suffix
if compress:
if self.compr_suffix is None:
raise RuntimeError, "Compression not supported."
self.filenames = self.filenames + self.compr_suffix
_PostScriptDevice.__init__(self)
class PostScriptFile(_PostScriptToFile):
suffix = ".ps"
compr_suffix = ".gz"
offset = (50,50)
# Inherits __init__
def Doplot(self, plotmethod, n, *args, **kargs):
filename = self.filenames % (n,)
self.owner.log("Output to PostScript file "+filename)
if self.compress:
file = os.popen("gzip > '"+filename+"'", "w")
else:
file = open(filename, "w")
apply(plotmethod, (file, n)+args, kargs)
file.close()
class _PS_via_PnmFile(_PostScriptToFile):
gscmd = "gs -q -sDEVICE=pnmraw -sOutputFile=- -dDEVICEWIDTH=%d -dDEVICEHEIGHT=%d - "
# Inherits __init__
def Doplot(self, plotmethod, n, *args, **kargs):
filename = self.filenames % (n,)
self.owner.log("Output to bitmapped file " + filename)
cmd = self.gscmd + self.converter
if self.compress:
cmd = cmd + "| gzip "
cmd = (cmd+" > '%s'") % (self.dims[0], self.dims[1], filename)
file = os.popen(cmd, "w")
apply(plotmethod, (file, n)+args, kargs)
file.close()
class PnmFile(_PS_via_PnmFile):
suffix = ".pnm"
compr_suffix = ".gz"
converter = ""
class GifFile(_PS_via_PnmFile):
suffix = ".gif"
converter = "| ppmquant -floyd 256 2>/dev/null | ppmtogif 2>/dev/null"
class JpegFile(_PS_via_PnmFile):
suffix = ".jpeg"
converter = "| ppmtojpeg --smooth=5"
class X11Window(_PostScriptDevice):
"""Shows the plot in an X11 window."""
#Inherits __init__
gscmd = "gs -q -sDEVICE=x11 -dDEVICEWIDTH=%d -dDEVICEHEIGHT=%d -r72x72 -"
def Doplot(self, plotmethod, n, *args, **kargs):
self.owner.log("Output to X11 window")
try:
file = self.pipe
self.pipe.write("showpage\n")
except AttributeError:
filename = self.gscmd % tuple(self.dims)
file = os.popen(filename, "w")
self.pipe = file
kargs["noshowpage"] = 1
apply(plotmethod, (file, n)+args, kargs)
file.write("flushpage\n")
file.flush()
# Helper functions
def _rot(v, axis):
ax1, ax2 = ((1, 2), (0, 2), (0, 1))[axis]
c, s = cos(v), sin(v)
m = zeros((3,3), float)
m[axis,axis] = 1.0
m[ax1,ax1] = c
m[ax2,ax2] = c
m[ax1,ax2] = s
m[ax2,ax1] = -s
return m
def _colorsfromdict(dict, cls):
"""Extract colors from dictionary using cls as key."""
assert(type(dict) == type({}))
# Allow local modifications, to replace strings with rgb values.
dict = dict.copy()
isgray, isrgb = 0, 0
for k in dict.keys():
v = dict[k]
if type(v) == type("string"):
v = color_table[v]
dict[k] = v
try:
if len(v) == 3:
isrgb = 1 # Assume it is an RGB value
if not hasattr(v, "shape"):
dict[k] = array(v) # Convert to array
else:
raise RuntimeError, "Unrecognized color object "+repr(v)
except TypeError:
isgray = 1 # Assume it is a number
if isgray and isrgb:
# Convert all to RGB
for k in dict.keys():
v = dict[k]
if not hasattr(v, "shape"):
dict[k] = v * ones(3, float)
# Now the dictionary is ready
if isrgb:
colors = zeros((len(cls),3), float)
else:
colors = zeros((len(cls),), float)
for i in xrange(len(cls)):
colors[i] = dict[cls[i]]
return colors
python-ase-3.6.0.2515/ase/visualize/fieldplotter.py 0000644 0001754 0001754 00000025564 11150750761 021051 0 ustar askhl askhl """plotting fields defined on atoms during a simulation."""
from ase.visualize.primiplotter import PostScriptFile, PnmFile, GifFile, JpegFile, X11Window
from ase.visualize.primiplotter import PrimiPlotter as _PrimiPlotter
import numpy
import time
class FieldPlotter(_PrimiPlotter):
def __init__(self, atoms, datasource=None, verbose=0, timing=0,
interval=1, initframe=0):
_PrimiPlotter.__init__(self, atoms, verbose=verbose, timing=timing,
interval=interval, initframe=initframe)
self.datasource = datasource
self.dims = (100,100)
self.set_plot_plane("xy")
self.set_data_range("plot")
self.set_background(0.0)
self.set_red_yellow_colors()
def set_plot_plane(self, plane):
"""Set the plotting plane to xy, xz or yz (default: xy)"""
if plane in ("xy", "xz", "yz"):
self.plane = plane
else:
raise ValueError, "The argument to plotPlane must be 'xy', 'xz' or 'yz'."
def set_data_range(self, range1, range2=None):
"""Set the range of the data used when coloring.
This function sets the range of data values mapped unto colors
in the final plot.
Three possibilities:
'data': Autoscale using the data on visible atoms.
The range goes from the lowest to the highest
value present on the atoms. If only a few atoms
have extreme values, the entire color range may not
be used on the plot, as many values may be averaged
on each point in the plot.
'plot': Autoscale using the data on the plot. Unlike 'data'
this guarantees that the entire color range is used.
min, max: Use the range [min, max]
"""
if (range1 == "data" or range1 == "plot") and range2 == None:
self.autorange = range1
elif range2 != None:
self.autorange = None
self.range = (range1, range2)
else:
raise ValueError, "Illegal argument(s) to set_data_range"
def set_background(self, value):
"""Set the data value of the background. See also set_background_color
Set the value of the background (parts of the plot without atoms) to
a specific value, or to 'min' or 'max' representing the minimal or
maximal data values on the atoms.
Calling set_background cancels previous calls to set_background_color.
"""
self.background = value
self.backgroundcolor = None
def set_background_color(self, color):
"""Set the background color. See also set_background.
Set the background color. Use a single value in the range [0, 1[
for gray values, or a tuple of three such values as an RGB color.
Calling set_background_color cancels previous calls to set_background.
"""
self.background = None
self.backgroundcolor = color
def set_red_yellow_colors(self, reverse=False):
"""Set colors to Black-Red-Yellow-White (a.k.a. STM colors)"""
self.set_colors([(0.0, 0, 0, 0),
(0.33, 1, 0, 0),
(0.66, 1, 1, 0),
(1.0, 1, 1, 1)],
reverse)
def set_black_white_colors(self, reverse=False):
"""Set the color to Black-White (greyscale)"""
self.set_colors([(0.0, 0), (1.0, 1)], reverse)
def set_colors(self, colors, reverse=False):
colors = numpy.array(colors, numpy.float)
if len(colors.shape) != 2:
raise ValueError, "Colors must be a 2D array."
if reverse:
colors[:,0] = 1 - colors[:,0]
colors = numpy.array(colors[::-1,:])
#print colors
if colors[0,0] != 0.0 or colors[-1,0] != 1.0:
raise ValueError, "First row must define the value 0 and last row must define the value 1"
if colors.shape[1] == 2:
self.colormode = 1
elif colors.shape[1] == 4:
self.colormode = 3
else:
raise ValueError, "Color specification must be Nx2 (grey) or Nx4 (rgb) matrix."
self.colorfunction = InterpolatingFunction(colors[:,0], colors[:,1:])
def plot(self, data=None):
"""Create a plot now. Does not respect the interval timer.
This method makes a plot unconditionally. It does not look at
the interval variable, nor is this plot taken into account in
the counting done by the update() method if an interval
variable was specified.
If data is specified, it must be an array of numbers with the
same length as the atoms. That data will then be plotted. If
no data is given, the data source specified when creating the
plotter is used.
"""
if self.timing:
self._starttimer()
self.log("FieldPlotter: Starting plot at "
+ time.strftime("%a, %d %b %Y %H:%M:%S"))
if data is None:
data = self.datasource()
if len(data) != len(self.atoms):
raise ValueError, ("Data has wrong length: %d instead of %d."
% (len(data), len(self.atoms)))
invisible = self._getinvisible()
coords = self._rotate(self._getpositions())
radii = self._getradii()
if self.autoscale:
self._autoscale(coords,radii)
scale = self.scale * self.relativescale
coords = scale * coords
center = self._getcenter(coords)
offset = numpy.array(self.dims + (0.0,))/2.0 - center
coords = coords + offset
radii = radii * scale
self.log("Scale is %f and size is (%d, %d)"
% (scale, self.dims[0], self.dims[1]))
self.log("Physical size of plot is %f Angstrom times %f Angstrom"
% (self.dims[0] / scale, self.dims[1] / scale))
# Remove invisible atoms
selector = numpy.logical_not(invisible)
coords = numpy.compress(selector, coords, 0)
radii = numpy.compress(selector, radii)
data = numpy.compress(selector, data)
self.log("plotting data in the range [%f,%f]" %
(data.min(), data.max()))
# Now create the output array
sumarray = numpy.zeros(self.dims, numpy.float)
weight = numpy.zeros(self.dims)
# Loop over all atoms, and plot them
nmiss = 0
if self.plane == "xy":
xy = coords[:,:2]
elif self.plane == "xz":
xy = coords[:,::2]
elif self.plane == "yz":
xy = coords[:,1:]
else:
raise RuntimeError, "self.plane is bogus: "+str(self.plane)
assert xy.shape[1] == 2
self.log("plotting %d atoms on %d * %d (= %d) grid" %
(len(xy), sumarray.shape[0], sumarray.shape[1],
len(sumarray.flat)))
xy = xy.astype(numpy.int)
for i in xrange(len(xy)):
(x, y) = xy[i]
d = data[i]
if (x >= 0 and x < self.dims[0] and y >= 0 and y < self.dims[1]):
sumarray[x,y] += d
weight[x,y] += 1
else:
nmiss += 1
print "... %d atoms fell outside plot." % (nmiss,)
datamap = self._makedatamap(sumarray, weight, data.min(), data.max())
self.log("Range of data map: [%f, %f]" %
(datamap.min(), datamap.max()))
plot = self._makeplotmap(datamap, weight)
#self.log("Range of plot: [%f, %f]" %
# (min(plot.flat), max(plot.flat)))
examinplot = plot[:]
examinplot.shape = (plot.shape[0] * plot.shape[1],) + plot.shape[2:]
self.log("Range of plot: %s -> %s" %
(str(examinplot.min(0)), str(examinplot.max(0))))
del examinplot
for device in self.outputdevice:
device.inform_about_scale(scale)
device.plotArray(self.n, numpy.swapaxes(plot,0,1))
self.n = self.n + 1
self.log("FieldPlotter: Finished plotting at "
+ time.strftime("%a, %d %b %Y %H:%M:%S"))
self.log("\n\n")
def _makedatamap(self, sumarray, weight, minimum, maximum):
background = numpy.equal(weight, 0)
print "Number of background points:", sum(background.flat)
datamap = sumarray / numpy.where(background, 1, weight)
if self.background is not None:
if self.background == "min":
bg = minimum
elif self.background == "max":
bg = maximum
else:
bg = self.background
datamap = numpy.where(background, bg, datamap)
if self.autorange == "data":
datamap = (datamap - minimum) / (maximum - minimum)
self.log("Autorange using data. Data range is [%f, %f]"
% (minimum, maximum))
elif self.autorange == "plot":
ma = numpy.where(background, minimum, datamap).max()
mi = numpy.where(background, maximum, datamap).min()
datamap = (datamap - mi) / (ma - mi)
self.log("Autorange using plot. Data range is [%f, %f]"
% (mi, ma))
else:
assert self.autorange == None
datamap = (datamap - self.range[0]) / (self.range[1]
- self.range[0])
datamap = numpy.clip(datamap, 0.0, 1.0)
self.log("Data range specified by user: [%f, %f]" % self.range)
datamap = numpy.where(background, bg, datamap)
assert datamap.min() >= 0 and datamap.max() <= 1.0
return datamap
def _makeplotmap(self, datamap, weight):
plot = numpy.zeros(self.dims + (self.colormode,), numpy.float)
for i in range(self.dims[0]):
for j in range(self.dims[1]):
if self.backgroundcolor is not None and weight[i,j] == 0:
plot[i,j,:] = self.backgroundcolor
else:
x = datamap[i,j]
plot[i,j,:] = self.colorfunction(x)
return plot
class InterpolatingFunction:
def __init__(self, xpoints, ypoints):
if len(xpoints) != len(ypoints):
raise ValueError, "Length of x and y arrays should be the same."
idx = xpoints.argsort()
self.xpoints = xpoints[idx]
self.ypoints = ypoints[idx]
def __call__(self, x):
n = self.xpoints.searchsorted(x)
if n == 0:
return self.ypoints[0]
if n == len(self.xpoints):
return self.xpoints[-1]
x0 = self.xpoints[n-1]
x1 = self.xpoints[n]
y0 = self.ypoints[n-1]
y1 = self.ypoints[n]
return y0 + (y1 - y0) / (x1 - x0) * (x - x0)
python-ase-3.6.0.2515/ase/visualize/vtk/ 0000755 0001754 0001754 00000000000 11757245034 016577 5 ustar askhl askhl python-ase-3.6.0.2515/ase/visualize/vtk/__init__.py 0000644 0001754 0001754 00000002076 11171354364 020712 0 ustar askhl askhl try:
import vtk
hasvtk = True
hasmpi = hasattr(vtk, 'vtkMPIController')
except ImportError:
hasvtk = False
hasmpi = False
def requirevtk(code=0, parallel=False):
from ase.test import NotAvailable
if not hasvtk:
# VTK required but not installed, force termination
# with exit status determined by the code argument.
raise NotAvailable('VTK is not installed.', code)
if parallel and not hasmpi:
# VTK MPI required but not installed, force termination
# with exit status determined by the code argument.
raise NotAvailable('VTK is not MPI compatible.', code)
def probe_vtk_kilobyte(default=None):
if not hasvtk:
return default
from vtk import vtkCharArray
vtk_da = vtkCharArray()
vtk_da.SetNumberOfComponents(1)
vtk_da.SetNumberOfTuples(1024**2)
# Size of 1 MB = 1024**2 bytes in "VTK kilobytes"
size = vtk_da.GetActualMemorySize()
if size == 1024:
return 1024
elif round(abs(size-1024**2/1e3)) == 0:
return 1e3
else:
return default
python-ase-3.6.0.2515/ase/visualize/vtk/data.py 0000644 0001754 0001754 00000016175 11215435733 020070 0 ustar askhl askhl
import numpy as np
from numpy.ctypeslib import ctypes
from vtk import vtkDataArray, vtkFloatArray, vtkDoubleArray
if ctypes is None:
class CTypesEmulator:
def __init__(self):
self._SimpleCData = np.number
self.c_float = np.float32
self.c_double = np.float64
try:
import ctypes
except ImportError:
ctypes = CTypesEmulator()
# -------------------------------------------------------------------
class vtkNumPyBuffer:
def __init__(self, data):
self.strbuf = data.tostring()
self.nitems = len(data.flat)
def __len__(self):
return self.nitems
def get_pointer(self):
# Any C/C++ method that requires a void * can be passed a Python
# string. No check is done to ensure that the string is the correct
# size, and the string's reference count is not incremented. Extreme
# caution should be applied when using this feature.
return self.strbuf
def notify(self, obj, event):
if event == 'DeleteEvent':
del self.strbuf
else:
raise RuntimeError('Event not recognized.')
class vtkDataArrayFromNumPyBuffer:
def __init__(self, vtk_class, ctype, data=None):
assert issubclass(ctype, ctypes._SimpleCData)
self.ctype = ctype
self.vtk_da = vtk_class()
assert isinstance(self.vtk_da, vtkDataArray)
assert self.vtk_da.GetDataTypeSize() == np.nbytes[np.dtype(self.ctype)]
if data is not None:
self.read_numpy_array(data)
def read_numpy_array(self, data):
if not isinstance(data, np.ndarray):
data = np.array(data, dtype=self.ctype)
if data.dtype != self.ctype: # NB: "is not" gets it wrong
data = data.astype(self.ctype)
self.vtk_da.SetNumberOfComponents(data.shape[-1])
# Passing the void* buffer to the C interface does not increase
# its reference count, hence the buffer is deleted by Python when
# the reference count of the string from tostring reaches zero.
# Also, the boolean True tells VTK to save (not delete) the buffer
# when the VTK data array is deleted - we want Python to do this.
npybuf = vtkNumPyBuffer(data)
self.vtk_da.SetVoidArray(npybuf.get_pointer(), len(npybuf), True)
self.vtk_da.AddObserver('DeleteEvent', npybuf.notify)
def get_output(self):
return self.vtk_da
def copy(self):
vtk_da_copy = self.vtk_da.NewInstance()
vtk_da_copy.SetNumberOfComponents(self.vtk_da.GetNumberOfComponents())
vtk_da_copy.SetNumberOfTuples(self.vtk_da.GetNumberOfTuples())
assert vtk_da_copy.GetSize() == self.vtk_da.GetSize()
vtk_da_copy.DeepCopy(self.vtk_da)
return vtk_da_copy
# -------------------------------------------------------------------
class vtkDataArrayFromNumPyArray(vtkDataArrayFromNumPyBuffer):
"""Class for reading vtkDataArray from 1D or 2D NumPy array.
This class can be used to generate a vtkDataArray from a NumPy array.
The NumPy array should be of the form x
where 'number of components' indicates the number of components in
each entry in the vtkDataArray. Note that this form is also expected
even in the case of only a single component.
"""
def __init__(self, vtk_class, ctype, data=None, buffered=True):
self.buffered = buffered
vtkDataArrayFromNumPyBuffer.__init__(self, vtk_class, ctype, data)
def read_numpy_array(self, data):
"""Read vtkDataArray from NumPy array"""
if not isinstance(data, np.ndarray):
data = np.array(data, dtype=self.ctype)
if data.dtype != self.ctype: # NB: "is not" gets it wrong
data = data.astype(self.ctype)
if data.ndim == 1:
data = data[:, np.newaxis]
elif data.ndim != 2:
raise ValueError('Data must be a 1D or 2D NumPy array.')
if self.buffered:
vtkDataArrayFromNumPyBuffer.read_numpy_array(self, data)
else:
self.vtk_da.SetNumberOfComponents(data.shape[-1])
self.vtk_da.SetNumberOfTuples(data.shape[0])
for i, d_c in enumerate(data):
for c, d in enumerate(d_c):
self.vtk_da.SetComponent(i, c, d)
class vtkFloatArrayFromNumPyArray(vtkDataArrayFromNumPyArray):
def __init__(self, data):
vtkDataArrayFromNumPyArray.__init__(self, vtkFloatArray,
ctypes.c_float, data)
class vtkDoubleArrayFromNumPyArray(vtkDataArrayFromNumPyArray):
def __init__(self, data):
vtkDataArrayFromNumPyArray.__init__(self, vtkDoubleArray,
ctypes.c_double, data)
# -------------------------------------------------------------------
class vtkDataArrayFromNumPyMultiArray(vtkDataArrayFromNumPyBuffer):
"""Class for reading vtkDataArray from a multi-dimensional NumPy array.
This class can be used to generate a vtkDataArray from a NumPy array.
The NumPy array should be of the form x
where 'number of components' indicates the number of components in
each gridpoint in the vtkDataArray. Note that this form is also expected
even in the case of only a single component.
"""
def __init__(self, vtk_class, ctype, data=None, buffered=True):
self.buffered = buffered
vtkDataArrayFromNumPyBuffer.__init__(self, vtk_class, ctype, data)
def read_numpy_array(self, data):
"""Read vtkDataArray from NumPy array"""
if not isinstance(data, np.ndarray):
data = np.array(data, dtype=self.ctype)
if data.dtype != self.ctype: # NB: "is not" gets it wrong
data = data.astype(self.ctype)
if data.ndim <=2:
raise Warning('This is inefficient for 1D and 2D NumPy arrays. ' +
'Use a vtkDataArrayFromNumPyArray subclass instead.')
if self.buffered:
# This is less than ideal, but will not copy data (uses views).
# To get the correct ordering, the grid dimensions have to be
# transposed without moving the last dimension (the components).
n = data.ndim-1
for c in range(n//2):
data = data.swapaxes(c,n-1-c)
vtkDataArrayFromNumPyBuffer.read_numpy_array(self, data)
else:
self.vtk_da.SetNumberOfComponents(data.shape[-1])
self.vtk_da.SetNumberOfTuples(np.prod(data.shape[:-1]))
for c, d_T in enumerate(data.T):
for i, d in enumerate(d_T.flat):
self.vtk_da.SetComponent(i, c, d)
class vtkFloatArrayFromNumPyMultiArray(vtkDataArrayFromNumPyMultiArray):
def __init__(self, data):
vtkDataArrayFromNumPyMultiArray.__init__(self, vtkFloatArray,
ctypes.c_float, data)
class vtkDoubleArrayFromNumPyMultiArray(vtkDataArrayFromNumPyMultiArray):
def __init__(self, data):
vtkDataArrayFromNumPyMultiArray.__init__(self, vtkDoubleArray,
ctypes.c_double, data)
python-ase-3.6.0.2515/ase/visualize/vtk/grid.py 0000644 0001754 0001754 00000025515 11230537506 020100 0 ustar askhl askhl
import numpy as np
from vtk import vtkPointData, vtkDataArray, vtkUnstructuredGrid, vtkPoints, \
vtkIdList, vtkStructuredPoints
from ase.visualize.vtk.cell import vtkUnitCellModule
from ase.visualize.vtk.data import vtkDataArrayFromNumPyBuffer, \
vtkDoubleArrayFromNumPyArray, \
vtkDoubleArrayFromNumPyMultiArray
# -------------------------------------------------------------------
class vtkBaseGrid:
def __init__(self, npoints, cell):
self.npoints = npoints
# Make sure cell argument is correct type
assert isinstance(cell, vtkUnitCellModule)
self.cell = cell
self.vtk_pointdata = None
def set_point_data(self, vtk_pointdata):
if self.vtk_pointdata is not None:
raise RuntimeError('VTK point data already present.')
assert isinstance(vtk_pointdata, vtkPointData)
self.vtk_pointdata = vtk_pointdata
#self.vtk_pointdata.SetCopyScalars(False)
#self.vtk_pointdata.SetCopyVectors(False)
#self.vtk_pointdata.SetCopyNormals(False)
def get_point_data(self):
if self.vtk_pointdata is None:
raise RuntimeError('VTK point data missing.')
return self.vtk_pointdata
def get_number_of_points(self):
return self.npoints
def add_scalar_data_array(self, data, name=None, active=True):
# Are we converting from NumPy buffer to VTK array?
if isinstance(data, vtkDataArray):
vtk_sda = data
elif isinstance(data, vtkDataArrayFromNumPyBuffer):
vtk_sda = data.get_output()
else:
raise ValueError('Data is not a valid scalar data array.')
del data
assert vtk_sda.GetNumberOfComponents() == 1
assert vtk_sda.GetNumberOfTuples() == self.npoints
if name is not None:
vtk_sda.SetName(name)
# Add VTK array to VTK point data
self.vtk_pointdata.AddArray(vtk_sda)
if active:
self.vtk_pointdata.SetActiveScalars(name)
return vtk_sda
def add_vector_data_array(self, data, name=None, active=True):
# Are we converting from NumPy buffer to VTK array?
if isinstance(data, vtkDataArray):
vtk_vda = data
elif isinstance(data, vtkDataArrayFromNumPyBuffer):
vtk_vda = data.get_output()
else:
raise ValueError('Data is not a valid vector data array.')
del data
assert vtk_vda.GetNumberOfComponents() == 3
assert vtk_vda.GetNumberOfTuples() == self.npoints
if name is not None:
vtk_vda.SetName(name)
# Add VTK array to VTK point data
self.vtk_pointdata.AddArray(vtk_vda)
if active:
self.vtk_pointdata.SetActiveVectors(name)
return vtk_vda
# -------------------------------------------------------------------
class vtkAtomicPositions(vtkBaseGrid):
"""Provides an interface for adding ``Atoms``-centered data to VTK
modules. Atomic positions, e.g. obtained using atoms.get_positions(),
constitute an unstructured grid in VTK, to which scalar and vector
can be added as point data sets.
Just like ``Atoms``, instances of ``vtkAtomicPositions`` can be divided
into subsets, which makes it easy to select atoms and add properties.
Example:
>>> cell = vtkUnitCellModule(atoms)
>>> apos = vtkAtomicPositions(atoms.get_positions(), cell)
>>> apos.add_scalar_property(atoms.get_charges(), 'charges')
>>> apos.add_vector_property(atoms.get_forces(), 'forces')
"""
def __init__(self, pos, cell):
"""Construct basic VTK-representation of a set of atomic positions.
pos: NumPy array of dtype float and shape ``(n,3)``
Cartesian positions of the atoms.
cell: Instance of vtkUnitCellModule of subclass thereof
Holds information equivalent to that of atoms.get_cell().
"""
# Make sure position argument is a valid array
if not isinstance(pos, np.ndarray):
pos = np.array(pos)
assert pos.dtype == float and pos.shape[1:] == (3,)
vtkBaseGrid.__init__(self, len(pos), cell)
# Convert positions to VTK array
npy2da = vtkDoubleArrayFromNumPyArray(pos)
vtk_pda = npy2da.get_output()
del npy2da
# Transfer atomic positions to VTK points
self.vtk_pts = vtkPoints()
self.vtk_pts.SetData(vtk_pda)
# Create a VTK unstructured grid of these points
self.vtk_ugd = vtkUnstructuredGrid()
self.vtk_ugd.SetWholeBoundingBox(self.cell.get_bounding_box())
self.vtk_ugd.SetPoints(self.vtk_pts)
# Extract the VTK point data set
self.set_point_data(self.vtk_ugd.GetPointData())
def get_points(self, subset=None):
"""Return (subset of) vtkPoints containing atomic positions.
subset=None: list of int
A list of indices into the atomic positions; ignored if None.
"""
if subset is None:
return self.vtk_pts
# Create a list of indices from the subset
vtk_il = vtkIdList()
for i in subset:
vtk_il.InsertNextId(i)
# Allocate VTK points for subset
vtk_subpts = vtkPoints()
vtk_subpts.SetDataType(self.vtk_pts.GetDataType())
vtk_subpts.SetNumberOfPoints(vtk_il.GetNumberOfIds())
# Transfer subset of VTK points
self.vtk_pts.GetPoints(vtk_il, vtk_subpts)
return vtk_subpts
def get_unstructured_grid(self, subset=None):
"""Return (subset of) an unstructured grid of the atomic positions.
subset=None: list of int
A list of indices into the atomic positions; ignored if None.
"""
if subset is None:
return self.vtk_ugd
# Get subset of VTK points
vtk_subpts = self.get_points(subset)
# Create a VTK unstructured grid of these points
vtk_subugd = vtkUnstructuredGrid()
vtk_subugd.SetWholeBoundingBox(self.cell.get_bounding_box())
vtk_subugd.SetPoints(vtk_subpts)
return vtk_subugd
def add_scalar_property(self, data, name=None, active=True):
"""Add VTK-representation of scalar data at the atomic positions.
data: NumPy array of dtype float and shape ``(n,)``
Scalar values corresponding to the atomic positions.
name=None: str
Unique identifier for the scalar data.
active=True: bool
Flag indicating whether to use as active scalar data.
"""
# Make sure data argument is a valid array
if not isinstance(data, np.ndarray):
data = np.array(data)
assert data.dtype == float and data.shape == (self.npoints,)
# Convert scalar properties to VTK array
npa2da = vtkDoubleArrayFromNumPyArray(data)
return vtkBaseGrid.add_scalar_data_array(self, npa2da, name, active)
def add_vector_property(self, data, name=None, active=True):
"""Add VTK-representation of vector data at the atomic positions.
data: NumPy array of dtype float and shape ``(n,3)``
Vector components corresponding to the atomic positions.
name=None: str
Unique identifier for the vector data.
active=True: bool
Flag indicating whether to use as active vector data.
"""
# Make sure data argument is a valid array
if not isinstance(data, np.ndarray):
data = np.array(data)
assert data.dtype == float and data.shape == (self.npoints,3,)
# Convert vector properties to VTK array
npa2da = vtkDoubleArrayFromNumPyArray(data)
return vtkBaseGrid.add_vector_data_array(self, npa2da, name, active)
# -------------------------------------------------------------------
class vtkVolumeGrid(vtkBaseGrid):
def __init__(self, elements, cell, origin=None):
# Make sure element argument is a valid array
if not isinstance(elements, np.ndarray):
elements = np.array(elements)
assert elements.dtype == int and elements.shape == (3,)
self.elements = elements
vtkBaseGrid.__init__(self, np.prod(self.elements), cell)
# Create a VTK grid of structured points
self.vtk_spts = vtkStructuredPoints()
self.vtk_spts.SetWholeBoundingBox(self.cell.get_bounding_box())
self.vtk_spts.SetDimensions(self.elements)
self.vtk_spts.SetSpacing(self.get_grid_spacing())
if origin is not None:
self.vtk_spts.SetOrigin(origin)
# Extract the VTK point data set
self.set_point_data(self.vtk_spts.GetPointData())
def get_grid_spacing(self):
# Periodic boundary conditions leave out one boundary along an axis
# Zero/fixed boundary conditions leave out both boundaries of an axis
return self.cell.get_size()/(self.elements+1.0-self.cell.get_pbc())
def get_relaxation_factor(self):
# The relaxation factor is a floating point value between zero and one.
# It expresses the need for smoothening (relaxation) e.g. of isosurfaces
# due to coarse grid spacings. Larger grid spacing -> larger relaxation.
x = self.get_grid_spacing().mean()/self.cell.get_characteristic_length()
# The relaxation function f(x) satisfies the following requirements
# f(x) -> 0 for x -> 0+ and f(x) -> b for x -> inf
# f'(x) -> a for x -> 0+ and f'(x) -> 0 for x -> inf
# Furthermore, it is a rescaling of arctan, hence we know
# f(x) = 2 b arctan(a pi x / 2 b) / pi
# Our reference point is x = r for which medium relaxion is needed
# f(r) = b/2 <=> r = 2 b / a pi <=> a = 2 b / r pi
r = 0.025 # corresponding to 0.2 Ang grid spacing in 8 Ang cell
b = 0.5
f = 2*b*np.arctan(x/r)/np.pi
if f > 0.1:
return f.round(1)
else:
return None
def get_structured_points(self):
return self.vtk_spts
def add_scalar_field(self, data, name=None, active=True):
# Make sure data argument is a valid array
if not isinstance(data, np.ndarray):
data = np.array(data)
assert data.dtype == float and data.shape == tuple(self.elements)
# Convert scalar field to VTK array
npa2da = vtkDoubleArrayFromNumPyMultiArray(data[...,np.newaxis])
return vtkBaseGrid.add_scalar_data_array(self, npa2da, name, active)
def add_vector_field(self, data, name=None, active=True):
# Make sure data argument is a valid array
if not isinstance(data, np.ndarray):
data = np.array(data)
assert data.dtype == float and data.shape == tuple(self.elements)+(3,)
# Convert vector field to VTK array
npa2da = vtkDoubleArrayFromNumPyMultiArray(data)
return vtkBaseGrid.add_vector_data_array(self, npa2da, name, active)
python-ase-3.6.0.2515/ase/visualize/vtk/sources.py 0000644 0001754 0001754 00000007541 11164377616 020647 0 ustar askhl askhl
import numpy as np
from vtk import vtkProperty, vtkSphereSource, vtkArrowSource, vtkConeSource
from ase.data import atomic_numbers
from ase.data import covalent_radii as atomic_radii
from ase.data.colors import jmol_colors as atomic_colors
#from ase.data.colors import cpk_colors as atomic_colors
avg_radius = np.mean(atomic_radii[np.isfinite(atomic_radii)])
# -------------------------------------------------------------------
class vtkCustomGlyphSource:
def __init__(self, scale, vtk_glyph_source):
self.scale = scale
self.vtk_glyph_source = vtk_glyph_source
self.vtk_property = vtkProperty()
def get_scale(self):
return self.scale
def get_property(self):
return self.vtk_property
def get_output(self):
return self.vtk_glyph_source.GetOutput()
class vtkAtomSource(vtkCustomGlyphSource):
def __init__(self, name, scale=1, fraction=0.25):
vtkCustomGlyphSource.__init__(self, scale, vtkSphereSource())
self.number = atomic_numbers[name]
self.radius = atomic_radii[self.number]
self.color = atomic_colors[self.number]
self.vtk_property.SetColor(self.color[0],self.color[1],self.color[2])
self.vtk_property.SetInterpolationToPhong()
self.vtk_property.SetDiffuse(0.7)
self.vtk_property.SetSpecular(0.4)
self.vtk_property.SetSpecularPower(20)
self.vtk_glyph_source.SetPhiResolution(16)
self.vtk_glyph_source.SetThetaResolution(16)
self.vtk_glyph_source.SetRadius(fraction*self.radius)
# -------------------------------------------------------------------
class vtkClampedGlyphSource(vtkCustomGlyphSource):
def __init__(self, scale, vtk_glyph_source, range_min, range_max):
vtkCustomGlyphSource.__init__(self, scale, vtk_glyph_source)
self.range = (range_min, range_max,)
def get_range(self):
return self.range
class vtkForceSource(vtkClampedGlyphSource):
def __init__(self, maxnorm, scale=1):
vtkClampedGlyphSource.__init__(self, scale, vtkArrowSource(),
range_min=0.0, range_max=maxnorm)
self.vtk_property.SetColor(1.0, 0.25, 0.25) # forces are red
self.vtk_property.SetInterpolationToPhong()
self.vtk_property.SetDiffuse(0.7)
self.vtk_property.SetSpecular(0.4)
self.vtk_property.SetSpecularPower(20)
self.vtk_glyph_source.SetShaftResolution(12)
self.vtk_glyph_source.SetShaftRadius(0.03*avg_radius) #default 0.03
self.vtk_glyph_source.SetTipResolution(20)
self.vtk_glyph_source.SetTipLength(0.3*avg_radius) #default 0.35
self.vtk_glyph_source.SetTipRadius(0.1*avg_radius) #default 0.1
class vtkVelocitySource(vtkClampedGlyphSource):
def __init__(self, maxnorm, scale=1):
vtkClampedGlyphSource.__init__(self, scale, vtkConeSource(),
range_min=0.0, range_max=maxnorm)
self.vtk_property.SetColor(0.25, 0.25, 1.0) # velocities blue
self.vtk_property.SetInterpolationToPhong()
self.vtk_property.SetDiffuse(0.9)
self.vtk_property.SetSpecular(1.0)
self.vtk_property.SetSpecularPower(50)
self.vtk_glyph_source.SetAngle(6)
self.vtk_glyph_source.SetHeight(avg_radius)
self.vtk_glyph_source.SetResolution(16)
self.vtk_glyph_source.SetCenter(0.05*avg_radius, 0.0, 0.0)
# -------------------------------------------------------------------
class vtkBondSource(vtkCustomGlyphSource):
def __init__(self, width, scale=1):
vtkCustomGlyphSource.__init__(self, scale, vtkCylinderSource())
self.width = width
self.vtk_property.SetColor(0.25, 1.0, 0.25) # bonds are green
# (and so are you)
self.vtk_glyph_source.SetRadius(self.scale*self.width)
self.vtk_glyph_source.SetResolution(16)
python-ase-3.6.0.2515/ase/visualize/vtk/cell.py 0000644 0001754 0001754 00000007727 11267075542 020106 0 ustar askhl askhl
import numpy as np
from ase import Atoms
from vtk import vtkOutlineSource, vtkAxesActor, vtkProperty2D, vtkTextProperty
from ase.visualize.vtk.module import vtkModule, vtkPolyDataModule
# -------------------------------------------------------------------
class vtkUnitCellModule(vtkPolyDataModule):
def __init__(self, atoms):
assert isinstance(atoms, Atoms)
self.pbc = atoms.get_pbc()
cell = atoms.get_cell()
"""
if not isinstance(cell, np.ndarray):
cell = np.array(cell)
if cell.shape == (3,):
cell = np.diag(cell)
assert cell.dtype == float and cell.shape == (3, 3)
"""
self.vtk_outline = vtkOutlineSource()
if (cell - np.diag(cell.diagonal())).any():
corners = np.empty((8,3), dtype=float)
# edges = [map(int,[(i-1)%2==0,i%4>=2,i>=4]) for i in range(8)]
for c,a in enumerate([(0, 0, 0), (1, 0, 0), (0, 1, 0), (1, 1, 0), \
(0, 0, 1), (1, 0, 1), (0, 1, 1), (1, 1, 1)]):
corners[c] = np.dot(a, cell)
self.bbox = np.array(zip(np.min(corners, axis=0), \
np.max(corners, axis=0))).ravel()
self.vtk_outline.SetCorners(corners.ravel())
self.vtk_outline.SetBoxTypeToOriented()
else:
self.bbox = np.array(zip(np.zeros(3),cell.diagonal())).ravel()
self.vtk_outline.SetBounds(self.bbox)
vtkPolyDataModule.__init__(self, self.vtk_outline)
def get_bounding_box(self):
return self.bbox
def get_size(self):
return self.bbox[1::2]-self.bbox[0::2]
def get_pbc(self):
return self.pbc
def get_characteristic_length(self):
return np.prod(self.get_size())**(1.0/3.0)
# -------------------------------------------------------------------
class vtkAxesModule(vtkModule):
def __init__(self, cell):
assert isinstance(cell, vtkUnitCellModule)
self.cell = cell
l0 = self.cell.get_characteristic_length()
# Create VTK axes actor (not really a VTK actor though)
self.vtk_ax = vtkAxesActor()
self.vtk_ax.SetTipTypeToCone()
self.vtk_ax.SetConeRadius(5e-2*l0)
self.vtk_ax.SetShaftTypeToCylinder()
self.vtk_ax.SetCylinderRadius(5e-3*l0)
# Create VTK two-dimensional property
p2d = vtkProperty2D()
p2d.SetDisplayLocationToBackground()
vtkModule.__init__(self, self.vtk_ax, p2d)
# Create VTK text property and apply to axes
vtk_textproperty = vtkTextProperty()
vtk_textproperty.SetFontSize(14)
vtk_textproperty.SetBold(True)
vtk_textproperty.SetItalic(True)
vtk_textproperty.SetShadow(True)
vtk_textproperty.SetJustificationToRight()
vtk_textproperty.SetVerticalJustificationToCentered()
self.set_text_property(vtk_textproperty)
def set_actor(self, vtk_act):
assert isinstance(vtk_act, vtkAxesActor) #fix for non-vtkActor actor
self.vtk_act = vtk_act
def set_property(self, vtk_property):
assert isinstance(vtk_property, vtkProperty2D)
for vtk_cap in [self.vtk_ax.GetXAxisCaptionActor2D(),
self.vtk_ax.GetYAxisCaptionActor2D(),
self.vtk_ax.GetZAxisCaptionActor2D()]:
#vtk_cap.ThreeDimensionalLeaderOn()
#vtk_cap.LeaderOn()
vtk_cap.SetProperty(vtk_property)
vtk_txt = vtk_cap.GetTextActor()
vtk_txt.SetProperty(vtk_property)
def set_text_property(self, vtk_textproperty, scaled=False):
assert isinstance(vtk_textproperty, vtkTextProperty)
for vtk_cap in [self.vtk_ax.GetXAxisCaptionActor2D(),
self.vtk_ax.GetYAxisCaptionActor2D(),
self.vtk_ax.GetZAxisCaptionActor2D()]:
vtk_txt = vtk_cap.GetTextActor()
vtk_txt.SetScaledText(scaled)
vtk_txt.SetTextProperty(vtk_textproperty)
python-ase-3.6.0.2515/ase/visualize/vtk/atoms.py 0000644 0001754 0001754 00000011172 11166515604 020273 0 ustar askhl askhl
import numpy as np
from ase import Atoms
from ase.visualize.vtk.sources import vtkAtomSource, vtkForceSource, \
vtkVelocitySource
from ase.visualize.vtk.cell import vtkUnitCellModule, vtkAxesModule
from ase.visualize.vtk.grid import vtkAtomicPositions
from ase.visualize.vtk.module import vtkModuleAnchor, vtkGlyphModule
# -------------------------------------------------------------------
class vtkAtoms(vtkModuleAnchor, vtkAtomicPositions):
"""Provides fundamental representation for ``Atoms``-specific data in VTK.
The ``vtkAtoms`` class plots atoms during simulations, extracting the
relevant information from the list of atoms. It is created using
the list of atoms as an argument to the constructor. Then one or more
visualization modules can be attached using add_module(name, module).
Example:
>>> va = vtkAtoms(atoms)
>>> va.add_forces()
>>> va.add_axes()
>>> XXX va.add_to_renderer(vtk_ren)
"""
def __init__(self, atoms, scale=1):
"""Construct a fundamental VTK-representation of atoms.
atoms: Atoms object or list of Atoms objects
The atoms to be plotted.
scale = 1: float or int
Relative scaling of all Atoms-specific visualization.
"""
assert isinstance(atoms, Atoms)
self.atoms = atoms
self.scale = scale
vtkModuleAnchor.__init__(self)
vtkAtomicPositions.__init__(self, self.atoms.get_positions(),
vtkUnitCellModule(self.atoms))
self.force = None
self.velocity = None
symbols = self.atoms.get_chemical_symbols()
for symbol in np.unique(symbols):
# Construct mask for all atoms with this symbol
mask = np.array(symbols) == symbol
if mask.all():
subset = None
else:
subset = np.argwhere(mask).ravel()
# Get relevant VTK unstructured grid
vtk_ugd = self.get_unstructured_grid(subset)
# Create atomic glyph source for this symbol
glyph_source = vtkAtomSource(symbol, self.scale)
# Create glyph module and anchor it
self.add_module(symbol, vtkGlyphModule(vtk_ugd, glyph_source))
def has_forces(self):
return self.force is not None
def has_velocities(self):
return self.velocity is not None
def add_cell(self):
"""Add a box outline of the cell using atoms.get_cell(). The existing
``vtkUnitCellModule`` is added to the module anchor under ``cell``."""
self.add_module('cell', self.cell)
def add_axes(self):
"""Add an orientation indicator for the cartesian axes. An appropriate
``vtkAxesModule`` is added to the module anchor under ``axes``."""
self.add_module('axes', vtkAxesModule(self.cell))
def add_forces(self):
"""Add force vectors for the atoms using atoms.get_forces(). A
``vtkGlyphModule`` is added to the module anchor under ``force``."""
if self.has_forces():
raise RuntimeError('Forces already present.')
elif self.has_velocities():
raise NotImplementedError('Can\'t add forces due to velocities.')
# Add forces to VTK unstructured grid as vector data
vtk_fda = self.add_vector_property(self.atoms.get_forces(), 'force')
# Calculate max norm of the forces
fmax = vtk_fda.GetMaxNorm()
# Get relevant VTK unstructured grid
vtk_ugd = self.get_unstructured_grid()
self.force = vtkGlyphModule(vtk_ugd, vtkForceSource(fmax, self.scale),
scalemode='vector', colormode=None)
self.add_module('force', self.force)
def add_velocities(self):
"""Add velocity vectors for the atoms using atoms.get_velocities(). A
``vtkGlyphModule`` is added to the module anchor under ``velocity``."""
if self.has_velocities():
raise RuntimeError('Velocities already present.')
elif self.has_forces():
raise NotImplementedError('Can\'t add velocities due to forces.')
# Add velocities to VTK unstructured grid as vector data
vtk_vda = self.add_vector_property(self.atoms.get_velocities(), 'velocity')
# Calculate max norm of the velocities
vmax = vtk_vda.GetMaxNorm()
# Get relevant VTK unstructured grid
vtk_ugd = self.get_unstructured_grid()
self.velocity = vtkGlyphModule(vtk_ugd, vtkVelocitySource(vmax, self.scale),
scalemode='vector', colormode=None)
self.add_module('velocity', self.velocity)
python-ase-3.6.0.2515/ase/visualize/vtk/pipeline.py 0000644 0001754 0001754 00000015372 11170133163 020752 0 ustar askhl askhl
import numpy as np
from vtk import vtkPolyDataMapper, vtkPolyDataNormals, \
vtkLinearSubdivisionFilter, vtkSmoothPolyDataFilter, \
vtkDepthSortPolyData, vtkAlgorithm, vtkAlgorithmOutput
from ase.visualize.vtk.grid import vtkVolumeGrid
# -------------------------------------------------------------------
class vtkPipeline:
_branchable = False
def __init__(self, vtkish_data=None):
self.vtkish_data = None
self.closed = False
self.pending = False
self.filters = tuple()
if vtkish_data is not None:
self.set_data(vtkish_data)
def hasdata(self):
return (self.vtkish_data is not None)
def hasfilters(self):
return len(self.filters)>0
def set_data(self, vtkish_data):
assert vtkish_data is not None
if self.hasdata():
raise RuntimeError('Pipeline already has input.')
elif vtkish_data in self:
raise ValueError('Pipeline loop detected.')
if isinstance(vtkish_data, vtkPipeline):
# The embedded pipeline takes over
vtkish_data.signal_close()
self.vtkish_data = vtkish_data
if not self.hasfilters():
return
vtkish_inner = self.filters[0]
if isinstance(vtkish_inner, vtkPipeline):
vtkish_inner.set_data(vtkish_data) #TODO does this work?
else:
assert isinstance(vtkish_inner, vtkAlgorithm)
if isinstance(vtkish_data, vtkPipeline):
# The embedded pipeline takes over
vtkish_data.connect(vtkish_inner)
else:
assert isinstance(vtkish_data, vtkAlgorithm)
vtkish_inner.SetInputConnection(vtkish_data.GetOutputPort())
def isempty(self):
return not self.hasdata() and not self.hasfilters()
def isclosed(self):
if self.pending:
raise RuntimeError('Pipeline output port state is pending.')
return self.closed
def signal_close(self):
if self.closed:
raise RuntimeError('Pipeline output port is already closed.')
elif not self._branchable:
self.pending = True
def get_output_port(self):
if self.closed:
raise RuntimeError('Pipeline output port is closed.')
elif self.pending:
self.closed = True
self.pending = False
if self.hasfilters():
vtkish_outer = self.filters[-1]
elif self.hasdata():
vtkish_outer = self.vtkish_data
else:
raise RuntimeError('Pipeline output port unavailable.')
if isinstance(vtkish_outer, vtkPipeline):
return vtkish_outer.get_output_port()
else:
assert isinstance(vtkish_outer, vtkAlgorithm)
return vtkish_outer.GetOutputPort()
def set_input_connection(self, vtk_port):
assert isinstance(vtk_port, vtkAlgorithmOutput)
vtkish_inner = self.filters[0]
if isinstance(vtkish_inner, vtkPipeline):
# Connect must be passed down
vtkish_inner.set_input_connection(vtk_port)
else:
vtkish_inner.SetInputConnection(vtk_port)
def connect(self, vtkish_filter):
if vtkish_filter in self:
raise ValueError('Pipeline loop detected.')
if isinstance(vtkish_filter, vtkPipeline):
# Connection must be passed down
if not self.isempty():
vtkish_filter.set_input_connection(self.get_output_port())
# The containing pipeline takes over
vtkish_filter.signal_close()
elif not self.isempty():
assert isinstance(vtkish_filter, vtkAlgorithm)
vtkish_filter.SetInputConnection(self.get_output_port())
def append(self, vtkish_filter):
self.connect(vtkish_filter)
self.filters += (vtkish_filter,)
def extend(self, vtkish_filters):
map(self.append, vtkish_filters)
def __contains__(self, vtkish_candidate):
if vtkish_candidate == self:
return True
if self.hasdata():
if isinstance(self.vtkish_data, vtkPipeline):
if vtkish_candidate in self.vtkish_data:
return True
else:
if vtkish_candidate == self.vtkish_data:
return True
if vtkish_candidate in self.filters:
return True
for vtkish_filter in self.filters:
if isinstance(vtkish_filter, vtkPipeline) \
and vtkish_candidate in vtkish_filter:
return True
return False
def __getitem__(self, i): #TODO XXX this is a hack
return self.filters[i]
# -------------------------------------------------------------------
class vtkPolyDataPipeline(vtkPipeline):
def __init__(self, vtkish_polydata=None):
vtkPipeline.__init__(self, vtkish_polydata)
def connect(self, vtkish_filter):
if isinstance(vtkish_filter, vtkPolyDataMapper):
self.signal_close()
vtkPipeline.connect(self, vtkish_filter)
class vtkSurfaceSmootherPipeline(vtkPolyDataPipeline):
def __init__(self, grid, vtkish_polydata=None, angle=15):
vtkPolyDataPipeline.__init__(self, vtkish_polydata)
# Make sure grid argument is correct type
assert isinstance(grid, vtkVolumeGrid)
self.grid = grid
# Split polys with intersection angles greater than angle
vtk_dnorm = vtkPolyDataNormals()
vtk_dnorm.SetFeatureAngle(angle)
vtk_dnorm.SplittingOn()
vtk_dnorm.ComputeCellNormalsOff()
vtk_dnorm.ComputePointNormalsOff()
self.append(vtk_dnorm)
relax = self.grid.get_relaxation_factor()
if relax is not None:
print 'relax=',relax
#vtk_subdiv = vtkButterflySubdivisionFilter()
vtk_subdiv = vtkLinearSubdivisionFilter()
self.append(vtk_subdiv)
# Smooth out some of the sharp points.
vtk_smooth = vtkSmoothPolyDataFilter()
vtk_smooth.SetRelaxationFactor(relax)
self.append(vtk_smooth)
class vtkDepthSortPipeline(vtkPolyDataPipeline):
def __init__(self, vtk_renderer, vtkish_polydata=None):
vtkPolyDataPipeline.__init__(self, vtkish_polydata)
# The depht sort object is set up to generate scalars representing
# the sort depth. A camera is assigned for the sorting. The camera
# defines the sort vector (position and focal point).
vtk_ds = vtkDepthSortPolyData()
vtk_ds.SetCamera(vtk_renderer.GetActiveCamera())
vtk_ds.SetDirectionToBackToFront()
#vtk_ds.SetVector(1, 1, 1)
#vtk_ds.SortScalarsOn()
#vtk_ds.Update()
self.append(vtk_ds)
vtk_renderer.ResetCamera()
python-ase-3.6.0.2515/ase/visualize/vtk/volume.py 0000644 0001754 0001754 00000004523 11164377616 020470 0 ustar askhl askhl
import numpy as np
from vtk import vtkContourFilter, vtkDepthSortPolyData
from ase.visualize.vtk.grid import vtkVolumeGrid
from ase.visualize.vtk.module import vtkPolyDataModule
from ase.visualize.vtk.pipeline import vtkSurfaceSmootherPipeline, \
vtkDepthSortPipeline
# -------------------------------------------------------------------
class vtkIsoSurfaceModule(vtkVolumeGrid, vtkPolyDataModule):
def __init__(self, data, cell, vtk_renderer, contours=1, depthsort=True):
#TODO don't require vtk_renderer... implement vtkScene
#TODO contour values from list or autocontours if int
# Make sure data argument is a valid array
if not isinstance(data, np.ndarray):
data = np.array(data)
vtkVolumeGrid.__init__(self, data.shape, cell)
self.vtk_iso = vtkContourFilter() #vtkMarchingContourFilter?
self.vtk_iso.SetInput(self.get_structured_points()) #TODO non-orthogonal
self.vtk_iso.SetValue(0, 0.25)
self.vtk_iso.SetValue(1, -0.25)
self.smoothpipe = vtkSurfaceSmootherPipeline(self, vtk_iso)
#TODO use vtkDepthSortPipeline - but vtkPolyDataModule isn't a pipeline
self.depthsort = depthsort
if self.depthsort:
# The depht sort object is set up to generate scalars representing
# the sort depth. A camera is assigned for the sorting. The camera
# defines the sort vector (position and focal point).
self.vtk_ds = vtkDepthSortPolyData()
self.vtk_ds.SetCamera(vtk_renderer.GetActiveCamera())
self.vtk_ds.SetInputConnection(self.vtk_iso.GetOutputPort())
self.vtk_ds.SetDirectionToBackToFront()
#vtk_ds.SetVector(1, 1, 1)
#vtk_ds.SortScalarsOn()
#vtk_ds.Update()
vtk_renderer.ResetCamera()
vtkPolyDataModule.__init__(self, self.vtk_ds)
else:
vtkPolyDataModule.__init__(self, self.vtk_iso)
#TODO add color function
"""
vtk_dmap = vtk.vtkPolyDataMapper()
vtk_dmap.ScalarVisibilityOn()
vtk_dmap.SetScalarRange(0, vtk_sda_x.GetMaxNorm()) #TODO GetMinNorm non-existing!
vtk_dmap.SetScalarModeToUsePointFieldData()
vtk_dmap.SelectColorArray("x")
#vtk_dmap.ColorByArrayComponent("x", 0)
"""
python-ase-3.6.0.2515/ase/visualize/vtk/module.py 0000644 0001754 0001754 00000017461 11173632064 020442 0 ustar askhl askhl
import numpy as np
from vtk import vtkProp3D, vtkPolyDataMapper, vtkActor, vtkLODActor, \
vtkPointSet, vtkGlyph3D, vtkRenderer
from ase.visualize.vtk.sources import vtkCustomGlyphSource, \
vtkClampedGlyphSource
# -------------------------------------------------------------------
class vtkModule:
"""Modules represent a unified collection of VTK objects needed for
introducing basic visualization concepts such as surfaces or shapes.
A common trait of all modules is the need for an actor representation and
corresponding generic properties such as lighting, color and transparency.
"""
def __init__(self, vtk_act, vtk_property=None):
"""Construct basic VTK-representation of a module.
vtk_act: Instance of vtkActor or subclass thereof
A vtkActor represents an entity in a rendering scene.
vtk_property = None: Instance of vtkProperty or subclass thereof
A vtkProperty represents e.g. lighting and other surface
properties of a geometric object, in this case the actor.
"""
self.vtk_act = None
self.set_actor(vtk_act)
if vtk_property is not None:
self.set_property(vtk_property)
def set_actor(self, vtk_act):
"""Set the actor representing this module in a rendering scene."""
assert isinstance(vtk_act, vtkActor)
self.vtk_act = vtk_act
def set_property(self, vtk_property):
"""Set the property of the actor representing this module."""
self.vtk_act.SetProperty(vtk_property)
def get_actor(self):
"""Return the actor representing this module in a rendering scene."""
return self.vtk_act
# -------------------------------------------------------------------
class vtkLODModule(vtkModule):
_vtk_actor_class = vtkLODActor
def get_lod(self):
return 100
def set_actor(self, vtk_act):
vtkModule.set_actor(self, vtk_act)
if isinstance(vtk_act, vtkLODActor):
vtk_act.SetNumberOfCloudPoints(self.get_lod())
class vtkPolyDataModule(vtkModule):
_vtk_actor_class = vtkActor
__doc__ = vtkModule.__doc__ + """
Poly data modules are based on polygonal data sets, which can be mapped
into graphics primitives suitable for rendering within the VTK framework.
"""
def __init__(self, vtk_polydata, vtk_property=None):
"""Construct VTK-representation of a module containing polygonals.
vtk_polydata: Instance of vtkPolyData, subclass thereof or
vtkPolyDataAlgorithm, which produces vtkPolyData as output.
A vtkPolyData represents a polygonal data set consisting of
point and cell attributes, which can be mapped to graphics
primitives for subsequent rendering.
vtk_property = None: Instance of vtkProperty or subclass thereof
A vtkProperty represents e.g. lighting and other surface
properties of a geometric object, in this case the polydata.
"""
vtkModule.__init__(self, self._vtk_actor_class(), vtk_property)
self.vtk_dmap = vtkPolyDataMapper()
self.vtk_dmap.SetInputConnection(vtk_polydata.GetOutputPort())
self.vtk_act.SetMapper(self.vtk_dmap)
class vtkGlyphModule(vtkPolyDataModule):
__doc__ = vtkPolyDataModule.__doc__ + """
Glyph modules construct these polygonal data sets by replicating a glyph
source across a specific set of points, using available scalar or vector
point data to scale and orientate the glyph source if desired.
Example:
>>> atoms = molecule('C60')
>>> cell = vtkUnitCellModule(atoms)
>>> apos = vtkAtomicPositions(atoms.get_positions(), cell)
>>> vtk_ugd = apos.get_unstructured_grid()
>>> glyph_source = vtkAtomSource('C')
>>> glyph_module = vtkGlyphModule(vtk_ugd, glyph_source)
"""
def __init__(self, vtk_pointset, glyph_source,
scalemode=None, colormode=None):
"""Construct VTK-representation of a module containing glyphs.
These glyphs share a common source, defining their geometrical
shape, which is cloned and oriented according to the input data.
vtk_pointset: Instance of vtkPointSet or subclass thereof
A vtkPointSet defines a set of positions, which may then be
assigned specific scalar of vector data across the entire set.
glyph_source: Instance of ~vtk.vtkCustomGlyphSource or subclass thereof
Provides the basic shape to distribute over the point set.
"""
assert isinstance(vtk_pointset, vtkPointSet)
assert isinstance(glyph_source, vtkCustomGlyphSource)
# Create VTK Glyph3D based on unstructured grid
self.vtk_g3d = vtkGlyph3D()
self.vtk_g3d.SetInput(vtk_pointset)
self.vtk_g3d.SetSource(glyph_source.get_output())
self.vtk_g3d.SetScaleFactor(glyph_source.get_scale())
# Clamping normalizes the glyph scaling to within the range [0,1].
# Setting a scale factor will then scale these by the given factor.
if isinstance(glyph_source, vtkClampedGlyphSource):
self.vtk_g3d.SetClamping(True)
self.vtk_g3d.SetRange(glyph_source.get_range())
if scalemode is 'off':
self.vtk_g3d.SetScaleModeToDataScalingOff()
elif scalemode is 'scalar':
self.vtk_g3d.SetScaleModeToScaleByScalar()
elif scalemode is 'vector':
self.vtk_g3d.SetScaleModeToScaleByVector()
elif scalemode is not None:
raise ValueError('Unrecognized scale mode \'%s\'.' % scalemode)
if colormode is 'scale':
self.vtk_g3d.SetColorModeToColorByScale()
elif colormode is 'scalar':
self.vtk_g3d.SetColorModeToColorByScalar()
elif colormode is 'vector':
self.vtk_g3d.SetColorModeToColorByVector()
elif colormode is not None:
raise ValueError('Unrecognized scale mode \'%s\'.' % scalemode)
vtkPolyDataModule.__init__(self, self.vtk_g3d, glyph_source.get_property())
# -------------------------------------------------------------------
class vtkLabelModule(vtkModule):
def __init__(self, vtk_pointset, vtk_property=None):
vtk_Module.__init__(self, vtkActor(), vtk_property)
assert isinstance(vtk_pointset, vtkPointSet)
self.vtk_dmap = vtkLabeledDataMapper()
#self.vtk_dmap.SetLabelModeToLabelIds() #TODO XXX strings!!!
self.vtk_dmap.GetLabelTextProperty().SetFontSize(12)
self.vtk_dmap.GetLabelTextProperty().SetJustificationToRight()
self.vtk_dmap.SetInputConnection(vtk_pointset.GetOutputPort())
self.vtk_act.SetMapper(self.vtk_dmap)
#vtk_g3d.GetPointIdsName...
# -------------------------------------------------------------------
class vtkModuleAnchor:
"""
TODO XXX
"""
def __init__(self):
"""Construct an anchoring point for various VTK modules.
"""
self.modules = {}
def get_module(self, name):
if name not in self.modules.keys():
raise RuntimeError('Module \'%s\' does not exists.' % name)
return self.modules[name]
def add_module(self, name, module):
if not isinstance(module, vtkModule):
raise ValueError('Module must be instance of vtkModule.')
if name in self.modules.keys():
raise RuntimeError('Module \'%s\' already exists.' % name)
self.modules[name] = module
def get_actor(self, name):
return self.get_module(name).get_actor()
def add_actors_to_renderer(self, vtk_renderer, name=None):
assert isinstance(vtk_renderer, vtkRenderer)
if name is None:
for module in self.modules.values():
vtk_renderer.AddActor(module.get_actor())
else:
vtk_renderer.AddActor(self.get_actor(name))
python-ase-3.6.0.2515/ase/visualize/sage.py 0000644 0001754 0001754 00000001432 11623435042 017254 0 ustar askhl askhl from ase.data.colors import jmol_colors
from ase.data import covalent_radii, atomic_numbers
def view_sage_jmol(atoms):
try:
from sage.plot.plot3d.shapes import ColorCube, Sphere
except:
raise ImportError(
'view_sage_jmol requires sage (http://www.sagemath.org/) ' +
'and is intended to be used directly in the browser')
cell = atoms.cell.diagonal() / 2
model = ColorCube(list(cell), ['blue', 'blue', 'blue'], opacity=0.1)
for atom in atoms:
atomic_number = atom.number
color = tuple(jmol_colors[atomic_number])
radius = covalent_radii[atomic_number]
model += Sphere(radius, color=color).translate(
*(atom.position - atoms.cell.diagonal() / 2))
model.show(aspect_ratio=1, frame=False)
python-ase-3.6.0.2515/ase/visualize/colortable.py 0000644 0001754 0001754 00000115176 11575617122 020505 0 ustar askhl askhl """Defines a table with X11 colors.
The key to the dictionary is a string with an X11 name for the color,
the value is either a number (a grayscale value) between 0.0 and 1.0,
or an array of three numbers (RGB values).
The table was generated by the _MakeColorTable function
(defined in this module).
"""
from numpy import array
color_table = {
'snow': array([1.0000, 0.9804, 0.9804]),
'ghost white': array([0.9725, 0.9725, 1.0000]),
'GhostWhite': array([0.9725, 0.9725, 1.0000]),
'white smoke': 0.9608,
'WhiteSmoke': 0.9608,
'gainsboro': 0.8627,
'floral white': array([1.0000, 0.9804, 0.9412]),
'FloralWhite': array([1.0000, 0.9804, 0.9412]),
'old lace': array([0.9922, 0.9608, 0.9020]),
'OldLace': array([0.9922, 0.9608, 0.9020]),
'linen': array([0.9804, 0.9412, 0.9020]),
'antique white': array([0.9804, 0.9216, 0.8431]),
'AntiqueWhite': array([0.9804, 0.9216, 0.8431]),
'papaya whip': array([1.0000, 0.9373, 0.8353]),
'PapayaWhip': array([1.0000, 0.9373, 0.8353]),
'blanched almond': array([1.0000, 0.9216, 0.8039]),
'BlanchedAlmond': array([1.0000, 0.9216, 0.8039]),
'bisque': array([1.0000, 0.8941, 0.7686]),
'peach puff': array([1.0000, 0.8549, 0.7255]),
'PeachPuff': array([1.0000, 0.8549, 0.7255]),
'navajo white': array([1.0000, 0.8706, 0.6784]),
'NavajoWhite': array([1.0000, 0.8706, 0.6784]),
'moccasin': array([1.0000, 0.8941, 0.7098]),
'cornsilk': array([1.0000, 0.9725, 0.8627]),
'ivory': array([1.0000, 1.0000, 0.9412]),
'lemon chiffon': array([1.0000, 0.9804, 0.8039]),
'LemonChiffon': array([1.0000, 0.9804, 0.8039]),
'seashell': array([1.0000, 0.9608, 0.9333]),
'honeydew': array([0.9412, 1.0000, 0.9412]),
'mint cream': array([0.9608, 1.0000, 0.9804]),
'MintCream': array([0.9608, 1.0000, 0.9804]),
'azure': array([0.9412, 1.0000, 1.0000]),
'alice blue': array([0.9412, 0.9725, 1.0000]),
'AliceBlue': array([0.9412, 0.9725, 1.0000]),
'lavender': array([0.9020, 0.9020, 0.9804]),
'lavender blush': array([1.0000, 0.9412, 0.9608]),
'LavenderBlush': array([1.0000, 0.9412, 0.9608]),
'misty rose': array([1.0000, 0.8941, 0.8824]),
'MistyRose': array([1.0000, 0.8941, 0.8824]),
'white': 1.0000,
'black': 0.0000,
'dark slate gray': array([0.1843, 0.3098, 0.3098]),
'DarkSlateGray': array([0.1843, 0.3098, 0.3098]),
'dark slate grey': array([0.1843, 0.3098, 0.3098]),
'DarkSlateGrey': array([0.1843, 0.3098, 0.3098]),
'dim gray': 0.4118,
'DimGray': 0.4118,
'dim grey': 0.4118,
'DimGrey': 0.4118,
'slate gray': array([0.4392, 0.5020, 0.5647]),
'SlateGray': array([0.4392, 0.5020, 0.5647]),
'slate grey': array([0.4392, 0.5020, 0.5647]),
'SlateGrey': array([0.4392, 0.5020, 0.5647]),
'light slate gray': array([0.4667, 0.5333, 0.6000]),
'LightSlateGray': array([0.4667, 0.5333, 0.6000]),
'light slate grey': array([0.4667, 0.5333, 0.6000]),
'LightSlateGrey': array([0.4667, 0.5333, 0.6000]),
'gray': 0.7451,
'grey': 0.7451,
'light grey': 0.8275,
'LightGrey': 0.8275,
'light gray': 0.8275,
'LightGray': 0.8275,
'midnight blue': array([0.0980, 0.0980, 0.4392]),
'MidnightBlue': array([0.0980, 0.0980, 0.4392]),
'navy': array([0.0000, 0.0000, 0.5020]),
'navy blue': array([0.0000, 0.0000, 0.5020]),
'NavyBlue': array([0.0000, 0.0000, 0.5020]),
'cornflower blue': array([0.3922, 0.5843, 0.9294]),
'CornflowerBlue': array([0.3922, 0.5843, 0.9294]),
'dark slate blue': array([0.2824, 0.2392, 0.5451]),
'DarkSlateBlue': array([0.2824, 0.2392, 0.5451]),
'slate blue': array([0.4157, 0.3529, 0.8039]),
'SlateBlue': array([0.4157, 0.3529, 0.8039]),
'medium slate blue': array([0.4824, 0.4078, 0.9333]),
'MediumSlateBlue': array([0.4824, 0.4078, 0.9333]),
'light slate blue': array([0.5176, 0.4392, 1.0000]),
'LightSlateBlue': array([0.5176, 0.4392, 1.0000]),
'medium blue': array([0.0000, 0.0000, 0.8039]),
'MediumBlue': array([0.0000, 0.0000, 0.8039]),
'royal blue': array([0.2549, 0.4118, 0.8824]),
'RoyalBlue': array([0.2549, 0.4118, 0.8824]),
'blue': array([0.0000, 0.0000, 1.0000]),
'dodger blue': array([0.1176, 0.5647, 1.0000]),
'DodgerBlue': array([0.1176, 0.5647, 1.0000]),
'deep sky blue': array([0.0000, 0.7490, 1.0000]),
'DeepSkyBlue': array([0.0000, 0.7490, 1.0000]),
'sky blue': array([0.5294, 0.8078, 0.9216]),
'SkyBlue': array([0.5294, 0.8078, 0.9216]),
'light sky blue': array([0.5294, 0.8078, 0.9804]),
'LightSkyBlue': array([0.5294, 0.8078, 0.9804]),
'steel blue': array([0.2745, 0.5098, 0.7059]),
'SteelBlue': array([0.2745, 0.5098, 0.7059]),
'light steel blue': array([0.6902, 0.7686, 0.8706]),
'LightSteelBlue': array([0.6902, 0.7686, 0.8706]),
'light blue': array([0.6784, 0.8471, 0.9020]),
'LightBlue': array([0.6784, 0.8471, 0.9020]),
'powder blue': array([0.6902, 0.8784, 0.9020]),
'PowderBlue': array([0.6902, 0.8784, 0.9020]),
'pale turquoise': array([0.6863, 0.9333, 0.9333]),
'PaleTurquoise': array([0.6863, 0.9333, 0.9333]),
'dark turquoise': array([0.0000, 0.8078, 0.8196]),
'DarkTurquoise': array([0.0000, 0.8078, 0.8196]),
'medium turquoise': array([0.2824, 0.8196, 0.8000]),
'MediumTurquoise': array([0.2824, 0.8196, 0.8000]),
'turquoise': array([0.2510, 0.8784, 0.8157]),
'cyan': array([0.0000, 1.0000, 1.0000]),
'light cyan': array([0.8784, 1.0000, 1.0000]),
'LightCyan': array([0.8784, 1.0000, 1.0000]),
'cadet blue': array([0.3725, 0.6196, 0.6275]),
'CadetBlue': array([0.3725, 0.6196, 0.6275]),
'medium aquamarine': array([0.4000, 0.8039, 0.6667]),
'MediumAquamarine': array([0.4000, 0.8039, 0.6667]),
'aquamarine': array([0.4980, 1.0000, 0.8314]),
'dark green': array([0.0000, 0.3922, 0.0000]),
'DarkGreen': array([0.0000, 0.3922, 0.0000]),
'dark olive green': array([0.3333, 0.4196, 0.1843]),
'DarkOliveGreen': array([0.3333, 0.4196, 0.1843]),
'dark sea green': array([0.5608, 0.7373, 0.5608]),
'DarkSeaGreen': array([0.5608, 0.7373, 0.5608]),
'sea green': array([0.1804, 0.5451, 0.3412]),
'SeaGreen': array([0.1804, 0.5451, 0.3412]),
'medium sea green': array([0.2353, 0.7020, 0.4431]),
'MediumSeaGreen': array([0.2353, 0.7020, 0.4431]),
'light sea green': array([0.1255, 0.6980, 0.6667]),
'LightSeaGreen': array([0.1255, 0.6980, 0.6667]),
'pale green': array([0.5961, 0.9843, 0.5961]),
'PaleGreen': array([0.5961, 0.9843, 0.5961]),
'spring green': array([0.0000, 1.0000, 0.4980]),
'SpringGreen': array([0.0000, 1.0000, 0.4980]),
'lawn green': array([0.4863, 0.9882, 0.0000]),
'LawnGreen': array([0.4863, 0.9882, 0.0000]),
'green': array([0.0000, 1.0000, 0.0000]),
'chartreuse': array([0.4980, 1.0000, 0.0000]),
'medium spring green': array([0.0000, 0.9804, 0.6039]),
'MediumSpringGreen': array([0.0000, 0.9804, 0.6039]),
'green yellow': array([0.6784, 1.0000, 0.1843]),
'GreenYellow': array([0.6784, 1.0000, 0.1843]),
'lime green': array([0.1961, 0.8039, 0.1961]),
'LimeGreen': array([0.1961, 0.8039, 0.1961]),
'yellow green': array([0.6039, 0.8039, 0.1961]),
'YellowGreen': array([0.6039, 0.8039, 0.1961]),
'forest green': array([0.1333, 0.5451, 0.1333]),
'ForestGreen': array([0.1333, 0.5451, 0.1333]),
'olive drab': array([0.4196, 0.5569, 0.1373]),
'OliveDrab': array([0.4196, 0.5569, 0.1373]),
'dark khaki': array([0.7412, 0.7176, 0.4196]),
'DarkKhaki': array([0.7412, 0.7176, 0.4196]),
'khaki': array([0.9412, 0.9020, 0.5490]),
'pale goldenrod': array([0.9333, 0.9098, 0.6667]),
'PaleGoldenrod': array([0.9333, 0.9098, 0.6667]),
'light goldenrod yellow': array([0.9804, 0.9804, 0.8235]),
'LightGoldenrodYellow': array([0.9804, 0.9804, 0.8235]),
'light yellow': array([1.0000, 1.0000, 0.8784]),
'LightYellow': array([1.0000, 1.0000, 0.8784]),
'yellow': array([1.0000, 1.0000, 0.0000]),
'gold': array([1.0000, 0.8431, 0.0000]),
'light goldenrod': array([0.9333, 0.8667, 0.5098]),
'LightGoldenrod': array([0.9333, 0.8667, 0.5098]),
'goldenrod': array([0.8549, 0.6471, 0.1255]),
'dark goldenrod': array([0.7216, 0.5255, 0.0431]),
'DarkGoldenrod': array([0.7216, 0.5255, 0.0431]),
'rosy brown': array([0.7373, 0.5608, 0.5608]),
'RosyBrown': array([0.7373, 0.5608, 0.5608]),
'indian red': array([0.8039, 0.3608, 0.3608]),
'IndianRed': array([0.8039, 0.3608, 0.3608]),
'saddle brown': array([0.5451, 0.2706, 0.0745]),
'SaddleBrown': array([0.5451, 0.2706, 0.0745]),
'sienna': array([0.6275, 0.3216, 0.1765]),
'peru': array([0.8039, 0.5216, 0.2471]),
'burlywood': array([0.8706, 0.7216, 0.5294]),
'beige': array([0.9608, 0.9608, 0.8627]),
'wheat': array([0.9608, 0.8706, 0.7020]),
'sandy brown': array([0.9569, 0.6431, 0.3765]),
'SandyBrown': array([0.9569, 0.6431, 0.3765]),
'tan': array([0.8235, 0.7059, 0.5490]),
'chocolate': array([0.8235, 0.4118, 0.1176]),
'firebrick': array([0.6980, 0.1333, 0.1333]),
'brown': array([0.6471, 0.1647, 0.1647]),
'dark salmon': array([0.9137, 0.5882, 0.4784]),
'DarkSalmon': array([0.9137, 0.5882, 0.4784]),
'salmon': array([0.9804, 0.5020, 0.4471]),
'light salmon': array([1.0000, 0.6275, 0.4784]),
'LightSalmon': array([1.0000, 0.6275, 0.4784]),
'orange': array([1.0000, 0.6471, 0.0000]),
'dark orange': array([1.0000, 0.5490, 0.0000]),
'DarkOrange': array([1.0000, 0.5490, 0.0000]),
'coral': array([1.0000, 0.4980, 0.3137]),
'light coral': array([0.9412, 0.5020, 0.5020]),
'LightCoral': array([0.9412, 0.5020, 0.5020]),
'tomato': array([1.0000, 0.3882, 0.2784]),
'orange red': array([1.0000, 0.2706, 0.0000]),
'OrangeRed': array([1.0000, 0.2706, 0.0000]),
'red': array([1.0000, 0.0000, 0.0000]),
'hot pink': array([1.0000, 0.4118, 0.7059]),
'HotPink': array([1.0000, 0.4118, 0.7059]),
'deep pink': array([1.0000, 0.0784, 0.5765]),
'DeepPink': array([1.0000, 0.0784, 0.5765]),
'pink': array([1.0000, 0.7529, 0.7961]),
'light pink': array([1.0000, 0.7137, 0.7569]),
'LightPink': array([1.0000, 0.7137, 0.7569]),
'pale violet red': array([0.8588, 0.4392, 0.5765]),
'PaleVioletRed': array([0.8588, 0.4392, 0.5765]),
'maroon': array([0.6902, 0.1882, 0.3765]),
'medium violet red': array([0.7804, 0.0824, 0.5216]),
'MediumVioletRed': array([0.7804, 0.0824, 0.5216]),
'violet red': array([0.8157, 0.1255, 0.5647]),
'VioletRed': array([0.8157, 0.1255, 0.5647]),
'magenta': array([1.0000, 0.0000, 1.0000]),
'violet': array([0.9333, 0.5098, 0.9333]),
'plum': array([0.8667, 0.6275, 0.8667]),
'orchid': array([0.8549, 0.4392, 0.8392]),
'medium orchid': array([0.7294, 0.3333, 0.8275]),
'MediumOrchid': array([0.7294, 0.3333, 0.8275]),
'dark orchid': array([0.6000, 0.1961, 0.8000]),
'DarkOrchid': array([0.6000, 0.1961, 0.8000]),
'dark violet': array([0.5804, 0.0000, 0.8275]),
'DarkViolet': array([0.5804, 0.0000, 0.8275]),
'blue violet': array([0.5412, 0.1686, 0.8863]),
'BlueViolet': array([0.5412, 0.1686, 0.8863]),
'purple': array([0.6275, 0.1255, 0.9412]),
'medium purple': array([0.5765, 0.4392, 0.8588]),
'MediumPurple': array([0.5765, 0.4392, 0.8588]),
'thistle': array([0.8471, 0.7490, 0.8471]),
'snow1': array([1.0000, 0.9804, 0.9804]),
'snow2': array([0.9333, 0.9137, 0.9137]),
'snow3': array([0.8039, 0.7882, 0.7882]),
'snow4': array([0.5451, 0.5373, 0.5373]),
'seashell1': array([1.0000, 0.9608, 0.9333]),
'seashell2': array([0.9333, 0.8980, 0.8706]),
'seashell3': array([0.8039, 0.7725, 0.7490]),
'seashell4': array([0.5451, 0.5255, 0.5098]),
'AntiqueWhite1': array([1.0000, 0.9373, 0.8588]),
'AntiqueWhite2': array([0.9333, 0.8745, 0.8000]),
'AntiqueWhite3': array([0.8039, 0.7529, 0.6902]),
'AntiqueWhite4': array([0.5451, 0.5137, 0.4706]),
'bisque1': array([1.0000, 0.8941, 0.7686]),
'bisque2': array([0.9333, 0.8353, 0.7176]),
'bisque3': array([0.8039, 0.7176, 0.6196]),
'bisque4': array([0.5451, 0.4902, 0.4196]),
'PeachPuff1': array([1.0000, 0.8549, 0.7255]),
'PeachPuff2': array([0.9333, 0.7961, 0.6784]),
'PeachPuff3': array([0.8039, 0.6863, 0.5843]),
'PeachPuff4': array([0.5451, 0.4667, 0.3961]),
'NavajoWhite1': array([1.0000, 0.8706, 0.6784]),
'NavajoWhite2': array([0.9333, 0.8118, 0.6314]),
'NavajoWhite3': array([0.8039, 0.7020, 0.5451]),
'NavajoWhite4': array([0.5451, 0.4745, 0.3686]),
'LemonChiffon1': array([1.0000, 0.9804, 0.8039]),
'LemonChiffon2': array([0.9333, 0.9137, 0.7490]),
'LemonChiffon3': array([0.8039, 0.7882, 0.6471]),
'LemonChiffon4': array([0.5451, 0.5373, 0.4392]),
'cornsilk1': array([1.0000, 0.9725, 0.8627]),
'cornsilk2': array([0.9333, 0.9098, 0.8039]),
'cornsilk3': array([0.8039, 0.7843, 0.6941]),
'cornsilk4': array([0.5451, 0.5333, 0.4706]),
'ivory1': array([1.0000, 1.0000, 0.9412]),
'ivory2': array([0.9333, 0.9333, 0.8784]),
'ivory3': array([0.8039, 0.8039, 0.7569]),
'ivory4': array([0.5451, 0.5451, 0.5137]),
'honeydew1': array([0.9412, 1.0000, 0.9412]),
'honeydew2': array([0.8784, 0.9333, 0.8784]),
'honeydew3': array([0.7569, 0.8039, 0.7569]),
'honeydew4': array([0.5137, 0.5451, 0.5137]),
'LavenderBlush1': array([1.0000, 0.9412, 0.9608]),
'LavenderBlush2': array([0.9333, 0.8784, 0.8980]),
'LavenderBlush3': array([0.8039, 0.7569, 0.7725]),
'LavenderBlush4': array([0.5451, 0.5137, 0.5255]),
'MistyRose1': array([1.0000, 0.8941, 0.8824]),
'MistyRose2': array([0.9333, 0.8353, 0.8235]),
'MistyRose3': array([0.8039, 0.7176, 0.7098]),
'MistyRose4': array([0.5451, 0.4902, 0.4824]),
'azure1': array([0.9412, 1.0000, 1.0000]),
'azure2': array([0.8784, 0.9333, 0.9333]),
'azure3': array([0.7569, 0.8039, 0.8039]),
'azure4': array([0.5137, 0.5451, 0.5451]),
'SlateBlue1': array([0.5137, 0.4353, 1.0000]),
'SlateBlue2': array([0.4784, 0.4039, 0.9333]),
'SlateBlue3': array([0.4118, 0.3490, 0.8039]),
'SlateBlue4': array([0.2784, 0.2353, 0.5451]),
'RoyalBlue1': array([0.2824, 0.4627, 1.0000]),
'RoyalBlue2': array([0.2627, 0.4314, 0.9333]),
'RoyalBlue3': array([0.2275, 0.3725, 0.8039]),
'RoyalBlue4': array([0.1529, 0.2510, 0.5451]),
'blue1': array([0.0000, 0.0000, 1.0000]),
'blue2': array([0.0000, 0.0000, 0.9333]),
'blue3': array([0.0000, 0.0000, 0.8039]),
'blue4': array([0.0000, 0.0000, 0.5451]),
'DodgerBlue1': array([0.1176, 0.5647, 1.0000]),
'DodgerBlue2': array([0.1098, 0.5255, 0.9333]),
'DodgerBlue3': array([0.0941, 0.4549, 0.8039]),
'DodgerBlue4': array([0.0627, 0.3059, 0.5451]),
'SteelBlue1': array([0.3882, 0.7216, 1.0000]),
'SteelBlue2': array([0.3608, 0.6745, 0.9333]),
'SteelBlue3': array([0.3098, 0.5804, 0.8039]),
'SteelBlue4': array([0.2118, 0.3922, 0.5451]),
'DeepSkyBlue1': array([0.0000, 0.7490, 1.0000]),
'DeepSkyBlue2': array([0.0000, 0.6980, 0.9333]),
'DeepSkyBlue3': array([0.0000, 0.6039, 0.8039]),
'DeepSkyBlue4': array([0.0000, 0.4078, 0.5451]),
'SkyBlue1': array([0.5294, 0.8078, 1.0000]),
'SkyBlue2': array([0.4941, 0.7529, 0.9333]),
'SkyBlue3': array([0.4235, 0.6510, 0.8039]),
'SkyBlue4': array([0.2902, 0.4392, 0.5451]),
'LightSkyBlue1': array([0.6902, 0.8863, 1.0000]),
'LightSkyBlue2': array([0.6431, 0.8275, 0.9333]),
'LightSkyBlue3': array([0.5529, 0.7137, 0.8039]),
'LightSkyBlue4': array([0.3765, 0.4824, 0.5451]),
'SlateGray1': array([0.7765, 0.8863, 1.0000]),
'SlateGray2': array([0.7255, 0.8275, 0.9333]),
'SlateGray3': array([0.6235, 0.7137, 0.8039]),
'SlateGray4': array([0.4235, 0.4824, 0.5451]),
'LightSteelBlue1': array([0.7922, 0.8824, 1.0000]),
'LightSteelBlue2': array([0.7373, 0.8235, 0.9333]),
'LightSteelBlue3': array([0.6353, 0.7098, 0.8039]),
'LightSteelBlue4': array([0.4314, 0.4824, 0.5451]),
'LightBlue1': array([0.7490, 0.9373, 1.0000]),
'LightBlue2': array([0.6980, 0.8745, 0.9333]),
'LightBlue3': array([0.6039, 0.7529, 0.8039]),
'LightBlue4': array([0.4078, 0.5137, 0.5451]),
'LightCyan1': array([0.8784, 1.0000, 1.0000]),
'LightCyan2': array([0.8196, 0.9333, 0.9333]),
'LightCyan3': array([0.7059, 0.8039, 0.8039]),
'LightCyan4': array([0.4784, 0.5451, 0.5451]),
'PaleTurquoise1': array([0.7333, 1.0000, 1.0000]),
'PaleTurquoise2': array([0.6824, 0.9333, 0.9333]),
'PaleTurquoise3': array([0.5882, 0.8039, 0.8039]),
'PaleTurquoise4': array([0.4000, 0.5451, 0.5451]),
'CadetBlue1': array([0.5961, 0.9608, 1.0000]),
'CadetBlue2': array([0.5569, 0.8980, 0.9333]),
'CadetBlue3': array([0.4784, 0.7725, 0.8039]),
'CadetBlue4': array([0.3255, 0.5255, 0.5451]),
'turquoise1': array([0.0000, 0.9608, 1.0000]),
'turquoise2': array([0.0000, 0.8980, 0.9333]),
'turquoise3': array([0.0000, 0.7725, 0.8039]),
'turquoise4': array([0.0000, 0.5255, 0.5451]),
'cyan1': array([0.0000, 1.0000, 1.0000]),
'cyan2': array([0.0000, 0.9333, 0.9333]),
'cyan3': array([0.0000, 0.8039, 0.8039]),
'cyan4': array([0.0000, 0.5451, 0.5451]),
'DarkSlateGray1': array([0.5922, 1.0000, 1.0000]),
'DarkSlateGray2': array([0.5529, 0.9333, 0.9333]),
'DarkSlateGray3': array([0.4745, 0.8039, 0.8039]),
'DarkSlateGray4': array([0.3216, 0.5451, 0.5451]),
'aquamarine1': array([0.4980, 1.0000, 0.8314]),
'aquamarine2': array([0.4627, 0.9333, 0.7765]),
'aquamarine3': array([0.4000, 0.8039, 0.6667]),
'aquamarine4': array([0.2706, 0.5451, 0.4549]),
'DarkSeaGreen1': array([0.7569, 1.0000, 0.7569]),
'DarkSeaGreen2': array([0.7059, 0.9333, 0.7059]),
'DarkSeaGreen3': array([0.6078, 0.8039, 0.6078]),
'DarkSeaGreen4': array([0.4118, 0.5451, 0.4118]),
'SeaGreen1': array([0.3294, 1.0000, 0.6235]),
'SeaGreen2': array([0.3059, 0.9333, 0.5804]),
'SeaGreen3': array([0.2627, 0.8039, 0.5020]),
'SeaGreen4': array([0.1804, 0.5451, 0.3412]),
'PaleGreen1': array([0.6039, 1.0000, 0.6039]),
'PaleGreen2': array([0.5647, 0.9333, 0.5647]),
'PaleGreen3': array([0.4863, 0.8039, 0.4863]),
'PaleGreen4': array([0.3294, 0.5451, 0.3294]),
'SpringGreen1': array([0.0000, 1.0000, 0.4980]),
'SpringGreen2': array([0.0000, 0.9333, 0.4627]),
'SpringGreen3': array([0.0000, 0.8039, 0.4000]),
'SpringGreen4': array([0.0000, 0.5451, 0.2706]),
'green1': array([0.0000, 1.0000, 0.0000]),
'green2': array([0.0000, 0.9333, 0.0000]),
'green3': array([0.0000, 0.8039, 0.0000]),
'green4': array([0.0000, 0.5451, 0.0000]),
'chartreuse1': array([0.4980, 1.0000, 0.0000]),
'chartreuse2': array([0.4627, 0.9333, 0.0000]),
'chartreuse3': array([0.4000, 0.8039, 0.0000]),
'chartreuse4': array([0.2706, 0.5451, 0.0000]),
'OliveDrab1': array([0.7529, 1.0000, 0.2431]),
'OliveDrab2': array([0.7020, 0.9333, 0.2275]),
'OliveDrab3': array([0.6039, 0.8039, 0.1961]),
'OliveDrab4': array([0.4118, 0.5451, 0.1333]),
'DarkOliveGreen1': array([0.7922, 1.0000, 0.4392]),
'DarkOliveGreen2': array([0.7373, 0.9333, 0.4078]),
'DarkOliveGreen3': array([0.6353, 0.8039, 0.3529]),
'DarkOliveGreen4': array([0.4314, 0.5451, 0.2392]),
'khaki1': array([1.0000, 0.9647, 0.5608]),
'khaki2': array([0.9333, 0.9020, 0.5216]),
'khaki3': array([0.8039, 0.7765, 0.4510]),
'khaki4': array([0.5451, 0.5255, 0.3059]),
'LightGoldenrod1': array([1.0000, 0.9255, 0.5451]),
'LightGoldenrod2': array([0.9333, 0.8627, 0.5098]),
'LightGoldenrod3': array([0.8039, 0.7451, 0.4392]),
'LightGoldenrod4': array([0.5451, 0.5059, 0.2980]),
'LightYellow1': array([1.0000, 1.0000, 0.8784]),
'LightYellow2': array([0.9333, 0.9333, 0.8196]),
'LightYellow3': array([0.8039, 0.8039, 0.7059]),
'LightYellow4': array([0.5451, 0.5451, 0.4784]),
'yellow1': array([1.0000, 1.0000, 0.0000]),
'yellow2': array([0.9333, 0.9333, 0.0000]),
'yellow3': array([0.8039, 0.8039, 0.0000]),
'yellow4': array([0.5451, 0.5451, 0.0000]),
'gold1': array([1.0000, 0.8431, 0.0000]),
'gold2': array([0.9333, 0.7882, 0.0000]),
'gold3': array([0.8039, 0.6784, 0.0000]),
'gold4': array([0.5451, 0.4588, 0.0000]),
'goldenrod1': array([1.0000, 0.7569, 0.1451]),
'goldenrod2': array([0.9333, 0.7059, 0.1333]),
'goldenrod3': array([0.8039, 0.6078, 0.1137]),
'goldenrod4': array([0.5451, 0.4118, 0.0784]),
'DarkGoldenrod1': array([1.0000, 0.7255, 0.0588]),
'DarkGoldenrod2': array([0.9333, 0.6784, 0.0549]),
'DarkGoldenrod3': array([0.8039, 0.5843, 0.0471]),
'DarkGoldenrod4': array([0.5451, 0.3961, 0.0314]),
'RosyBrown1': array([1.0000, 0.7569, 0.7569]),
'RosyBrown2': array([0.9333, 0.7059, 0.7059]),
'RosyBrown3': array([0.8039, 0.6078, 0.6078]),
'RosyBrown4': array([0.5451, 0.4118, 0.4118]),
'IndianRed1': array([1.0000, 0.4157, 0.4157]),
'IndianRed2': array([0.9333, 0.3882, 0.3882]),
'IndianRed3': array([0.8039, 0.3333, 0.3333]),
'IndianRed4': array([0.5451, 0.2275, 0.2275]),
'sienna1': array([1.0000, 0.5098, 0.2784]),
'sienna2': array([0.9333, 0.4745, 0.2588]),
'sienna3': array([0.8039, 0.4078, 0.2235]),
'sienna4': array([0.5451, 0.2784, 0.1490]),
'burlywood1': array([1.0000, 0.8275, 0.6078]),
'burlywood2': array([0.9333, 0.7725, 0.5686]),
'burlywood3': array([0.8039, 0.6667, 0.4902]),
'burlywood4': array([0.5451, 0.4510, 0.3333]),
'wheat1': array([1.0000, 0.9059, 0.7294]),
'wheat2': array([0.9333, 0.8471, 0.6824]),
'wheat3': array([0.8039, 0.7294, 0.5882]),
'wheat4': array([0.5451, 0.4941, 0.4000]),
'tan1': array([1.0000, 0.6471, 0.3098]),
'tan2': array([0.9333, 0.6039, 0.2863]),
'tan3': array([0.8039, 0.5216, 0.2471]),
'tan4': array([0.5451, 0.3529, 0.1686]),
'chocolate1': array([1.0000, 0.4980, 0.1412]),
'chocolate2': array([0.9333, 0.4627, 0.1294]),
'chocolate3': array([0.8039, 0.4000, 0.1137]),
'chocolate4': array([0.5451, 0.2706, 0.0745]),
'firebrick1': array([1.0000, 0.1882, 0.1882]),
'firebrick2': array([0.9333, 0.1725, 0.1725]),
'firebrick3': array([0.8039, 0.1490, 0.1490]),
'firebrick4': array([0.5451, 0.1020, 0.1020]),
'brown1': array([1.0000, 0.2510, 0.2510]),
'brown2': array([0.9333, 0.2314, 0.2314]),
'brown3': array([0.8039, 0.2000, 0.2000]),
'brown4': array([0.5451, 0.1373, 0.1373]),
'salmon1': array([1.0000, 0.5490, 0.4118]),
'salmon2': array([0.9333, 0.5098, 0.3843]),
'salmon3': array([0.8039, 0.4392, 0.3294]),
'salmon4': array([0.5451, 0.2980, 0.2235]),
'LightSalmon1': array([1.0000, 0.6275, 0.4784]),
'LightSalmon2': array([0.9333, 0.5843, 0.4471]),
'LightSalmon3': array([0.8039, 0.5059, 0.3843]),
'LightSalmon4': array([0.5451, 0.3412, 0.2588]),
'orange1': array([1.0000, 0.6471, 0.0000]),
'orange2': array([0.9333, 0.6039, 0.0000]),
'orange3': array([0.8039, 0.5216, 0.0000]),
'orange4': array([0.5451, 0.3529, 0.0000]),
'DarkOrange1': array([1.0000, 0.4980, 0.0000]),
'DarkOrange2': array([0.9333, 0.4627, 0.0000]),
'DarkOrange3': array([0.8039, 0.4000, 0.0000]),
'DarkOrange4': array([0.5451, 0.2706, 0.0000]),
'coral1': array([1.0000, 0.4471, 0.3373]),
'coral2': array([0.9333, 0.4157, 0.3137]),
'coral3': array([0.8039, 0.3569, 0.2706]),
'coral4': array([0.5451, 0.2431, 0.1843]),
'tomato1': array([1.0000, 0.3882, 0.2784]),
'tomato2': array([0.9333, 0.3608, 0.2588]),
'tomato3': array([0.8039, 0.3098, 0.2235]),
'tomato4': array([0.5451, 0.2118, 0.1490]),
'OrangeRed1': array([1.0000, 0.2706, 0.0000]),
'OrangeRed2': array([0.9333, 0.2510, 0.0000]),
'OrangeRed3': array([0.8039, 0.2157, 0.0000]),
'OrangeRed4': array([0.5451, 0.1451, 0.0000]),
'red1': array([1.0000, 0.0000, 0.0000]),
'red2': array([0.9333, 0.0000, 0.0000]),
'red3': array([0.8039, 0.0000, 0.0000]),
'red4': array([0.5451, 0.0000, 0.0000]),
'DeepPink1': array([1.0000, 0.0784, 0.5765]),
'DeepPink2': array([0.9333, 0.0706, 0.5373]),
'DeepPink3': array([0.8039, 0.0627, 0.4627]),
'DeepPink4': array([0.5451, 0.0392, 0.3137]),
'HotPink1': array([1.0000, 0.4314, 0.7059]),
'HotPink2': array([0.9333, 0.4157, 0.6549]),
'HotPink3': array([0.8039, 0.3765, 0.5647]),
'HotPink4': array([0.5451, 0.2275, 0.3843]),
'pink1': array([1.0000, 0.7098, 0.7725]),
'pink2': array([0.9333, 0.6627, 0.7216]),
'pink3': array([0.8039, 0.5686, 0.6196]),
'pink4': array([0.5451, 0.3882, 0.4235]),
'LightPink1': array([1.0000, 0.6824, 0.7255]),
'LightPink2': array([0.9333, 0.6353, 0.6784]),
'LightPink3': array([0.8039, 0.5490, 0.5843]),
'LightPink4': array([0.5451, 0.3725, 0.3961]),
'PaleVioletRed1': array([1.0000, 0.5098, 0.6706]),
'PaleVioletRed2': array([0.9333, 0.4745, 0.6235]),
'PaleVioletRed3': array([0.8039, 0.4078, 0.5373]),
'PaleVioletRed4': array([0.5451, 0.2784, 0.3647]),
'maroon1': array([1.0000, 0.2039, 0.7020]),
'maroon2': array([0.9333, 0.1882, 0.6549]),
'maroon3': array([0.8039, 0.1608, 0.5647]),
'maroon4': array([0.5451, 0.1098, 0.3843]),
'VioletRed1': array([1.0000, 0.2431, 0.5882]),
'VioletRed2': array([0.9333, 0.2275, 0.5490]),
'VioletRed3': array([0.8039, 0.1961, 0.4706]),
'VioletRed4': array([0.5451, 0.1333, 0.3216]),
'magenta1': array([1.0000, 0.0000, 1.0000]),
'magenta2': array([0.9333, 0.0000, 0.9333]),
'magenta3': array([0.8039, 0.0000, 0.8039]),
'magenta4': array([0.5451, 0.0000, 0.5451]),
'orchid1': array([1.0000, 0.5137, 0.9804]),
'orchid2': array([0.9333, 0.4784, 0.9137]),
'orchid3': array([0.8039, 0.4118, 0.7882]),
'orchid4': array([0.5451, 0.2784, 0.5373]),
'plum1': array([1.0000, 0.7333, 1.0000]),
'plum2': array([0.9333, 0.6824, 0.9333]),
'plum3': array([0.8039, 0.5882, 0.8039]),
'plum4': array([0.5451, 0.4000, 0.5451]),
'MediumOrchid1': array([0.8784, 0.4000, 1.0000]),
'MediumOrchid2': array([0.8196, 0.3725, 0.9333]),
'MediumOrchid3': array([0.7059, 0.3216, 0.8039]),
'MediumOrchid4': array([0.4784, 0.2157, 0.5451]),
'DarkOrchid1': array([0.7490, 0.2431, 1.0000]),
'DarkOrchid2': array([0.6980, 0.2275, 0.9333]),
'DarkOrchid3': array([0.6039, 0.1961, 0.8039]),
'DarkOrchid4': array([0.4078, 0.1333, 0.5451]),
'purple1': array([0.6078, 0.1882, 1.0000]),
'purple2': array([0.5686, 0.1725, 0.9333]),
'purple3': array([0.4902, 0.1490, 0.8039]),
'purple4': array([0.3333, 0.1020, 0.5451]),
'MediumPurple1': array([0.6706, 0.5098, 1.0000]),
'MediumPurple2': array([0.6235, 0.4745, 0.9333]),
'MediumPurple3': array([0.5373, 0.4078, 0.8039]),
'MediumPurple4': array([0.3647, 0.2784, 0.5451]),
'thistle1': array([1.0000, 0.8824, 1.0000]),
'thistle2': array([0.9333, 0.8235, 0.9333]),
'thistle3': array([0.8039, 0.7098, 0.8039]),
'thistle4': array([0.5451, 0.4824, 0.5451]),
'gray0': 0.0000,
'grey0': 0.0000,
'gray1': 0.0118,
'grey1': 0.0118,
'gray2': 0.0196,
'grey2': 0.0196,
'gray3': 0.0314,
'grey3': 0.0314,
'gray4': 0.0392,
'grey4': 0.0392,
'gray5': 0.0510,
'grey5': 0.0510,
'gray6': 0.0588,
'grey6': 0.0588,
'gray7': 0.0706,
'grey7': 0.0706,
'gray8': 0.0784,
'grey8': 0.0784,
'gray9': 0.0902,
'grey9': 0.0902,
'gray10': 0.1020,
'grey10': 0.1020,
'gray11': 0.1098,
'grey11': 0.1098,
'gray12': 0.1216,
'grey12': 0.1216,
'gray13': 0.1294,
'grey13': 0.1294,
'gray14': 0.1412,
'grey14': 0.1412,
'gray15': 0.1490,
'grey15': 0.1490,
'gray16': 0.1608,
'grey16': 0.1608,
'gray17': 0.1686,
'grey17': 0.1686,
'gray18': 0.1804,
'grey18': 0.1804,
'gray19': 0.1882,
'grey19': 0.1882,
'gray20': 0.2000,
'grey20': 0.2000,
'gray21': 0.2118,
'grey21': 0.2118,
'gray22': 0.2196,
'grey22': 0.2196,
'gray23': 0.2314,
'grey23': 0.2314,
'gray24': 0.2392,
'grey24': 0.2392,
'gray25': 0.2510,
'grey25': 0.2510,
'gray26': 0.2588,
'grey26': 0.2588,
'gray27': 0.2706,
'grey27': 0.2706,
'gray28': 0.2784,
'grey28': 0.2784,
'gray29': 0.2902,
'grey29': 0.2902,
'gray30': 0.3020,
'grey30': 0.3020,
'gray31': 0.3098,
'grey31': 0.3098,
'gray32': 0.3216,
'grey32': 0.3216,
'gray33': 0.3294,
'grey33': 0.3294,
'gray34': 0.3412,
'grey34': 0.3412,
'gray35': 0.3490,
'grey35': 0.3490,
'gray36': 0.3608,
'grey36': 0.3608,
'gray37': 0.3686,
'grey37': 0.3686,
'gray38': 0.3804,
'grey38': 0.3804,
'gray39': 0.3882,
'grey39': 0.3882,
'gray40': 0.4000,
'grey40': 0.4000,
'gray41': 0.4118,
'grey41': 0.4118,
'gray42': 0.4196,
'grey42': 0.4196,
'gray43': 0.4314,
'grey43': 0.4314,
'gray44': 0.4392,
'grey44': 0.4392,
'gray45': 0.4510,
'grey45': 0.4510,
'gray46': 0.4588,
'grey46': 0.4588,
'gray47': 0.4706,
'grey47': 0.4706,
'gray48': 0.4784,
'grey48': 0.4784,
'gray49': 0.4902,
'grey49': 0.4902,
'gray50': 0.4980,
'grey50': 0.4980,
'gray51': 0.5098,
'grey51': 0.5098,
'gray52': 0.5216,
'grey52': 0.5216,
'gray53': 0.5294,
'grey53': 0.5294,
'gray54': 0.5412,
'grey54': 0.5412,
'gray55': 0.5490,
'grey55': 0.5490,
'gray56': 0.5608,
'grey56': 0.5608,
'gray57': 0.5686,
'grey57': 0.5686,
'gray58': 0.5804,
'grey58': 0.5804,
'gray59': 0.5882,
'grey59': 0.5882,
'gray60': 0.6000,
'grey60': 0.6000,
'gray61': 0.6118,
'grey61': 0.6118,
'gray62': 0.6196,
'grey62': 0.6196,
'gray63': 0.6314,
'grey63': 0.6314,
'gray64': 0.6392,
'grey64': 0.6392,
'gray65': 0.6510,
'grey65': 0.6510,
'gray66': 0.6588,
'grey66': 0.6588,
'gray67': 0.6706,
'grey67': 0.6706,
'gray68': 0.6784,
'grey68': 0.6784,
'gray69': 0.6902,
'grey69': 0.6902,
'gray70': 0.7020,
'grey70': 0.7020,
'gray71': 0.7098,
'grey71': 0.7098,
'gray72': 0.7216,
'grey72': 0.7216,
'gray73': 0.7294,
'grey73': 0.7294,
'gray74': 0.7412,
'grey74': 0.7412,
'gray75': 0.7490,
'grey75': 0.7490,
'gray76': 0.7608,
'grey76': 0.7608,
'gray77': 0.7686,
'grey77': 0.7686,
'gray78': 0.7804,
'grey78': 0.7804,
'gray79': 0.7882,
'grey79': 0.7882,
'gray80': 0.8000,
'grey80': 0.8000,
'gray81': 0.8118,
'grey81': 0.8118,
'gray82': 0.8196,
'grey82': 0.8196,
'gray83': 0.8314,
'grey83': 0.8314,
'gray84': 0.8392,
'grey84': 0.8392,
'gray85': 0.8510,
'grey85': 0.8510,
'gray86': 0.8588,
'grey86': 0.8588,
'gray87': 0.8706,
'grey87': 0.8706,
'gray88': 0.8784,
'grey88': 0.8784,
'gray89': 0.8902,
'grey89': 0.8902,
'gray90': 0.8980,
'grey90': 0.8980,
'gray91': 0.9098,
'grey91': 0.9098,
'gray92': 0.9216,
'grey92': 0.9216,
'gray93': 0.9294,
'grey93': 0.9294,
'gray94': 0.9412,
'grey94': 0.9412,
'gray95': 0.9490,
'grey95': 0.9490,
'gray96': 0.9608,
'grey96': 0.9608,
'gray97': 0.9686,
'grey97': 0.9686,
'gray98': 0.9804,
'grey98': 0.9804,
'gray99': 0.9882,
'grey99': 0.9882,
'gray100': 1.0000,
'grey100': 1.0000,
'dark grey': 0.6627,
'DarkGrey': 0.6627,
'dark gray': 0.6627,
'DarkGray': 0.6627,
'dark blue': array([0.0000, 0.0000, 0.5451]),
'DarkBlue': array([0.0000, 0.0000, 0.5451]),
'dark cyan': array([0.0000, 0.5451, 0.5451]),
'DarkCyan': array([0.0000, 0.5451, 0.5451]),
'dark magenta': array([0.5451, 0.0000, 0.5451]),
'DarkMagenta': array([0.5451, 0.0000, 0.5451]),
'dark red': array([0.5451, 0.0000, 0.0000]),
'DarkRed': array([0.5451, 0.0000, 0.0000]),
'light green': array([0.5647, 0.9333, 0.5647]),
'LightGreen': array([0.5647, 0.9333, 0.5647]),
}
del array # Prevent namespace pollution.
def _MakeColorTable(outfile = None, infile = "/usr/lib/X11/rgb.txt"):
import string, sys
if type(infile) == type("string"):
infile = open(infile)
if outfile is None:
outfile = sys.stdout
if type(outfile) == type("string"):
outfile = open(outfile, "w")
outfile.write("ColorTable = {\n");
for line in infile.readlines():
line = string.strip(line)
if not line or (line[0] in "%#!;"):
continue
# This is not a comment or an empty line
words = string.split(line)
name = "'" + string.join(words[3:], " ") + "':"
if words[0] == words[1] and words[0] == words[2]:
# Gray color
clr = float(words[0])/255.0
outfile.write(" %-20s %6.4f,\n" % (name,clr))
else:
clr = (name, float(words[0])/255.0, float(words[1])/255.0,
float(words[2])/255.0)
outfile.write(" %-20s array([%6.4f, %6.4f, %6.4f]),\n" % clr)
outfile.write("}\n")
outfile.flush()
python-ase-3.6.0.2515/ase/md/ 0000755 0001754 0001754 00000000000 11757245036 014362 5 ustar askhl askhl python-ase-3.6.0.2515/ase/md/logger.py 0000644 0001754 0001754 00000006261 11551006462 016206 0 ustar askhl askhl """Logging for molecular dynamics."""
import weakref
import sys
import ase.units as units
# ase.parallel imported in __init__
class MDLogger:
"""Class for logging molecular dynamics simulations.
Parameters:
dyn: The dynamics. Only a weak reference is kept.
atoms: The atoms.
logfile: File name or open file, "-" meaning standart output.
stress=False: Include stress in log.
peratom=False: Write energies per atom.
mode="a": How the file is opened if logfile is a filename.
"""
def __init__(self, dyn, atoms, logfile, header=True, stress=False,
peratom=False, mode="a"):
import ase.parallel
if ase.parallel.rank > 0:
logfile="/dev/null" # Only log on master
if hasattr(dyn, "get_time"):
self.dyn = weakref.proxy(dyn)
else:
self.dyn = None
self.atoms = atoms
self.natoms = atoms.get_number_of_atoms()
if logfile == "-":
self.logfile = sys.stdout
self.ownlogfile = False
elif hasattr(logfile, "write"):
self.logfile = logfile
self.ownlogfile = False
else:
self.logfile = open(logfile, mode)
self.ownlogfile = True
self.stress = stress
self.peratom = peratom
if self.dyn is not None:
self.hdr = "%-8s " % ("Time[ps]",)
self.fmt = "%-8.2f "
else:
self.hdr = ""
self.fmt = ""
if self.peratom:
self.hdr += "%12s %12s %12s %6s" % ("Etot/N[eV]", "Epot/N[eV]",
"Ekin/N[eV]", "T[K]")
self.fmt += "%12.4f %12.4f %12.4f %6.1f"
else:
self.hdr += "%12s %12s %12s %6s" % ("Etot[eV]", "Epot[eV]",
"Ekin[eV]", "T[K]")
# Choose a sensible number of decimals
if self.natoms <= 10:
digits = 4
elif self.natoms <= 100:
digits = 3
elif self.natoms <= 1000:
digits = 2
else:
digits = 1
self.fmt += 3*("%%12.%df " % (digits,)) + " %6.1f"
if self.stress:
self.hdr += " ---------------- stress [GPa] -----------------"
self.fmt += 6*" %10.3f"
self.fmt += "\n"
if header:
self.logfile.write(self.hdr+"\n")
def __del__(self):
self.close()
def close(self):
if self.ownlogfile:
self.logfile.close()
def __call__(self):
epot = self.atoms.get_potential_energy()
ekin = self.atoms.get_kinetic_energy()
temp = ekin / (1.5 * units.kB * self.natoms)
if self.peratom:
epot /= self.natoms
ekin /= self.natoms
if self.dyn is not None:
t = self.dyn.get_time() / (1000*units.fs)
dat = (t,)
else:
dat = ()
dat += (epot+ekin, epot, ekin, temp)
if self.stress:
dat += tuple(self.atoms.get_stress() / units.GPa)
self.logfile.write(self.fmt % dat)
self.logfile.flush()
python-ase-3.6.0.2515/ase/md/__init__.py 0000644 0001754 0001754 00000000214 11361570336 016463 0 ustar askhl askhl """Molecular Dynamics."""
from ase.md.logger import MDLogger
from ase.md.verlet import VelocityVerlet
from ase.md.langevin import Langevin
python-ase-3.6.0.2515/ase/md/velocitydistribution.py 0000644 0001754 0001754 00000004453 11710343512 021223 0 ustar askhl askhl # VelocityDistributions.py -- set up a velocity distribution
"""Module for setting up e.g. Maxwell-Boltzmann velocity distributions.
Currently, only one function is defined, MaxwellBoltzmannDistribution,
which sets the momenta of a list of atoms according to a
Maxwell-Boltzmann distribution at a given temperature.
"""
import sys
import numpy as np
from ase.parallel import world
def _maxwellboltzmanndistribution(masses, temp, communicator=world):
# For parallel GPAW simulations, the random velocities should be
# distributed. Uses gpaw world communicator as default, but allow
# option of specifying other communicator (for ensemble runs)
xi = np.random.standard_normal((len(masses), 3))
communicator.broadcast(xi, 0)
momenta = xi * np.sqrt(masses * temp)[:, np.newaxis]
return momenta
def MaxwellBoltzmannDistribution(atoms, temp, communicator=world):
"""Sets the momenta to a Maxwell-Boltzmann distribution."""
momenta = _maxwellboltzmanndistribution(atoms.get_masses(), temp,
communicator)
atoms.set_momenta(momenta)
def Stationary(atoms):
"Sets the center-of-mass momentum to zero."
p = atoms.get_momenta()
p0 = np.sum(p, 0)
# We should add a constant velocity, not momentum, to the atoms
m = atoms.get_masses()
mtot = np.sum(m)
v0 = p0 / mtot
p -= v0 * m[:, np.newaxis]
atoms.set_momenta(p)
def ZeroRotation(atoms):
"Sets the total angular momentum to zero by counteracting rigid rotations."
# Find the principal moments of inertia and principal axes basis vectors
Ip, basis = atoms.get_moments_of_inertia(vectors=True)
# Calculate the total angular momentum and transform to principal basis
Lp = np.dot(basis, atoms.get_angular_momentum())
# Calculate the rotation velocity vector in the principal basis, avoiding
# zero division, and transform it back to the cartesian coordinate system
omega = np.dot(np.linalg.inv(basis), np.select([Ip > 0], [Lp / Ip]))
# We subtract a rigid rotation corresponding to this rotation vector
com = atoms.get_center_of_mass()
positions = atoms.get_positions()
positions -= com # translate center of mass to origin
velocities = atoms.get_velocities()
atoms.set_velocities(velocities - np.cross(omega, positions))
python-ase-3.6.0.2515/ase/md/md.py 0000644 0001754 0001754 00000002424 11556111170 015322 0 ustar askhl askhl """Molecular Dynamics."""
import warnings
import numpy as np
from ase.optimize.optimize import Dynamics
from ase.data import atomic_masses
from ase.md.logger import MDLogger
class MolecularDynamics(Dynamics):
"""Base-class for all MD classes."""
def __init__(self, atoms, timestep, trajectory, logfile=None,
loginterval=1):
Dynamics.__init__(self, atoms, logfile=None, trajectory=trajectory)
self.dt = timestep
self.masses = self.atoms.get_masses()
if 0 in self.masses:
warnings.warn('Zero mass encountered in atoms; this will '
'likely lead to errors if the massless atoms '
'are unconstrained.')
self.masses.shape = (-1, 1)
if logfile:
self.attach(MDLogger(dyn=self, atoms=atoms, logfile=logfile),
interval=loginterval)
def run(self, steps=50):
"""Integrate equation of motion."""
f = self.atoms.get_forces()
if not self.atoms.has('momenta'):
self.atoms.set_momenta(np.zeros_like(f))
for step in xrange(steps):
f = self.step(f)
self.nsteps += 1
self.call_observers()
def get_time(self):
return self.nsteps * self.dt
python-ase-3.6.0.2515/ase/md/npt.py 0000644 0001754 0001754 00000077634 11600331247 015541 0 ustar askhl askhl '''Constant pressure/stress and temperature dynamics.
Combined Nose-Hoover and Parrinello-Rahman dynamics, creating an NPT
(or N,stress,T) ensemble.
The method is the one proposed by Melchionna et al. [1] and later
modified by Melchionna [2]. The differential equations are integrated
using a centered difference method [3].
1. S. Melchionna, G. Ciccotti and B. L. Holian, "Hoover NPT dynamics
for systems varying in shape and size", Molecular Physics 78, p. 533
(1993).
2. S. Melchionna, "Constrained systems and statistical distribution",
Physical Review E, 61, p. 6165 (2000).
3. B. L. Holian, A. J. De Groot, W. G. Hoover, and C. G. Hoover,
"Time-reversible equilibrium and nonequilibrium isothermal-isobaric
simulations with centered-difference Stoermer algorithms.", Physical
Review A, 41, p. 4552 (1990).
'''
__docformat__ = 'reStructuredText'
from numpy import *
import sys
import weakref
from ase.md.md import MolecularDynamics
#from ASE.Trajectories.NetCDFTrajectory import NetCDFTrajectory
# Delayed imports: If the trajectory object is reading a special ASAP version
# of HooverNPT, that class is imported from Asap.Dynamics.NPTDynamics.
class NPT(MolecularDynamics):
'''Constant pressure/stress and temperature dynamics.
Combined Nose-Hoover and Parrinello-Rahman dynamics, creating an
NPT (or N,stress,T) ensemble.
The method is the one proposed by Melchionna et al. [1] and later
modified by Melchionna [2]. The differential equations are integrated
using a centered difference method [3]. See also NPTdynamics.tex
The dynamics object is called with the following parameters:
atoms
The list of atoms.
dt
The timestep in units matching eV, A, u.
temperature
The desired temperature in eV.
externalstress
The external stress in eV/A^3. Either a symmetric
3x3 tensor, a 6-vector representing the same, or a
scalar representing the pressure. Note that the
stress is positive in tension whereas the pressure is
positive in compression: giving a scalar p is
equivalent to giving the tensor (-p, -p, -p, 0, 0, 0).
ttime
Characteristic timescale of the thermostat.
Set to None to disable the thermostat.
pfactor
A constant in the barostat differential equation. If
a characteristic barostat timescale of ptime is
desired, set pfactor to ptime^2 * B (where B is the
Bulk Modulus). Set to None to disable the barostat.
Typical metallic bulk moduli are of the order of
100 GPa or 0.6 eV/A^3.
mask=None
Optional argument. A tuple of three integers (0 or 1),
indicating if the system can change size along the
three Cartesian axes. Set to (1,1,1) or None to allow
a fully flexible computational box. Set to (1,1,0)
to disallow elongations along the z-axis etc.
Useful parameter values:
* The same timestep can be used as in Verlet dynamics, i.e. 5 fs is fine
for bulk copper.
* The ttime and pfactor are quite critical[4], too small values may
cause instabilites and/or wrong fluctuations in T / p. Too
large values cause an oscillation which is slow to die. Good
values for the characteristic times seem to be 25 fs for ttime,
and 75 fs for ptime (used to calculate pfactor), at least for
bulk copper with 15000-200000 atoms. But this is not well
tested, it is IMPORTANT to monitor the temperature and
stress/pressure fluctuations.
It has the following methods:
__call__(n)
Perform n timesteps.
initialize()
Estimates the dynamic variables for time=-1 to start
the algorithm. This is automatically called before
the first timestep.
set_stress()
Set the external stress. Use with care. It is
preferable to set the right value when creating the
object.
set_mask()
Change the mask. Use with care, as you may "freeze"
a fluctuation in the strain rate.
get_gibbs_free_energy()
Gibbs free energy is supposed to be preserved by this
dynamics. This is mainly intended as a diagnostic
tool.
References:
1) S. Melchionna, G. Ciccotti and B. L. Holian, Molecular
Physics 78, p. 533 (1993).
2) S. Melchionna, Physical
Review E 61, p. 6165 (2000).
3) B. L. Holian, A. J. De Groot, W. G. Hoover, and C. G. Hoover,
Physical Review A 41, p. 4552 (1990).
4) F. D. Di Tolla and M. Ronchetti, Physical
Review E 48, p. 1726 (1993).
'''
classname = "NPT" # Used by the trajectory.
def __init__(self, atoms,
timestep, temperature, externalstress, ttime, pfactor,
mask=None, trajectory=None, logfile=None, loginterval=1):
MolecularDynamics.__init__(self, atoms, timestep, trajectory,
logfile, loginterval)
#self.atoms = atoms
#self.timestep = timestep
self.zero_center_of_mass_momentum(verbose=1)
self.temperature = temperature
self.set_stress(externalstress)
self.set_mask(mask)
self.eta = zeros((3,3), float)
self.zeta = 0.0
self.zeta_integrated = 0.0
self.initialized = 0
self.ttime = ttime
self.pfactor_given = pfactor
self._calculateconstants()
self.timeelapsed = 0.0
self.frac_traceless = 1
def set_temperature(self, temperature):
self.temperature = temperature
self._calculateconstants()
def set_stress(self, stress):
"""Set the applied stress.
Must be a symmetric 3x3 tensor, a 6-vector representing a symmetric
3x3 tensor, or a number representing the pressure.
"""
if type(stress) == type(1.0) or type(stress) == type(1):
stress = array((-stress, -stress, -stress, 0.0, 0.0, 0.0))
elif stress.shape == (3,3):
if not self._issymmetric(stress):
raise ValueError, "The external stress must be a symmetric tensor."
stress = array((stress[0,0], stress[1,1], stress[2,2], stress[1,2],
stress[0,2], stress[0,1]))
elif stress.shape != (6,):
raise ValueError, "The external stress has the wrong shape."
self.externalstress = stress
def set_mask(self, mask):
"""Set the mask indicating dynamic elements of the computational box.
If set to None, all elements may change. If set to a 3-vector
of ones and zeros, elements which are zero specify directions
along which the size of the computational box cannot change.
For example, if mask = {1,1,0} the length of the system along
the z-axis cannot change, although xz and yz shear is still
possible. To disable shear globally, set the mode to diagonal
(not yet implemented).
"""
if mask is None:
mask = ones((3,))
if not hasattr(mask, "shape"):
mask = array(mask)
if mask.shape != (3,) and mask.shape != (3,3):
raise "The mask has the wrong shape (must be a 3-vector or 3x3 matrix)"
else:
mask = not_equal(mask, 0) # Make sure it is 0/1
if mask.shape == (3,):
self.mask = outer(mask, mask)
else:
self.mask = mask
def set_fraction_traceless(self, fracTraceless):
"""set what fraction of the traceless part of the force
on eta is kept.
By setting this to zero, the volume may change but the shape may not.
"""
self.frac_traceless = fracTraceless
def get_strain_rate(self):
"Get the strain rate as an upper-triangular 3x3 matrix"
return array(self.eta, copy=1)
def set_strain_rate(self, rate):
"Set the strain rate. Must be an upper triangular 3x3 matrix."
if not (rate.shape == (3,3) and self._isuppertriangular(rate)):
raise ValueError, "Strain rate must be an upper triangular matrix."
self.eta = rate
if self.initialized:
# Recalculate h_past and eta_past so they match the current value.
self._initialize_eta_h()
def get_time(self):
"Get the elapsed time."
return self.timeelapsed
def run(self, steps):
"""Perform a number of time steps."""
if not self.initialized:
self.initialize()
else:
if self.have_the_atoms_been_changed():
raise NotImplementedError, "You have modified the atoms since the last timestep."
for i in xrange(steps):
self.step()
self.nsteps += 1
self.call_observers()
def have_the_atoms_been_changed(self):
"Checks if the user has modified the positions or momenta of the atoms"
limit = 1e-10
h = self._getbox()
if max(abs((h - self.h).ravel())) > limit:
self._warning("The computational box has been modified.")
return 1
expected_r = dot(self.q + 0.5, h)
err = max(abs((expected_r - self.atoms.get_positions()).ravel()))
if err > limit:
self._warning("The atomic positions have been modified: "+ str(err))
return 1
return 0
def step(self):
"""Perform a single time step.
Assumes that the forces and stresses are up to date, and that
the positions and momenta have not been changed since last
timestep.
"""
## Assumes the following variables are OK
# q_past, q, q_future, p, eta, eta_past, zeta, zeta_past, h, h_past
#
# q corresponds to the current positions
# p must be equal to self.atoms.GetCartesianMomenta()
# h must be equal to self.atoms.GetUnitCell()
#
#print "Making a timestep"
dt = self.dt
h_future = self.h_past + 2*dt * dot(self.h, self.eta)
if self.pfactor_given is None:
deltaeta = zeros(6, float)
else:
stress = self.stresscalculator()
deltaeta = -2*dt * (self.pfact * linalg.det(self.h)
* (stress - self.externalstress))
if self.frac_traceless == 1:
eta_future = self.eta_past + self.mask * self._makeuppertriangular(deltaeta)
else:
trace_part, traceless_part = self._separatetrace(self._makeuppertriangular(deltaeta))
eta_future = self.eta_past + trace_part + self.frac_traceless * traceless_part
deltazeta = 2*dt*self.tfact * (self.atoms.get_kinetic_energy()
- self.desiredEkin)
zeta_future = self.zeta_past + deltazeta
# Advance time
#print "Max change in scaled positions:", max(abs(self.q_future.flat - self.q.flat))
#print "Max change in basis set", max(abs((h_future - self.h).flat))
self.timeelapsed += dt
self.h_past = self.h
self.h = h_future
self.inv_h = linalg.inv(self.h)
# Do not throw away the q arrays, they are "magical" on parallel
# simulations (the contents migrate along with the atoms).
(self.q_past, self.q, self.q_future) = (self.q, self.q_future,
self.q_past)
self._setbox_and_positions(self.h,self.q)
self.eta_past = self.eta
self.eta = eta_future
self.zeta_past = self.zeta
self.zeta = zeta_future
self._synchronize() # for parallel simulations.
self.zeta_integrated += dt * self.zeta
force = self.forcecalculator()
# The periodic boundary conditions may have moved the atoms.
self.post_pbc_fix(fixfuture=0)
self._calculate_q_future(force)
self.atoms.set_momenta(dot(self.q_future-self.q_past, self.h/(2*dt)) *
self._getmasses())
#self.stresscalculator()
def forcecalculator(self):
return self.atoms.get_forces()
def stresscalculator(self):
return self.atoms.get_stress()
def initialize(self):
"""Initialize the dynamics.
The dynamics requires positions etc for the two last times to
do a timestep, so the algorithm is not self-starting. This
method performs a 'backwards' timestep to generate a
configuration before the current.
"""
#print "Initializing the NPT dynamics."
dt = self.dt
atoms = self.atoms
self.h = self._getbox()
if not self._isuppertriangular(self.h):
print "I am", self
print "self.h:"
print self.h
print "Min:", min((self.h[1,0], self.h[2,0], self.h[2,1]))
print "Max:", max((self.h[1,0], self.h[2,0], self.h[2,1]))
raise NotImplementedError, "Can (so far) only operate on lists of atoms where the computational box is an upper triangular matrix."
self.inv_h = linalg.inv(self.h)
# The contents of the q arrays should migrate in parallel simulations.
self._make_special_q_arrays()
self.q[:] = dot(self.atoms.get_positions(),
self.inv_h) - 0.5
# zeta and eta were set in __init__
self._initialize_eta_h()
deltazeta = dt * self.tfact * (atoms.get_kinetic_energy() -
self.desiredEkin)
self.zeta_past = self.zeta - deltazeta
self._calculate_q_past_and_future()
self.initialized = 1
def get_gibbs_free_energy(self):
"""Return the Gibb's free energy, which is supposed to be conserved.
Requires that the energies of the atoms are up to date.
This is mainly intended as a diagnostic tool. If called before the
first timestep, Initialize will be called.
"""
if not self.initialized:
self.initialize()
n = self._getnatoms()
#tretaTeta = sum(diagonal(matrixmultiply(transpose(self.eta),
# self.eta)))
contractedeta = sum((self.eta*self.eta).ravel())
gibbs = (self.atoms.get_potential_energy() +
self.atoms.get_kinetic_energy()
- sum(self.externalstress[0:3]) * linalg.det(self.h) / 3.0)
if self.ttime is not None:
gibbs += (1.5 * n * self.temperature * (self.ttime * self.zeta)**2
+ 3 * self.temperature * (n-1) * self.zeta_integrated)
else:
assert self.zeta == 0.0
if self.pfactor_given is not None:
gibbs += 0.5 / self.pfact * contractedeta
else:
assert contractedeta == 0.0
return gibbs
def get_center_of_mass_momentum(self):
"Get the center of mass momentum."
return self.atoms.get_momenta().sum(0)
def zero_center_of_mass_momentum(self, verbose=0):
"Set the center of mass momentum to zero."
cm = self.get_center_of_mass_momentum()
abscm = sqrt(sum(cm*cm))
if verbose and abscm > 1e-4:
self._warning(self.classname+": Setting the center-of-mass momentum to zero (was %.6g %.6g %.6g)" % tuple(cm))
self.atoms.set_momenta(self.atoms.get_momenta()
- cm / self._getnatoms())
def post_pbc_fix(self, fixfuture=1):
"""Correct for atoms moved by the boundary conditions.
If the fixfuture argument is 1 (the default), q_future is also
corrected. This is not necessary when post_pbc_fix() is called from
within Timestep(), but must be done when the user calls post_pbc_fix
(for example if a CNA calculation may have triggered a migration).
"""
q = dot(self.atoms.get_positions(),
self.inv_h) - 0.5
delta_q = floor(0.5 + (q - self.q))
self.q += delta_q
self.q_past += delta_q
if fixfuture:
self.q_future += delta_q
def attach_atoms(self, atoms):
"""Assign atoms to a restored dynamics object.
This function must be called to set the atoms immediately after the
dynamics object has been read from a trajectory.
"""
try:
self.atoms
except AttributeError:
pass
else:
raise RuntimeError, "Cannot call attach_atoms on a dynamics which already has atoms."
MolecularDynamics.__init__(self, atoms, self.dt)
####self.atoms = atoms
limit = 1e-6
h = self._getbox()
if max(abs((h - self.h).ravel())) > limit:
raise RuntimeError, "The unit cell of the atoms does not match the unit cell stored in the file."
self.inv_h = linalg.inv(self.h)
self._make_special_q_arrays()
self.q[:] = dot(self.atoms.get_positions(),
self.inv_h) - 0.5
self._calculate_q_past_and_future()
self.initialized = 1
def attach(self, function, interval=1, *args, **kwargs):
"""Attach callback function or trajectory.
At every *interval* steps, call *function* with arguments
*args* and keyword arguments *kwargs*.
If *function* is a trajectory object, its write() method is
attached, but if *function* is a BundleTrajectory (or another
trajectory supporting set_extra_data(), said method is first
used to instruct the trajectory to also save internal
data from the NPT dynamics object.
"""
if hasattr(function, "set_extra_data"):
# We are attaching a BundleTrajectory or similar
function.set_extra_data("npt_init",
WeakMethodWrapper(self, "get_init_data"),
once=True)
function.set_extra_data("npt_dynamics",
WeakMethodWrapper(self, "get_data"))
MolecularDynamics.attach(self, function, interval, *args, **kwargs)
def get_init_data(self):
"Return the data needed to initialize a new NPT dynamics."
return {'dt': self.dt,
'temperature': self.temperature,
'desiredEkin': self.desiredEkin,
'externalstress': self.externalstress,
'mask': self.mask,
'ttime': self.ttime,
'tfact': self.tfact,
'pfactor_given': self.pfactor_given,
'pfact': self.pfact,
'frac_traceless': self.frac_traceless}
def get_data(self):
"Return data needed to restore the state."
return {'eta': self.eta,
'eta_past': self.eta_past,
'zeta': self.zeta,
'zeta_past': self.zeta_past,
'zeta_integrated': self.zeta_integrated,
'h': self.h,
'h_past': self.h_past,
'timeelapsed': self.timeelapsed}
@classmethod
def read_from_trajectory(cls, trajectory, frame=-1, atoms=None):
"""Read dynamics and atoms from trajectory (Class method).
Simultaneously reads the atoms and the dynamics from a BundleTrajectory,
including the internal data of the NPT dynamics object (automatically
saved when attaching a BundleTrajectory to an NPT object).
Arguments::
trajectory
The filename or an open BundleTrajectory object.
frame (optional)
Which frame to read. Default: the last.
atoms (optional, internal use only)
Pre-read atoms. Do not use.
"""
if isinstance(trajectory, str):
if trajectory.endswith('/'):
trajectory = trajectory[:-1]
if trajectory.endswith('.bundle'):
from ase.io.bundletrajectory import BundleTrajectory
trajectory = BundleTrajectory(trajectory)
else:
raise ValueError("Cannot open '%': unsupported file format" % trajectory)
# trajectory is now a BundleTrajectory object (or compatible)
if atoms is None:
atoms = trajectory[frame]
init_data = trajectory.read_extra_data('npt_init', 0)
frame_data = trajectory.read_extra_data('npt_dynamics', frame)
dyn = cls(atoms, timestep=init_data['dt'],
temperature=init_data['temperature'],
externalstress=init_data['externalstress'],
ttime=init_data['ttime'],
pfactor=init_data['pfactor_given'],
mask=init_data['mask'])
dyn.desiredEkin = init_data['desiredEkin']
dyn.tfact = init_data['tfact']
dyn.pfact = init_data['pfact']
dyn.frac_traceless = init_data['frac_traceless']
for k, v in frame_data.items():
setattr(dyn, k, v)
return (dyn, atoms)
def _getbox(self):
"Get the computational box."
return self.atoms.get_cell()
def _getmasses(self):
"Get the masses as an Nx1 array."
return reshape(self.atoms.get_masses(), (-1,1))
# def _getcartesianpositions(self):
# "Get the cartesian positions of the atoms"
# return self.atoms.get_positions()
# def _getmomenta(self):
# "Get the (cartesian) momenta of the atoms"
# return self.atoms.GetCartesianMomenta()
# def _getforces(self):
# "Get the (cartesian) forces of the atoms"
# return self.atoms.GetCartesianForces()
# def _setmomenta(self, momenta):
# "Set the (cartesian) momenta of the atoms"
# self.atoms.SetCartesianMomenta(momenta)
def _separatetrace(self, mat):
"""return two matrices, one proportional to the identity
the other traceless, which sum to the given matrix
"""
tracePart = ((mat[0][0] + mat[1][1] + mat[2][2]) / 3.) * identity(3)
return tracePart, mat - tracePart
# A number of convenient helper methods
def _warning(self, text):
"Emit a warning."
sys.stderr.write("WARNING: "+text+"\n")
sys.stderr.flush()
def _calculate_q_future(self, force):
"Calculate future q. Needed in Timestep and Initialization."
dt = self.dt
id3 = identity(3)
alpha = (dt * dt) * dot(force / self._getmasses(),
self.inv_h)
beta = dt * dot(self.h, dot(self.eta + 0.5 * self.zeta * id3,
self.inv_h))
inv_b = linalg.inv(beta + id3)
self.q_future[:] = dot(2*self.q + dot(self.q_past, beta - id3) + alpha,
inv_b)
def _calculate_q_past_and_future(self):
def ekin(p, m = self.atoms.get_masses()):
p2 = sum(p*p, -1)
return 0.5 * sum(p2 / m) / len(m)
p0 = self.atoms.get_momenta()
m = self._getmasses()
e0 = ekin(p0)
p = array(p0, copy=1)
dt = self.dt
for i in range(2):
self.q_past[:] = self.q - dt * dot(p / m, self.inv_h)
self._calculate_q_future(self.atoms.get_forces())
p = dot(self.q_future - self.q_past, self.h/(2*dt)) * m
e = ekin(p)
if e < 1e-5:
# The kinetic energy and momenta are virtually zero
return
p = (p0 - p) + p0
def _initialize_eta_h(self):
self.h_past = self.h - self.dt * dot(self.h, self.eta)
if self.pfactor_given is None:
deltaeta = zeros(6, float)
else:
deltaeta = (-self.dt * self.pfact * linalg.det(self.h)
* (self.atoms.get_stress() - self.externalstress))
if self.frac_traceless == 1:
self.eta_past = self.eta - self.mask * self._makeuppertriangular(deltaeta)
else:
trace_part, traceless_part = self._separatetrace(self._makeuppertriangular(deltaeta))
self.eta_past = self.eta - trace_part - self.frac_traceless * traceless_part
def _makeuppertriangular(self, sixvector):
"Make an upper triangular matrix from a 6-vector."
return array(((sixvector[0], sixvector[5], sixvector[4]),
(0, sixvector[1], sixvector[3]),
(0, 0, sixvector[2])))
def _isuppertriangular(self, m):
"Check that a matrix is on upper triangular form."
return m[1,0] == m[2,0] == m[2,1] == 0.0
def _calculateconstants(self):
"(Re)calculate some constants when pfactor, ttime or temperature have been changed."
n = self._getnatoms()
if self.ttime is None:
self.tfact = 0.0
else:
self.tfact = 2.0 / (3 * n * self.temperature *
self.ttime * self.ttime)
if self.pfactor_given is None:
self.pfact = 0.0
else:
self.pfact = 1.0 / (self.pfactor_given
* linalg.det(self._getbox()))
#self.pfact = 1.0/(n * self.temperature * self.ptime * self.ptime)
self.desiredEkin = 1.5 * (n - 1) * self.temperature
def _setbox_and_positions(self, h, q):
"""Set the computational box and the positions."""
self.atoms.set_cell(h, scale_atoms=True)
r = dot(q + 0.5, h)
self.atoms.set_positions(r)
# A few helper methods, which have been placed in separate methods
# so they can be replaced in the parallel version.
def _synchronize(self):
"""Synchronizes eta, h and zeta on all processors in a parallel simulation.
In a parallel simulation, eta, h and zeta are communicated
from the master to all slaves, to prevent numerical noise from
causing them to diverge.
In a serial simulation, do nothing.
"""
pass # This is a serial simulation object. Do nothing.
def _getnatoms(self):
"""Get the number of atoms.
In a parallel simulation, this is the total number of atoms on all
processors.
"""
return len(self.atoms)
def _make_special_q_arrays(self):
"""Make the arrays used to store data about the atoms.
In a parallel simulation, these are migrating arrays. In a
serial simulation they are ordinary Numeric arrays.
"""
natoms = len(self.atoms)
self.q = zeros((natoms,3), float)
self.q_past = zeros((natoms,3), float)
self.q_future = zeros((natoms,3), float)
class WeakMethodWrapper:
"""A weak reference to a method.
Create an object storing a weak reference to an instance and
the name of the method to call. When called, calls the method.
Just storing a weak reference to a bound method would not work,
as the bound method object would go away immediately.
"""
def __init__(self, obj, method):
self.obj = weakref.proxy(obj)
self.method = method
def __call__(self, *args, **kwargs):
m = getattr(self.obj, self.method)
return m(*args, **kwargs)
# class _HooverNPTTrajectory:
# """A Trajectory-like object storing data in a HooverNPT object."""
# def InitForWrite(self):
# """Does initialization related to write mode."""
# self.CreateDimension('unlim', None)
# self.nc.history = 'ASE NPT trajectory'
# self.nc.version = '0.1'
# self.nc.classname = self.atoms.classname
# self.unlim = 0
# self.nc.lengthunit = units.GetLengthUnit()
# self.nc.energyunit = units.GetEnergyUnit()
# self.conversion = (1, 1)
# def InitForWriteOrAppend(self):
# """Does initialization related to write and append mode.
# Either InitForWrite or InitForReadOrAppend will have been
# called before calling this method.
# """
# names = copy.copy(self.known_names)
# if self.atoms.ttime is None:
# del names['ttime']
# if self.atoms.pfactor_given is None:
# del names['pfactor_given']
# for d in names.keys():
# def getdata(atoms=self.atoms, name=d):
# return getattr(atoms, name)
# self.Add(d, data = getdata)
# known_names = {
# # name shape typecode once units
# # ----------------------------------------------------------------
# 'dt': ((), Float, True, (1, -0.5)),
# 'temperature': ((), Float, True, (0, 1)),
# 'desiredEkin': ((), Float, True, (0, 1)),
# 'externalstress': ((6,), Float, True, (-3, 1)),
# 'mask': ((3, 3), Float, True, (0, 0)),
# 'ttime': ((), Float, True, (1, -0.5)),
# 'tfact': ((), Float, True, (-2, 0)),
# 'pfactor_given': ((), Float, True, (-1, 0)),
# 'pfact': ((), Float, True, (-2, 0)),
# 'frac_traceless': ((), Float, True, (0, 0)),
# 'eta': ((3, 3), Float, False, (-1, 0.5)),
# 'eta_past': ((3, 3), Float, False, (-1, 0.5)),
# 'zeta': ((), Float, False, (-1, 0.5)),
# 'zeta_past': ((), Float, False, (-1, 0.5)),
# 'zeta_integrated': ((), Float, False, (0, 0)),
# 'h': ((3, 3), Float, False, (1, 0)),
# 'h_past': ((3, 3), Float, False, (1, 0)),
# 'timeelapsed': ((), Float, False, (1, -0.5))
# }
# # This trajectory does not store a list of atoms
# def GetListOfAtoms(self, frame=None):
# raise AttributeError, "GetListOfAtoms makes no sense in a HooverNPTTrajectory"
# # Instead, we store a dynamics
# def GetDynamics(self, frame=None):
# """Get a HooverNPT Dynamics object.
# If a frame number is not given, the current frame is used.
# The variant of the object (ASE HooverNPT, ASAP Serial/Parallel NPT)
# will be the same as the stored object.
# After getting the dynamics, the atoms should be attached with the
# dynamics.attach_atoms(atoms) method.
# """
# # Bypass calling the normal constructor
# class Dummy:
# pass
# dyn = Dummy()
# dyn.__class__ = self.getClass(self.nc.classname)
# vars = self.nc.variables
# for q in self.known_names.keys():
# if vars.has_key(q):
# once = self.known_names[q][2]
# if once:
# setattr(dyn, q, vars[q].getValue())
# else:
# setattr(dyn, q, vars[q][frame])
# return dyn
# def getClass(self, classname):
# "Internal function: turns a class name into a class object."
# if self.nc.classname == "HooverNPT":
# return HooverNPT
# else:
# raise RuntimeError, ("Cannot create a dynamics of type "
# + self.nc.classname)
# class HooverNPTTrajectory(_HooverNPTTrajectory,NetCDFTrajectory):
# """A Trajectory-like object storing data in a HooverNPT object."""
# def __init__(self, filename, dynamics=None, mode=None, interval=1):
# """Open the NetCDF file.
# If there is no ``dynamics`` argument, then the file is opened
# in read mode - otherwise, write or append mode is used. The
# ``interval`` argument determines how often the configurations
# are written to file."""
# # Call the original constructor, but passing the dynamics instead of
# # the atoms.
# if dynamics is not None:
# # Prevents a circular reference when the trajectory is attached
# # to the dynamics it observes.
# dynamics = weakref.proxy(dynamics)
# NetCDFTrajectory.__init__(self, filename,
# atoms=dynamics,
# mode=mode, interval=interval)
python-ase-3.6.0.2515/ase/md/nvtberendsen.py 0000644 0001754 0001754 00000006211 11564503727 017431 0 ustar askhl askhl """Berendsen NVT dynamics class."""
import sys
import numpy as np
from ase.md.md import MolecularDynamics
from ase.parallel import world
class NVTBerendsen(MolecularDynamics):
"""Berendsen (constant N, V, T) molecular dynamics.
Usage: NVTBerendsen(atoms, timestep, temperature, taut, fixcm)
atoms
The list of atoms.
timestep
The time step.
temperature
The desired temperature, in Kelvin.
taut
Time constant for Berendsen temperature coupling.
fixcm
If True, the position and momentum of the center of mass is
kept unperturbed. Default: True.
"""
def __init__(self, atoms, timestep, temperature, taut, fixcm=True,
trajectory=None, logfile=None, loginterval=1,
communicator=world):
MolecularDynamics.__init__(self, atoms, timestep, trajectory,
logfile, loginterval)
self.taut = taut
self.temperature = temperature
self.fixcm = fixcm # will the center of mass be held fixed?
self.communicator = communicator
def set_taut(self, taut):
self.taut = taut
def get_taut(self):
return self.taut
def set_temperature(self, temperature):
self.temperature = temperature
def get_temperature(self):
return self.temperature
def set_timestep(self, timestep):
self.dt = timestep
def get_timestep(self):
return self.dt
def scale_velocities(self):
""" Do the NVT Berendsen velocity scaling """
tautscl = self.dt / self.taut
old_temperature = self.atoms.get_temperature()
scl_temperature = np.sqrt(1.0+ (self.temperature/ old_temperature- 1.0)
*tautscl)
#limit the velocity scaling to reasonable values
if scl_temperature > 1.1:
scl_temperature = 1.1
if scl_temperature < 0.9:
scl_temperature = 0.9
atoms = self.atoms
p = self.atoms.get_momenta()
p = scl_temperature * p
self.atoms.set_momenta(p)
return
def step(self, f):
""" move one timestep forward using Berenden NVT molecular dynamics."""
self.scale_velocities()
#one step velocity verlet
atoms = self.atoms
p = self.atoms.get_momenta()
p += 0.5 * self.dt * f
if self.fixcm:
# calculate the center of mass
# momentum and subtract it
psum = p.sum(axis=0) / float(len(p))
p = p - psum
self.atoms.set_positions(self.atoms.get_positions() +
self.dt * p / self.atoms.get_masses()[:,np.newaxis])
# We need to store the momenta on the atoms before calculating
# the forces, as in a parallel Asap calculation atoms may
# migrate during force calculations, and the momenta need to
# migrate along with the atoms. For the same reason, we
# cannot use self.masses in the line above.
self.atoms.set_momenta(p)
f = self.atoms.get_forces()
atoms.set_momenta(self.atoms.get_momenta() + 0.5 * self.dt * f)
return f
python-ase-3.6.0.2515/ase/md/nptberendsen.py 0000644 0001754 0001754 00000013344 11551006462 017416 0 ustar askhl askhl """Berendsen NPT dynamics class."""
import numpy as np
#from ase.md import MolecularDynamics
from ase.md.nvtberendsen import NVTBerendsen
import ase.units as units
#import math
class NPTBerendsen(NVTBerendsen):
"""Berendsen (constant N, P, T) molecular dynamics.
This dynamics scale the velocities and volumes to maintain a constant
pressure and temperature. The shape of the simulation cell is not
altered, if that is desired use Inhomogenous_NPTBerendsen.
Usage: NPTBerendsen(atoms, timestep, temperature, taut, pressure, taup)
atoms
The list of atoms.
timestep
The time step.
temperature
The desired temperature, in Kelvin.
taut
Time constant for Berendsen temperature coupling.
fixcm
If True, the position and momentum of the center of mass is
kept unperturbed. Default: True.
pressure
The desired pressure, in bar (1 bar = 1e5 Pa).
taup
Time constant for Berendsen pressure coupling.
compressibility
The compressibility of the material, water 4.57E-5 bar-1, in bar-1
"""
def __init__(self, atoms, timestep, temperature, taut=0.5e3*units.fs,
pressure = 1.01325, taup=1e3*units.fs,
compressibility=4.57e-5, fixcm=True,
trajectory=None, logfile=None, loginterval=1):
NVTBerendsen.__init__(self, atoms, timestep, temperature, taut, fixcm,
trajectory,
logfile, loginterval)
self.taup = taup
self.pressure = pressure
self.compressibility = compressibility
def set_taup(self, taut):
self.taut = taut
def get_taup(self):
return self.taut
def set_pressure(self, pressure):
self.pressure = pressure
def get_pressure(self):
return self.pressure
def set_compressibility(self, compressibility):
self.compressibility = compressibility
def get_compressibility(self):
return self.compressibility
def set_timestep(self, timestep):
self.dt = timestep
def get_timestep(self):
return self.dt
def scale_positions_and_cell(self):
""" Do the Berendsen pressure coupling,
scale the atom positon and the simulation cell."""
taupscl = self.dt / self.taup
stress = self.atoms.get_stress()
old_pressure = self.atoms.get_isotropic_pressure(stress)
scl_pressure = 1.0 - taupscl * self.compressibility / 3.0 * \
(self.pressure - old_pressure)
#print "old_pressure", old_pressure
#print "volume scaling by:", scl_pressure
cell = self.atoms.get_cell()
cell = scl_pressure * cell
self.atoms.set_cell(cell, scale_atoms=True)
def step(self, f):
""" move one timestep forward using Berenden NPT molecular dynamics."""
NVTBerendsen.scale_velocities(self)
self.scale_positions_and_cell()
#one step velocity verlet
atoms = self.atoms
p = self.atoms.get_momenta()
p += 0.5 * self.dt * f
if self.fixcm:
# calculate the center of mass
# momentum and subtract it
psum = p.sum(axis=0) / float(len(p))
p = p - psum
self.atoms.set_positions(self.atoms.get_positions() +
self.dt * p / self.atoms.get_masses()[:,np.newaxis])
# We need to store the momenta on the atoms before calculating
# the forces, as in a parallel Asap calculation atoms may
# migrate during force calculations, and the momenta need to
# migrate along with the atoms. For the same reason, we
# cannot use self.masses in the line above.
self.atoms.set_momenta(p)
f = self.atoms.get_forces()
atoms.set_momenta(self.atoms.get_momenta() + 0.5 * self.dt * f)
return f
class Inhomogenous_NPTBerendsen(NPTBerendsen):
"""Berendsen (constant N, P, T) molecular dynamics.
This dynamics scale the velocities and volumes to maintain a constant
pressure and temperature. The size of the unit cell is allowed to change
independently in the three directions, but the angles remain constant.
Usage: NPTBerendsen(atoms, timestep, temperature, taut, pressure, taup)
atoms
The list of atoms.
timestep
The time step.
temperature
The desired temperature, in Kelvin.
taut
Time constant for Berendsen temperature coupling.
fixcm
If True, the position and momentum of the center of mass is
kept unperturbed. Default: True.
pressure
The desired pressure, in bar (1 bar = 1e5 Pa).
taup
Time constant for Berendsen pressure coupling.
compressibility
The compressibility of the material, water 4.57E-5 bar-1, in bar-1
"""
def scale_positions_and_cell(self):
""" Do the Berendsen pressure coupling,
scale the atom positon and the simulation cell."""
taupscl = self.dt * self.compressibility / self.taup / 3.0
stress = - self.atoms.get_stress() * 1e-5 / units.Pascal
if stress.shape == (6,):
stress = stress[:3]
elif stress.shape == (3,3):
stress = [stress[i][i] for i in range(3)]
else:
raise ValueError("Cannot use a stress tensor of shape " + str(stress.shape))
scl_pressurex = 1.0 - taupscl * (self.pressure - stress[0])
scl_pressurey = 1.0 - taupscl * (self.pressure - stress[1])
scl_pressurez = 1.0 - taupscl * (self.pressure - stress[2])
cell = self.atoms.get_cell()
cell = np.array([scl_pressurex * cell[0],scl_pressurey * cell[1],scl_pressurez * cell[2]])
self.atoms.set_cell(cell, scale_atoms=True)
python-ase-3.6.0.2515/ase/md/verlet.py 0000644 0001754 0001754 00000002020 11441375152 016220 0 ustar askhl askhl import numpy as np
from ase.md.md import MolecularDynamics
class VelocityVerlet(MolecularDynamics):
def __init__(self, atoms, dt, trajectory=None, logfile=None,
loginterval=1):
MolecularDynamics.__init__(self, atoms, dt, trajectory, logfile,
loginterval)
def step(self, f):
p = self.atoms.get_momenta()
p += 0.5 * self.dt * f
self.atoms.set_positions(self.atoms.get_positions() +
self.dt * p / self.atoms.get_masses()[:,np.newaxis])
# We need to store the momenta on the atoms before calculating
# the forces, as in a parallel Asap calculation atoms may
# migrate during force calculations, and the momenta need to
# migrate along with the atoms. For the same reason, we
# cannot use self.masses in the line above.
self.atoms.set_momenta(p)
f = self.atoms.get_forces()
self.atoms.set_momenta(self.atoms.get_momenta() + 0.5 * self.dt * f)
return f
python-ase-3.6.0.2515/ase/md/langevin.py 0000644 0001754 0001754 00000007751 11564503727 016551 0 ustar askhl askhl """Langevin dynamics class."""
import sys
import numpy as np
from numpy.random import standard_normal
from ase.md.md import MolecularDynamics
from ase.parallel import world
class Langevin(MolecularDynamics):
"""Langevin (constant N, V, T) molecular dynamics.
Usage: Langevin(atoms, dt, temperature, friction)
atoms
The list of atoms.
dt
The time step.
temperature
The desired temperature, in energy units.
friction
A friction coefficient, typically 1e-4 to 1e-2.
fixcm
If True, the position and momentum of the center of mass is
kept unperturbed. Default: True.
The temperature and friction are normally scalars, but in principle one
quantity per atom could be specified by giving an array.
This dynamics accesses the atoms using Cartesian coordinates."""
def __init__(self, atoms, timestep, temperature, friction, fixcm=True,
trajectory=None, logfile=None, loginterval=1,
communicator=world):
MolecularDynamics.__init__(self, atoms, timestep, trajectory,
logfile, loginterval)
self.temp = temperature
self.frict = friction
self.fixcm = fixcm # will the center of mass be held fixed?
self.communicator = communicator
self.updatevars()
def set_temperature(self, temperature):
self.temp = temperature
self.updatevars()
def set_friction(self, friction):
self.frict = friction
self.updatevars()
def set_timestep(self, timestep):
self.dt = timestep
self.updatevars()
def updatevars(self):
dt = self.dt
# If the friction is an array some other constants must be arrays too.
self._localfrict = hasattr(self.frict, 'shape')
lt = self.frict * dt
masses = self.masses
sdpos = dt * np.sqrt(self.temp / masses * (2.0/3.0 - 0.5 * lt) * lt)
sdpos.shape = (-1, 1)
sdmom = np.sqrt(self.temp * masses * 2.0 * (1.0 - lt) * lt)
sdmom.shape = (-1, 1)
pmcor = np.sqrt(3.0)/2.0 * (1.0 - 0.125 * lt)
cnst = np.sqrt((1.0 - pmcor) * (1.0 + pmcor))
act0 = 1.0 - lt + 0.5 * lt * lt
act1 = (1.0 - 0.5 * lt + (1.0/6.0) * lt * lt)
act2 = 0.5 - (1.0/6.0) * lt + (1.0/24.0) * lt * lt
c1 = act1 * dt / masses
c1.shape = (-1, 1)
c2 = act2 * dt * dt / masses
c2.shape = (-1, 1)
c3 = (act1 - act2) * dt
c4 = act2 * dt
del act1, act2
if self._localfrict:
# If the friction is an array, so are these
act0.shape = (-1, 1)
c3.shape = (-1, 1)
c4.shape = (-1, 1)
pmcor.shape = (-1, 1)
cnst.shape = (-1, 1)
self.sdpos = sdpos
self.sdmom = sdmom
self.c1 = c1
self.c2 = c2
self.act0 = act0
self.c3 = c3
self.c4 = c4
self.pmcor = pmcor
self.cnst = cnst
def step(self, f):
atoms = self.atoms
p = self.atoms.get_momenta()
random1 = standard_normal(size=(len(atoms), 3))
random2 = standard_normal(size=(len(atoms), 3))
self.communicator.broadcast(random1, 0)
self.communicator.broadcast(random2, 0)
rrnd = self.sdpos * random1
prnd = (self.sdmom * self.pmcor * random1 +
self.sdmom * self.cnst * random2)
if self.fixcm:
rrnd = rrnd - np.sum(rrnd, 0) / len(atoms)
prnd = prnd - np.sum(prnd, 0) / len(atoms)
n = len(atoms)
rrnd *= np.sqrt(n / (n - 1.0))
prnd *= np.sqrt(n / (n - 1.0))
atoms.set_positions(atoms.get_positions() +
self.c1 * p +
self.c2 * f + rrnd)
p *= self.act0
p += self.c3 * f + prnd
atoms.set_momenta(p)
f = atoms.get_forces()
atoms.set_momenta(p + self.c4 * f)
return f
python-ase-3.6.0.2515/ase/dimer.py 0000644 0001754 0001754 00000131100 11526201367 015421 0 ustar askhl askhl """Minimum mode follower for finding saddle points in an unbiased way.
There is, currently, only one implemented method: The Dimer method.
"""
import sys
import time
import warnings
import numpy as np
from ase.optimize.optimize import Optimizer
from math import cos, sin, atan, tan, degrees, pi, sqrt
from ase.parallel import rank, size, world
from ase.calculators.singlepoint import SinglePointCalculator
# Handy vector methods
norm = np.linalg.norm
def normalize(vector):
"""Create a unit vector along *vector*"""
return vector / norm(vector)
def parallel_vector(vector, base):
"""Extract the components of *vector* that are parallel to *base*"""
return np.vdot(vector, base) * base
def perpendicular_vector(vector, base):
"""Remove the components of *vector* that are parallel to *base*"""
return vector - parallel_vector(vector, base)
def rotate_vectors(v1i, v2i, angle):
"""Rotate vectors *v1i* and *v2i* by *angle*"""
cAng = cos(angle)
sAng = sin(angle)
v1o = v1i * cAng + v2i * sAng
v2o = v2i * cAng - v1i * sAng
# Ensure the length of the input and output vectors is equal
return normalize(v1o) * norm(v1i), normalize(v2o) * norm(v2i)
class DimerEigenmodeSearch:
"""An implementation of the Dimer's minimum eigenvalue mode search.
This class implements the rotational part of the dimer saddle point
searching method.
Parameters:
atoms : MinModeAtoms object
MinModeAtoms is an extension to the Atoms object, which includes
information about the lowest eigenvalue mode.
control : DimerControl object
Contains the parameters necessary for the eigenmode search.
If no control object is supplied a default DimerControl
will be created and used.
basis : list of xyz-values
Eigenmode. Must be an ndarray of shape (n, 3).
It is possible to constrain the eigenmodes to be orthogonal
to this given eigenmode.
Notes:
The code is inspired, with permission, by code written by the Henkelman
group, which can be found at http://theory.cm.utexas.edu/vtsttools/code/
References:
.. [1] Henkelman and Jonsson, JCP 111, 7010 (1999)
.. [2] Olsen, Kroes, Henkelman, Arnaldsson, and Jonsson, JCP 121,
9776 (2004).
.. [3] Heyden, Bell, and Keil, JCP 123, 224101 (2005).
.. [4] Kastner and Sherwood, JCP 128, 014106 (2008).
"""
def __init__(self, atoms, control=None, eigenmode=None, basis=None, \
**kwargs):
if hasattr(atoms, 'get_eigenmode'):
self.atoms = atoms
else:
e = 'The atoms object must be a MinModeAtoms object'
raise TypeError(e)
self.basis = basis
if eigenmode is None:
self.eigenmode = self.atoms.get_eigenmode()
else:
self.eigenmode = eigenmode
if control is None:
self.control = DimerControl(**kwargs)
w = 'Missing control object in ' + self.__class__.__name__ + \
'. Using default: DimerControl()'
warnings.warn(w, UserWarning)
if self.control.logfile is not None:
self.control.logfile.write('DIM:WARN: ' + w + '\n')
self.control.logfile.flush()
else:
self.control = control
# kwargs must be empty if a control object is supplied
for key in kwargs:
e = '__init__() got an unexpected keyword argument \'%s\'' % \
(key)
raise TypeError(e)
self.dR = self.control.get_parameter('dimer_separation')
self.logfile = self.control.get_logfile()
def converge_to_eigenmode(self):
"""Perform an eigenmode search."""
self.set_up_for_eigenmode_search()
stoprot = False
# Load the relevant parameters from control
f_rot_min = self.control.get_parameter('f_rot_min')
f_rot_max = self.control.get_parameter('f_rot_max')
trial_angle = self.control.get_parameter('trial_angle')
max_num_rot = self.control.get_parameter('max_num_rot')
extrapolate = self.control.get_parameter('extrapolate_forces')
while not stoprot:
if self.forces1E == None:
self.update_virtual_forces()
else:
self.update_virtual_forces(extrapolated_forces = True)
self.forces1A = self.forces1
self.update_curvature()
f_rot_A = self.get_rotational_force()
# Pre rotation stop criteria
if norm(f_rot_A) <= f_rot_min:
self.log(f_rot_A, None)
stoprot = True
else:
n_A = self.eigenmode
rot_unit_A = normalize(f_rot_A)
# Get the curvature and its derivative
c0 = self.get_curvature()
c0d = np.vdot((self.forces2 - self.forces1), rot_unit_A) / \
self.dR
# Trial rotation (no need to store the curvature)
# NYI variable trial angles from [3]
n_B, rot_unit_B = rotate_vectors(n_A, rot_unit_A, trial_angle)
self.eigenmode = n_B
self.update_virtual_forces()
self.forces1B = self.forces1
# Get the curvature's derivative
c1d = np.vdot((self.forces2 - self.forces1), rot_unit_B) / \
self.dR
# Calculate the Fourier coefficients
a1 = c0d * cos(2 * trial_angle) - c1d / \
(2 * sin(2 * trial_angle))
b1 = 0.5 * c0d
a0 = 2 * (c0 - a1)
# Estimate the rotational angle
rotangle = atan(b1 / a1) / 2.0
# Make sure that you didn't find a maximum
cmin = a0 / 2.0 + a1 * cos(2 * rotangle) + \
b1 * sin(2 * rotangle)
if c0 < cmin:
rotangle += pi / 2.0
# Rotate into the (hopefully) lowest eigenmode
# NYI Conjugate gradient rotation
n_min, dummy = rotate_vectors(n_A, rot_unit_A, rotangle)
self.update_eigenmode(n_min)
# Store the curvature estimate instead of the old curvature
self.update_curvature(cmin)
self.log(f_rot_A, rotangle)
# Force extrapolation scheme from [4]
if extrapolate:
self.forces1E = sin(trial_angle - rotangle) / \
sin(trial_angle) * self.forces1A + sin(rotangle) / \
sin(trial_angle) * self.forces1B + \
(1 - cos(rotangle) - sin(rotangle) * \
tan(trial_angle / 2.0)) * self.forces0
else:
self.forces1E = None
# Post rotation stop criteria
if not stoprot:
if self.control.get_counter('rotcount') >= max_num_rot:
stoprot = True
elif norm(f_rot_A) <= f_rot_max:
stoprot = True
def log(self, f_rot_A, angle):
"""Log each rotational step."""
# NYI Log for the trial angle
if self.logfile is not None:
if angle:
l = 'DIM:ROT: %7d %9d %9.4f %9.4f %9.4f\n' % \
(self.control.get_counter('optcount'),
self.control.get_counter('rotcount'),
self.get_curvature(), degrees(angle), norm(f_rot_A))
else:
l = 'DIM:ROT: %7d %9d %9.4f %9s %9.4f\n' % \
(self.control.get_counter('optcount'),
self.control.get_counter('rotcount'),
self.get_curvature(), '---------', norm(f_rot_A))
self.logfile.write(l)
self.logfile.flush()
def get_rotational_force(self):
"""Calculate the rotational force that acts on the dimer."""
rot_force = perpendicular_vector((self.forces1 - self.forces2),
self.eigenmode) / (2.0 * self.dR)
if self.basis is not None:
if len(self.basis) == len(self.atoms) and len(self.basis[0]) == \
3 and isinstance(self.basis[0][0], float):
rot_force = perpendicular_vector(rot_force, self.basis)
else:
for base in self.basis:
rot_force = perpendicular_vector(rot_force, base)
return rot_force
def update_curvature(self, curv = None):
"""Update the curvature in the MinModeAtoms object."""
if curv:
self.curvature = curv
else:
self.curvature = np.vdot((self.forces2 - self.forces1),
self.eigenmode) / (2.0 * self.dR)
def update_eigenmode(self, eigenmode):
"""Update the eigenmode in the MinModeAtoms object."""
self.eigenmode = eigenmode
self.update_virtual_positions()
self.control.increment_counter('rotcount')
def get_eigenmode(self):
"""Returns the current eigenmode."""
return self.eigenmode
def get_curvature(self):
"""Returns the curvature along the current eigenmode."""
return self.curvature
def get_control(self):
"""Return the control object."""
return self.control
def update_center_forces(self):
"""Get the forces at the center of the dimer."""
self.atoms.set_positions(self.pos0)
self.forces0 = self.atoms.get_forces(real = True)
self.energy0 = self.atoms.get_potential_energy()
def update_virtual_forces(self, extrapolated_forces = False):
"""Get the forces at the endpoints of the dimer."""
self.update_virtual_positions()
# Estimate / Calculate the forces at pos1
if extrapolated_forces:
self.forces1 = self.forces1E.copy()
else:
self.forces1 = self.atoms.get_forces(real = True, pos = self.pos1)
# Estimate / Calculate the forces at pos2
if self.control.get_parameter('use_central_forces'):
self.forces2 = 2 * self.forces0 - self.forces1
else:
self.forces2 = self.atoms.get_forces(real = True, pos = self.pos2)
def update_virtual_positions(self):
"""Update the end point positions."""
self.pos1 = self.pos0 + self.eigenmode * self.dR
self.pos2 = self.pos0 - self.eigenmode * self.dR
def set_up_for_eigenmode_search(self):
"""Before eigenmode search, prepare for rotation."""
self.pos0 = self.atoms.get_positions()
self.update_center_forces()
self.update_virtual_positions()
self.control.reset_counter('rotcount')
self.forces1E = None
def set_up_for_optimization_step(self):
"""At the end of rotation, prepare for displacement of the dimer."""
self.atoms.set_positions(self.pos0)
self.forces1E = None
class MinModeControl:
"""A parent class for controlling minimum mode saddle point searches.
Method specific control classes inherit this one. The only thing
inheriting classes need to implement are the log() method and
the *parameters* class variable with default values for ALL
parameters needed by the method in question.
When instantiating control classes default parameter values can
be overwritten.
"""
parameters = {}
def __init__(self, logfile = '-', eigenmode_logfile=None, **kwargs):
# Overwrite the defaults with the input parameters given
for key in kwargs:
if not key in self.parameters.keys():
e = 'Invalid parameter >>%s<< with value >>%s<< in %s' % \
(key, str(kwargs[key]), self.__class__.__name__)
raise ValueError(e)
else:
self.set_parameter(key, kwargs[key], log = False)
# Initialize the log files
self.initialize_logfiles(logfile, eigenmode_logfile)
# Initialize the counters
self.counters = {'forcecalls': 0, 'rotcount': 0, 'optcount': 0}
self.log()
def initialize_logfiles(self, logfile=None, eigenmode_logfile=None):
"""Set up the log files."""
# Set up the regular logfile
if rank != 0:
logfile = None
elif isinstance(logfile, str):
if logfile == '-':
logfile = sys.stdout
else:
logfile = open(logfile, 'a')
self.logfile = logfile
# Set up the eigenmode logfile
if eigenmode_logfile:
if rank != 0:
eigenmode_logfile = None
elif isinstance(eigenmode_logfile, str):
if eigenmode_logfile == '-':
eigenmode_logfile = sys.stdout
else:
eigenmode_logfile = open(eigenmode_logfile, 'a')
self.eigenmode_logfile = eigenmode_logfile
def log(self, parameter=None):
"""Log the parameters of the eigenmode search."""
pass
def set_parameter(self, parameter, value, log=True):
"""Change a parameter's value."""
if not parameter in self.parameters.keys():
e = 'Invalid parameter >>%s<< with value >>%s<<' % \
(parameter, str(value))
raise ValueError(e)
self.parameters[parameter] = value
if log:
self.log(parameter)
def get_parameter(self, parameter):
"""Returns the value of a parameter."""
if not parameter in self.parameters.keys():
e = 'Invalid parameter >>%s<<' % \
(parameter)
raise ValueError(e)
return self.parameters[parameter]
def get_logfile(self):
"""Returns the log file."""
return self.logfile
def get_eigenmode_logfile(self):
"""Returns the eigenmode log file."""
return self.eigenmode_logfile
def get_counter(self, counter):
"""Returns a given counter."""
return self.counters[counter]
def increment_counter(self, counter):
"""Increment a given counter."""
self.counters[counter] += 1
def reset_counter(self, counter):
"""Reset a given counter."""
self.counters[counter] = 0
def reset_all_counters(self):
"""Reset all counters."""
for key in self.counters.keys():
self.counters[key] = 0
class DimerControl(MinModeControl):
"""A class that takes care of the parameters needed for a Dimer search.
Parameters:
eigenmode_method: str
The name of the eigenmode search method.
f_rot_min: float
Size of the rotational force under which no rotation will be
performed.
f_rot_max: float
Size of the rotational force under which only one rotation will be
performed.
max_num_rot: int
Maximum number of rotations per optimizer step.
trial_angle: float
Trial angle for the finite difference estimate of the rotational
angle in radians.
trial_trans_step: float
Trial step size for the MinModeTranslate optimizer.
maximum_translation: float
Maximum step size and forced step size when the curvature is still
positive for the MinModeTranslate optimizer.
cg_translation: bool
Conjugate Gradient for the MinModeTranslate optimizer.
use_central_forces: bool
Only calculate the forces at one end of the dimer and extrapolate
the forces to the other.
dimer_separation: float
Separation of the dimer's images.
initial_eigenmode_method: str
How to construct the initial eigenmode of the dimer. If an eigenmode
is given when creating the MinModeAtoms object, this will be ignored.
Possible choices are: 'gauss' and 'displacement'
extrapolate_forces: bool
When more than one rotation is performed, an extrapolation scheme can
be used to reduce the number of force evaluations.
displacement_method: str
How to displace the atoms. Possible choices are 'gauss' and 'vector'.
gauss_std: float
The standard deviation of the gauss curve used when doing random
displacement.
order: int
How many lowest eigenmodes will be inverted.
mask: list of bool
Which atoms will be moved during displacement.
displacement_center: int or [float, float, float]
The center of displacement, nearby atoms will be displaced.
displacement_radius: float
When choosing which atoms to displace with the *displacement_center*
keyword, this decides how many nearby atoms to displace.
number_of_displacement_atoms: int
The amount of atoms near *displacement_center* to displace.
"""
# Default parameters for the Dimer eigenmode search
parameters = {'eigenmode_method': 'dimer',
'f_rot_min': 0.1,
'f_rot_max': 1.00,
'max_num_rot': 1,
'trial_angle': pi / 4.0,
'trial_trans_step': 0.001,
'maximum_translation': 0.1,
'cg_translation': True,
'use_central_forces': True,
'dimer_separation': 0.0001,
'initial_eigenmode_method': 'gauss',
'extrapolate_forces': False,
'displacement_method': 'gauss',
'gauss_std': 0.1,
'order': 1,
'mask': None, # NB mask should not be a "parameter"
'displacement_center': None,
'displacement_radius': None,
'number_of_displacement_atoms': None}
# NB: Can maybe put this in EigenmodeSearch and MinModeControl
def log(self, parameter=None):
"""Log the parameters of the eigenmode search."""
if self.logfile is not None:
if parameter is not None:
l = 'DIM:CONTROL: Updated Parameter: %s = %s\n' % (parameter,
str(self.get_parameter(parameter)))
else:
l = 'MINMODE:METHOD: Dimer\n'
l += 'DIM:CONTROL: Search Parameters:\n'
l += 'DIM:CONTROL: ------------------\n'
for key in self.parameters:
l += 'DIM:CONTROL: %s = %s\n' % (key,
str(self.get_parameter(key)))
l += 'DIM:CONTROL: ------------------\n'
l += 'DIM:ROT: OPT-STEP ROT-STEP CURVATURE ROT-ANGLE ' + \
'ROT-FORCE\n'
self.logfile.write(l)
self.logfile.flush()
class MinModeAtoms:
"""Wrapper for Atoms with information related to minimum mode searching.
Contains an Atoms object and pipes all unknown function calls to that
object.
Other information that is stored in this object are the estimate for
the lowest eigenvalue, *curvature*, and its corresponding eigenmode,
*eigenmode*. Furthermore, the original configuration of the Atoms
object is stored for use in multiple minimum mode searches.
The forces on the system are modified by inverting the component
along the eigenmode estimate. This eventually brings the system to
a saddle point.
Parameters:
atoms : Atoms object
A regular Atoms object
control : MinModeControl object
Contains the parameters necessary for the eigenmode search.
If no control object is supplied a default DimerControl
will be created and used.
mask: list of bool
Determines which atoms will be moved when calling displace()
random_seed: int
The seed used for the random number generator. Defaults to
modified version the current time.
References:
.. [1] Henkelman and Jonsson, JCP 111, 7010 (1999)
.. [2] Olsen, Kroes, Henkelman, Arnaldsson, and Jonsson, JCP 121,
9776 (2004).
.. [3] Heyden, Bell, and Keil, JCP 123, 224101 (2005).
.. [4] Kastner and Sherwood, JCP 128, 014106 (2008).
"""
def __init__(self, atoms, control=None, eigenmodes=None, random_seed=None, **kwargs):
self.minmode_init = True
self.atoms = atoms
# Initialize to None to avoid strange behaviour due to __getattr__
self.eigenmodes = eigenmodes
self.curvatures = None
if control is None:
self.control = DimerControl(**kwargs)
w = 'Missing control object in ' + self.__class__.__name__ + \
'. Using default: DimerControl()'
warnings.warn(w, UserWarning)
if self.control.logfile is not None:
self.control.logfile.write('DIM:WARN: ' + w + '\n')
self.control.logfile.flush()
else:
self.control = control
logfile = self.control.get_logfile()
mlogfile = self.control.get_eigenmode_logfile()
for key in kwargs:
if key == 'logfile':
logfile = kwargs[key]
elif key == 'eigenmode_logfile':
mlogfile = kwargs[key]
else:
self.control.set_parameter(key, kwargs[key])
self.control.initialize_logfiles(logfile = logfile,
eigenmode_logfile = mlogfile)
# Seed the randomness
if random_seed is None:
t = time.time()
if size > 1:
t = world.sum(t) / float(size)
# Harvest the latter part of the current time
random_seed = int(('%30.9f' % t)[-9:])
self.random_state = np.random.RandomState(random_seed)
# Check the order
self.order = self.control.get_parameter('order')
# Construct the curvatures list
self.curvatures = [100.0] * self.order
# Save the original state of the atoms.
self.atoms0 = self.atoms.copy()
self.save_original_forces()
# Get a reference to the log files
self.logfile = self.control.get_logfile()
self.mlogfile = self.control.get_eigenmode_logfile()
def save_original_forces(self, force_calculation=False):
"""Store the forces (and energy) of the original state."""
# NB: Would be nice if atoms.copy() took care of this.
if self.calc is not None:
# Hack because some calculators do not have calculation_required
if (hasattr(self.calc, 'calculation_required') \
and not self.calc.calculation_required(self.atoms,
['energy', 'forces'])) or force_calculation:
calc = SinglePointCalculator( \
self.atoms.get_potential_energy(), \
self.atoms.get_forces(), None, None, self.atoms0)
self.atoms0.set_calculator(calc)
def initialize_eigenmodes(self, method=None, eigenmodes=None, \
gauss_std=None):
"""Make an initial guess for the eigenmode."""
if eigenmodes is None:
pos = self.get_positions()
old_pos = self.get_original_positions()
if method == None:
method = \
self.control.get_parameter('initial_eigenmode_method')
if method.lower() == 'displacement' and (pos - old_pos).any():
eigenmode = normalize(pos - old_pos)
elif method.lower() == 'gauss':
self.displace(log = False, gauss_std = gauss_std,
method = method)
new_pos = self.get_positions()
eigenmode = normalize(new_pos - pos)
self.set_positions(pos)
else:
e = 'initial_eigenmode must use either \'gauss\' or ' + \
'\'displacement\', if the latter is used the atoms ' + \
'must have moved away from the original positions.' + \
'You have requested \'%s\'.' % method
raise NotImplementedError(e) # NYI
eigenmodes = [eigenmode]
# Create random higher order mode guesses
if self.order > 1:
if len(eigenmodes) == 1:
for k in range(1, self.order):
pos = self.get_positions()
self.displace(log = False, gauss_std = gauss_std,
method = method)
new_pos = self.get_positions()
eigenmode = normalize(new_pos - pos)
self.set_positions(pos)
eigenmodes += [eigenmode]
self.eigenmodes = eigenmodes
# Ensure that the higher order mode guesses are all orthogonal
if self.order > 1:
for k in range(self.order):
self.ensure_eigenmode_orthogonality(k)
self.eigenmode_log()
# NB maybe this name might be confusing in context to
# calc.calculation_required()
def calculation_required(self):
"""Check if a calculation is required."""
return self.minmode_init or self.check_atoms != self.atoms
def calculate_real_forces_and_energies(self, **kwargs):
"""Calculate and store the potential energy and forces."""
if self.minmode_init:
self.minmode_init = False
self.initialize_eigenmodes(eigenmodes = self.eigenmodes)
self.rotation_required = True
self.forces0 = self.atoms.get_forces(**kwargs)
self.energy0 = self.atoms.get_potential_energy()
self.control.increment_counter('forcecalls')
self.check_atoms = self.atoms.copy()
def get_potential_energy(self):
"""Return the potential energy."""
if self.calculation_required():
self.calculate_real_forces_and_energies()
return self.energy0
def get_forces(self, real=False, pos=None, **kwargs):
"""Return the forces, projected or real."""
if self.calculation_required() and pos is None:
self.calculate_real_forces_and_energies(**kwargs)
if real and pos is None:
return self.forces0
elif real and pos != None:
old_pos = self.atoms.get_positions()
self.atoms.set_positions(pos)
forces = self.atoms.get_forces()
self.control.increment_counter('forcecalls')
self.atoms.set_positions(old_pos)
return forces
else:
if self.rotation_required:
self.find_eigenmodes(order = self.order)
self.eigenmode_log()
self.rotation_required = False
self.control.increment_counter('optcount')
return self.get_projected_forces()
def ensure_eigenmode_orthogonality(self, order):
mode = self.eigenmodes[order - 1].copy()
for k in range(order - 1):
mode = perpendicular_vector(mode, self.eigenmodes[k])
self.eigenmodes[order - 1] = normalize(mode)
def find_eigenmodes(self, order=1):
"""Launch eigenmode searches."""
if self.control.get_parameter('eigenmode_method').lower() != 'dimer':
e = 'Only the Dimer control object has been implemented.'
raise NotImplementedError(e) # NYI
for k in range(order):
if k > 0:
self.ensure_eigenmode_orthogonality(k + 1)
search = DimerEigenmodeSearch(self, self.control, \
eigenmode = self.eigenmodes[k], basis = self.eigenmodes[:k])
search.converge_to_eigenmode()
search.set_up_for_optimization_step()
self.eigenmodes[k] = search.get_eigenmode()
self.curvatures[k] = search.get_curvature()
def get_projected_forces(self, pos=None):
"""Return the projected forces."""
if pos is not None:
forces = self.get_forces(real = True, pos = pos).copy()
else:
forces = self.forces0.copy()
# Loop through all the eigenmodes
# NB: Can this be done with a linear combination, instead?
for k, mode in enumerate(self.eigenmodes):
# NYI This If statement needs to be overridable in the control
if self.get_curvature(order = k) > 0.0 and self.order == 1:
forces = -parallel_vector(forces, mode)
else:
forces -= 2 * parallel_vector(forces, mode)
return forces
def restore_original_positions(self):
"""Restore the MinModeAtoms object positions to the original state."""
self.atoms.set_positions(self.get_original_positions())
def get_barrier_energy(self):
"""The energy difference between the current and original states"""
try:
original_energy = self.get_original_potential_energy()
dimer_energy = self.get_potential_energy()
return dimer_energy - original_energy
except RuntimeError:
w = 'The potential energy is not available, without further ' + \
'calculations, most likely at the original state.'
warnings.warn(w, UserWarning)
return np.nan
def get_control(self):
"""Return the control object."""
return self.control
def get_curvature(self, order='max'):
"""Return the eigenvalue estimate."""
if order == 'max':
return max(self.curvatures)
else:
return self.curvatures[order - 1]
def get_eigenmode(self, order=1):
"""Return the current eigenmode guess."""
return self.eigenmodes[order - 1]
def get_atoms(self):
"""Return the unextended Atoms object."""
return self.atoms
def set_atoms(self, atoms):
"""Set a new Atoms object"""
self.atoms = atoms
def set_eigenmode(self, eigenmode, order=1):
"""Set the eigenmode guess."""
self.eigenmodes[order - 1] = eigenmode
def set_curvature(self, curvature, order=1):
"""Set the eigenvalue estimate."""
self.curvatures[order - 1] = curvature
# Pipe all the stuff from Atoms that is not overwritten.
# Pipe all requests for get_original_* to self.atoms0.
def __getattr__(self, attr):
"""Return any value of the Atoms object"""
if 'original' in attr.split('_'):
attr = attr.replace('_original_', '_')
return getattr(self.atoms0, attr)
else:
return getattr(self.atoms, attr)
def displace(self, displacement_vector=None, mask=None, method=None,
displacement_center=None, radius=None, number_of_atoms=None,
gauss_std=None, mic=True, log=True):
"""Move the atoms away from their current position.
This is one of the essential parts of minimum mode searches.
The parameters can all be set in the control object and overwritten
when this method is run, apart from *displacement_vector*.
It is preferred to modify the control values rather than those here
in order for the correct ones to show up in the log file.
*method* can be either 'gauss' for random displacement or 'vector'
to perform a predefined displacement.
*gauss_std* is the standard deviation of the gauss curve that is
used for random displacement.
*displacement_center* can be either the number of an atom or a 3D
position. It must be accompanied by a *radius* (all atoms within it
will be displaced) or a *number_of_atoms* which decides how many of
the closest atoms will be displaced.
*mic* controls the usage of the Minimum Image Convention.
If both *mask* and *displacement_center* are used, the atoms marked
as False in the *mask* will not be affected even though they are
within reach of the *displacement_center*.
The parameters priority order:
1) displacement_vector
2) mask
3) displacement_center (with radius and/or number_of_atoms)
If both *radius* and *number_of_atoms* are supplied with
*displacement_center*, only atoms that fulfill both criteria will
be displaced.
"""
# Fetch the default values from the control
if mask is None:
mask = self.control.get_parameter('mask')
if method is None:
method = self.control.get_parameter('displacement_method')
if gauss_std is None:
gauss_std = self.control.get_parameter('gauss_std')
if displacement_center is None:
displacement_center = \
self.control.get_parameter('displacement_center')
if radius is None:
radius = self.control.get_parameter('displacement_radius')
if number_of_atoms is None:
number_of_atoms = \
self.control.get_parameter('number_of_displacement_atoms')
# Check for conflicts
if displacement_vector is not None and method.lower() != 'vector':
e = 'displacement_vector was supplied but a different method ' + \
'(\'%s\') was chosen.\n' % str(method)
raise ValueError(e)
elif displacement_vector is None and method.lower() == 'vector':
e = 'A displacement_vector must be supplied when using ' + \
'method = \'%s\'.\n' % str(method)
raise ValueError(e)
elif displacement_center is not None and radius is None and \
number_of_atoms is None:
e = 'When displacement_center is chosen, either radius or ' + \
'number_of_atoms must be supplied.\n'
raise ValueError(e)
# Set up the center of displacement mask (c_mask)
if displacement_center is not None:
c = displacement_center
# Construct a distance list
# The center is an atom
if type(c) is int:
# Parse negative indexes
c = displacement_center % len(self)
d = [(k, self.get_distance(k, c, mic = mic)) for k in \
range(len(self))]
# The center is a position in 3D space
elif len(c) == 3 and [type(c_k) for c_k in c] == [float]*3:
# NB: MIC is not considered.
d = [(k, norm(self.get_positions()[k] - c)) \
for k in range(len(self))]
else:
e = 'displacement_center must be either the number of an ' + \
'atom in MinModeAtoms object or a 3D position ' + \
'(3-tuple of floats).'
raise ValueError(e)
# Set up the mask
if radius is not None:
r_mask = [dist[1] < radius for dist in d]
else:
r_mask = [True for _ in self]
if number_of_atoms is not None:
d_sorted = [n[0] for n in sorted(d, key = lambda k: k[1])]
n_nearest = d_sorted[:number_of_atoms]
n_mask = [k in n_nearest for k in range(len(self))]
else:
n_mask = [True for _ in self]
# Resolve n_mask / r_mask conflicts
c_mask = [n_mask[k] and r_mask[k] for k in range(len(self))]
else:
c_mask = None
# Set up a True mask if there is no mask supplied
if mask is None:
mask = [True for _ in self]
if c_mask is None:
w = 'It was not possible to figure out which atoms to ' + \
'displace, Will try to displace all atoms.\n'
warnings.warn(w, UserWarning)
if self.logfile is not None:
self.logfile.write('MINMODE:WARN: ' + w + '\n')
self.logfile.flush()
# Resolve mask / c_mask conflicts
if c_mask is not None:
mask = [mask[k] and c_mask[k] for k in range(len(self))]
if displacement_vector is None:
displacement_vector = []
for k in range(len(self)):
if mask[k]:
diff_line = []
for _ in range(3):
if method.lower() == 'gauss':
if not gauss_std:
gauss_std = \
self.control.get_parameter('gauss_std')
diff = self.random_state.normal(0.0, gauss_std)
else:
e = 'Invalid displacement method >>%s<<' % \
str(method)
raise ValueError(e)
diff_line.append(diff)
displacement_vector.append(diff_line)
else:
displacement_vector.append([0.0]*3)
# Remove displacement of masked atoms
for k in range(len(mask)):
if not mask[k]:
displacement_vector[k] = [0.0]*3
# Perform the displacement and log it
if log:
pos0 = self.get_positions()
self.set_positions(self.get_positions() + displacement_vector)
if log:
parameters = {'mask': mask,
'displacement_method': method,
'gauss_std': gauss_std,
'displacement_center': displacement_center,
'displacement_radius': radius,
'number_of_displacement_atoms': number_of_atoms}
self.displacement_log(self.get_positions() - pos0, parameters)
def eigenmode_log(self):
"""Log the eigenmodes (eigenmode estimates)"""
if self.mlogfile is not None:
l = 'MINMODE:MODE: Optimization Step: %i\n' % \
(self.control.get_counter('optcount'))
for m_num, mode in enumerate(self.eigenmodes):
l += 'MINMODE:MODE: Order: %i\n' % m_num
for k in range(len(mode)):
l += 'MINMODE:MODE: %7i %15.8f %15.8f %15.8f\n' % (k,
mode[k][0], mode[k][1], mode[k][2])
self.mlogfile.write(l)
self.mlogfile.flush()
def displacement_log(self, displacement_vector, parameters):
"""Log the displacement"""
if self.logfile is not None:
lp = 'MINMODE:DISP: Parameters, different from the control:\n'
mod_para = False
for key in parameters:
if parameters[key] != self.control.get_parameter(key):
lp += 'MINMODE:DISP: %s = %s\n' % (str(key),
str(parameters[key]))
mod_para = True
if mod_para:
l = lp
else:
l = ''
for k in range(len(displacement_vector)):
l += 'MINMODE:DISP: %7i %15.8f %15.8f %15.8f\n' % (k,
displacement_vector[k][0], displacement_vector[k][1],
displacement_vector[k][2])
self.logfile.write(l)
self.logfile.flush()
def summarize(self):
"""Summarize the Minimum mode search."""
if self.logfile is None:
logfile = sys.stdout
else:
logfile = self.logfile
c = self.control
label = 'MINMODE:SUMMARY: '
l = label + '-------------------------\n'
l += label + 'Barrier: %16.4f\n' % self.get_barrier_energy()
l += label + 'Curvature: %14.4f\n' % self.get_curvature()
l += label + 'Optimizer steps: %8i\n' % c.get_counter('optcount')
l += label + 'Forcecalls: %13i\n' % c.get_counter('forcecalls')
l += label + '-------------------------\n'
logfile.write(l)
class MinModeTranslate(Optimizer):
"""An Optimizer specifically tailored to minimum mode following."""
def __init__(self, atoms, logfile='-', trajectory=None):
Optimizer.__init__(self, atoms, None, logfile, trajectory)
self.control = atoms.get_control()
# Make a header for the log
if self.logfile is not None:
l = ''
if isinstance(self.control, DimerControl):
l = 'MinModeTranslate: STEP TIME ENERGY ' + \
'MAX-FORCE STEPSIZE CURVATURE ROT-STEPS\n'
self.logfile.write(l)
self.logfile.flush()
# Load the relevant parameters from control
self.cg_on = self.control.get_parameter('cg_translation')
self.trial_step = self.control.get_parameter('trial_trans_step')
self.max_step = self.control.get_parameter('maximum_translation')
# Start conjugate gradient
if self.cg_on:
self.cg_init = True
def initialize(self):
"""Set initial values."""
self.r0 = None
self.f0 = None
def run(self, fmax=0.05, steps=100000000):
"""Run structure optimization algorithm.
This method will return when the forces on all individual
atoms are less than *fmax* or when the number of steps exceeds
*steps*.
"""
self.fmax = fmax
step = 0
while step < steps:
f = self.atoms.get_forces()
self.call_observers()
if self.converged(f):
self.log(f, None)
return
self.step(f)
self.nsteps += 1
step += 1
def step(self, f):
"""Perform the optimization step."""
atoms = self.atoms
r = atoms.get_positions()
curv = atoms.get_curvature()
f0p = f.copy()
r0 = r.copy()
direction = f0p.copy()
if self.cg_on:
direction = self.get_cg_direction(direction)
direction = normalize(direction)
if curv > 0.0:
step = direction * self.max_step
else:
r0t = r0 + direction * self.trial_step
f0tp = self.atoms.get_projected_forces(r0t)
F = np.vdot((f0tp + f0p), direction) / 2.0
C = np.vdot((f0tp - f0p), direction) / self.trial_step
step = ( -F / C + self.trial_step / 2.0 ) * direction
if norm(step) > self.max_step:
step = direction * self.max_step
self.log(f0p, norm(step))
atoms.set_positions(r + step)
self.f0 = f.flat.copy()
self.r0 = r.flat.copy()
def get_cg_direction(self, direction):
"""Apply the Conjugate Gradient algorithm to the step direction."""
if self.cg_init:
self.cg_init = False
self.direction_old = direction.copy()
self.cg_direction = direction.copy()
old_norm = np.vdot(self.direction_old, self.direction_old)
# Polak-Ribiere Conjugate Gradient
if old_norm != 0.0:
betaPR = np.vdot(direction, (direction - self.direction_old)) / \
old_norm
else:
betaPR = 0.0
if betaPR < 0.0:
betaPR = 0.0
self.cg_direction = direction + self.cg_direction * betaPR
self.direction_old = direction.copy()
return self.cg_direction.copy()
def log(self, f, stepsize):
"""Log each step of the optimization."""
if self.logfile is not None:
T = time.localtime()
e = self.atoms.get_potential_energy()
fmax = sqrt((f**2).sum(axis = 1).max())
rotsteps = self.atoms.control.get_counter('rotcount')
curvature = self.atoms.get_curvature()
l = ''
if stepsize:
if isinstance(self.control, DimerControl):
l = '%s: %4d %02d:%02d:%02d %15.6f %12.4f %12.6f ' \
'%12.6f %10d\n' % ('MinModeTranslate', self.nsteps,
T[3], T[4], T[5], e, fmax, stepsize, curvature,
rotsteps)
else:
if isinstance(self.control, DimerControl):
l = '%s: %4d %02d:%02d:%02d %15.6f %12.4f %s ' \
'%12.6f %10d\n' % ('MinModeTranslate', self.nsteps,
T[3], T[4], T[5], e, fmax, ' --------',
curvature, rotsteps)
self.logfile.write(l)
self.logfile.flush()
def read_eigenmode(mlog, index = -1):
"""Read an eigenmode.
To access the pre optimization eigenmode set index = 'null'.
"""
if isinstance(mlog, str):
f = open(mlog, 'r')
else:
f = mlog
lines = f.readlines()
# Detect the amount of atoms and iterations
k = 2
while lines[k].split()[1].lower() not in ['optimization', 'order']:
k += 1
n = k - 2
n_itr = (len(lines) / (n + 1)) - 2
# Locate the correct image.
if type(index) == str:
if index.lower() == 'null':
i = 0
else:
i = int(index) + 1
else:
if index >= 0:
i = index + 1
else:
if index < -n_itr - 1:
raise IndexError('list index out of range')
else:
i = index
mode = np.ndarray(shape = (n, 3), dtype = float)
k_atom = 0
for k in range(1, n + 1):
line = lines[i * (n + 1) + k].split()
for k_dim in range(3):
mode[k_atom][k_dim] = float(line[k_dim + 2])
k_atom += 1
return mode
# Aliases
DimerAtoms = MinModeAtoms
DimerTranslate = MinModeTranslate
python-ase-3.6.0.2515/ase/utils/ 0000755 0001754 0001754 00000000000 11757245036 015122 5 ustar askhl askhl python-ase-3.6.0.2515/ase/utils/eos.py 0000644 0001754 0001754 00000004755 11403135522 016257 0 ustar askhl askhl # -*- coding: utf-8 -*-
from math import sqrt
import numpy as np
from ase.units import kJ
class EquationOfState:
"""Fit equation of state for bulk systems.
The following equation is used::
2 3 -1/3
E(V) = c + c t + c t + c t , t = V
0 1 2 3
Use::
eos = EquationOfState(volumes, energies)
v0, e0, B = eos.fit()
eos.plot()
"""
def __init__(self, volumes, energies):
self.v = np.array(volumes)
self.e = np.array(energies)
self.v0 = None
def fit(self):
"""Calculate volume, energy, and bulk modulus.
Returns the optimal volume, the minumum energy, and the bulk
modulus. Notice that the ASE units for the bulk modulus is
eV/Angstrom^3 - to get the value in GPa, do this::
v0, e0, B = eos.fit()
print B / kJ * 1.0e24, 'GPa'
"""
fit0 = np.poly1d(np.polyfit(self.v**-(1.0 / 3), self.e, 3))
fit1 = np.polyder(fit0, 1)
fit2 = np.polyder(fit1, 1)
self.v0 = None
for t in np.roots(fit1):
if t > 0 and fit2(t) > 0:
self.v0 = t**-3
break
if self.v0 is None:
raise ValueError('No minimum!')
self.e0 = fit0(t)
self.B = t**5 * fit2(t) / 9
self.fit0 = fit0
return self.v0, self.e0, self.B
def plot(self, filename=None, show=None):
"""Plot fitted energy curve.
Uses Matplotlib to plot the energy curve. Use *show=True* to
show the figure and *filename='abc.png'* or
*filename='abc.eps'* to save the figure to a file."""
#import matplotlib.pyplot as plt
import pylab as plt
if self.v0 is None:
self.fit()
if filename is None and show is None:
show = True
x = 3.95
f = plt.figure(figsize=(x * 2.5**0.5, x))
f.subplots_adjust(left=0.12, right=0.9, top=0.9, bottom=0.15)
plt.plot(self.v, self.e, 'o')
x = np.linspace(min(self.v), max(self.v), 100)
plt.plot(x, self.fit0(x**-(1.0 / 3)), '-r')
plt.xlabel(u'volume [Ã…^3]')
plt.ylabel(u'energy [eV]')
plt.title(u'E: %.3f eV, V: %.3f Ã…^3, B: %.3f GPa' %
(self.e0, self.v0, self.B / kJ * 1.0e24))
if show:
plt.show()
if filename is not None:
f.savefig(filename)
return f
python-ase-3.6.0.2515/ase/utils/__init__.py 0000644 0001754 0001754 00000011101 11712736711 017221 0 ustar askhl askhl import os
import sys
from math import sin, cos, radians, atan2, degrees
import numpy as np
from ase.parallel import world
class DevNull:
def write(self, string):
pass
def flush(self):
pass
def seek(self, offset, whence=0):
return 0
def tell(self):
return 0
def close(self):
pass
devnull = DevNull()
def opencew(filename):
"""Create and open filename exclusively for writing.
If master cpu gets exclusive write access til filename, a file
descriptor is returned (a dummy file descriptor is returned on the
slaves). If the master cpu doet not get write access, None is
returned on all processors."""
if world.rank == 0:
try:
fd = os.open(filename, os.O_CREAT | os.O_EXCL | os.O_WRONLY)
except OSError:
ok = 0
else:
ok = 1
fd = os.fdopen(fd, 'w')
else:
ok = 0
fd = devnull
# Syncronize:
if world.sum(ok) == 0:
return None
else:
return fd
def prnt(*args, **kwargs):
"""Python 3 style print function."""
kwargs.pop('file', sys.stdout).write(
kwargs.pop('sep', ' ').join(str(arg) for arg in args) +
kwargs.pop('end', '\n'))
if kwargs:
raise TypeError('%r is an invalid keyword argument for this function' %
kwargs.keys()[0])
def gcd(a, b):
"""Greatest common divisor of a and b."""
while a != 0:
a, b = b % a, a
return b
def rotate(rotations, rotation=np.identity(3)):
"""Convert string of format '50x,-10y,120z' to a rotation matrix.
Note that the order of rotation matters, i.e. '50x,40z' is different
from '40z,50x'.
"""
if rotations == '':
return rotation.copy()
for i, a in [('xyz'.index(s[-1]), radians(float(s[:-1])))
for s in rotations.split(',')]:
s = sin(a)
c = cos(a)
if i == 0:
rotation = np.dot(rotation, [(1, 0, 0),
(0, c, s),
(0, -s, c)])
elif i == 1:
rotation = np.dot(rotation, [(c, 0, -s),
(0, 1, 0),
(s, 0, c)])
else:
rotation = np.dot(rotation, [(c, s, 0),
(-s, c, 0),
(0, 0, 1)])
return rotation
def givens(a, b):
"""Solve the equation system::
[ c s] [a] [r]
[ ] . [ ] = [ ]
[-s c] [b] [0]
"""
sgn = lambda x: cmp(x, 0)
if b == 0:
c = sgn(a)
s = 0
r = abs(a)
elif abs(b) >= abs(a):
cot = a / b
u = sgn(b) * (1 + cot**2)**0.5
s = 1. / u
c = s * cot
r = b * u
else:
tan = b / a
u = sgn(a) * (1 + tan**2)**0.5
c = 1. / u
s = c * tan
r = a * u
return c, s, r
def irotate(rotation, initial=np.identity(3)):
"""Determine x, y, z rotation angles from rotation matrix."""
a = np.dot(initial, rotation)
cx, sx, rx = givens(a[2, 2], a[1, 2])
cy, sy, ry = givens(rx, a[0, 2])
cz, sz, rz = givens(cx * a[1, 1] - sx * a[2, 1],
cy * a[0, 1] - sy * (sx * a[1, 1] + cx * a[2, 1]))
x = degrees(atan2(sx, cx))
y = degrees(atan2(-sy, cy))
z = degrees(atan2(sz, cz))
return x, y, z
def hsv2rgb(h, s, v):
"""http://en.wikipedia.org/wiki/HSL_and_HSV
h (hue) in [0, 360[
s (saturation) in [0, 1]
v (value) in [0, 1]
return rgb in range [0, 1]
"""
if v == 0:
return 0, 0, 0
if s == 0:
return v, v, v
i, f = divmod(h / 60., 1)
p = v * (1 - s)
q = v * (1 - s * f)
t = v * (1 - s * (1 - f))
if i == 0:
return v, t, p
elif i == 1:
return q, v, p
elif i == 2:
return p, v, t
elif i == 3:
return p, q, v
elif i == 4:
return t, p, v
elif i == 5:
return v, p, q
else:
raise RuntimeError('h must be in [0, 360]')
def hsv(array, s=.9, v=.9):
array = (array + array.min()) * 359. / (array.max() - array.min())
result = np.empty((len(array.flat), 3))
for rgb, h in zip(result, array.flat):
rgb[:] = hsv2rgb(h, s, v)
return np.reshape(result, array.shape + (3,))
## This code does the same, but requires pylab
## def cmap(array, name='hsv'):
## import pylab
## a = (array + array.min()) / array.ptp()
## rgba = getattr(pylab.cm, name)(a)
## return rgba[:-1] # return rgb only (not alpha)
python-ase-3.6.0.2515/ase/utils/molecule_test.py 0000755 0001754 0001754 00000022763 11122747414 020346 0 ustar askhl askhl #!/usr/bin/env python
"""This module defines extensible classes for running tests on molecules.
Use this to compare different calculators, XC functionals and so on by
calculating e.g. atomization energies and bond lengths across the
g2 database of small molecules.
"""
import os
import sys
import traceback
import numpy as np
from ase import PickleTrajectory, read
from ase.calculators.emt import EMT
from ase.data.molecules import molecule, atoms as g2_atoms, g1
class BatchTest:
"""Contains logic for looping over tests and file management."""
def __init__(self, test):
self.test = test
self.txt = sys.stdout # ?
def run_single_test(self, formula):
print >> self.txt, self.test.name, formula, '...',
self.txt.flush()
filename = self.test.get_filename(formula)
if os.path.exists(filename):
print >> self.txt, 'Skipped.'
return
try:
open(filename, 'w').close() # Empty file
system, calc = self.test.setup(formula)
self.test.run(formula, system, filename)
print >> self.txt, 'OK!'
self.txt.flush()
except self.test.exceptions:
print >> self.txt, 'Failed!'
traceback.print_exc(file=self.txt)
print >> self.txt
self.txt.flush()
def run(self, formulas):
"""Run a batch of tests.
This will invoke the test method on each formula, printing
status to stdout.
Those formulas that already have test result files will
be skipped."""
# Create directories if necessary
if self.test.dir and not os.path.isdir(self.test.dir):
os.mkdir(self.test.dir) # Won't work on 'dir1/dir2', but oh well
for formula in formulas:
self.run_single_test(formula)
def collect(self, formulas, verbose=False):
"""Yield results of previous calculations."""
for formula in formulas:
try:
filename = self.test.get_filename(formula)
results = self.test.retrieve(formula, filename)
if verbose:
print >> self.txt, 'Loaded:', formula, filename
yield formula, results
except (IOError, RuntimeError, TypeError):
# XXX which errors should we actually catch?
if verbose:
print >> self.txt, 'Error:', formula, '[%s]' % filename
traceback.print_exc(file=self.txt)
class MoleculeTest:
"""Generic class for runnings various tests on the g2 dataset.
Usage: instantiate MoleculeTest with desired test settings and
invoke its run() method on the desired formulas.
This class will use the ASE EMT calculator by default. You can
create a subclass using an arbitrary calculator by overriding the
setup_calculator method. Most methods can be overridden to
provide highly customized behaviour. """
def __init__(self, name, vacuum=6.0, exceptions=None):
"""Create a molecule test.
The name parameter will be part of all output files generated
by this molecule test. If name contains a '/' character, the
preceding part will be interpreted as a directory in which to
put files.
The vacuum parameter is used to set the cell size.
A tuple of exception types can be provided which will be
caught during a batch of calculations. Types not specified
will be considered fatal."""
dir, path = os.path.split(name)
self.dir = dir
self.name = name
self.vacuum = vacuum
if exceptions is None:
exceptions = ()
self.exceptions = exceptions
def setup_calculator(self, system, formula):
"""Create a new calculator.
Default is an EMT calculator. Most implementations will want to
override this method."""
raise NotImplementedError
def setup_system(self, formula):
"""Create an Atoms object from the given formula.
By default this will be loaded from the g2 database, setting
the cell size by means of the molecule test's vacuum parameter."""
system = molecule(formula)
system.center(vacuum=self.vacuum)
return system
def setup(self, formula):
"""Build calculator and atoms objects.
This will invoke the setup_calculator and setup_system methods."""
system = self.setup_system(formula)
calc = self.setup_calculator(system, formula)
system.set_calculator(calc)
return system, calc
def get_filename(self, formula, extension='traj'):
"""Returns the filename for a test result file.
Default format is ..traj
The test may write other files, but this filename is used as a
flag denoting whether the calculation has been done
already."""
return '.'.join([self.name, formula, extension])
def run(self, formula, system, filename):
raise NotImplementedError
def retrieve(self, formula, filename):
"""Retrieve results of previous calculation from file.
Default implementation returns the total energy.
This method should be overridden whenever the test method is
overridden to calculate something else than the total energy."""
raise NotImplementedError
class EnergyTest:
def run(self, formula, system, filename):
"""Calculate energy of specified system and save to file."""
system.get_potential_energy()
# Won't create .bak file:
traj = PickleTrajectory(open(filename, 'w'), 'w')
traj.write(system)
traj.close()
def retrieve(self, formula, filename):
system = read(filename)
energy = system.get_potential_energy()
return energy
def calculate_atomization_energies(self, molecular_energies,
atomic_energies):
atomic_energy_dict = dict(atomic_energies)
for formula, molecular_energy in molecular_energies:
try:
system = molecule(formula)
atomic = [atomic_energy_dict[s]
for s in system.get_chemical_symbols()]
atomization_energy = molecular_energy - sum(atomic)
yield formula, atomization_energy
except KeyError:
pass
class BondLengthTest:
def run(self, formula, system, filename):
"""Calculate bond length of a dimer.
This will calculate total energies for varying atomic
separations close to the g2 bond length, allowing
determination of bond length by fitting.
"""
if len(system) != 2:
raise ValueError('Not a dimer')
traj = PickleTrajectory(open(filename, 'w'), 'w')
pos = system.positions
d = np.linalg.norm(pos[1] - pos[0])
for x in range(-2, 3):
system.set_distance(0, 1, d * (1.0 + x * 0.02))
traj.write(system)
traj.close()
def retrieve(self, formula, filename):
traj = PickleTrajectory(filename, 'r')
distances = np.array([np.linalg.norm(a.positions[1] - a.positions[0])
for a in traj])
energies = np.array([a.get_potential_energy() for a in traj])
polynomial = np.polyfit(distances, energies, 2) # or maybe 3rd order?
# With 3rd order it is not always obvious which root is right
pderiv = np.polyder(polynomial, 1)
d0 = np.roots(pderiv)
e0 = np.polyval(energies, d0)
return distances, energies, d0, e0, polynomial
class EMTTest(MoleculeTest):
def setup_calculator(self, system, calculator):
return EMT()
class EMTEnergyTest(EnergyTest, EMTTest):
pass
class EMTBondLengthTest(BondLengthTest, EMTTest):
pass
def main():
supported_elements = 'Ni, C, Pt, Ag, H, Al, O, N, Au, Pd, Cu'.split(', ')
formulas = [formula for formula in g1
if np.all([symbol in supported_elements
for symbol
in molecule(formula).get_chemical_symbols()])]
atoms = [symbol for symbol in g2_atoms if symbol in supported_elements]
dimers = [formula for formula in formulas if len(molecule(formula)) == 2]
name1 = 'testfiles/energy'
name2 = 'testfiles/bond'
test1 = BatchTest(EMTEnergyTest(name1, vacuum=3.0))
test2 = BatchTest(EMTBondLengthTest(name2, vacuum=3.0))
print 'Energy test'
print '-----------'
test1.run(formulas + atoms)
print
print 'Bond length test'
print '----------------'
test2.run(dimers)
print
print 'Atomization energies'
print '--------------------'
atomic_energies = dict(test1.collect(atoms))
molecular_energies = dict(test1.collect(formulas))
atomization_energies = {}
for formula, energy in molecular_energies.iteritems():
system = molecule(formula)
atomic = [atomic_energies[s] for s in system.get_chemical_symbols()]
atomization_energy = energy - sum(atomic)
atomization_energies[formula] = atomization_energy
print formula.rjust(10), '%.02f' % atomization_energy
print
print 'Bond lengths'
print '------------'
for formula, (d_i, e_i, d0, e0, poly) in test2.collect(dimers):
system = molecule(formula)
bref = np.linalg.norm(system.positions[1] - system.positions[0])
print formula.rjust(10), '%6.3f' % d0, ' g2ref =', '%2.3f' % bref
if __name__ == '__main__':
main()
python-ase-3.6.0.2515/ase/utils/bee.py 0000644 0001754 0001754 00000002557 11267454627 016244 0 ustar askhl askhl import numpy as np
# NB! This module was ported from a 4 year old CamposASE2 module.
"""Bayesian Error Estimation
For details, see: "Bayesian Error Estimation in Density Functional
Theory", J. J. Mortensen, K. Kaasbjerg, S. L. Frederiksen,
J. K. Norskov, J. P. Sethna, K. W. Jacobsen, Phys. Rev. Lett. 95,
216401 (2005)."""
# T
# cost(c) = cost0 + 0.5 * (c - c0) H (c - c0)
#
# Cost function minimum value:
cost0 = 3.4660625596
# Best fit parameters:
c0 = np.array([1.000787451, 0.1926284063, 1.896191546])
# Hessian:
# H = np.array([[ 1.770035168e+03, -3.732470432e+02, -2.105836167e+02],
# [-3.732470432e+02, 1.188857209e+02, 6.054102443e+01],
# [-2.105836167e+02, 6.054102443e+01, 3.211200293e+01]])
#
# 0.5 * np * T = cost0 (np=3: number of parameters)
T = cost0 * 2 / 3
def make_ensemble(N=1000, seed=None):
np.random.seed(seed) # None means /dev/urandom seed
M = np.array([(0.066, -0.812, 1.996),
(0.055, 0.206, 0.082),
(-0.034, 0.007, 0.004)])
alpha = np.random.normal(0.0, 1.0, (N, 3))
return c0 + np.dot(alpha, M)
c = make_ensemble()
def get_ensemble_energies(atoms, c=c):
if hasattr(atoms, 'get_calculator'):
coefs = atoms.get_calculator().get_ensemble_coefficients()
else:
coefs = atoms
return coefs[0] + np.dot(c, coefs[1:])
python-ase-3.6.0.2515/ase/utils/adsorb.py 0000644 0001754 0001754 00000014362 11652200253 016736 0 ustar askhl askhl #!/usr/bin/env python
# Copyright 2010 CAMd
# (see accompanying license files for details).
from optparse import OptionParser
import numpy as np
from ase.lattice.surface import fcc111, hcp0001, bcc110, diamond111, \
add_adsorbate
from ase.structure import estimate_lattice_constant
from ase.data import reference_states, atomic_numbers, covalent_radii
from ase.io import write
from ase.visualize import view
from ase.atoms import Atoms, string2symbols
from ase.data.molecules import molecule
def build():
p = OptionParser(usage='%prog [options] [ads@]surf [output file]',
version='%prog 0.1',
description='Example ads/surf: fcc-CO@2x2Ru0001')
p.add_option('-l', '--layers', type='int',
default=4,
help='Number of layers.')
p.add_option('-v', '--vacuum', type='float',
default=5.0,
help='Vacuum.')
p.add_option('-x', '--crystal-structure',
help='Crystal structure.',
choices=['sc', 'fcc', 'bcc', 'hcp'])
p.add_option('-a', '--lattice-constant', type='float',
help='Lattice constant in Angstrom.')
p.add_option('--c-over-a', type='float',
help='c/a ratio.')
p.add_option('--height', type='float',
help='Height of adsorbate over surface.')
p.add_option('--distance', type='float',
help='Distance between adsorbate and nearest surface atoms.')
p.add_option('-M', '--magnetic-moment', type='float', default=0.0,
help='Magnetic moment.')
p.add_option('-G', '--gui', action='store_true',
help="Pop up ASE's GUI.")
p.add_option('-P', '--python', action='store_true',
help="Write Python script.")
opt, args = p.parse_args()
if not 1 <= len(args) <= 2:
p.error("incorrect number of arguments")
if '@' in args[0]:
ads, surf = args[0].split('@')
else:
ads = None
surf = args[0]
if surf[0].isdigit():
i1 = surf.index('x')
n = int(surf[:i1])
i2 = i1 + 1
while surf[i2].isdigit():
i2 += 1
m = int(surf[i1 + 1:i2])
surf = surf[i2:]
else:
n = 1
m = 1
if surf[-1].isdigit():
if surf[1].isdigit():
face = surf[1:]
surf = surf[0]
else:
face = surf[2:]
surf = surf[:2]
else:
face = None
Z = atomic_numbers[surf]
state = reference_states[Z]
if opt.crystal_structure:
x = opt.crystal_structure
else:
x = state['symmetry']
if opt.lattice_constant:
a = opt.lattice_constant
else:
a = estimate_lattice_constant(surf, x, opt.c_over_a)
script = ['from ase.lattice.surface import ',
'vac = %r' % opt.vacuum,
'a = %r' % a]
if x == 'fcc':
if face is None:
face = '111'
slab = fcc111(surf, (n, m, opt.layers), a, opt.vacuum)
script[0] += 'fcc111'
script += ['slab = fcc111(%r, (%d, %d, %d), a, vac)' %
(surf, n, m, opt.layers)]
r = a / np.sqrt(2) / 2
elif x == 'bcc':
if face is None:
face = '110'
slab = bcc110(surf, (n, m, opt.layers), a, opt.vacuum)
script[0] += 'bcc110'
script += ['slab = bcc110(%r, (%d, %d, %d), a, vac)' %
(surf, n, m, opt.layers)]
r = a * np.sqrt(3) / 4
elif x == 'hcp':
if face is None:
face = '0001'
if opt.c_over_a is None:
c = np.sqrt(8 / 3.0) * a
else:
c = opt.c_over_a * a
slab = hcp0001(surf, (n, m, opt.layers), a, c, opt.vacuum)
script[0] += 'hcp0001'
script += ['c = %r * a' % (c / a),
'slab = hcp0001(%r, (%d, %d, %d), a, c, vac)' %
(surf, n, m, opt.layers)]
r = a / 2
elif x == 'diamond':
if face is None:
face = '111'
slab = diamond111(surf, (n, m, opt.layers), a, opt.vacuum)
script[0] += 'diamond111'
script += ['slab = diamond111(%r, (%d, %d, %d), a, vac)' %
(surf, n, m, opt.layers)]
r = a * np.sqrt(3) / 8
else:
raise NotImplementedError
magmom = opt.magnetic_moment
if magmom is None:
magmom = {'Ni': 0.6, 'Co': 1.2, 'Fe': 2.3}.get(surf, 0.0)
slab.set_initial_magnetic_moments([magmom] * len(slab))
if magmom != 0:
script += ['slab.set_initial_magnetic_moments([%r] * len(slab))' %
magmom]
slab.pbc = 1
script += ['slab.pbc = True']
name = '%dx%d%s%s' % (n, m, surf, face)
if ads:
site = 'ontop'
if '-' in ads:
site, ads = ads.split('-')
name = site + '-' + ads + '@' + name
symbols = string2symbols(ads)
nads = len(symbols)
if nads == 1:
script[:0] = ['from ase import Atoms']
script += ['ads = Atoms(%r)' % ads]
ads = Atoms(ads)
else:
script[:0] = ['from ase.data.molecules import molecule']
script += ['ads = molecule(%r)' % ads]
ads = molecule(ads)
add_adsorbate(slab, ads, 0.0, site)
d = opt.distance
if d is None:
d = r + covalent_radii[ads[0].number] / 2
h = opt.height
if h is None:
R = slab.positions
y = ((R[:-nads] - R[-nads])**2).sum(1).min()**0.5
h = (d**2 - y**2)**0.5
else:
assert opt.distance is None
slab.positions[-nads:, 2] += h
script[1] += ', add_adsorbate'
script += ['add_adsorbate(slab, ads, %r, %r)' % (h, site)]
if len(args) == 2:
write(args[1], slab)
script[1:1] = ['from ase.io import write']
script += ['write(%r, slab)' % args[1]]
elif not opt.gui:
write(name + '.traj', slab)
script[1:1] = ['from ase.io import write']
script += ['write(%r, slab)' % (name + '.traj')]
if opt.gui:
view(slab)
script[1:1] = ['from ase.visualize import view']
script += ['view(slab)']
if opt.python:
print('\n'.join(script))
if __name__ == '__main__':
build()
python-ase-3.6.0.2515/ase/utils/geometry.py 0000644 0001754 0001754 00000040116 11632077176 017331 0 ustar askhl askhl # Copyright (C) 2010, Jesper Friis
# (see accompanying license files for details).
"""Utility tools for convenient creation of slabs and interfaces of
different orientations."""
import numpy as np
def get_layers(atoms, miller, tolerance=0.001):
"""Returns two arrays describing which layer each atom belongs
to and the distance between the layers and origo.
Parameters:
miller: 3 integers
The Miller indices of the planes. Actually, any direction
in reciprocal space works, so if a and b are two float
vectors spanning an atomic plane, you can get all layers
parallel to this with miller=np.cross(a,b).
tolerance: float
The maximum distance in Angstrom along the plane normal for
counting two atoms as belonging to the same plane.
Returns:
tags: array of integres
Array of layer indices for each atom.
levels: array of floats
Array of distances in Angstrom from each layer to origo.
Example:
>>> import numpy as np
>>> from ase.lattice.spacegroup import crystal
>>> atoms = crystal('Al', [(0,0,0)], spacegroup=225, cellpar=4.05)
>>> np.round(atoms.positions, decimals=5)
array([[ 0. , 0. , 0. ],
[ 0. , 2.025, 2.025],
[ 2.025, 0. , 2.025],
[ 2.025, 2.025, 0. ]])
>>> get_layers(atoms, (0,0,1))
(array([0, 1, 1, 0]), array([ 0. , 2.025]))
"""
miller = np.asarray(miller)
metric = np.dot(atoms.cell, atoms.cell.T)
c = np.linalg.solve(metric.T, miller.T).T
miller_norm = np.sqrt(np.dot(c, miller))
d = np.dot(atoms.get_scaled_positions(), miller)/miller_norm
keys = np.argsort(d)
ikeys = np.argsort(keys)
mask = np.concatenate(([True], np.diff(d[keys]) > tolerance))
tags = np.cumsum(mask)[ikeys]
if tags.min() == 1:
tags -= 1
levels = d[keys][mask]
return tags, levels
def cut(atoms, a=(1, 0, 0), b=(0, 1, 0), c=None, clength=None,
origo=(0, 0, 0), nlayers=None, extend=1.0, tolerance=0.01,
maxatoms=None):
"""Cuts out a cell defined by *a*, *b*, *c* and *origo* from a
sufficiently repeated copy of *atoms*.
Typically, this function is used to create slabs of different
sizes and orientations. The vectors *a*, *b* and *c* are in scaled
coordinates and defines the returned cell and should normally be
integer-valued in order to end up with a periodic
structure. However, for systems with sub-translations, like fcc,
integer multiples of 1/2 or 1/3 might also make sence for some
directions (and will be treated correctly).
Parameters:
atoms: Atoms instance
This should correspond to a repeatable unit cell.
a: int | 3 floats
The a-vector in scaled coordinates of the cell to cut out. If
integer, the a-vector will be the scaled vector from *origo* to the
atom with index *a*.
b: int | 3 floats
The b-vector in scaled coordinates of the cell to cut out. If
integer, the b-vector will be the scaled vector from *origo* to the
atom with index *b*.
c: None | int | 3 floats
The c-vector in scaled coordinates of the cell to cut out.
if integer, the c-vector will be the scaled vector from *origo* to
the atom with index *c*.
If *None* it will be along cross(a, b) converted to real space
and normalised with the cube root of the volume. Note that this
in general is not perpendicular to a and b for non-cubic
systems. For cubic systems however, this is redused to
c = cross(a, b).
clength: None | float
If not None, the length of the c-vector will be fixed to
*clength* Angstroms. Should not be used together with
*nlayers*.
origo: int | 3 floats
Position of origo of the new cell in scaled coordinates. If
integer, the position of the atom with index *origo* is used.
nlayers: None | int
If *nlayers* is not *None*, the returned cell will have
*nlayers* atomic layers in the c-direction.
extend: 1 or 3 floats
The *extend* argument scales the effective cell in which atoms
will be included. It must either be three floats or a single
float scaling all 3 directions. By setting to a value just
above one, e.g. 1.05, it is possible to all the corner and
edge atoms in the returned cell. This will of cause make the
returned cell non-repeatable, but is very usefull for
visualisation.
tolerance: float
Determines what is defined as a plane. All atoms within
*tolerance* Angstroms from a given plane will be considered to
belong to that plane.
maxatoms: None | int
This option is used to auto-tune *tolerance* when *nlayers* is
given for high zone axis systems. For high zone axis one
needs to reduce *tolerance* in order to distinguise the atomic
planes, resulting in the more atoms will be added and
eventually MemoryError. A too small *tolerance*, on the other
hand, might result in inproper splitting of atomic planes and
that too few layers are returned. If *maxatoms* is not None,
*tolerance* will automatically be gradually reduced until
*nlayers* atomic layers is obtained, when the number of atoms
exceeds *maxatoms*.
Example:
>>> import ase
>>> from ase.lattice.spacegroup import crystal
>>>
# Create an aluminium (111) slab with three layers
#
# First an unit cell of Al
>>> a = 4.05
>>> aluminium = crystal('Al', [(0,0,0)], spacegroup=225,
... cellpar=[a, a, a, 90, 90, 90])
>>>
# Then cut out the slab
>>> al111 = cut(aluminium, (1,-1,0), (0,1,-1), nlayers=3)
>>>
# Visualisation of the skutterudite unit cell
#
# Again, create a skutterudite unit cell
>>> a = 9.04
>>> skutterudite = crystal(
... ('Co', 'Sb'),
... basis=[(0.25,0.25,0.25), (0.0, 0.335, 0.158)],
... spacegroup=204,
... cellpar=[a, a, a, 90, 90, 90])
>>>
# Then use *origo* to put 'Co' at the corners and *extend* to
# include all corner and edge atoms.
>>> s = cut(skutterudite, origo=(0.25, 0.25, 0.25), extend=1.01)
>>> ase.view(s) # doctest: +SKIP
"""
atoms = atoms.copy()
cell = atoms.cell
if isinstance(origo, int):
origo = atoms.get_scaled_positions()[origo]
origo = np.array(origo, dtype=float)
scaled = (atoms.get_scaled_positions() - origo)%1.0
scaled %= 1.0 # needed to ensure that all numbers are *less* than one
atoms.set_scaled_positions(scaled)
if isinstance(a, int):
a = scaled[a] - origo
if isinstance(b, int):
b = scaled[b] - origo
if isinstance(c, int):
c = scaled[c] - origo
a = np.array(a, dtype=float)
b = np.array(b, dtype=float)
if c is None:
metric = np.dot(cell, cell.T)
vol = np.sqrt(np.linalg.det(metric))
h = np.cross(a, b)
H = np.linalg.solve(metric.T, h.T)
c = vol*H/vol**(1./3.)
c = np.array(c, dtype=float)
if nlayers:
# Recursive increase the length of c until we have at least
# *nlayers* atomic layers parallell to the a-b plane
while True:
at = cut(atoms, a, b, c, origo=origo, extend=extend,
tolerance=tolerance)
scaled = at.get_scaled_positions()
d = scaled[:,2]
keys = np.argsort(d)
ikeys = np.argsort(keys)
tol = tolerance
while True:
mask = np.concatenate(([True], np.diff(d[keys]) > tol))
tags = np.cumsum(mask)[ikeys] - 1
levels = d[keys][mask]
if (maxatoms is None or len(at) < maxatoms or
len(levels) > nlayers):
break
tol *= 0.9
if len(levels) > nlayers:
break
c *= 2
at.cell[2] *= levels[nlayers]
return at[tags < nlayers]
newcell = np.dot(np.array([a, b, c]), cell)
if nlayers is None and clength is not None:
newcell[2,:] *= clength/np.linalg.norm(newcell[2])
# Create a new atoms object, repeated and translated such that
# it completely covers the new cell
scorners_newcell = np.array([[0., 0., 0.], [0., 0., 1.],
[0., 1., 0.], [0., 1., 1.],
[1., 0., 0.], [1., 0., 1.],
[1., 1., 0.], [1., 1., 1.]])
corners = np.dot(scorners_newcell, newcell*extend)
scorners = np.linalg.solve(cell.T, corners.T).T
rep = np.ceil(scorners.ptp(axis=0)).astype('int') + 1
trans = np.dot(np.floor(scorners.min(axis=0)), cell)
atoms = atoms.repeat(rep)
atoms.translate(trans)
atoms.set_cell(newcell)
# Mask out atoms outside new cell
stol = 0.1*tolerance # scaled tolerance, XXX
maskcell = atoms.cell*extend
sp = np.linalg.solve(maskcell.T, (atoms.positions).T).T
mask = np.all(np.logical_and(-stol <= sp, sp < 1-stol), axis=1)
atoms = atoms[mask]
return atoms
class IncompatibleCellError(ValueError):
"""Exception raised if stacking fails due to incompatible cells
between *atoms1* and *atoms2*."""
pass
def stack(atoms1, atoms2, axis=2, cell=None, fix=0.5,
maxstrain=0.5, distance=None, reorder=False):
"""Return a new Atoms instance with *atoms2* stacked on top of
*atoms1* along the given axis. Periodicity in all directions is
ensured.
The size of the final cell is determined by *cell*, except
that the length alongh *axis* will be the sum of
*atoms1.cell[axis]* and *atoms2.cell[axis]*. If *cell* is None,
it will be interpolated between *atoms1* and *atoms2*, where
*fix* determines their relative weight. Hence, if *fix* equals
zero, the final cell will be determined purely from *atoms1* and
if *fix* equals one, it will be determined purely from
*atoms2*.
An ase.geometry.IncompatibleCellError exception is raised if the
cells of *atoms1* and *atoms2* are incopatible, e.g. if the far
corner of the unit cell of either *atoms1* or *atoms2* is
displaced more than *maxstrain*. Setting *maxstrain* to None,
disable this check.
If *distance* is not None, the size of the final cell, along the
direction perpendicular to the interface, will be adjusted such
that the distance between the closest atoms in *atoms1* and
*atoms2* will be equal to *distance*. This option uses
scipy.optimize.fmin() and hence require scipy to be installed.
If *reorder* is True, then the atoms will be reordred such that
all atoms with the same symbol will follow sequensially after each
other, eg: 'Al2MnAl10Fe' -> 'Al12FeMn'.
Example:
>>> import ase
>>> from ase.lattice.spacegroup import crystal
>>>
# Create an Ag(110)-Si(110) interface with three atomic layers
# on each side.
>>> a_ag = 4.09
>>> ag = crystal(['Ag'], basis=[(0,0,0)], spacegroup=225,
... cellpar=[a_ag, a_ag, a_ag, 90., 90., 90.])
>>> ag110 = cut(ag, (0, 0, 3), (-1.5, 1.5, 0), nlayers=3)
>>>
>>> a_si = 5.43
>>> si = crystal(['Si'], basis=[(0,0,0)], spacegroup=227,
... cellpar=[a_si, a_si, a_si, 90., 90., 90.])
>>> si110 = cut(si, (0, 0, 2), (-1, 1, 0), nlayers=3)
>>>
>>> interface = stack(ag110, si110, maxstrain=1)
>>> ase.view(interface) # doctest: +SKIP
>>>
# Once more, this time adjusted such that the distance between
# the closest Ag and Si atoms will be 2.3 Angstrom (requires scipy).
>>> interface2 = stack(ag110, si110,
... maxstrain=1, distance=2.3) # doctest:+ELLIPSIS
Optimization terminated successfully.
...
>>> ase.view(interface2) # doctest: +SKIP
"""
atoms1 = atoms1.copy()
atoms2 = atoms2.copy()
if (np.sign(np.linalg.det(atoms1.cell)) !=
np.sign(np.linalg.det(atoms2.cell))):
raise IncompatibleCellError('*atoms1* amd *atoms2* must both either '
'have a lefthanded or a righanded cell.')
c1 = np.linalg.norm(atoms1.cell[axis])
c2 = np.linalg.norm(atoms2.cell[axis])
if cell is None:
cell1 = atoms1.cell.copy()
cell2 = atoms2.cell.copy()
cell1[axis] /= c1
cell2[axis] /= c2
cell = cell1 + fix*(cell2 - cell1)
cell[axis] /= np.linalg.norm(cell[axis])
cell1 = cell.copy()
cell2 = cell.copy()
cell1[axis] *= c1
cell2[axis] *= c2
if maxstrain:
strain1 = np.sqrt(((cell1 - atoms1.cell).sum(axis=0)**2).sum())
strain2 = np.sqrt(((cell2 - atoms2.cell).sum(axis=0)**2).sum())
if strain1 > maxstrain or strain2 > maxstrain:
raise IncompatibleCellError(
'*maxstrain* exceeded. *atoms1* strained %f and '
'*atoms2* strained %f.'%(strain1, strain2))
atoms1.set_cell(cell1, scale_atoms=True)
atoms2.set_cell(cell2, scale_atoms=True)
if distance is not None:
from scipy.optimize import fmin
def mindist(pos1, pos2):
n1 = len(pos1)
n2 = len(pos2)
idx1 = np.arange(n1).repeat(n2)
idx2 = np.tile(np.arange(n2), n1)
return np.sqrt(((pos1[idx1] - pos2[idx2])**2).sum(axis=1).min())
def func(x):
t1, t2, h1, h2 = x[0:3], x[3:6], x[6], x[7]
pos1 = atoms1.positions + t1
pos2 = atoms2.positions + t2
d1 = mindist(pos1, pos2 + (h1 + 1.0)*atoms1.cell[axis])
d2 = mindist(pos2, pos1 + (h2 + 1.0)*atoms2.cell[axis])
return (d1 - distance)**2 + (d2 - distance)**2
atoms1.center()
atoms2.center()
x0 = np.zeros((8,))
x = fmin(func, x0)
t1, t2, h1, h2 = x[0:3], x[3:6], x[6], x[7]
atoms1.translate(t1)
atoms2.translate(t2)
atoms1.cell[axis] *= 1.0 + h1
atoms2.cell[axis] *= 1.0 + h2
atoms2.translate(atoms1.cell[axis])
atoms1.cell[axis] += atoms2.cell[axis]
atoms1.extend(atoms2)
if reorder:
atoms1 = sort(atoms1)
return atoms1
def sort(atoms, tags=None):
"""Return a new Atoms object with sorted atomic order. The default
is to order according to chemical symbols, but if *tags* is not
None, it will be used instead. A stable sorting algorithm is used.
Example:
>>> import ase
>>> from ase.lattice.spacegroup import crystal
>>>
# Two unit cells of NaCl
>>> a = 5.64
>>> nacl = crystal(['Na', 'Cl'], [(0, 0, 0), (0.5, 0.5, 0.5)],
... spacegroup=225, cellpar=[a, a, a, 90, 90, 90]).repeat((2, 1, 1))
>>> nacl.get_chemical_symbols()
['Na', 'Na', 'Na', 'Na', 'Cl', 'Cl', 'Cl', 'Cl', 'Na', 'Na', 'Na', 'Na', 'Cl', 'Cl', 'Cl', 'Cl']
>>> nacl_sorted = sort(nacl)
>>> nacl_sorted.get_chemical_symbols()
['Cl', 'Cl', 'Cl', 'Cl', 'Cl', 'Cl', 'Cl', 'Cl', 'Na', 'Na', 'Na', 'Na', 'Na', 'Na', 'Na', 'Na']
>>> np.all(nacl_sorted.cell == nacl.cell)
True
"""
if tags is None:
tags = atoms.get_chemical_symbols()
else:
tags = list(tags)
deco = [(tag, i) for i, tag in enumerate(tags)]
deco.sort()
indices = [i for tag, i in deco]
return atoms[indices]
def rotate(atoms, a1, a2, b1, b2, rotate_cell=True):
"""Rotate *atoms*, such that *a1* will be rotated to *a2* and *b1*
to *b2*."""
from numpy.linalg import norm, det
a1 = np.asarray(a1, dtype=float)/norm(a1)
a2 = np.asarray(a2, dtype=float)/norm(a2)
b1 = np.asarray(b1, dtype=float)/norm(b1)
b2 = np.asarray(b2, dtype=float)/norm(b2)
if norm(a2 - a1) < 1e-5:
n = 0.5*(a1 + a2)
a1, a2 = b1, b2
elif norm(b2 - b1) < 1e-5:
n = 0.5*(b1 + b2)
else:
n = np.cross(a2 - a1, b2 - b1)
n /= norm(n)
ap1 = a1 - np.dot(a1, n)*n
ap2 = a2 - np.dot(a2, n)*n
angle = np.arccos(np.dot(ap1, ap2)/(norm(ap1)*norm(ap2)))
angle *= np.sign(det((ap1, ap2, n)))
atoms.rotate(n, angle, rotate_cell=rotate_cell)
#-----------------------------------------------------------------
# Self test
if __name__ == '__main__':
import doctest
print 'doctest: ', doctest.testmod()
python-ase-3.6.0.2515/ase/utils/linesearch.py 0000644 0001754 0001754 00000033724 11401652206 017605 0 ustar askhl askhl import numpy as np
import __builtin__
pymin = __builtin__.min
pymax = __builtin__.max
class LineSearch:
def __init__(self, xtol=1e-14):
self.xtol = xtol
self.task = 'START'
self.isave = np.zeros((2,), np.intc)
self.dsave = np.zeros((13,), float)
self.fc = 0
self.gc = 0
self.case = 0
self.old_stp = 0
def _line_search(self, func, myfprime, xk, pk, gfk, old_fval, old_old_fval,
maxstep=.2, c1=.23, c2=0.46, xtrapl=1.1, xtrapu=4.,
stpmax=50., stpmin=1e-8, args=()):
self.stpmin = stpmin
self.pk = pk
p_size = np.sqrt((pk **2).sum())
self.stpmax = stpmax
self.xtrapl = xtrapl
self.xtrapu = xtrapu
self.maxstep = maxstep
phi0 = old_fval
derphi0 = np.dot(gfk,pk)
self.dim = len(pk)
self.gms = np.sqrt(self.dim) * maxstep
#alpha1 = pymin(maxstep,1.01*2*(phi0-old_old_fval)/derphi0)
alpha1 = 1.
self.no_update = False
if isinstance(myfprime,type(())):
eps = myfprime[1]
fprime = myfprime[0]
newargs = (f,eps) + args
gradient = False
else:
fprime = myfprime
newargs = args
gradient = True
fval = old_fval
gval = gfk
self.steps=[]
while 1:
stp = self.step(alpha1, phi0, derphi0, c1, c2,
self.xtol,
self.isave, self.dsave)
if self.task[:2] == 'FG':
alpha1 = stp
fval = func(xk + stp * pk, *args)
self.fc += 1
gval = fprime(xk + stp * pk, *newargs)
if gradient: self.gc += 1
else: self.fc += len(xk) + 1
phi0 = fval
derphi0 = np.dot(gval,pk)
self.old_stp = alpha1
if self.no_update == True:
break
else:
break
if self.task[:5] == 'ERROR' or self.task[1:4] == 'WARN':
stp = None # failed
return stp, fval, old_fval, self.no_update
def step(self, stp, f, g, c1, c2, xtol, isave, dsave):
if self.task[:5] == 'START':
# Check the input arguments for errors.
if stp < self.stpmin:
self.task = 'ERROR: STP .LT. minstep'
if stp > self.stpmax:
self.task = 'ERROR: STP .GT. maxstep'
if g >= 0:
self.task = 'ERROR: INITIAL G >= 0'
if c1 < 0:
self.task = 'ERROR: c1 .LT. 0'
if c2 < 0:
self.task = 'ERROR: c2 .LT. 0'
if xtol < 0:
self.task = 'ERROR: XTOL .LT. 0'
if self.stpmin < 0:
self.task = 'ERROR: minstep .LT. 0'
if self.stpmax < self.stpmin:
self.task = 'ERROR: maxstep .LT. minstep'
if self.task[:5] == 'ERROR':
return stp
# Initialize local variables.
self.bracket = False
stage = 1
finit = f
ginit = g
gtest = c1 * ginit
width = self.stpmax - self.stpmin
width1 = width / .5
# The variables stx, fx, gx contain the values of the step,
# function, and derivative at the best step.
# The variables sty, fy, gy contain the values of the step,
# function, and derivative at sty.
# The variables stp, f, g contain the values of the step,
# function, and derivative at stp.
stx = 0
fx = finit
gx = ginit
sty = 0
fy = finit
gy = ginit
stmin = 0
stmax = stp + self.xtrapu * stp
self.task = 'FG'
self.save((stage, ginit, gtest, gx,
gy, finit, fx, fy, stx, sty,
stmin, stmax, width, width1))
stp = self.determine_step(stp)
#return stp, f, g
return stp
else:
if self.isave[0] == 1:
self.bracket = True
else:
self.bracket = False
stage = self.isave[1]
(ginit, gtest, gx, gy, finit, fx, fy, stx, sty, stmin, stmax, \
width, width1) =self.dsave
# If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the
# algorithm enters the second stage.
ftest = finit + stp * gtest
if stage == 1 and f < ftest and g >= 0.:
stage = 2
# Test for warnings.
if self.bracket and (stp <= stmin or stp >= stmax):
self.task = 'WARNING: ROUNDING ERRORS PREVENT PROGRESS'
if self.bracket and stmax - stmin <= self.xtol * stmax:
self.task = 'WARNING: XTOL TEST SATISFIED'
if stp == self.stpmax and f <= ftest and g <= gtest:
self.task = 'WARNING: STP = maxstep'
if stp == self.stpmin and (f > ftest or g >= gtest):
self.task = 'WARNING: STP = minstep'
# Test for convergence.
if f <= ftest and abs(g) <= c2 * (- ginit):
self.task = 'CONVERGENCE'
# Test for termination.
if self.task[:4] == 'WARN' or self.task[:4] == 'CONV':
self.save((stage, ginit, gtest, gx,
gy, finit, fx, fy, stx, sty,
stmin, stmax, width, width1))
#return stp, f, g
return stp
# A modified function is used to predict the step during the
# first stage if a lower function value has been obtained but
# the decrease is not sufficient.
#if stage == 1 and f <= fx and f > ftest:
# # Define the modified function and derivative values.
# fm =f - stp * gtest
# fxm = fx - stx * gtest
# fym = fy - sty * gtest
# gm = g - gtest
# gxm = gx - gtest
# gym = gy - gtest
# Call step to update stx, sty, and to compute the new step.
# stx, sty, stp, gxm, fxm, gym, fym = self.update (stx, fxm, gxm, sty,
# fym, gym, stp, fm, gm,
# stmin, stmax)
# # Reset the function and derivative values for f.
# fx = fxm + stx * gtest
# fy = fym + sty * gtest
# gx = gxm + gtest
# gy = gym + gtest
#else:
# Call step to update stx, sty, and to compute the new step.
stx, sty, stp, gx, fx, gy, fy= self.update(stx, fx, gx, sty,
fy, gy, stp, f, g,
stmin, stmax)
# Decide if a bisection step is needed.
if self.bracket:
if abs(sty-stx) >= .66 * width1:
stp = stx + .5 * (sty - stx)
width1 = width
width = abs(sty - stx)
# Set the minimum and maximum steps allowed for stp.
if self.bracket:
stmin = min(stx, sty)
stmax = max(stx, sty)
else:
stmin = stp + self.xtrapl * (stp - stx)
stmax = stp + self.xtrapu * (stp - stx)
# Force the step to be within the bounds maxstep and minstep.
stp = max(stp, self.stpmin)
stp = min(stp, self.stpmax)
if (stx == stp and stp == self.stpmax and stmin > self.stpmax):
self.no_update = True
# If further progress is not possible, let stp be the best
# point obtained during the search.
if (self.bracket and stp < stmin or stp >= stmax) \
or (self.bracket and stmax - stmin < self.xtol * stmax):
stp = stx
# Obtain another function and derivative.
self.task = 'FG'
self.save((stage, ginit, gtest, gx,
gy, finit, fx, fy, stx, sty,
stmin, stmax, width, width1))
return stp
def update(self, stx, fx, gx, sty, fy, gy, stp, fp, gp,
stpmin, stpmax):
sign = gp * (gx / abs(gx))
# First case: A higher function value. The minimum is bracketed.
# If the cubic step is closer to stx than the quadratic step, the
# cubic step is taken, otherwise the average of the cubic and
# quadratic steps is taken.
if fp > fx: #case1
self.case = 1
theta = 3. * (fx - fp) / (stp - stx) + gx + gp
s = max(abs(theta), abs(gx), abs(gp))
gamma = s * np.sqrt((theta / s) ** 2. - (gx / s) * (gp / s))
if stp < stx:
gamma = -gamma
p = (gamma - gx) + theta
q = ((gamma - gx) + gamma) + gp
r = p / q
stpc = stx + r * (stp - stx)
stpq = stx + ((gx / ((fx - fp) / (stp-stx) + gx)) / 2.) \
* (stp - stx)
if (abs(stpc - stx) < abs(stpq - stx)):
stpf = stpc
else:
stpf = stpc + (stpq - stpc) / 2.
self.bracket = True
# Second case: A lower function value and derivatives of opposite
# sign. The minimum is bracketed. If the cubic step is farther from
# stp than the secant step, the cubic step is taken, otherwise the
# secant step is taken.
elif sign < 0: #case2
self.case = 2
theta = 3. * (fx - fp) / (stp - stx) + gx + gp
s = max(abs(theta), abs(gx), abs(gp))
gamma = s * np.sqrt((theta / s) ** 2 - (gx / s) * (gp / s))
if stp > stx:
gamma = -gamma
p = (gamma - gp) + theta
q = ((gamma - gp) + gamma) + gx
r = p / q
stpc = stp + r * (stx - stp)
stpq = stp + (gp / (gp - gx)) * (stx - stp)
if (abs(stpc - stp) > abs(stpq - stp)):
stpf = stpc
else:
stpf = stpq
self.bracket = True
# Third case: A lower function value, derivatives of the same sign,
# and the magnitude of the derivative decreases.
elif abs(gp) < abs(gx): #case3
self.case = 3
# The cubic step is computed only if the cubic tends to infinity
# in the direction of the step or if the minimum of the cubic
# is beyond stp. Otherwise the cubic step is defined to be the
# secant step.
theta = 3. * (fx - fp) / (stp - stx) + gx + gp
s = max(abs(theta), abs(gx), abs(gp))
# The case gamma = 0 only arises if the cubic does not tend
# to infinity in the direction of the step.
gamma = s * np.sqrt(max(0.,(theta / s) ** 2-(gx / s) * (gp / s)))
if stp > stx:
gamma = -gamma
p = (gamma - gp) + theta
q = (gamma + (gx - gp)) + gamma
r = p / q
if r < 0. and gamma != 0:
stpc = stp + r * (stx - stp)
elif stp > stx:
stpc = stpmax
else:
stpc = stpmin
stpq = stp + (gp / (gp - gx)) * (stx - stp)
if self.bracket:
# A minimizer has been bracketed. If the cubic step is
# closer to stp than the secant step, the cubic step is
# taken, otherwise the secant step is taken.
if abs(stpc - stp) < abs(stpq - stp):
stpf = stpc
else:
stpf = stpq
if stp > stx:
stpf = min(stp + .66 * (sty - stp), stpf)
else:
stpf = max(stp + .66 * (sty - stp), stpf)
else:
# A minimizer has not been bracketed. If the cubic step is
# farther from stp than the secant step, the cubic step is
# taken, otherwise the secant step is taken.
if abs(stpc - stp) > abs(stpq - stp):
stpf = stpc
else:
stpf = stpq
stpf = min(stpmax, stpf)
stpf = max(stpmin, stpf)
# Fourth case: A lower function value, derivatives of the same sign,
# and the magnitude of the derivative does not decrease. If the
# minimum is not bracketed, the step is either minstep or maxstep,
# otherwise the cubic step is taken.
else: #case4
self.case = 4
if self.bracket:
theta = 3. * (fp - fy) / (sty - stp) + gy + gp
s = max(abs(theta), abs(gy), abs(gp))
gamma = s * np.sqrt((theta / s) ** 2 - (gy / s) * (gp / s))
if stp > sty:
gamma = -gamma
p = (gamma - gp) + theta
q = ((gamma - gp) + gamma) + gy
r = p / q
stpc = stp + r * (sty - stp)
stpf = stpc
elif stp > stx:
stpf = stpmax
else:
stpf = stpmin
# Update the interval which contains a minimizer.
if fp > fx:
sty = stp
fy = fp
gy = gp
else:
if sign < 0:
sty = stx
fy = fx
gy = gx
stx = stp
fx = fp
gx = gp
# Compute the new step.
stp = self.determine_step(stpf)
return stx, sty, stp, gx, fx, gy, fy
def determine_step(self, stp):
dr = stp - self.old_stp
if abs(pymax(self.pk) * dr) > self.maxstep:
dr /= abs((pymax(self.pk) * dr) / self.maxstep)
stp = self.old_stp + dr
return stp
def save(self, data):
if self.bracket:
self.isave[0] = 1
else:
self.isave[0] = 0
self.isave[1] = data[0]
self.dsave = data[1:]
python-ase-3.6.0.2515/ase/utils/deprecate.py 0000644 0001754 0001754 00000002603 11410100502 017377 0 ustar askhl askhl import warnings
class Deprecate:
def __init__(self, obj, name, newmodule, oldmodule='ase'):
self.obj = obj
self.name = name
self.newmodule = newmodule
self.oldmodule = oldmodule
def __call__(self, *args, **kwargs):
message = ('%s.%s is deprecated, use %s.%s instead' %
(self.oldmodule, self.name, self.newmodule, self.name))
warnings.warn(message, DeprecationWarning, stacklevel=2)
return self.obj(*args, **kwargs)
def _dep(method):
def _method(self, *args):
message = ('ase.%s is deprecated, use %s.%s instead' %
(self.name, self.newmodule, self.name))
warnings.warn(message, DeprecationWarning, stacklevel=2)
return method(self, *args)
return _method
class DeprecatedFloat(float):
def __new__(cls, value, name, newmodule):
return float.__new__(cls, value)
def __init__(self, value, name, newmodule):
self.name = name
self.newmodule = newmodule
__mul__ = _dep(float.__mul__)
__rmul__ = _dep(float.__rmul__)
__div__ = _dep(float.__div__)
__rdiv__ = _dep(float.__rdiv__)
class DeprecatedNumpyImport:
def __init__(self):
import numpy
self.numpy = numpy
def __getattr__(self, key):
warnings.warn('ase.np is deprecated; use import numpy as np instead')
return getattr(self.numpy, key)
python-ase-3.6.0.2515/ase/utils/memory.py 0000644 0001754 0001754 00000040514 11216673141 017000 0 ustar askhl askhl import os
import numpy as np
from UserDict import DictMixin
# -------------------------------------------------------------------
class MemoryBase(object, DictMixin):
"""Virtual memory (VM) statistics of the current process
obtained from the relevant entries in /proc//status:
VmPeak Peak virtual memory size in bytes.
VmLck ???
VmHWM Peak resident set size ("high water mark") in bytes.
VmRSS Resident memory usage in bytes.
VmSize VM usage of the entire process in bytes.
VmData VM usage of heap in bytes.
VmStk VM usage of stack in bytes.
VmExe VM usage of exe's and statically linked libraries in bytes.
VmLib VM usage of dynamically linked libraries in bytes.
VmPTE ???
Note that VmSize > VmData + VmStk + VmExe + VmLib due to overhead.
"""
_scale = {'KB':1024.0, 'MB':1024.0**2}
_keys = ('VmPeak', 'VmLck', 'VmHWM', 'VmRSS', 'VmSize', 'VmData', \
'VmStk', 'VmExe', 'VmLib', 'VmPTE')
def __init__(self, verbose=0):
self.verbose = verbose
if self.verbose>=2: print 'MemoryBase.__init__'
object.__init__(self)
self._values = np.empty(len(self._keys), dtype=np.float)
def __repr__(self):
"""Return a representation of recorded VM statistics.
x.__repr__() <==> repr(x)"""
if self.verbose>=2: print 'MemoryBase.__repr__'
s = object.__repr__(self)
w = max(map(len, self._keys))
unit = 'MB'
for k,v in self.iteritems():
res = ''
if not np.isnan(v):
res = '%8.3f %s' % (v/self._scale[unit], unit)
s += '\n\t' + k.ljust(w) + ': ' + res.rjust(8)
return s
def __len__(self):
"""Number of VM keys which have not been outdated.
x.__len__() <==> len(x)"""
if self.verbose>=3: print 'MemoryBase.__len__'
return np.sum(~np.isnan(self._values))
def __getitem__(self, key):
"""Return floating point number associated with a VM key.
x.__getitem__(y) <==> x[y]"""
if self.verbose>=2: print 'MemoryBase.__getitem__'
if key not in self:
raise KeyError(key)
i = self.keys().index(key)
return self._values[i]
def __setitem__(self, key, value):
"""x.__setitem__(i, y) <==> x[i]=y"""
if self.verbose>=2: print 'MemoryBase.__setitem__'
raise Exception('Virtual member function.')
def __delitem__(self, key):
"""x.__delitem__(y) <==> del x[y]"""
if self.verbose>=2: print 'MemoryBase.__delitem__'
raise Exception('Virtual member function.')
def clear(self):
"""D.clear() -> None. Remove all items from D."""
if self.verbose>=1: print 'MemoryBase.clear'
raise Exception('Virtual member function.')
def update(self, other=None):
"""D.update(E) -> None. Update D from E: for k in E.keys(): D[k] = E[k]"""
if self.verbose>=1: print 'MemoryBase.update'
DictMixin.update(self, other)
def copy(self):
"""Return a shallow copy of a VM statistics instance.
D.copy() -> a shallow copy of D"""
if self.verbose>=1: print 'MemoryBase.copy'
res = object.__new__(self.__class__)
MemoryBase.__init__(res, self.verbose)
DictMixin.update(res, self)
return res
def has_key(self, key): #necessary to avoid infinite recursion
"""Return boolean to indicate whether key is a supported VM key.
D.has_key(k) -> True if D has a key k, else False"""
if self.verbose>=3: print 'MemoryBase.has_key'
return key in self._keys
def keys(self):
"""Return list of supported VM keys.
D.keys() -> list of D's keys"""
if self.verbose>=3: print 'MemoryBase.keys'
return list(self._keys)
def values(self):
"""Return list of recorded VM statistics.
D.values() -> list of D's values"""
if self.verbose>=3: print 'MemoryBase.values'
return list(self._values)
def get(self, key, default=None):
"""Return floating point number associated with a VM key.
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None."""
if self.verbose>=1: print 'MemoryBase.get'
v = self[key]
if type(default) in [int,float]:
default = np.float_(default)
if default is not None and not isinstance(default, np.floating):
raise ValueError('Default value must be a floating point number.')
if default is not None and np.isnan(v):
return default
else:
return v
def setdefault(self, key, default=None):
"""Return floating point number associated with a VM key.
D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"""
if self.verbose>=1: print 'MemoryBase.setdefault'
v = self[key]
if type(default) in [int,float]:
default = np.float_(default)
if default is not None and not isinstance(default, np.floating):
raise ValueError('Default value must be a floating point number.')
if default is not None and np.isnan(v):
self[key] = default
return default
else:
return v
def pop(self, key, default=None):
"""Return floating point number for a VM key and mark it as outdated.
D.pop(k[,d]) -> v, remove specified key and return the corresponding value
If key is not found, d is returned if given, otherwise KeyError is raised"""
if self.verbose>=1: print 'MemoryBase.pop'
v = self[key]
if type(default) in [int,float]:
default = np.float_(default)
if default is not None and not isinstance(default, np.floating):
raise ValueError('Default value must be a floating point number.')
if default is not None and np.isnan(v):
return default
else:
del self[key]
return v
def popitem(self):
"""Return floating point number for some not-yet outdated VM key.
D.popitem() -> (k, v), remove and return some (key, value) pair as a
2-tuple; but raise KeyError if D is empty"""
if self.verbose>=1: print 'MemoryBase.popitem'
for k,v in self.iteritems():
if not np.isnan(v):
del self[k]
return (k,v)
raise KeyError
def __add__(self, other):
"""x.__add__(y) <==> x+y"""
if self.verbose>=1: print 'MemoryBase.__add__(%s,%s)' \
% (object.__repr__(self), object.__repr__(other))
res = self.copy()
if isinstance(other, MemoryBase):
res._values.__iadd__(other._values)
elif type(other) in [int,float]:
res._values.__iadd__(other)
else:
raise TypeError('Unsupported operand type')
return res
def __sub__(self, other):
"""x.__sub__(y) <==> x-y"""
if self.verbose>=1: print 'MemoryBase.__sub__(%s,%s)' \
% (object.__repr__(self), object.__repr__(other))
res = self.copy()
if isinstance(other, MemoryBase):
res._values.__isub__(other._values)
elif type(other) in [int,float]:
res._values.__isub__(other)
else:
raise TypeError('Unsupported operand type')
return res
def __radd__(self, other):
"""x.__radd__(y) <==> y+x"""
if self.verbose>=1: print 'MemoryBase.__radd__(%s,%s)' \
% (object.__repr__(self), object.__repr__(other))
res = self.copy()
if isinstance(other, MemoryBase):
res._values.__iadd__(other._values)
elif type(other) in [int,float]:
res._values.__iadd__(other)
else:
raise TypeError('Unsupported operand type')
return res
def __rsub__(self, other):
"""x.__rsub__(y) <==> y-x"""
if self.verbose>=1: print 'MemoryBase.__rsub__(%s,%s)' \
% (object.__repr__(self), object.__repr__(other))
res = self.copy()
res._values.__imul__(-1.0)
if isinstance(other, MemoryBase):
res._values.__iadd__(other._values)
elif type(other) in [int,float]:
res._values.__iadd__(other)
else:
raise TypeError('Unsupported operand type')
return res
# -------------------------------------------------------------------
class MemoryStatistics(MemoryBase):
def __init__(self, verbose=0):
MemoryBase.__init__(self, verbose)
self.update()
def __setitem__(self, key, value):
"""Set VM key to a floating point number.
x.__setitem__(i, y) <==> x[i]=y"""
if self.verbose>=2: print 'MemoryStatistics.__setitem__'
if key not in self:
raise KeyError(key)
if type(value) in [int,float]:
value = np.float_(value)
if not isinstance(value, np.floating):
raise ValueError('Value must be a floating point number.')
i = self.keys().index(key)
self._values[i] = value
def __delitem__(self, key):
"""Mark a VK key as outdated.
x.__delitem__(y) <==> del x[y]"""
if self.verbose>=2: print 'MemoryStatistics.__delitem__'
if key not in self:
raise KeyError(key)
self[key] = np.nan
def clear(self):
"""Mark all supported VM keys as outdated.
D.clear() -> None. Remove all items from D."""
if self.verbose>=1: print 'MemoryStatistics.clear'
self._values[:] = np.nan
def refresh(self):
"""Refresh all outdated VM keys by reading /proc//status."""
if self.verbose>=1: print 'MemoryBase.refresh'
# NB: Linux /proc is for humans; Solaris /proc is for programs!
# TODO: Use pipe from 'prstat -p ' or 'pmap -x 1 1'
# Skip refresh if none are outdated (i.e. nan)
if not np.isnan(self._values).any():
if self.verbose>=2: print 'refresh: skipping...'
return
try:
f = open('/proc/%d/status' % os.getpid(), 'r')
for line in f:
k, v = line.decode('ascii').split(':')
# Only refresh supported keys that are outdated (i.e. nan)
if k in self and np.isnan(self[k]):
t, s = v.strip().split(None, 1)
if self.verbose >= 2:
print 'refresh: k=%s, t=%s, s=%s' % (k, t, s)
self[k] = float(t) * self._scale[s.upper()]
f.close()
except (IOError, UnicodeError, ValueError):
# Reset on error
self.clear()
def update(self, other=None):
"""Update VM statistics from a supplied dict, else clear and refresh.
D.update(E) -> None. Update D from E: for k in E.keys(): D[k] = E[k]"""
if self.verbose>=1: print 'MemoryStatistics.update'
# Call to update without arguments has special meaning
if other is None:
self.clear()
self.refresh()
else:
MemoryBase.update(self, other)
def __iadd__(self, other):
"""x.__iadd__(y) <==> x+=y"""
if self.verbose>=1: print 'MemoryStatistics.__iadd__(%s,%s)' \
% (object.__repr__(self), object.__repr__(other))
if isinstance(other, MemoryBase):
self._values.__iadd__(other._values)
elif type(other) in [int,float]:
self._values.__iadd__(other)
else:
raise TypeError('Unsupported operand type')
return self
def __isub__(self, other):
"""x.__isub__(y) <==> x-=y"""
if self.verbose>=1: print 'MemoryStatistics.__isub__(%s,%s)' \
% (object.__repr__(self), object.__repr__(other))
if isinstance(other, MemoryBase):
self._values.__isub__(other._values)
elif type(other) in [int,float]:
self._values.__isub__(other)
else:
raise TypeError('Unsupported operand type')
return self
# -------------------------------------------------------------------
#http://www.eecho.info/Echo/python/singleton/
#http://mail.python.org/pipermail/python-list/2007-July/622333.html
class Singleton(object):
"""A Pythonic Singleton object."""
def __new__(cls, *args, **kwargs):
if '_inst' not in vars(cls):
cls._inst = object.__new__(cls, *args, **kwargs)
#cls._inst = super(type, cls).__new__(cls, *args, **kwargs)
return cls._inst
class MemorySingleton(MemoryBase, Singleton):
__doc__ = MemoryBase.__doc__ + """
The singleton variant is immutable once it has been instantiated, which
makes it suitable for recording the initial overhead of starting Python."""
def __init__(self, verbose=0):
if verbose>=1: print 'MemorySingleton.__init__'
if '_values' not in vars(self):
if verbose>=1: print 'MemorySingleton.__init__ FIRST!'
# Hack to circumvent singleton immutability
self.__class__ = MemoryStatistics
self.__init__(verbose)
self.__class__ = MemorySingleton
def __setitem__(self, key, value):
"""Disabled for the singleton.
x.__setitem__(i, y) <==> x[i]=y"""
if self.verbose>=2: print 'MemorySingleton.__setitem__'
raise ReferenceError('Singleton is immutable.')
def __delitem__(self, key):
"""Disabled for the singleton.
x.__delitem__(y) <==> del x[y]"""
if self.verbose>=2: print 'MemorySingleton.__delitem__'
raise ReferenceError('Singleton is immutable.')
def clear(self):
"""Disabled for the singleton.
D.clear() -> None. Remove all items from D."""
if self.verbose>=1: print 'MemorySingleton.clear'
raise ReferenceError('Singleton is immutable.')
def update(self):
"""Disabled for the singleton.
D.update(E) -> None. Update D from E: for k in E.keys(): D[k] = E[k]"""
if self.verbose>=1: print 'MemorySingleton.update'
raise ReferenceError('Singleton is immutable.')
def copy(self):
"""Return a shallow non-singleton copy of a VM statistics instance.
D.copy() -> a shallow copy of D"""
if self.verbose>=1: print 'MemorySingleton.copy'
# Hack to circumvent singleton self-copy
self.__class__ = MemoryStatistics
res = self.copy()
self.__class__ = MemorySingleton
return res
# Make sure singleton is instantiated
MemorySingleton()
# -------------------------------------------------------------------
# Helper functions for leak testing with NumPy arrays
def shapegen(size, ndims, ecc=0.5):
"""Return a generator of an N-dimensional array shape
which approximately contains a given number of elements.
size: int or long in [1,inf[
The total number of elements
ndims=3: int in [1,inf[
The number of dimensions
ecc=0.5: float in ]0,1[
The eccentricity of the distribution
"""
assert type(size) in [int,float] and size>=1
assert type(ndims) is int and ndims>=1
assert type(ecc) in [int,float] and ecc>0 and ecc<1
for i in range(ndims-1):
scale = size**(1.0/(ndims-i))
c = round(np.random.uniform((1-ecc)*scale, 1.0/(1-ecc)*scale))
size/=c
yield c
yield round(size)
def shapeopt(maxseed, size, ndims, ecc=0.5):
"""Return optimal estimate of an N-dimensional array shape
which is closest to containing a given number of elements.
maxseed: int in [1,inf[
The maximal number of seeds to try
size: int or long in [1,inf[
The total number of elements
ndims=3: int in [1,inf[
The number of dimensions
ecc=0.5: float in ]0,1[
The eccentricity of the distribution
"""
assert type(maxseed) is int and maxseed>=1
assert type(size) in [int,float] and size>=1
assert type(ndims) is int and ndims>=1
assert type(ecc) in [int,float] and ecc>0 and ecc<1
digits_best = np.inf
shape_best = None
for seed in range(maxseed):
np.random.seed(seed)
shape = tuple(shapegen(size, ndims, ecc))
if np.prod(shape) == size:
return -np.inf, shape
digits = np.log10(abs(np.prod(shape)-size))
if digits < digits_best:
(digits_best, shape_best) = (digits, shape)
return digits_best, shape_best
python-ase-3.6.0.2515/ase/io/ 0000755 0001754 0001754 00000000000 11757245036 014371 5 ustar askhl askhl python-ase-3.6.0.2515/ase/io/aims.py 0000644 0001754 0001754 00000030404 11641564004 015664 0 ustar askhl askhl
def read_aims(filename):
"""Import FHI-aims geometry type files.
Reads unitcell, atom positions and constraints from
a geometry.in file.
"""
from ase import Atoms
from ase.constraints import FixAtoms, FixCartesian
import numpy as np
atoms = Atoms()
fd = open(filename, 'r')
lines = fd.readlines()
fd.close()
positions = []
cell = []
symbols = []
fix = []
fix_cart = []
xyz = np.array([0, 0, 0])
i = -1
n_periodic = -1
periodic = np.array([False, False, False])
for n, line in enumerate(lines):
inp = line.split()
if inp == []:
continue
if inp[0] == 'atom':
if xyz.all():
fix.append(i)
elif xyz.any():
fix_cart.append(FixCartesian(i, xyz))
floatvect = float(inp[1]), float(inp[2]), float(inp[3])
positions.append(floatvect)
symbols.append(inp[-1])
i += 1
xyz = np.array([0, 0, 0])
elif inp[0] == 'lattice_vector':
floatvect = float(inp[1]), float(inp[2]), float(inp[3])
cell.append(floatvect)
n_periodic = n_periodic + 1
periodic[n_periodic] = True
if inp[0] == 'constrain_relaxation':
if inp[1] == '.true.':
fix.append(i)
elif inp[1] == 'x':
xyz[0] = 1
elif inp[1] == 'y':
xyz[1] = 1
elif inp[1] == 'z':
xyz[2] = 1
if xyz.all():
fix.append(i)
elif xyz.any():
fix_cart.append(FixCartesian(i, xyz))
atoms = Atoms(symbols, positions)
if periodic.all():
atoms.set_cell(cell)
atoms.set_pbc(periodic)
if len(fix):
atoms.set_constraint([FixAtoms(indices=fix)]+fix_cart)
else:
atoms.set_constraint(fix_cart)
return atoms
def write_aims(filename, atoms):
"""Method to write FHI-aims geometry files.
Writes the atoms positions and constraints (only FixAtoms is
supported at the moment).
"""
from ase.constraints import FixAtoms, FixCartesian
import numpy as np
if isinstance(atoms, (list, tuple)):
if len(atoms) > 1:
raise RuntimeError("Don't know how to save more than "+
"one image to FHI-aims input")
else:
atoms = atoms[0]
fd = open(filename, 'w')
fd.write('#=======================================================\n')
fd.write('#FHI-aims file: '+filename+'\n')
fd.write('#Created using the Atomic Simulation Environment (ASE)\n')
fd.write('#=======================================================\n')
i = 0
if atoms.get_pbc().any():
for n, vector in enumerate(atoms.get_cell()):
fd.write('lattice_vector ')
for i in range(3):
fd.write('%16.16f ' % vector[i])
fd.write('\n')
fix_cart = np.zeros([len(atoms),3])
if atoms.constraints:
for constr in atoms.constraints:
if isinstance(constr, FixAtoms):
fix_cart[constr.index] = [1,1,1]
elif isinstance(constr, FixCartesian):
fix_cart[constr.a] = -constr.mask+1
for i, atom in enumerate(atoms):
fd.write('atom ')
for pos in atom.position:
fd.write('%16.16f ' % pos)
fd.write(atom.symbol)
fd.write('\n')
# (1) all coords are constrained:
if fix_cart[i].all():
fd.write('constrain_relaxation .true.\n')
# (2) some coords are constrained:
elif fix_cart[i].any():
xyz = fix_cart[i]
for n in range(3):
if xyz[n]:
fd.write('constrain_relaxation %s\n' % 'xyz'[n])
if atom.charge:
fd.write('initial_charge %16.6f\n' % atom.charge)
if atom.magmom:
fd.write('initial_moment %16.6f\n' % atom.magmom)
# except KeyError:
# continue
def read_energy(filename):
for line in open(filename, 'r'):
if line.startswith(' | Total energy corrected'):
E = float(line.split()[-2])
return E
def read_aims_output(filename, index = -1):
""" Import FHI-aims output files with all data available, i.e. relaxations,
MD information, force information etc etc etc. """
from ase import Atoms, Atom
from ase.calculators.singlepoint import SinglePointCalculator
from ase.units import Ang, fs
from ase.constraints import FixAtoms, FixCartesian
molecular_dynamics = False
fd = open(filename, 'r')
cell = []
images = []
fix = []
fix_cart = []
n_periodic = -1
f = None
pbc = False
found_aims_calculator = False
v_unit = Ang/(1000.0*fs)
while True:
line = fd.readline()
if not line:
break
if "List of parameters used to initialize the calculator:" in line:
fd.readline()
calc = read_aims_calculator(fd)
calc.out = filename
found_aims_calculator = True
if "Number of atoms" in line:
inp = line.split()
n_atoms = int(inp[5])
if "| Unit cell:" in line:
if not pbc:
pbc = True
for i in range(3):
inp = fd.readline().split()
cell.append([inp[1],inp[2],inp[3]])
if "Found relaxation constraint for atom" in line:
xyz = [0, 0, 0]
ind = int(line.split()[5][:-1])-1
if "All coordinates fixed" in line:
if ind not in fix:
fix.append(ind)
if "coordinate fixed" in line:
coord = line.split()[6]
constr_ind = 0
if coord == 'x':
xyz[0] = 1
elif coord == 'y':
xyz[1] = 1
elif coord == 'z':
xyz[2] = 1
keep = True
for n,c in enumerate(fix_cart):
if ind == c.a:
keep = False
constr_ind = n
if keep:
fix_cart.append(FixCartesian(ind, xyz))
else:
fix_cart[n].mask[xyz.index(1)] = 0
if "Atomic structure:" in line and not molecular_dynamics:
fd.readline()
atoms = Atoms()
for i in range(n_atoms):
inp = fd.readline().split()
atoms.append(Atom(inp[3],(inp[4],inp[5],inp[6])))
if "Complete information for previous time-step:" in line:
molecular_dynamics = True
if "Updated atomic structure:" in line and not molecular_dynamics:
fd.readline()
atoms = Atoms()
velocities = []
for i in range(n_atoms):
inp = fd.readline().split()
if 'lattice_vector' in inp[0]:
cell = []
for i in range(3):
cell += [[float(inp[1]),float(inp[2]),float(inp[3])]]
inp = fd.readline().split()
atoms.set_cell(cell)
inp = fd.readline().split()
atoms.append(Atom(inp[4],(inp[1],inp[2],inp[3])))
if molecular_dynamics:
inp = fd.readline().split()
if "Atomic structure (and velocities)" in line:
fd.readline()
atoms = Atoms()
velocities = []
for i in range(n_atoms):
inp = fd.readline().split()
atoms.append(Atom(inp[4],(inp[1],inp[2],inp[3])))
inp = fd.readline().split()
velocities += [[float(inp[1])*v_unit,float(inp[2])*v_unit,float(inp[3])*v_unit]]
atoms.set_velocities(velocities)
if len(fix):
atoms.set_constraint([FixAtoms(indices=fix)]+fix_cart)
else:
atoms.set_constraint(fix_cart)
images.append(atoms)
if "Total atomic forces" in line:
f = []
for i in range(n_atoms):
inp = fd.readline().split()
f.append([float(inp[2]),float(inp[3]),float(inp[4])])
if not found_aims_calculator:
e = images[-1].get_potential_energy()
images[-1].set_calculator(SinglePointCalculator(e,f,None,None,atoms))
e = None
f = None
if "Total energy corrected" in line:
e = float(line.split()[5])
if pbc:
atoms.set_cell(cell)
atoms.pbc = True
if not found_aims_calculator:
atoms.set_calculator(SinglePointCalculator(e,None,None,None,atoms))
if not molecular_dynamics:
if len(fix):
atoms.set_constraint([FixAtoms(indices=fix)]+fix_cart)
else:
atoms.set_constraint(fix_cart)
images.append(atoms)
e = None
if found_aims_calculator:
calc.set_results(images[-1])
images[-1].set_calculator(calc)
fd.close()
if molecular_dynamics:
images = images[1:]
# return requested images, code borrowed from ase/io/trajectory.py
if isinstance(index, int):
return images[index]
else:
step = index.step or 1
if step > 0:
start = index.start or 0
if start < 0:
start += len(images)
stop = index.stop or len(images)
if stop < 0:
stop += len(images)
else:
if index.start is None:
start = len(images) - 1
else:
start = index.start
if start < 0:
start += len(images)
if index.stop is None:
stop = -1
else:
stop = index.stop
if stop < 0:
stop += len(images)
return [images[i] for i in range(start, stop, step)]
def read_aims_calculator(file):
""" found instructions for building an FHI-aims calculator in the output file,
read its specifications and return it. """
from ase.calculators.aims import Aims
calc = Aims()
while True:
line = file.readline()
if "=======================================================" in line:
break
else:
args = line.split()
key = '#'
if len(args) > 0:
key = args[0]
if key == '#':
comment = True
elif calc.float_params.has_key(key):
calc.float_params[key] = float(args[1])
elif calc.exp_params.has_key(key):
calc.exp_params[key] = float(args[1])
elif calc.string_params.has_key(key):
calc.string_params[key] = args[1]
if len(args) > 2:
for s in args[2:]:
calc.string_params[key] += " "+s
elif calc.int_params.has_key(key):
calc.int_params[key] = int(args[1])
elif calc.bool_params.has_key(key):
try:
calc.bool_params[key] = bool(args[1])
except:
if key == 'vdw_correction_hirshfeld':
calc.bool_params[key] = True
elif calc.list_params.has_key(key):
if key == 'output':
# build output string from args:
out_option = ''
for arg in args[1:]:
out_option +=str(arg)+' '
if calc.list_params['output'] is not None:
calc.list_params['output'] += [out_option]
else:
calc.list_params['output'] = [out_option]
else:
calc.list_params[key] = list(args[1:])
elif '#' in key:
key = key[1:]
if calc.input_parameters.has_key(key):
calc.input_parameters[key] = args[1]
if len(args) > 2:
for s in args[2:]:
calc.input_parameters[key] += " "+s
else:
raise TypeError('FHI-aims keyword not defined in ASE: ' + key + '. Please check.')
return calc
python-ase-3.6.0.2515/ase/io/__init__.py 0000644 0001754 0001754 00000045512 11706611736 016507 0 ustar askhl askhl import os
import sys
from tarfile import is_tarfile
from zipfile import is_zipfile
from ase.atoms import Atoms
from ase.units import Bohr, Hartree
from ase.io.trajectory import PickleTrajectory
from ase.io.bundletrajectory import BundleTrajectory
from ase.calculators.singlepoint import SinglePointCalculator
__all__ = ['read', 'write', 'PickleTrajectory', 'BundleTrajectory']
def read(filename, index=-1, format=None):
"""Read Atoms object(s) from file.
filename: str
Name of the file to read from.
index: int or slice
If the file contains several configurations, the last configuration
will be returned by default. Use index=n to get configuration
number n (counting from zero).
format: str
Used to specify the file-format. If not given, the
file-format will be guessed by the *filetype* function.
Known formats:
========================= ===========
format short name
========================= ===========
GPAW restart-file gpw
Dacapo netCDF output file dacapo
Old ASE netCDF trajectory nc
Virtual Nano Lab file vnl
ASE pickle trajectory traj
ASE bundle trajectory bundle
GPAW text output gpaw-text
CUBE file cube
XCrySDen Structure File xsf
Dacapo text output dacapo-text
XYZ-file xyz
VASP POSCAR/CONTCAR file vasp
VASP OUTCAR file vasp_out
SIESTA STRUCT file struct_out
ABINIT input file abinit
V_Sim ascii file v_sim
Protein Data Bank pdb
CIF-file cif
FHI-aims geometry file aims
FHI-aims output file aims_out
VTK XML Image Data vti
VTK XML Structured Grid vts
VTK XML Unstructured Grid vtu
TURBOMOLE coord file tmol
TURBOMOLE gradient file tmol-gradient
exciting input exi
AtomEye configuration cfg
WIEN2k structure file struct
DftbPlus input file dftb
CASTEP geom file cell
CASTEP output file castep
CASTEP trajectory file geom
ETSF format etsf.nc
DFTBPlus GEN format gen
CMR db/cmr-file db
CMR db/cmr-file cmr
LAMMPS dump file lammps
========================= ===========
"""
if isinstance(filename, str):
p = filename.rfind('@')
if p != -1:
try:
index = string2index(filename[p + 1:])
except ValueError:
pass
else:
filename = filename[:p]
if isinstance(index, str):
index = string2index(index)
if format is None:
format = filetype(filename)
if format.startswith('gpw'):
import gpaw
r = gpaw.io.open(filename, 'r')
positions = r.get('CartesianPositions') * Bohr
numbers = r.get('AtomicNumbers')
cell = r.get('UnitCell') * Bohr
pbc = r.get('BoundaryConditions')
tags = r.get('Tags')
magmoms = r.get('MagneticMoments')
energy = r.get('PotentialEnergy') * Hartree
if r.has_array('CartesianForces'):
forces = r.get('CartesianForces') * Hartree / Bohr
else:
forces = None
atoms = Atoms(positions=positions,
numbers=numbers,
cell=cell,
pbc=pbc)
if tags.any():
atoms.set_tags(tags)
if magmoms.any():
atoms.set_initial_magnetic_moments(magmoms)
else:
magmoms = None
atoms.calc = SinglePointCalculator(energy, forces, None, magmoms,
atoms)
return atoms
if format == 'castep':
from ase.io.castep import read_castep
return read_castep(filename, index)
if format == 'castep_cell':
import ase.io.castep
return ase.io.castep.read_cell(filename, index)
if format == 'castep_geom':
import ase.io.castep
return ase.io.castep.read_geom(filename, index)
if format == 'exi':
from ase.io.exciting import read_exciting
return read_exciting(filename, index)
if format == 'xyz':
from ase.io.xyz import read_xyz
return read_xyz(filename, index)
if format == 'traj':
from ase.io.trajectory import read_trajectory
return read_trajectory(filename, index)
if format == 'bundle':
from ase.io.bundletrajectory import read_bundletrajectory
return read_bundletrajectory(filename, index)
if format == 'cube':
from ase.io.cube import read_cube
return read_cube(filename, index)
if format == 'nc':
from ase.io.netcdf import read_netcdf
return read_netcdf(filename, index)
if format == 'gpaw-text':
from ase.io.gpawtext import read_gpaw_text
return read_gpaw_text(filename, index)
if format == 'dacapo-text':
from ase.io.dacapo import read_dacapo_text
return read_dacapo_text(filename)
if format == 'dacapo':
from ase.io.dacapo import read_dacapo
return read_dacapo(filename)
if format == 'xsf':
from ase.io.xsf import read_xsf
return read_xsf(filename, index)
if format == 'vasp':
from ase.io.vasp import read_vasp
return read_vasp(filename)
if format == 'vasp_out':
from ase.io.vasp import read_vasp_out
return read_vasp_out(filename, index)
if format == 'abinit':
from ase.io.abinit import read_abinit
return read_abinit(filename)
if format == 'v_sim':
from ase.io.v_sim import read_v_sim
return read_v_sim(filename)
if format == 'mol':
from ase.io.mol import read_mol
return read_mol(filename)
if format == 'pdb':
from ase.io.pdb import read_pdb
return read_pdb(filename, index)
if format == 'cif':
from ase.io.cif import read_cif
return read_cif(filename, index)
if format == 'struct':
from ase.io.wien2k import read_struct
return read_struct(filename)
if format == 'struct_out':
from ase.io.siesta import read_struct
return read_struct(filename)
if format == 'vti':
from ase.io.vtkxml import read_vti
return read_vti(filename)
if format == 'vts':
from ase.io.vtkxml import read_vts
return read_vts(filename)
if format == 'vtu':
from ase.io.vtkxml import read_vtu
return read_vtu(filename)
if format == 'aims':
from ase.io.aims import read_aims
return read_aims(filename)
if format == 'aims_out':
from ase.io.aims import read_aims_output
return read_aims_output(filename, index)
if format == 'iwm':
from ase.io.iwm import read_iwm
return read_iwm(filename)
if format == 'Cmdft':
from ase.io.cmdft import read_I_info
return read_I_info(filename)
if format == 'tmol':
from ase.io.turbomole import read_turbomole
return read_turbomole(filename)
if format == 'tmol-gradient':
from ase.io.turbomole import read_turbomole_gradient
return read_turbomole_gradient(filename)
if format == 'cfg':
from ase.io.cfg import read_cfg
return read_cfg(filename)
if format == 'dftb':
from ase.io.dftb import read_dftb
return read_dftb(filename)
if format == 'sdf':
from ase.io.sdf import read_sdf
return read_sdf(filename)
if format == 'etsf':
from ase.io.etsf import ETSFReader
return ETSFReader(filename).read_atoms()
if format == 'gen':
from ase.io.gen import read_gen
return read_gen(filename)
if format == 'db':
from ase.io.cmr_io import read_db
return read_db(filename, index)
if format == 'lammps':
from ase.io.lammps import read_lammps_dump
return read_lammps_dump(filename, index)
raise RuntimeError('File format descriptor '+format+' not recognized!')
def write(filename, images, format=None, **kwargs):
"""Write Atoms object(s) to file.
filename: str
Name of the file to write to.
images: Atoms object or list of Atoms objects
A single Atoms object or a list of Atoms objects.
format: str
Used to specify the file-format. If not given, the
file-format will be taken from suffix of the filename.
The accepted output formats:
========================= ===========
format short name
========================= ===========
ASE pickle trajectory traj
ASE bundle trajectory bundle
CUBE file cube
XYZ-file xyz
VASP POSCAR/CONTCAR file vasp
ABINIT input file abinit
Protein Data Bank pdb
CIF-file cif
XCrySDen Structure File xsf
FHI-aims geometry file aims
gOpenMol .plt file plt
Python script py
Encapsulated Postscript eps
Portable Network Graphics png
Persistance of Vision pov
VTK XML Image Data vti
VTK XML Structured Grid vts
VTK XML Unstructured Grid vtu
TURBOMOLE coord file tmol
exciting exi
AtomEye configuration cfg
WIEN2k structure file struct
CASTEP cell file cell
DftbPlus input file dftb
ETSF etsf.nc
DFTBPlus GEN format gen
CMR db/cmr-file db
CMR db/cmr-file cmr
========================= ===========
The use of additional keywords is format specific.
The ``cube`` and ``plt`` formats accept (plt requires it) a ``data``
keyword, which can be used to write a 3D array to the file along
with the nuclei coordinates.
The ``vti``, ``vts`` and ``vtu`` formats are all specifically directed
for use with MayaVi, and the latter is designated for visualization of
the atoms whereas the two others are intended for volume data. Further,
it should be noted that the ``vti`` format is intended for orthogonal
unit cells as only the grid-spacing is stored, whereas the ``vts`` format
additionally stores the coordinates of each grid point, thus making it
useful for volume date in more general unit cells.
The ``eps``, ``png``, and ``pov`` formats are all graphics formats,
and accept the additional keywords:
rotation: str (default '')
The rotation angles, e.g. '45x,70y,90z'.
show_unit_cell: int (default 0)
Can be 0, 1, 2 to either not show, show, or show all of the unit cell.
radii: array or float (default 1.0)
An array of same length as the list of atoms indicating the sphere radii.
A single float specifies a uniform scaling of the default covalent radii.
bbox: 4 floats (default None)
Set the bounding box to (xll, yll, xur, yur) (lower left, upper right).
colors: array (default None)
An array of same length as the list of atoms, indicating the rgb color
code for each atom. Default is the jmol_colors of ase/data/colors.
scale: int (default 20)
Number of pixels per Angstrom.
For the ``pov`` graphics format, ``scale`` should not be specified.
The elements of the color array can additionally be strings, or 4
and 5 vectors for named colors, rgb + filter, and rgb + filter + transmit
specification. This format accepts the additional keywords:
``run_povray``, ``display``, ``pause``, ``transparent``,
``canvas_width``, ``canvas_height``, ``camera_dist``,
``image_plane``, ``camera_type``, ``point_lights``,
``area_light``, ``background``, ``textures``, ``celllinewidth``,
``bondlinewidth``, ``bondatoms``
"""
if format is None:
if filename == '-':
format = 'xyz'
filename = sys.stdout
elif 'POSCAR' in filename or 'CONTCAR' in filename:
format = 'vasp'
elif 'OUTCAR' in filename:
format = 'vasp_out'
elif filename.endswith('etsf.nc'):
format = 'etsf'
else:
suffix = filename.split('.')[-1]
format = {'cell':'castep_cell',
}.get(suffix, suffix) # XXX this does not make sense
# Maybe like this:
## format = {'traj': 'trajectory',
## 'nc': 'netcdf',
## 'exi': 'exciting',
## 'in': 'aims',
## 'tmol': 'turbomole',
## }.get(suffix, suffix)
if format == 'castep_cell':
from ase.io.castep import write_cell
write_cell(filename, images, **kwargs)
return
if format == 'exi':
from ase.io.exciting import write_exciting
write_exciting(filename, images)
return
if format == 'cif':
from ase.io.cif import write_cif
write_cif(filename, images)
if format == 'xyz':
from ase.io.xyz import write_xyz
write_xyz(filename, images)
return
if format == 'gen':
from ase.io.gen import write_gen
write_gen(filename, images)
return
elif format == 'in':
format = 'aims'
elif format == 'tmol':
from ase.io.turbomole import write_turbomole
write_turbomole(filename, images)
return
elif format == 'dftb':
from ase.io.dftb import write_dftb
write_dftb(filename, images)
return
elif format == 'struct':
from ase.io.wien2k import write_struct
write_struct(filename, images, **kwargs)
return
elif format == 'findsym':
from ase.io.findsym import write_findsym
write_findsym(filename, images)
return
elif format == 'etsf':
from ase.io.etsf import ETSFWriter
writer = ETSFWriter(filename)
if not isinstance(images, (list, tuple)):
images = [images]
writer.write_atoms(images[0])
writer.close()
return
elif format == 'db' or format == 'cmr':
from ase.io.cmr_io import write_db
return write_db(filename, images, **kwargs)
format = {'traj': 'trajectory',
'nc': 'netcdf',
'bundle': 'bundletrajectory'
}.get(format, format)
name = 'write_' + format
if format in ['vti', 'vts', 'vtu']:
format = 'vtkxml'
if format is None:
format = filetype(filename)
try:
write = getattr(__import__('ase.io.%s' % format, {}, {}, [name]), name)
except ImportError:
raise TypeError('Unknown format: "%s".' % format)
write(filename, images, **kwargs)
def string2index(string):
if ':' not in string:
return int(string)
i = []
for s in string.split(':'):
if s == '':
i.append(None)
else:
i.append(int(s))
i += (3 - len(i)) * [None]
return slice(*i)
def filetype(filename):
"""Try to guess the type of the file."""
if os.path.isdir(filename):
# Potentially a BundleTrajectory
if BundleTrajectory.is_bundle(filename):
return 'bundle'
else:
raise IOError('Directory: ' + filename)
fileobj = open(filename)
s3 = fileobj.read(3)
if len(s3) == 0:
raise IOError('Empty file: ' + filename)
if filename.lower().endswith('.db') or filename.lower().endswith('.cmr'):
return 'db'
if is_tarfile(filename):
return 'gpw'
if s3 == 'CDF':
from ase.io.pupynere import NetCDFFile
nc = NetCDFFile(filename)
if 'number_of_dynamic_atoms' in nc.dimensions:
return 'dacapo'
history = nc.history
if history == 'GPAW restart file':
return 'gpw-nc'
if history == 'ASE trajectory':
return 'nc'
if history == 'Dacapo':
return 'dacapo'
if hasattr(nc, 'file_format') and nc.file_format.startswith('ETSF'):
return 'etsf'
raise IOError('Unknown netCDF file!')
if is_zipfile(filename):
return 'vnl'
fileobj.seek(0)
lines = fileobj.readlines(1000)
if lines[0].startswith('PickleTrajectory'):
return 'traj'
if lines[1].startswith('OUTER LOOP:') or filename.lower().endswith('.cube'):
return 'cube'
if ' ___ ___ ___ _ _ _ \n' in lines:
return 'gpaw-text'
if (' &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n'
in lines[:90]):
return 'dacapo-text'
for line in lines:
if line[0] != '#':
word = line.strip()
if word in ['ANIMSTEPS', 'CRYSTAL', 'SLAB', 'POLYMER', 'MOLECULE']:
return 'xsf'
filename_v = os.path.basename(filename)
if 'POSCAR' in filename_v or 'CONTCAR' in filename_v:
return 'vasp'
if 'OUTCAR' in filename_v:
return 'vasp_out'
if filename.lower().endswith('.exi'):
return 'exi'
if filename.lower().endswith('.mol'):
return 'mol'
if filename.lower().endswith('.pdb'):
return 'pdb'
if filename.lower().endswith('.cif'):
return 'cif'
if filename.lower().endswith('.struct'):
return 'struct'
if filename.lower().endswith('.struct_out'):
return 'struct_out'
for line in lines:
if 'Invoking FHI-aims ...' in line:
return 'aims_out'
if 'atom' in line:
data = line.split()
try:
a = Atoms(symbols=[data[4]],positions = [[float(data[1]),float(data[2]),float(data[3])]])
return 'aims'
except:
pass
if filename.lower().endswith('.in'):
return 'aims'
if filename.lower().endswith('.cfg'):
return 'cfg'
if os.path.split(filename)[1] == 'atoms.dat':
return 'iwm'
if filename.endswith('I_info'):
return 'Cmdft'
if lines[0].startswith('$coord') or os.path.basename(filename) == 'coord':
return 'tmol'
if lines[0].startswith('$grad') or os.path.basename(filename) == 'gradient':
return 'tmol-gradient'
if lines[0].startswith('Geometry'):
return 'dftb'
if filename.lower().endswith('.geom'):
return 'castep_geom'
if filename.lower().endswith('.castep'):
return 'castep'
if filename.lower().endswith('.cell'):
return 'castep_cell'
if s3 == '0.3.2 is required')
python-ase-3.6.0.2515/ase/io/nwchem.py 0000644 0001754 0001754 00000003664 11721163635 016230 0 ustar askhl askhl from cStringIO import StringIO
from ase.atoms import Atoms
from ase.io.xyz import read_xyz
def read_nwchem(filename):
"""Method to read geometry from a nwchem output
"""
from ase import Atoms, Atom
if isinstance(filename, str):
f = open(filename)
lines = f.readlines()
i = 0
while i < len(lines):
if lines[i].find('XYZ format geometry') >=0:
natoms = int(lines[i + 2].split()[0])
string = ''
for j in range(2, natoms + 4):
xyzstring = lines[i + j]
symbol = xyzstring.split()[0].strip()
# replace bq ghost with X: MDTMP can we do better?
if symbol.startswith('bq'):
xyzstring = xyzstring.replace(symbol, 'X')
string += xyzstring
atoms = read_xyz(StringIO(string))
i += natoms + 4
else:
i += 1
if type(filename) == str:
f.close()
return atoms
def write_nwchem(filename, atoms, geometry=None):
"""Method to write nwchem coord file
"""
import numpy as np
if isinstance(filename, str):
f = open(filename, 'w')
else: # Assume it's a 'file-like object'
f = filename
# autosym and autoz are defaults
# http://www.nwchem-sw.org/index.php/Geometry
# geometry noautoz results in higher memory demand!
# http://www.emsl.pnl.gov/docs/nwchem/nwchem-support/2010/10/0060.RE:_NWCHEM_Geometry_problem_fwd_
if geometry is not None:
f.write('geometry ' + str(geometry) + '\n')
else:
f.write('geometry\n')
for atom in atoms:
if atom.tag == -71: # 71 is ascii G (Ghost)
symbol = 'bq' + atom.symbol
else:
symbol = atom.symbol
f.write(' ' + symbol + ' ' +
str(atom.position[0]) + ' ' +
str(atom.position[1]) + ' ' +
str(atom.position[2]) + '\n' )
f.write('end\n')
python-ase-3.6.0.2515/ase/io/pupynere.py 0000644 0001754 0001754 00000051344 11144273672 016616 0 ustar askhl askhl """
NetCDF reader/writer module.
This module implements the Scientific.IO.NetCDF API to read and create
NetCDF files. The same API is also used in the PyNIO and pynetcdf
modules, allowing these modules to be used interchangebly when working
with NetCDF files. The major advantage of ``scipy.io.netcdf`` over other
modules is that it doesn't require the code to be linked to the NetCDF
libraries as the other modules do.
The code is based on the NetCDF file format specification
(http://www.unidata.ucar.edu/software/netcdf/guide_15.html). A NetCDF
file is a self-describing binary format, with a header followed by
data. The header contains metadata describing dimensions, variables
and the position of the data in the file, so access can be done in an
efficient manner without loading unnecessary data into memory. We use
the ``mmap`` module to create Numpy arrays mapped to the data on disk,
for the same purpose.
The structure of a NetCDF file is as follows:
C D F
Record data refers to data where the first axis can be expanded at
will. All record variables share a same dimension at the first axis,
and they are stored at the end of the file per record, ie
A[0], B[0], ..., A[1], B[1], ..., etc,
so that new data can be appended to the file without changing its original
structure. Non-record data are padded to a 4n bytes boundary. Record data
are also padded, unless there is exactly one record variable in the file,
in which case the padding is dropped. All data is stored in big endian
byte order.
The Scientific.IO.NetCDF API allows attributes to be added directly to
instances of ``netcdf_file`` and ``netcdf_variable``. To differentiate
between user-set attributes and instance attributes, user-set attributes
are automatically stored in the ``_attributes`` attribute by overloading
``__setattr__``. This is the reason why the code sometimes uses
``obj.__dict__['key'] = value``, instead of simply ``obj.key = value``;
otherwise the key would be inserted into userspace attributes.
To create a NetCDF file::
>>> import time
>>> f = netcdf_file('simple.nc', 'w')
>>> f.history = 'Created for a test'
>>> f.createDimension('time', 10)
>>> time = f.createVariable('time', 'i', ('time',))
>>> time[:] = range(10)
>>> time.units = 'days since 2008-01-01'
>>> f.close()
To read the NetCDF file we just created::
>>> f = netcdf_file('simple.nc', 'r')
>>> print f.history
Created for a test
>>> time = f.variables['time']
>>> print time.units
days since 2008-01-01
>>> print time.shape
(10,)
>>> print time[-1]
9
>>> f.close()
TODO: properly implement ``_FillValue``.
"""
__all__ = ['netcdf_file', 'netcdf_variable']
from operator import mul
from mmap import mmap, ACCESS_READ
from numpy import fromstring, ndarray, dtype, empty, array, asarray
from numpy import little_endian as LITTLE_ENDIAN
ABSENT = '\x00\x00\x00\x00\x00\x00\x00\x00'
ZERO = '\x00\x00\x00\x00'
NC_BYTE = '\x00\x00\x00\x01'
NC_CHAR = '\x00\x00\x00\x02'
NC_SHORT = '\x00\x00\x00\x03'
NC_INT = '\x00\x00\x00\x04'
NC_FLOAT = '\x00\x00\x00\x05'
NC_DOUBLE = '\x00\x00\x00\x06'
NC_DIMENSION = '\x00\x00\x00\n'
NC_VARIABLE = '\x00\x00\x00\x0b'
NC_ATTRIBUTE = '\x00\x00\x00\x0c'
TYPEMAP = { NC_BYTE: ('b', 1),
NC_CHAR: ('c', 1),
NC_SHORT: ('h', 2),
NC_INT: ('i', 4),
NC_FLOAT: ('f', 4),
NC_DOUBLE: ('d', 8) }
REVERSE = { 'b': NC_BYTE,
'c': NC_CHAR,
'h': NC_SHORT,
'i': NC_INT,
'f': NC_FLOAT,
'd': NC_DOUBLE,
# these come from asarray(1).dtype.char and asarray('foo').dtype.char,
# used when getting the types from generic attributes.
'l': NC_INT,
'S': NC_CHAR }
class netcdf_file(object):
"""
A ``netcdf_file`` object has two standard attributes: ``dimensions`` and
``variables``. The values of both are dictionaries, mapping dimension
names to their associated lengths and variable names to variables,
respectively. Application programs should never modify these
dictionaries.
All other attributes correspond to global attributes defined in the
NetCDF file. Global file attributes are created by assigning to an
attribute of the ``netcdf_file`` object.
"""
def __init__(self, filename, mode='r', mmap=True):
if not __debug__:
raise RuntimeError('Current version of pupynere does not ' +
'work with -O option. We need to update ' +
'to version 1.0.7!')
self.filename = filename
self.use_mmap = mmap
assert mode in 'rw', "Mode must be either 'r' or 'w'."
self.mode = mode
self.dimensions = {}
self.variables = {}
self._dims = []
self._recs = 0
self._recsize = 0
self.fp = open(self.filename, '%sb' % mode)
self._attributes = {}
if mode is 'r':
self._read()
def __setattr__(self, attr, value):
# Store user defined attributes in a separate dict,
# so we can save them to file later.
try:
self._attributes[attr] = value
except AttributeError:
pass
self.__dict__[attr] = value
def close(self):
if not self.fp.closed:
try:
self.flush()
finally:
self.fp.close()
__del__ = close
def createDimension(self, name, length):
self.dimensions[name] = length
self._dims.append(name)
def createVariable(self, name, type, dimensions):
shape = tuple([self.dimensions[dim] for dim in dimensions])
shape_ = tuple([dim or 0 for dim in shape]) # replace None with 0 for numpy
if isinstance(type, basestring): type = dtype(type)
typecode, size = type.char, type.itemsize
dtype_ = '>%s' % typecode
if size > 1: dtype_ += str(size)
data = empty(shape_, dtype=dtype_)
self.variables[name] = netcdf_variable(data, typecode, shape, dimensions)
return self.variables[name]
def flush(self):
if self.mode is 'w':
self._write()
sync = flush
def _write(self):
self.fp.write('CDF')
self.__dict__['version_byte'] = 1
self.fp.write(array(1, '>b').tostring())
# Write headers and data.
self._write_numrecs()
self._write_dim_array()
self._write_gatt_array()
self._write_var_array()
def _write_numrecs(self):
# Get highest record count from all record variables.
for var in self.variables.values():
if var.isrec and len(var.data) > self._recs:
self.__dict__['_recs'] = len(var.data)
self._pack_int(self._recs)
def _write_dim_array(self):
if self.dimensions:
self.fp.write(NC_DIMENSION)
self._pack_int(len(self.dimensions))
for name in self._dims:
self._pack_string(name)
length = self.dimensions[name]
self._pack_int(length or 0) # replace None with 0 for record dimension
else:
self.fp.write(ABSENT)
def _write_gatt_array(self):
self._write_att_array(self._attributes)
def _write_att_array(self, attributes):
if attributes:
self.fp.write(NC_ATTRIBUTE)
self._pack_int(len(attributes))
for name, values in attributes.items():
self._pack_string(name)
self._write_values(values)
else:
self.fp.write(ABSENT)
def _write_var_array(self):
if self.variables:
self.fp.write(NC_VARIABLE)
self._pack_int(len(self.variables))
# Sort variables non-recs first, then recs.
variables = self.variables.items()
if True: # Backwards compatible with Python versions < 2.4
keys = [(v._shape and not v.isrec, k) for k, v in variables]
keys.sort()
keys.reverse()
variables = [k for isrec, k in keys]
else: # Python version must be >= 2.4
variables.sort(key=lambda (k, v): v._shape and not v.isrec)
variables.reverse()
variables = [k for (k, v) in variables]
# Set the metadata for all variables.
for name in variables:
self._write_var_metadata(name)
# Now that we have the metadata, we know the vsize of
# each record variable, so we can calculate recsize.
self.__dict__['_recsize'] = sum([
var._vsize for var in self.variables.values()
if var.isrec])
# Set the data for all variables.
for name in variables:
self._write_var_data(name)
else:
self.fp.write(ABSENT)
def _write_var_metadata(self, name):
var = self.variables[name]
self._pack_string(name)
self._pack_int(len(var.dimensions))
for dimname in var.dimensions:
dimid = self._dims.index(dimname)
self._pack_int(dimid)
self._write_att_array(var._attributes)
nc_type = REVERSE[var.typecode()]
self.fp.write(nc_type)
if not var.isrec:
vsize = var.data.size * var.data.itemsize
vsize += -vsize % 4
else: # record variable
try:
vsize = var.data[0].size * var.data.itemsize
except IndexError:
vsize = 0
rec_vars = len([var for var in self.variables.values()
if var.isrec])
if rec_vars > 1:
vsize += -vsize % 4
self.variables[name].__dict__['_vsize'] = vsize
self._pack_int(vsize)
# Pack a bogus begin, and set the real value later.
self.variables[name].__dict__['_begin'] = self.fp.tell()
self._pack_begin(0)
def _write_var_data(self, name):
var = self.variables[name]
# Set begin in file header.
the_beguine = self.fp.tell()
self.fp.seek(var._begin)
self._pack_begin(the_beguine)
self.fp.seek(the_beguine)
# Write data.
if not var.isrec:
self.fp.write(var.data.tostring())
count = var.data.size * var.data.itemsize
self.fp.write('0' * (var._vsize - count))
else: # record variable
# Handle rec vars with shape[0] < nrecs.
if self._recs > len(var.data):
shape = (self._recs,) + var.data.shape[1:]
var.data.resize(shape)
pos0 = pos = self.fp.tell()
for rec in var.data:
# Apparently scalars cannot be converted to big endian. If we
# try to convert a ``=i4`` scalar to, say, '>i4' the dtype
# will remain as ``=i4``.
if not rec.shape and (rec.dtype.byteorder == '<' or
(rec.dtype.byteorder == '=' and LITTLE_ENDIAN)):
rec = rec.byteswap()
self.fp.write(rec.tostring())
# Padding
count = rec.size * rec.itemsize
self.fp.write('0' * (var._vsize - count))
pos += self._recsize
self.fp.seek(pos)
self.fp.seek(pos0 + var._vsize)
def _write_values(self, values):
values = asarray(values)
values = values.astype(values.dtype.newbyteorder('>'))
nc_type = REVERSE[values.dtype.char]
self.fp.write(nc_type)
if values.dtype.char == 'S':
nelems = values.itemsize
else:
nelems = values.size
self._pack_int(nelems)
if not values.shape and (values.dtype.byteorder == '<' or
(values.dtype.byteorder == '=' and LITTLE_ENDIAN)):
values = values.byteswap()
self.fp.write(values.tostring())
count = values.size * values.itemsize
self.fp.write('0' * (-count % 4)) # pad
def _read(self):
# Check magic bytes and version
assert self.fp.read(3) == 'CDF', "Error: %s is not a valid NetCDF 3 file" % self.filename
self.__dict__['version_byte'] = fromstring(self.fp.read(1), '>b')[0]
# Read file headers and set data.
self._read_numrecs()
self._read_dim_array()
self._read_gatt_array()
self._read_var_array()
def _read_numrecs(self):
self.__dict__['_recs'] = self._unpack_int()
def _read_dim_array(self):
assert self.fp.read(4) in [ZERO, NC_DIMENSION]
count = self._unpack_int()
for dim in range(count):
name = self._unpack_string()
length = self._unpack_int() or None # None for record dimension
self.dimensions[name] = length
self._dims.append(name) # preserve order
def _read_gatt_array(self):
for k, v in self._read_att_array().items():
self.__setattr__(k, v)
def _read_att_array(self):
assert self.fp.read(4) in [ZERO, NC_ATTRIBUTE]
count = self._unpack_int()
attributes = {}
for attr in range(count):
name = self._unpack_string()
attributes[name] = self._read_values()
return attributes
def _read_var_array(self):
assert self.fp.read(4) in [ZERO, NC_VARIABLE]
begin = 0
dtypes = {'names': [], 'formats': []}
rec_vars = []
count = self._unpack_int()
for var in range(count):
name, dimensions, shape, attributes, typecode, size, dtype_, begin_, vsize = self._read_var()
if shape and shape[0] is None:
rec_vars.append(name)
self.__dict__['_recsize'] += vsize
if begin == 0: begin = begin_
dtypes['names'].append(name)
dtypes['formats'].append(str(shape[1:]) + dtype_)
# Handle padding with a virtual variable.
if typecode in 'bch':
actual_size = reduce(mul, (1,) + shape[1:]) * size
padding = -actual_size % 4
if padding:
dtypes['names'].append('_padding_%d' % var)
dtypes['formats'].append('(%d,)>b' % padding)
# Data will be set later.
data = None
else:
if self.use_mmap:
mm = mmap(self.fp.fileno(), begin_+vsize, access=ACCESS_READ)
data = ndarray.__new__(ndarray, shape, dtype=dtype_,
buffer=mm, offset=begin_, order=0)
else:
pos = self.fp.tell()
self.fp.seek(begin_)
data = fromstring(self.fp.read(vsize), dtype=dtype_)
data.shape = shape
self.fp.seek(pos)
# Add variable.
self.variables[name] = netcdf_variable(
data, typecode, shape, dimensions, attributes)
if rec_vars:
# Remove padding when only one record variable.
if len(rec_vars) == 1:
dtypes['names'] = dtypes['names'][:1]
dtypes['formats'] = dtypes['formats'][:1]
# Build rec array.
if self.use_mmap:
mm = mmap(self.fp.fileno(), begin+self._recs*self._recsize, access=ACCESS_READ)
rec_array = ndarray.__new__(ndarray, (self._recs,), dtype=dtypes,
buffer=mm, offset=begin, order=0)
else:
pos = self.fp.tell()
self.fp.seek(begin)
rec_array = fromstring(self.fp.read(self._recs*self._recsize), dtype=dtypes)
rec_array.shape = (self._recs,)
self.fp.seek(pos)
for var in rec_vars:
self.variables[var].__dict__['data'] = rec_array[var]
def _read_var(self):
name = self._unpack_string()
dimensions = []
shape = []
dims = self._unpack_int()
for i in range(dims):
dimid = self._unpack_int()
dimname = self._dims[dimid]
dimensions.append(dimname)
dim = self.dimensions[dimname]
shape.append(dim)
dimensions = tuple(dimensions)
shape = tuple(shape)
attributes = self._read_att_array()
nc_type = self.fp.read(4)
vsize = self._unpack_int()
begin = [self._unpack_int, self._unpack_int64][self.version_byte-1]()
typecode, size = TYPEMAP[nc_type]
if typecode is 'c':
dtype_ = '>c'
else:
dtype_ = '>%s' % typecode
if size > 1: dtype_ += str(size)
return name, dimensions, shape, attributes, typecode, size, dtype_, begin, vsize
def _read_values(self):
nc_type = self.fp.read(4)
n = self._unpack_int()
typecode, size = TYPEMAP[nc_type]
count = n*size
values = self.fp.read(count)
self.fp.read(-count % 4) # read padding
if typecode is not 'c':
values = fromstring(values, dtype='>%s%d' % (typecode, size))
if values.shape == (1,): values = values[0]
else:
values = values.rstrip('\x00')
return values
def _pack_begin(self, begin):
if self.version_byte == 1:
self._pack_int(begin)
elif self.version_byte == 2:
self._pack_int64(begin)
def _pack_int(self, value):
self.fp.write(array(value, '>i').tostring())
_pack_int32 = _pack_int
def _unpack_int(self):
return int(fromstring(self.fp.read(4), '>i')[0])
_unpack_int32 = _unpack_int
def _pack_int64(self, value):
self.fp.write(array(value, '>q').tostring())
def _unpack_int64(self):
return int(fromstring(self.fp.read(8), '>q')[0])
def _pack_string(self, s):
count = len(s)
self._pack_int(count)
self.fp.write(s)
self.fp.write('0' * (-count % 4)) # pad
def _unpack_string(self):
count = self._unpack_int()
s = self.fp.read(count).rstrip('\x00')
self.fp.read(-count % 4) # read padding
return s
class netcdf_variable(object):
"""
``netcdf_variable`` objects are constructed by calling the method
``createVariable`` on the netcdf_file object.
``netcdf_variable`` objects behave much like array objects defined in
Numpy, except that their data resides in a file. Data is read by
indexing and written by assigning to an indexed subset; the entire
array can be accessed by the index ``[:]`` or using the methods
``getValue`` and ``assignValue``. ``netcdf_variable`` objects also
have attribute ``shape`` with the same meaning as for arrays, but
the shape cannot be modified. There is another read-only attribute
``dimensions``, whose value is the tuple of dimension names.
All other attributes correspond to variable attributes defined in
the NetCDF file. Variable attributes are created by assigning to an
attribute of the ``netcdf_variable`` object.
"""
def __init__(self, data, typecode, shape, dimensions, attributes=None):
self.data = data
self._typecode = typecode
self._shape = shape
self.dimensions = dimensions
self._attributes = attributes or {}
for k, v in self._attributes.items():
self.__dict__[k] = v
def __setattr__(self, attr, value):
# Store user defined attributes in a separate dict,
# so we can save them to file later.
try:
self._attributes[attr] = value
except AttributeError:
pass
self.__dict__[attr] = value
def isrec(self):
return self.data.shape and not self._shape[0]
isrec = property(isrec)
def shape(self):
return self.data.shape
shape = property(shape)
def getValue(self):
return self.data.item()
def assignValue(self, value):
self.data.itemset(value)
def typecode(self):
return self._typecode
def __getitem__(self, index):
return self.data[index]
def __setitem__(self, index, data):
# Expand data for record vars?
if self.isrec:
if isinstance(index, tuple):
rec_index = index[0]
else:
rec_index = index
if isinstance(rec_index, slice):
recs = (rec_index.start or 0) + len(data)
else:
recs = rec_index + 1
if recs > len(self.data):
shape = (recs,) + self._shape[1:]
self.data.resize(shape)
self.data[index] = data
NetCDFFile = netcdf_file
NetCDFVariable = netcdf_variable
python-ase-3.6.0.2515/ase/io/gpawtext.py 0000644 0001754 0001754 00000011501 11631610371 016571 0 ustar askhl askhl import numpy as np
from ase.atoms import Atom, Atoms
from ase.calculators.singlepoint import SinglePointDFTCalculator
from ase.calculators.singlepoint import SinglePointKPoint
def read_gpaw_text(fileobj, index=-1):
if isinstance(fileobj, str):
fileobj = open(fileobj)
def index_startswith(lines, string):
for i, line in enumerate(lines):
if line.startswith(string):
return i
raise ValueError
lines = fileobj.readlines()
images = []
while True:
try:
i = lines.index('Unit Cell:\n')
except ValueError:
pass
else:
cell = []
pbc = []
for line in lines[i + 3:i + 6]:
words = line.split()
if len(words) == 5: # old format
cell.append(float(words[2]))
pbc.append(words[1] == 'yes')
else: # new format with GUC
cell.append([float(word) for word in words[3:6]])
pbc.append(words[2] == 'yes')
try:
i = lines.index('Positions:\n')
except ValueError:
break
atoms = Atoms(cell=cell, pbc=pbc)
for line in lines[i + 1:]:
words = line.split()
if len(words) != 5:
break
n, symbol, x, y, z = words
symbol = symbol.split('.')[0]
atoms.append(Atom(symbol, [float(x), float(y), float(z)]))
lines = lines[i + 5:]
try:
i = lines.index('-------------------------\n')
except ValueError:
e = None
else:
line = lines[i + 9]
assert line.startswith('Zero Kelvin:')
e = float(line.split()[-1])
try:
ii = index_startswith(lines, 'Fermi Level:')
except ValueError:
eFermi = None
else:
try:
eFermi = float(lines[ii].split()[2])
except ValueError: # we have two Fermi levels
fields = lines[ii].split()
def strip(string):
for rubbish in '[],':
string = string.replace(rubbish, '')
return string
eFermi = [float(strip(fields[2])),
float(strip(fields[3])) ]
# read Eigenvalues and occupations
ii1 = ii2 = 1e32
try:
ii1 = index_startswith(lines, ' Band Eigenvalues Occupancy')
except ValueError:
pass
try:
ii2 = index_startswith(lines, ' Band Eigenvalues Occupancy')
except ValueError:
pass
ii = min(ii1, ii2)
if ii == 1e32:
kpts = None
else:
ii += 1
words = lines[ii].split()
vals = []
while(len(words) > 2):
vals.append([float(word) for word in words])
ii += 1
words = lines[ii].split()
vals = np.array(vals).transpose()
kpts = [SinglePointKPoint(0, 0)]
kpts[0].eps_n = vals[1]
kpts[0].f_n = vals[2]
if vals.shape[0] > 3:
kpts.append(SinglePointKPoint(0, 1))
kpts[1].eps_n = vals[3]
kpts[1].f_n = vals[4]
# read charge
try:
ii = index_startswith(lines, 'Total Charge:')
except ValueError:
q = None
else:
q = float(lines[ii].split()[2])
try:
ii = index_startswith(lines, 'Local Magnetic Moments')
except ValueError:
magmoms = None
else:
magmoms = []
for i in range(ii + 1, ii + 1 + len(atoms)):
iii, magmom = lines[i].split()[:2]
magmoms.append(float(magmom))
try:
ii = lines.index('Forces in eV/Ang:\n')
except ValueError:
f = None
else:
f = []
for i in range(ii + 1, ii + 1 + len(atoms)):
try:
x, y, z = lines[i].split()[-3:]
f.append((float(x), float(y), float(z)))
except (ValueError, IndexError), m:
raise IOError('Malformed GPAW log file: %s' % m)
if len(images) > 0 and e is None:
break
if e is not None or f is not None:
calc = SinglePointDFTCalculator(e, f, None, magmoms, atoms, eFermi)
if kpts is not None:
calc.kpts = kpts
atoms.set_calculator(calc)
if q is not None and len(atoms) > 0:
n = len(atoms)
atoms.set_charges([q / n] * n)
images.append(atoms)
lines = lines[i:]
if len(images) == 0:
raise IOError('Corrupted GPAW-text file!')
return images[index]
python-ase-3.6.0.2515/ase/io/py.py 0000644 0001754 0001754 00000001425 11410146060 015354 0 ustar askhl askhl from ase.atoms import Atoms
def write_py(fileobj, images, **kwargs):
if isinstance(fileobj, str):
fileobj = open(fileobj, 'w')
fileobj.write('from ase import Atoms\n\n')
fileobj.write('import numpy as np\n\n')
if not isinstance(images, (list, tuple)):
images = [images]
fileobj.write('images = [\n')
for image in images:
fileobj.write(" Atoms(symbols='%s',\n"
" pbc=np.%s,\n"
" cell=np.array(\n %s,\n"
" positions=np.array(\n %s),\n" % (
image.get_chemical_symbols(reduce=True),
repr(image.pbc),
repr(image.cell)[6:],
repr(image.positions)[6:]))
fileobj.write(']')
python-ase-3.6.0.2515/ase/io/bader.py 0000644 0001754 0001754 00000003313 11267606613 016016 0 ustar askhl askhl import numpy as np
from ase.units import Bohr
def attach_charges(atoms, fileobj='ACF.dat', displacement=1e-4):
"""Attach the charges from the fileobj to the Atoms."""
if isinstance(fileobj, str):
fileobj = open(fileobj)
sep = '---------------'
i = 0 # Counter for the lines
k = 0 # Counter of sep
assume6columns = False
for line in fileobj:
if line[0] == '\n': # check if there is an empty line in the
i -= 1 # head of ACF.dat file
if i == 0:
headings = line
if 'BADER' in headings.split():
j = headings.split().index('BADER')
elif 'CHARGE' in headings.split():
j = headings.split().index('CHARGE')
else:
print 'Can\'t find keyword "BADER" or "CHARGE".' \
+' Assuming the ACF.dat file has 6 columns.'
j = 4
assume6columns = True
if sep in line: # Stop at last seperator line
if k == 1:
break
k += 1
if not i > 1:
pass
else:
words = line.split()
if assume6columns is True:
if len(words) != 6:
raise IOError('Number of columns in ACF file incorrect!\n'
'Check that Bader program version >= 0.25')
atom = atoms[int(words[0]) - 1]
atom.charge = atom.number - float(words[j])
if displacement is not None: # check if the atom positions match
xyz = np.array([float(w) for w in words[1:4]]) * Bohr
assert np.linalg.norm(atom.position - xyz) < displacement
i += 1
python-ase-3.6.0.2515/ase/io/cube.py 0000644 0001754 0001754 00000005473 11307457017 015665 0 ustar askhl askhl """
IO support for the Gaussian cube format.
See the format specifications on:
http://local.wasp.uwa.edu.au/~pbourke/dataformats/cube/
"""
import numpy as np
from ase.atoms import Atoms
from ase.units import Bohr
from ase.parallel import paropen
def write_cube(fileobj, atoms, data=None):
if isinstance(fileobj, str):
fileobj = paropen(fileobj, 'w')
if isinstance(atoms, list):
if len(atoms) > 1:
raise ValueError('Can only write one configuration '
'to a cube file!')
atoms = atoms[0]
if data is None:
data = np.ones((2, 2, 2))
data = np.asarray(data)
if data.dtype == complex:
data = np.abs(data)
fileobj.write('cube file from ase\n')
fileobj.write('OUTER LOOP: X, MIDDLE LOOP: Y, INNER LOOP: Z\n')
cell = atoms.get_cell()
shape = np.array(data.shape)
corner = np.zeros(3)
for i in range(3):
if shape[i] % 2 == 1:
shape[i] += 1
corner += cell[i] / shape[i] / Bohr
fileobj.write('%5d%12.6f%12.6f%12.6f\n' % (len(atoms), corner[0],
corner[1], corner[2]))
for i in range(3):
n = data.shape[i]
d = cell[i] / shape[i] / Bohr
fileobj.write('%5d%12.6f%12.6f%12.6f\n' % (n, d[0], d[1], d[2]))
positions = atoms.get_positions() / Bohr
numbers = atoms.get_atomic_numbers()
for Z, (x, y, z) in zip(numbers, positions):
fileobj.write('%5d%12.6f%12.6f%12.6f%12.6f\n' % (Z, 0.0, x, y, z))
data.tofile(fileobj, sep='\n', format='%e')
def read_cube(fileobj, index=-1, read_data=False):
if isinstance(fileobj, str):
fileobj = open(fileobj)
readline = fileobj.readline
readline()
axes = ['XYZ'.index(s[0]) for s in readline().split()[2::3]]
if axes == []:
axes = [0, 1, 2]
line = readline().split()
natoms = int(line[0])
corner = [Bohr * float(x) for x in line[1:]]
cell = np.empty((3, 3))
shape = []
for i in range(3):
n, x, y, z = [float(s) for s in readline().split()]
shape.append(n)
if n % 2 == 1:
n += 1
cell[i] = n * Bohr * np.array([x, y, z])
numbers = np.empty(natoms, int)
positions = np.empty((natoms, 3))
for i in range(natoms):
line = readline().split()
numbers[i] = int(line[0])
positions[i] = [float(s) for s in line[2:]]
positions *= Bohr
atoms = Atoms(numbers=numbers, positions=positions, cell=cell)
if read_data:
data = np.array([float(s)
for s in fileobj.read().split()]).reshape(shape)
if axes != [0, 1, 2]:
data = data.transpose(axes).copy()
return data, atoms
return atoms
def read_cube_data(fileobj):
return read_cube(fileobj, read_data=True)
python-ase-3.6.0.2515/ase/io/trajectory.py 0000644 0001754 0001754 00000046575 11663247765 017161 0 ustar askhl askhl import os
import sys
import cPickle as pickle
import warnings
from ase.calculators.singlepoint import SinglePointCalculator
from ase.atoms import Atoms
from ase.parallel import rank, barrier
from ase.utils import devnull
class PickleTrajectory:
"""Reads/writes Atoms objects into a .traj file."""
# Per default, write these quantities
write_energy = True
write_forces = True
write_stress = True
write_magmoms = True
write_momenta = True
write_info = True
def __init__(self, filename, mode='r', atoms=None, master=None,
backup=True):
"""A PickleTrajectory can be created in read, write or append mode.
Parameters:
filename:
The name of the parameter file. Should end in .traj.
mode='r':
The mode.
'r' is read mode, the file should already exist, and
no atoms argument should be specified.
'w' is write mode. If the file already exists, is it
renamed by appending .bak to the file name. The atoms
argument specifies the Atoms object to be written to the
file, if not given it must instead be given as an argument
to the write() method.
'a' is append mode. It acts a write mode, except that
data is appended to a preexisting file.
atoms=None:
The Atoms object to be written in write or append mode.
master=None:
Controls which process does the actual writing. The
default is that process number 0 does this. If this
argument is given, processes where it is True will write.
backup=True:
Use backup=False to disable renaming of an existing file.
"""
self.numbers = None
self.pbc = None
self.sanitycheck = True
self.pre_observers = [] # Callback functions before write
self.post_observers = [] # Callback functions after write
self.write_counter = 0 # Counter used to determine when callbacks
# are called
self.offsets = []
if master is None:
master = (rank == 0)
self.master = master
self.backup = backup
self.set_atoms(atoms)
self.open(filename, mode)
def open(self, filename, mode):
"""Opens the file.
For internal use only.
"""
self.fd = filename
if mode == 'r':
if isinstance(filename, str):
self.fd = open(filename, 'rb')
self.read_header()
elif mode == 'a':
exists = True
if isinstance(filename, str):
exists = os.path.isfile(filename)
if exists:
self.fd = open(filename, 'rb')
self.read_header()
self.fd.close()
barrier()
if self.master:
self.fd = open(filename, 'ab+')
else:
self.fd = devnull
elif mode == 'w':
if self.master:
if isinstance(filename, str):
if self.backup and os.path.isfile(filename):
os.rename(filename, filename + '.bak')
self.fd = open(filename, 'wb')
else:
self.fd = devnull
else:
raise ValueError('mode must be "r", "w" or "a".')
def set_atoms(self, atoms=None):
"""Associate an Atoms object with the trajectory.
Mostly for internal use.
"""
if atoms is not None and not hasattr(atoms, 'get_positions'):
raise TypeError('"atoms" argument is not an Atoms object.')
self.atoms = atoms
def read_header(self):
self.fd.seek(0)
try:
if self.fd.read(len('PickleTrajectory')) != 'PickleTrajectory':
raise IOError('This is not a trajectory file!')
d = pickle.load(self.fd)
except EOFError:
raise EOFError('Bad trajectory file.')
self.pbc = d['pbc']
self.numbers = d['numbers']
self.tags = d.get('tags')
self.masses = d.get('masses')
self.constraints = dict2constraints(d)
self.offsets.append(self.fd.tell())
def write(self, atoms=None):
"""Write the atoms to the file.
If the atoms argument is not given, the atoms object specified
when creating the trajectory object is used.
"""
self._call_observers(self.pre_observers)
if atoms is None:
atoms = self.atoms
if hasattr(atoms, 'interpolate'):
# seems to be a NEB
neb = atoms
assert not neb.parallel
try:
neb.get_energies_and_forces(all=True)
except AttributeError:
pass
for image in neb.images:
self.write(image)
return
if len(self.offsets) == 0:
self.write_header(atoms)
else:
if (atoms.pbc != self.pbc).any():
raise ValueError('Bad periodic boundary conditions!')
elif self.sanitycheck and len(atoms) != len(self.numbers):
raise ValueError('Bad number of atoms!')
elif self.sanitycheck and (atoms.numbers != self.numbers).any():
raise ValueError('Bad atomic numbers!')
if atoms.has('momenta'):
momenta = atoms.get_momenta()
else:
momenta = None
d = {'positions': atoms.get_positions(),
'cell': atoms.get_cell(),
'momenta': momenta}
if atoms.get_calculator() is not None:
if self.write_energy:
d['energy'] = atoms.get_potential_energy()
if self.write_forces:
assert self.write_energy
try:
d['forces'] = atoms.get_forces(apply_constraint=False)
except NotImplementedError:
pass
if self.write_stress:
assert self.write_energy
try:
d['stress'] = atoms.get_stress()
except NotImplementedError:
pass
if self.write_magmoms:
try:
if atoms.calc.get_spin_polarized():
d['magmoms'] = atoms.get_magnetic_moments()
except (NotImplementedError, AttributeError):
pass
if 'magmoms' not in d and atoms.has('magmoms'):
d['magmoms'] = atoms.get_initial_magnetic_moments()
if self.write_info:
d['info'] = stringnify_info(atoms.info)
if self.master:
pickle.dump(d, self.fd, protocol=-1)
self.fd.flush()
self.offsets.append(self.fd.tell())
self._call_observers(self.post_observers)
self.write_counter += 1
def write_header(self, atoms):
self.fd.write('PickleTrajectory')
if atoms.has('tags'):
tags = atoms.get_tags()
else:
tags = None
if atoms.has('masses'):
masses = atoms.get_masses()
else:
masses = None
d = {'version': 3,
'pbc': atoms.get_pbc(),
'numbers': atoms.get_atomic_numbers(),
'tags': tags,
'masses': masses,
'constraints': [], # backwards compatibility
'constraints_string': pickle.dumps(atoms.constraints)}
pickle.dump(d, self.fd, protocol=-1)
self.header_written = True
self.offsets.append(self.fd.tell())
# Atomic numbers and periodic boundary conditions are only
# written once - in the header. Store them here so that we can
# check that they are the same for all images:
self.numbers = atoms.get_atomic_numbers()
self.pbc = atoms.get_pbc()
def close(self):
"""Close the trajectory file."""
self.fd.close()
def __getitem__(self, i=-1):
if isinstance(i, slice):
return [self[j] for j in range(*i.indices(len(self)))]
N = len(self.offsets)
if 0 <= i < N:
self.fd.seek(self.offsets[i])
try:
d = pickle.load(self.fd)
except EOFError:
raise IndexError
if i == N - 1:
self.offsets.append(self.fd.tell())
try:
magmoms = d['magmoms']
except KeyError:
magmoms = None
atoms = Atoms(positions=d['positions'],
numbers=self.numbers,
cell=d['cell'],
momenta=d['momenta'],
magmoms=magmoms,
tags=self.tags,
masses=self.masses,
pbc=self.pbc,
info=unstringnify_info(d.get('info', {})),
constraint=[c.copy() for c in self.constraints])
if 'energy' in d:
calc = SinglePointCalculator(
d.get('energy', None), d.get('forces', None),
d.get('stress', None), magmoms, atoms)
atoms.set_calculator(calc)
return atoms
if i >= N:
for j in range(N - 1, i + 1):
atoms = self[j]
return atoms
i = len(self) + i
if i < 0:
raise IndexError('Trajectory index out of range.')
return self[i]
def __len__(self):
if len(self.offsets) == 0:
return 0
N = len(self.offsets) - 1
while True:
self.fd.seek(self.offsets[N])
try:
pickle.load(self.fd)
except EOFError:
return N
self.offsets.append(self.fd.tell())
N += 1
def __iter__(self):
del self.offsets[1:]
return self
def next(self):
try:
return self[len(self.offsets) - 1]
except IndexError:
raise StopIteration
def guess_offsets(self):
size = os.path.getsize(self.fd.name)
while True:
self.fd.seek(self.offsets[-1])
try:
pickle.load(self.fd)
except:
raise EOFError('Damaged trajectory file.')
else:
self.offsets.append(self.fd.tell())
if self.offsets[-1] >= size:
break
if len(self.offsets) > 2:
step1 = self.offsets[-1] - self.offsets[-2]
step2 = self.offsets[-2] - self.offsets[-3]
if step1 == step2:
m = int((size - self.offsets[-1]) / step1) - 1
while m > 1:
self.fd.seek(self.offsets[-1] + m * step1)
try:
pickle.load(self.fd)
except:
m = m / 2
else:
for i in range(m):
self.offsets.append(self.offsets[-1] + step1)
m = 0
def pre_write_attach(self, function, interval=1, *args, **kwargs):
"""Attach a function to be called before writing begins.
function: The function or callable object to be called.
interval: How often the function is called. Default: every time (1).
All other arguments are stored, and passed to the function.
"""
if not callable(function):
raise ValueError('Callback object must be callable.')
self.pre_observers.append((function, interval, args, kwargs))
def post_write_attach(self, function, interval=1, *args, **kwargs):
"""Attach a function to be called after writing ends.
function: The function or callable object to be called.
interval: How often the function is called. Default: every time (1).
All other arguments are stored, and passed to the function.
"""
if not callable(function):
raise ValueError('Callback object must be callable.')
self.post_observers.append((function, interval, args, kwargs))
def _call_observers(self, obs):
"""Call pre/post write observers."""
for function, interval, args, kwargs in obs:
if self.write_counter % interval == 0:
function(*args, **kwargs)
def stringnify_info(info):
"""Return a stringnified version of the dict *info* that is
ensured to be picklable. Items with non-string keys or
unpicklable values are dropped and a warning is issued."""
stringnified = {}
for k, v in info.items():
if not isinstance(k, basestring):
warnings.warn('Non-string info-dict key is not stored in ' +
'trajectory: ' + repr(k), UserWarning)
continue
try:
# Should highest protocol be used here for efficiency?
# Protocol 2 seems not to raise an exception when one
# tries to pickle a file object, so by using that, we
# might end up with file objects in inconsistent states.
s = pickle.dumps(v)
except:
warnings.warn('Skipping not picklable info-dict item: ' +
'"%s" (%s)' % (k, sys.exc_info()[1]), UserWarning)
else:
stringnified[k] = s
return stringnified
def unstringnify_info(stringnified):
"""Convert the dict *stringnified* to a dict with unstringnified
objects and return it. Objects that cannot be unpickled will be
skipped and a warning will be issued."""
info = {}
for k, s in stringnified.items():
try:
v = pickle.loads(s)
except:
warnings.warn('Skipping not unpicklable info-dict item: ' +
'"%s" (%s)' % (k, sys.exc_info()[1]), UserWarning)
else:
info[k] = v
return info
def read_trajectory(filename, index=-1):
traj = PickleTrajectory(filename, mode='r')
if isinstance(index, int):
return traj[index]
else:
# Here, we try to read only the configurations we need to read
# and len(traj) should only be called if we need to as it will
# read all configurations!
# XXX there must be a simpler way?
step = index.step or 1
if step > 0:
start = index.start or 0
if start < 0:
start += len(traj)
stop = index.stop or len(traj)
if stop < 0:
stop += len(traj)
else:
if index.start is None:
start = len(traj) - 1
else:
start = index.start
if start < 0:
start += len(traj)
if index.stop is None:
stop = -1
else:
stop = index.stop
if stop < 0:
stop += len(traj)
return [traj[i] for i in range(start, stop, step)]
def write_trajectory(filename, images):
"""Write image(s) to trajectory.
Write also energy, forces, and stress if they are already
calculated."""
traj = PickleTrajectory(filename, mode='w')
if not isinstance(images, (list, tuple)):
images = [images]
for atoms in images:
# Avoid potentially expensive calculations:
calc = atoms.get_calculator()
if calc is not None:
if hasattr(calc, 'calculation_required'):
if calc.calculation_required(atoms, ['energy']):
traj.write_energy = False
if calc.calculation_required(atoms, ['forces']):
traj.write_forces = False
if calc.calculation_required(atoms, ['stress']):
traj.write_stress = False
if calc.calculation_required(atoms, ['magmoms']):
traj.write_magmoms = False
else:
traj.write_energy = False
traj.write_forces = False
traj.write_stress = False
traj.write_magmoms = False
traj.write(atoms)
traj.close()
def dict2constraints(d):
"""Convert dict unpickled from trajectory file to list of constraints."""
version = d.get('version', 1)
if version == 1:
return d['constraints']
elif version in (2, 3):
try:
return pickle.loads(d['constraints_string'])
except (AttributeError, KeyError, EOFError):
warnings.warn('Could not unpickle constraints!')
return []
else:
return []
def print_trajectory_info(filename):
"""Prints information about a PickleTrajectory file.
Mainly intended to be called from a command line tool.
"""
f = open(filename)
hdr = 'PickleTrajectory'
x = f.read(len(hdr))
if x != hdr:
raise ValueError('Not a PickleTrajectory file!')
# Head header
header = pickle.load(f)
print('Header information of trajectory file %r:' % filename)
print(' Version: %d' % header.get('version', 1))
print(' Boundary conditions: %s' % header['pbc'])
print(' Atomic numbers: shape = %s, type = %s' %
(header['numbers'].shape, header['numbers'].dtype))
if header.get('tags') is None:
print(' Tags are absent.')
else:
print(' Tags: shape = %s, type = %s' %
(header['tags'].shape, header['tags'].dtype))
if header.get('masses') is None:
print(' Masses are absent.')
else:
print(' Masses: shape = %s, type = %s' %
(header['masses'].shape, header['masses'].dtype))
constraints = dict2constraints(header)
if constraints:
print(' %d constraints are present.' % len(constraints))
else:
print(' No constraints.')
after_header = f.tell()
# Read the first frame
frame = pickle.load(f)
print('Contents of first frame:')
for k, v in frame.items():
if hasattr(v, 'shape'):
print(' %s: shape = %s, type = %s' % (k, v.shape, v.dtype))
else:
print(' %s: %s' % (k, v))
after_frame = f.tell()
kB = 1024
MB = 1024 * kB
GB = 1024 * MB
framesize = after_frame - after_header
if framesize >= GB:
print('Frame size: %.2f GB' % (1.0 * framesize / GB))
elif framesize >= MB:
print('Frame size: %.2f MB' % (1.0 * framesize / MB))
else:
print('Frame size: %.2f kB' % (1.0 * framesize / kB))
# Print information about file size
try:
filesize = os.path.getsize(filename)
except IOError:
print('No information about the file size.')
else:
if filesize >= GB:
print('File size: %.2f GB' % (1.0 * filesize / GB))
elif filesize >= MB:
print('File size: %.2f MB' % (1.0 * filesize / MB))
else:
print('File size: %.2f kB' % (1.0 * filesize / kB))
nframes = (filesize - after_header) // framesize
offset = nframes * framesize + after_header - filesize
if offset == 0:
if nframes == 1:
print('Trajectory contains 1 frame.')
else:
print('Trajectory contains %d frames.' % nframes)
else:
print('Trajectory appears to contain approximately %d frames,' %
nframes)
print('but the file size differs by %d bytes from the expected' %
-offset)
print('value.')
python-ase-3.6.0.2515/ase/io/cif.py 0000644 0001754 0001754 00000027523 11710516023 015477 0 ustar askhl askhl """Module to read and write atoms in cif file format.
See http://www.iucr.org/resources/cif/spec/version1.1/cifsyntax for a
description of the file format. STAR extensions as save frames,
global blocks, nested loops and multi-data values are not supported.
"""
import shlex
import re
import numpy as np
from ase.parallel import paropen
from ase.lattice.spacegroup import crystal
from ase.lattice.spacegroup.spacegroup import spacegroup_from_data
def get_lineno(fileobj):
"""Returns the line number of current line in fileobj."""
pos = fileobj.tell()
try:
fileobj.seek(0)
s = fileobj.read(pos)
lineno = s.count('\n')
finally:
fileobj.seek(pos)
return lineno
def unread_line(fileobj):
"""Unread the last line read from *fileobj*."""
# If previous line ends with CRLF, we have to back up one extra
# character before entering the loop below
if fileobj.tell() > 2:
fileobj.seek(-2, 1)
if fileobj.read(2) == '\r\n':
fileobj.seek(-1, 1)
while True:
if fileobj.tell() == 0:
break
fileobj.seek(-2, 1)
if fileobj.read(1) in ('\n', '\r'):
break
def convert_value(value):
"""Convert CIF value string to corresponding python type."""
value = value.strip()
if re.match('(".*")|(\'.*\')$', value):
return value[1:-1]
elif re.match(r'[+-]?\d+$', value):
return int(value)
elif re.match(r'[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$', value):
return float(value)
elif re.match(r'[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?\(\d+\)$',
value):
return float(value[:value.index('(')]) # strip off uncertainties
else:
return value
def parse_multiline_string(fileobj, line):
"""Parse semicolon-enclosed multiline string and return it."""
assert line[0] == ';'
lines = [line[1:].lstrip()]
while True:
line = fileobj.readline().strip()
if line == ';':
break
lines.append(line)
return '\n'.join(lines).strip()
def parse_singletag(fileobj, line):
"""Parse a CIF tag (entries starting with underscore). Returns
a key-value pair."""
kv = line.split(None, 1)
if len(kv) == 1:
key = line
line = fileobj.readline().strip()
while not line or line[0] == '#':
line = fileobj.readline().strip()
if line[0] == ';':
value = parse_multiline_string(fileobj, line)
else:
value = line
else:
key, value = kv
return key, convert_value(value)
def parse_loop(fileobj):
"""Parse a CIF loop. Returns a dict with column tag names as keys
and a lists of the column content as values."""
header = []
line = fileobj.readline().strip()
while line.startswith('_'):
header.append(line.lower())
line = fileobj.readline().strip()
columns = dict([(h, []) for h in header])
tokens = []
while True:
lowerline = line.lower()
if (not line or
line.startswith('_') or
lowerline.startswith('data_') or
lowerline.startswith('loop_')):
break
if line.startswith('#'):
line = fileobj.readline().strip()
continue
if line.startswith(';'):
t = [parse_multiline_string(fileobj, line)]
else:
t = shlex.split(line)
line = fileobj.readline().strip()
tokens.extend(t)
if len(tokens) < len(columns):
continue
assert len(tokens) == len(header)
for h, t in zip(header, tokens):
columns[h].append(convert_value(t))
tokens = []
if line:
unread_line(fileobj)
return columns
def parse_items(fileobj, line):
"""Parse a CIF data items and return a dict with all tags."""
tags = {}
while True:
line = fileobj.readline()
if not line:
break
line = line.strip()
lowerline = line.lower()
if not line or line.startswith('#'):
continue
elif line.startswith('_'):
key, value = parse_singletag(fileobj, line)
tags[key.lower()] = value
elif lowerline.startswith('loop_'):
tags.update(parse_loop(fileobj))
elif lowerline.startswith('data_'):
unread_line(fileobj)
break
elif line.startswith(';'):
temp = parse_multiline_string(fileobj, line)
else:
raise ValueError('%s:%d: Unexpected CIF file entry: "%s"'%(
fileobj.name, get_lineno(fileobj), line))
return tags
def parse_block(fileobj, line):
"""Parse a CIF data block and return a tuple with the block name
and a dict with all tags."""
assert line.lower().startswith('data_')
blockname = line.split('_', 1)[1].rstrip()
tags = parse_items(fileobj, line)
return blockname, tags
def parse_cif(fileobj):
"""Parse a CIF file. Returns a list of blockname and tag
pairs. All tag names are converted to lower case."""
if isinstance(fileobj, basestring):
fileobj = open(fileobj)
blocks = []
while True:
line = fileobj.readline()
if not line:
break
line = line.strip()
if not line or line.startswith('#'):
continue
blocks.append(parse_block(fileobj, line))
return blocks
def tags2atoms(tags, store_tags=False, **kwargs):
"""Returns an Atoms object from a cif tags dictionary. If
*store_tags* is true, the *info* attribute of the returned Atoms
object will be populated with all the cif tags. Keyword arguments
are passed to the Atoms constructor."""
a = tags['_cell_length_a']
b = tags['_cell_length_b']
c = tags['_cell_length_c']
alpha = tags['_cell_angle_alpha']
beta = tags['_cell_angle_beta']
gamma = tags['_cell_angle_gamma']
scaled_positions = np.array([tags['_atom_site_fract_x'],
tags['_atom_site_fract_y'],
tags['_atom_site_fract_z']]).T
symbols = []
if '_atom_site_type_symbol' in tags:
labels = tags['_atom_site_type_symbol']
else:
labels = tags['_atom_site_label']
for s in labels:
# Strip off additional labeling on chemical symbols
m = re.search(r'([A-Z][a-z]?)', s)
symbol = m.group(0)
symbols.append(symbol)
# Symmetry specification, see
# http://www.iucr.org/resources/cif/dictionaries/cif_sym for a
# complete list of official keys. In addition we also try to
# support some commonly used depricated notations
no = None
if '_space_group.it_number' in tags:
no = tags['_space_group.it_number']
elif '_space_group_it_number' in tags:
no = tags['_space_group_it_number']
elif '_symmetry_int_tables_number' in tags:
no = tags['_symmetry_int_tables_number']
symbolHM = None
if '_space_group.Patterson_name_h-m' in tags:
symbolHM = tags['_space_group.patterson_name_h-m']
elif '_symmetry_space_group_name_h-m' in tags:
symbolHM = tags['_symmetry_space_group_name_h-m']
sitesym = None
if '_space_group_symop.operation_xyz' in tags:
sitesym = tags['_space_group_symop.operation_xyz']
elif '_symmetry_equiv_pos_as_xyz' in tags:
sitesym = tags['_symmetry_equiv_pos_as_xyz']
spacegroup = 1
if sitesym is not None:
spacegroup = spacegroup_from_data(no=no, symbol=symbolHM,
sitesym=sitesym)
elif no is not None:
spacegroup = no
elif symbolHM is not None:
spacegroup = symbolHM
else:
spacegroup = 1
if store_tags:
info = tags.copy()
if 'info' in kwargs:
info.update(kwargs['info'])
kwargs['info'] = info
atoms = crystal(symbols, basis=scaled_positions,
cellpar=[a, b, c, alpha, beta, gamma],
spacegroup=spacegroup, **kwargs)
return atoms
def read_cif(fileobj, index=-1, store_tags=False, **kwargs):
"""Read Atoms object from CIF file. *index* specifies the data
block number or name (if string) to return.
If *index* is None or a slice object, a list of atoms objects will
be returned. In the case of *index* is *None* or *slice(None)*,
only blocks with valid crystal data will be included.
If *store_tags* is true, the *info* attribute of the returned
Atoms object will be populated with all tags in the corresponding
cif data block.
Keyword arguments are passed on to the Atoms constructor."""
blocks = parse_cif(fileobj)
if isinstance(index, str):
tags = dict(blocks)[index]
return tags2atoms(tags, **kwargs)
elif isinstance(index, int):
name, tags = blocks[index]
return tags2atoms(tags, **kwargs)
elif index is None or index == slice(None):
# Return all CIF blocks with valid crystal data
images = []
for name, tags in blocks:
try:
atoms = tags2atoms(tags)
images.append(atoms)
except KeyError:
pass
if not images:
# No block contained a a valid atoms object
# Provide an useful error by try converting the first
# block to atoms
name, tags = blocks[0]
tags2atoms(tags)
return images
else:
return [tags2atoms(tags) for name, tags in blocks[index]]
def write_cif(fileobj, images):
"""Write *images* to CIF file."""
if isinstance(fileobj, str):
fileobj = paropen(fileobj, 'w')
if not isinstance(images, (list, tuple)):
images = [images]
for i, atoms in enumerate(images):
fileobj.write('data_image%d\n' % i)
from numpy import arccos, pi, dot
from numpy.linalg import norm
cell = atoms.cell
a = norm(cell[0])
b = norm(cell[1])
c = norm(cell[2])
alpha = arccos(dot(cell[1], cell[2])/(b*c))*180./pi
beta = arccos(dot(cell[0], cell[2])/(a*c))*180./pi
gamma = arccos(dot(cell[0], cell[1])/(a*b))*180./pi
fileobj.write('_cell_length_a %g\n' % a)
fileobj.write('_cell_length_b %g\n' % b)
fileobj.write('_cell_length_c %g\n' % c)
fileobj.write('_cell_angle_alpha %g\n' % alpha)
fileobj.write('_cell_angle_beta %g\n' % beta)
fileobj.write('_cell_angle_gamma %g\n' % gamma)
fileobj.write('\n')
if atoms.pbc.all():
fileobj.write('_symmetry_space_group_name_H-M %s\n' % 'P 1')
fileobj.write('_symmetry_int_tables_number %d\n' % 1)
fileobj.write('\n')
fileobj.write('loop_\n')
fileobj.write(' _symmetry_equiv_pos_as_xyz\n')
fileobj.write(" 'x, y, z'\n")
fileobj.write('\n')
fileobj.write('loop_\n')
fileobj.write(' _atom_site_label\n')
fileobj.write(' _atom_site_occupancy\n')
fileobj.write(' _atom_site_fract_x\n')
fileobj.write(' _atom_site_fract_y\n')
fileobj.write(' _atom_site_fract_z\n')
fileobj.write(' _atom_site_thermal_displace_type\n')
fileobj.write(' _atom_site_B_iso_or_equiv\n')
fileobj.write(' _atom_site_type_symbol\n')
scaled = atoms.get_scaled_positions()
no = {}
for i, atom in enumerate(atoms):
symbol = atom.symbol
if symbol in no:
no[symbol] += 1
else:
no[symbol] = 1
fileobj.write(
' %-8s %6.4f %7.5f %7.5f %7.5f %4s %6.3f %s\n'%(
'%s%d' % (symbol, no[symbol]),
1.0,
scaled[i][0],
scaled[i][1],
scaled[i][2],
'Biso',
1.0,
symbol))
python-ase-3.6.0.2515/ase/io/v_sim.py 0000644 0001754 0001754 00000004621 11656024552 016057 0 ustar askhl askhl """
This module contains functionality for reading an ASE
Atoms object in V_Sim ascii format.
"""
import os
def read_v_sim(filename='demo.ascii'):
"""Import V_Sim input file.
Reads cell, atom positions, etc. from v_sim ascii file
"""
from ase import Atoms, units
from ase.lattice.spacegroup import cell
import re
if isinstance(filename, str):
f = open(filename)
else: # Assume it's a file-like object
f = filename
comment = f.readline()
line = f.readline() + ' ' + f.readline()
box = line.split()
for i in range(len(box)):
box[i] = float(box[i])
keywords = []
positions= []
symbols = []
unit = 1.0
re_comment = re.compile('^\s*[#!]')
re_node = re.compile('^\s*\S+\s+\S+\s+\S+\s+\S+')
while(True):
line = f.readline()
if line == '':
break # EOF
p = re_comment.match(line)
if p != None:
# remove comment character at the beginning of line
line = line[p.end():].replace(',', ' ').lower()
if line[:8] == "keyword:":
keywords.extend(line[8:].split())
elif(re_node.match(line)):
unit = 1.0
if not ("reduced" in keywords) :
if ("bohr" in keywords) or ("bohrd0" in keywords) or ("atomic" in keywords) or ("atomicd0" in keywords):
unit = units.Bohr
fields = line.split()
positions.append([unit*float(fields[0]),
unit*float(fields[1]),
unit*float(fields[2])])
symbols.append(fields[3])
f.close()
if ("surface" in keywords) or ("freeBC" in keywords):
raise NotImplementedError
# create atoms object based on the information
if ("angdeg" in keywords) :
cell = cellpar_to_cell(box)
else:
unit = 1.0
if ("bohr" in keywords) or ("bohrd0" in keywords) or ("atomic" in keywords) or ("atomicd0" in keywords):
unit = units.Bohr
cell = [[unit*box[0], 0.0, 0.0],
[unit*box[1], unit*box[2], 0.0],
[unit*box[3], unit*box[4], unit*box[5]]]
if ("reduced" in keywords) :
atoms = Atoms(cell=cell, scaled_positions=positions)
else :
atoms = Atoms(cell=cell, positions=positions)
atoms.set_chemical_symbols(symbols)
return atoms
python-ase-3.6.0.2515/ase/io/abinit.py 0000644 0001754 0001754 00000012423 11656043534 016210 0 ustar askhl askhl """
This module contains functionality for reading an ASE
Atoms object in ABINIT input format.
"""
import os
def read_abinit(filename='abinit.in'):
"""Import ABINIT input file.
Reads cell, atom positions, etc. from abinit input file
"""
from ase import Atoms, units
if isinstance(filename, str):
f = open(filename)
else: # Assume it's a file-like object
f = filename
lines = f.readlines()
if type(filename) == str:
f.close()
full_file = ''
for line in lines:
if '#' in line:
meat, comment = line.split('#')
else:
meat = line
full_file = full_file + meat + ' '
full_file.strip()
tokens = full_file.lower().split()
# note that the file can not be scanned sequentially
index = tokens.index("acell")
unit = 1.0
if(tokens[index+4].lower()[:3] != 'ang'):
unit = units.Bohr
acell = [unit*float(tokens[index+1]),
unit*float(tokens[index+2]),
unit*float(tokens[index+3])]
index = tokens.index("natom")
natom = int(tokens[index+1])
index = tokens.index("ntypat")
ntypat = int(tokens[index+1])
index = tokens.index("typat")
typat = []
for i in range(natom):
typat.append(int(tokens[index+1+i]))
index = tokens.index("znucl")
znucl = []
for i in range(ntypat):
znucl.append(int(tokens[index+1+i]))
index = tokens.index("rprim")
rprim = []
for i in range(3):
rprim.append([acell[i]*float(tokens[index+3*i+1]),
acell[i]*float(tokens[index+3*i+2]),
acell[i]*float(tokens[index+3*i+3])])
# create a list with the atomic numbers
numbers = []
for i in range(natom):
ii = typat[i] - 1
numbers.append(znucl[ii])
# now the positions of the atoms
if "xred" in tokens:
index = tokens.index("xred")
xred = []
for i in range(natom):
xred.append([float(tokens[index+3*i+1]),
float(tokens[index+3*i+2]),
float(tokens[index+3*i+3])])
atoms = Atoms(cell=rprim, scaled_positions=xred, numbers=numbers)
return atoms
index = None
if "xcart" in tokens:
index = tokens.index("xcart")
unit = units.Bohr
elif "xangs" in tokens:
unit = 1.0
index = tokens.index("xangs")
if(index != None):
xangs = []
for i in range(natom):
xangs.append([unit*float(tokens[index+3*i+1]),
unit*float(tokens[index+3*i+2]),
unit*float(tokens[index+3*i+3])])
atoms = Atoms(cell=rprim, positions=xangs, numbers=numbers)
return atoms
raise IOError("No xred, xcart, or xangs keyword in abinit input file")
def write_abinit(filename, atoms, cartesian=False, long_format=True):
"""Method to write abinit input files."""
import numpy as np
from ase import Atoms, data
if isinstance(filename, str):
f = open(filename, 'w')
else: # Assume it's a 'file-like object'
f = filename
if isinstance(atoms, (list, tuple)):
if len(atoms) > 1:
raise RuntimeError("Don't know how to save more than "+
"one image to input")
else:
atoms = atoms[0]
# Write atom positions in scaled or cartesian coordinates
if cartesian:
coord = atoms.get_positions()
else:
coord = atoms.get_scaled_positions()
# let us order the atoms according to chemical symbol
ind = np.argsort(atoms.get_chemical_symbols())
symbols = np.array(atoms.get_chemical_symbols())[ind]
coord = coord[ind]
# and now we count how many atoms of which type we have
sc = []
psym = symbols[0]
count = 0
for sym in symbols:
if sym != psym:
sc.append((psym, count))
psym = sym
count = 1
else:
count += 1
sc.append((psym, count))
f.write('\n# Definition of the atom types\n')
f.write("ntypat " + str(len(sc)) + "\n")
f.write("znucl ")
for specie in sc:
f.write(str(data.atomic_numbers[specie[0]]) + " ")
f.write('\n')
f.write('\n# Definition of the atoms\n')
f.write('natom ' + str(len(symbols)) + '\n')
f.write('typat ')
typat = 1
for specie in sc:
for natom in range(specie[1]):
f.write(str(typat) + ' ')
typat = typat + 1
f.write('\n')
f.write('\n# Definition of the unit cell\n')
f.write('acell\n')
f.write('%.14f %.14f %.14f Angstrom\n' % (1.0, 1.0, 1.0))
f.write('\n')
f.write('rprim\n')
if long_format:
latt_form = ' %21.16f'
else:
latt_form = ' %11.6f'
for vec in atoms.get_cell():
f.write(' ')
for el in vec:
f.write(latt_form % el)
f.write('\n')
f.write('\n')
# Write atom positions in scaled or cartesian coordinates
if cartesian:
f.write('xangst\n')
else:
f.write('xred\n')
if long_format:
cform = ' %19.16f'
else:
cform = ' %9.6f'
for iatom, atom in enumerate(coord):
f.write(' ')
for dcoord in atom:
f.write(cform % dcoord)
f.write('\n')
if type(filename) == str:
f.close()
python-ase-3.6.0.2515/ase/io/lammps.py 0000644 0001754 0001754 00000007372 11664651351 016243 0 ustar askhl askhl from ase.atoms import Atoms
from ase.quaternions import Quaternions
from ase.parallel import paropen
def read_lammps_dump(fileobj, index=-1):
"""Method which reads a LAMMPS dump file."""
if isinstance(fileobj, str):
f = paropen(fileobj)
else:
f = fileobj
# load everything into memory
lines = f.readlines()
natoms = 0
images = []
while len(lines) > natoms:
line = lines.pop(0)
if 'ITEM: TIMESTEP' in line:
n_atoms = 0
lo = [] ; hi = [] ; tilt = []
id = [] ; type = []
positions = []
velocities = []
forces = []
quaternions = []
if 'ITEM: NUMBER OF ATOMS' in line:
line = lines.pop(0)
natoms = int(line.split()[0])
if 'ITEM: BOX BOUNDS' in line:
# save labels behind "ITEM: BOX BOUNDS" in triclinic case (>=lammps-7Jul09)
tilt_items = line.split()[3:]
for i in range(3):
line = lines.pop(0)
fields = line.split()
lo.append(float(fields[0]))
hi.append(float(fields[1]))
if (len(fields) >= 3):
tilt.append(float(fields[2]))
# determine cell tilt (triclinic case!)
if (len(tilt) >= 3):
# for >=lammps-7Jul09 use labels behind "ITEM: BOX BOUNDS" to assign tilt (vector) elements ...
if (len(tilt_items) >= 3):
xy = tilt[tilt_items.index('xy')]
xz = tilt[tilt_items.index('xz')]
yz = tilt[tilt_items.index('yz')]
# ... otherwise assume default order in 3rd column (if the latter was present)
else:
xy = tilt[0]
xz = tilt[1]
yz = tilt[2]
else:
xy = xz = yz = 0
xhilo = (hi[0] - lo[0]) - xy - xz
yhilo = (hi[1] - lo[1]) - yz
zhilo = (hi[2] - lo[2])
cell = [[xhilo,0,0],[xy,yhilo,0],[xz,yz,zhilo]]
def add_quantity(fields, var, labels):
for label in labels:
if label not in atom_attributes:
return
var.append([float(fields[atom_attributes[label]])
for label in labels])
if 'ITEM: ATOMS' in line:
# (reliably) identify values by labels behind "ITEM: ATOMS" - requires >=lammps-7Jul09
# create corresponding index dictionary before iterating over atoms to (hopefully) speed up lookups...
atom_attributes = {}
for (i, x) in enumerate(line.split()[2:]):
atom_attributes[x] = i
for n in range(natoms):
line = lines.pop(0)
fields = line.split()
id.append( int(fields[atom_attributes['id']]) )
type.append( int(fields[atom_attributes['type']]) )
add_quantity(fields, positions, ['x', 'y', 'z'])
add_quantity(fields, velocities, ['vx', 'vy', 'vz'])
add_quantity(fields, forces, ['fx', 'fy', 'fz'])
add_quantity(fields, quaternions, ['c_q[1]', 'c_q[2]',
'c_q[3]', 'c_q[4]'])
if len(quaternions):
images.append(Quaternions(symbols=type,
positions=positions,
cell=cell,
quaternions=quaternions))
else:
images.append(Atoms(symbols=type,
positions=positions,
cell=cell))
return images[index]
python-ase-3.6.0.2515/ase/io/exciting.py 0000644 0001754 0001754 00000010766 11666143273 016566 0 ustar askhl askhl """
This is the Implementation of the exciting I/O Functions
The functions are called with read write usunf the format "exi"
The module depends on lxml http://codespeak.net/lxml/
"""
from math import pi, cos, sin, sqrt, acos
import numpy as np
from ase.atoms import Atoms
from ase.parallel import paropen
from ase.units import Bohr
def read_exciting(fileobj, index=-1):
"""Reads structure from exiting xml file.
Parameters
----------
fileobj: file object
File handle from which data should be read.
Other parameters
----------------
index: integer -1
Not used in this implementation.
"""
from lxml import etree as ET
#parse file into element tree
doc = ET.parse(fileobj)
root = doc.getroot()
speciesnodes = root.find('structure').getiterator('species')
symbols = []
positions = []
basevects = []
atoms = None
#collect data from tree
for speciesnode in speciesnodes:
symbol = speciesnode.get('speciesfile').split('.')[0]
natoms = speciesnode.getiterator('atom')
for atom in natoms:
x, y, z = atom.get('coord').split()
positions.append([float(x), float(y), float(z)])
symbols.append(symbol)
# scale unit cell accorting to scaling attributes
if doc.xpath('//crystal/@scale'):
scale = float(str(doc.xpath('//crystal/@scale')[0]))
else:
scale = 1
if doc.xpath('//crystal/@stretch'):
a, b, c = doc.xpath('//crystal/@scale')[0].split()
stretch = np.array([float(a),float(b),float(c)])
else:
stretch = np.array([1.0, 1.0, 1.0])
basevectsn = doc.xpath('//basevect/text()')
for basevect in basevectsn:
x, y, z = basevect.split()
basevects.append(np.array([float(x) * Bohr * stretch[0],
float(y) * Bohr * stretch[1],
float(z) * Bohr * stretch[2]
]) * scale)
atoms = Atoms(symbols=symbols, cell=basevects)
atoms.set_scaled_positions(positions)
if 'molecule' in root.find('structure').attrib.keys():
if root.find('structure').attrib['molecule']:
atoms.set_pbc(False)
else:
atoms.set_pbc(True)
return atoms
def write_exciting(fileobj, images):
"""writes exciting input structure in XML
Parameters
----------
fileobj : File object
Filehandle to which data should be written
images : Atom Object or List of Atoms objects
This function will write the first Atoms object to file
Returns
-------
"""
from lxml import etree as ET
if isinstance(fileobj, str):
fileobj = paropen(fileobj, 'w')
root = atoms2etree(images)
fileobj.write(ET.tostring(root, method='xml',
pretty_print=True,
xml_declaration=True,
encoding='UTF-8'))
def atoms2etree(images):
"""This function creates the XML DOM corresponding
to the structure for use in write and calculator
Parameters
----------
images : Atom Object or List of Atoms objects
This function will create a
Returns
-------
root : etree object
Element tree of exciting input file containing the structure
"""
from lxml import etree as ET
if not isinstance(images, (list, tuple)):
images = [images]
root = ET.Element('input')
title = ET.SubElement(root, 'title')
title.text = ''
structure = ET.SubElement(root, 'structure')
crystal= ET.SubElement(structure, 'crystal')
atoms = images[0]
for vec in atoms.cell:
basevect = ET.SubElement(crystal, 'basevect')
basevect.text = '%.14f %.14f %.14f' % tuple(vec / Bohr)
species = {}
symbols = []
for aindex, symbol in enumerate(atoms.get_chemical_symbols()):
if symbol in species:
species[symbol].append(aindex)
else:
species[symbol] = [aindex]
symbols.append(symbol)
scaled = atoms.get_scaled_positions()
for symbol in symbols:
speciesnode = ET.SubElement(structure, 'species',
speciesfile='%s.xml' % symbol,
chemicalSymbol=symbol)
for a in species[symbol]:
atom = ET.SubElement(speciesnode, 'atom',
coord='%.14f %.14f %.14f' % tuple(scaled[a]))
return root
python-ase-3.6.0.2515/ase/io/cfg.py 0000644 0001754 0001754 00000015047 11576407474 015516 0 ustar askhl askhl import numpy as np
import ase
from ase.parallel import paropen
cfg_default_fields = np.array( [ 'positions', 'momenta', 'numbers', 'magmoms' ] )
def write_cfg(f, a):
"""Write atomic configuration to a CFG-file (native AtomEye format).
See: http://mt.seas.upenn.edu/Archive/Graphics/A/
"""
if isinstance(f, str):
f = paropen(f, 'w')
f.write('Number of particles = %i\n' % len(a))
f.write('A = 1.0 Angstrom\n')
cell = a.get_cell()
for i in range(3):
for j in range(3):
f.write('H0(%1.1i,%1.1i) = %f A\n' % ( i + 1, j + 1, cell[i, j] ))
entry_count = 3
for x in a.arrays.keys():
if not x in cfg_default_fields:
if len(a.get_array(x).shape) == 1:
entry_count += 1
else:
entry_count += a.get_array(x).shape[1]
vels = a.get_velocities()
if type(vels) == np.ndarray:
entry_count += 3
else:
f.write('.NO_VELOCITY.\n')
f.write('entry_count = %i\n' % entry_count)
i = 0
for name, aux in a.arrays.iteritems():
if not name in cfg_default_fields:
if len(aux.shape) == 1:
f.write('auxiliary[%i] = %s [a.u.]\n' % ( i, name ))
i += 1
else:
for j in range(aux.shape[1]):
f.write('auxiliary[%i] = %s_%1.1i [a.u.]\n' % ( i, name, j ))
i += 1
# Distinct elements
spos = a.get_scaled_positions()
for i in a:
el = i.symbol
f.write('%f\n' % ase.data.atomic_masses[ase.data.chemical_symbols.index(el)])
f.write('%s\n' % el)
x, y, z = spos[i.index, :]
s = '%e %e %e ' % ( x, y, z )
if type(vels) == np.ndarray:
vx, vy, vz = vels[i.index, :]
s = s + ' %e %e %e ' % ( vx, vy, vz )
for name, aux in a.arrays.iteritems():
if not name in cfg_default_fields:
if len(aux.shape) == 1:
s += ' %e' % aux[i.index]
else:
s += ( aux.shape[1]*' %e' ) % tuple(aux[i.index].tolist())
f.write('%s\n' % s)
default_color = {
'H': [ 0.800, 0.800, 0.800 ],
'C': [ 0.350, 0.350, 0.350 ],
'O': [ 0.800, 0.200, 0.200 ]
}
default_radius = {
'H': 0.435,
'C': 0.655,
'O': 0.730
}
def write_clr(f, atoms):
"""Write extra color and radius code to a CLR-file (for use with AtomEye).
Hit F12 in AtomEye to use.
See: http://mt.seas.upenn.edu/Archive/Graphics/A/
"""
color = None
radius = None
if atoms.has('color'):
color = atoms.get_array('color')
if atoms.has('radius'):
radius = atoms.get_array('radius')
if color is None:
color = np.zeros([len(atoms),3], dtype=float)
for a in atoms:
color[a.index, :] = default_color[a.symbol]
if radius is None:
radius = np.zeros(len(atoms), dtype=float)
for a in atoms:
radius[a.index] = default_radius[a.symbol]
radius.shape = (-1, 1)
if isinstance(f, str):
f = paropen(f, 'w')
for c1, c2, c3, r in np.append(color, radius, axis=1):
f.write('%f %f %f %f\n' % ( c1, c2, c3, r ))
###
def read_key_val(f):
if isinstance(f, str):
l = f
else:
l = f.readline()
s = l.split('=')
if len(s) != 2:
raise RuntimeError("Line '%s' is not of the form 'key = value'." % l[:-1])
return ( s[0].strip(), s[1].strip() )
def read_str_key(f, key, key2=None):
in_key, val = read_key_val(f)
if key2 is None:
if key.upper() != in_key.upper():
raise RuntimeError("Key '%s' expected, '%s' found." % ( key, in_key ))
else:
if key.upper() != in_key.upper() and key2.upper() != in_key.upper():
raise RuntimeError("Key '%s' or '%s' expected, '%s' found." % ( key, key2, in_key ))
return val
def read_int_key(f, key):
vals = read_str_key(f, key).split()
# Ignore units
return int(vals[0])
def read_float_key(f, key):
vals = read_str_key(f, key).split()
# Ignore units
return float(vals[0])
###
def read_cfg(f):
"""Read atomic configuration from a CFG-file (native AtomEye format).
See: http://mt.seas.upenn.edu/Archive/Graphics/A/
"""
if isinstance(f, str):
f = open(f)
nat = read_int_key(f, 'Number of particles')
unit = read_float_key(f, 'A')
cell = np.zeros( [ 3, 3 ] )
for i in range(3):
for j in range(3):
cell[i, j] = read_float_key(f, 'H0(%1.1i,%1.1i)' % (i + 1, j + 1))
l = f.readline()
vels = None
if l.strip() == '.NO_VELOCITY.':
l = f.readline()
else:
vels = np.zeros( [ nat, 3 ] )
naux = read_int_key(l, 'entry_count') - 3
if vels is not None:
naux -= 3
aux = np.zeros( [ nat, naux ] )
auxstrs = [ ]
for i in range(naux):
s = read_str_key(f, 'auxiliary[%1.1i]' % i, 'auxiliary[%2.2i]' % i)
auxstrs += [ s[:s.find('[')].strip() ]
spos = np.zeros( [ nat, 3 ] )
masses = np.zeros( nat )
syms = [ '' for i in range(nat) ]
i = 0
s = f.readline().split()
while l:
mass = float(s[0])
sym = f.readline().strip()
l = f.readline()
s = l.split()
while l and len(s) > 1:
masses[i] = mass
syms[i] = sym
props = [ float(x) for x in s ]
spos[i, :] = props[0:3]
off = 3
if vels is not None:
off = 6
vels[i, :] = props[3:6]
aux[i, :] = props[off:]
i += 1
l = f.readline()
if l:
s = l.split()
if vels is None:
a = ase.Atoms(
symbols = syms,
masses = masses,
scaled_positions = spos,
cell = cell,
pbc = True
)
else:
a = ase.Atoms(
symbols = syms,
masses = masses,
scaled_positions = spos,
momenta = masses.reshape(-1,1)*vels,
cell = cell,
pbc = True
)
i = 0
while i < naux:
auxstr = auxstrs[i]
if auxstr[-2:] == '_x':
a.set_array(auxstr[:-2], aux[:, i:i+3])
i += 3
else:
a.set_array(auxstr, aux[:, i])
i += 1
return a
python-ase-3.6.0.2515/ase/io/dftb.py 0000644 0001754 0001754 00000007445 11462015141 015655 0 ustar askhl askhl from ase.atoms import Atoms
def read_dftb(filename='dftb_in.hsd'):
"""Method to read coordinates form DFTB+ input file dftb_in.hsd
additionally read information about fixed atoms
and periodic boundary condition
"""
from ase import Atoms
if isinstance(filename, str):
myfile = open(filename)
lines = myfile.readlines()
atoms_pos = []
atom_symbols = []
type_names = []
my_pbc = False
mycell = []
for iline, line in enumerate(lines):
if (line.strip().startswith('#')):
pass
else:
if ('TypeNames' in line):
col = line.split()
for i in range(3, len(col)-1):
type_names.append(col[i].strip("\""))
elif ('Periodic' in line):
if ('Yes' in line):
my_pbc = True
elif ('LatticeVectors' in line):
for imycell in range(3):
extraline = lines[iline+imycell+1]
cols = extraline.split()
mycell.append(\
[float(cols[0]),float(cols[1]),float(cols[2])])
else:
pass
start_reading_coords = False
stop_reading_coords = False
for line in lines:
if (line.strip().startswith('#')):
pass
else:
if ('TypesAndCoordinates' in line):
start_reading_coords = True
if start_reading_coords:
if ('}' in line):
stop_reading_coords = True
if (start_reading_coords and not(stop_reading_coords)
and not 'TypesAndCoordinates' in line):
typeindexstr, xxx, yyy, zzz = line.split()[:4]
typeindex = int(typeindexstr)
symbol = type_names[typeindex-1]
atom_symbols.append(symbol)
atoms_pos.append([float(xxx), float(yyy), float(zzz)])
if type(filename) == str:
myfile.close()
atoms = Atoms(positions = atoms_pos, symbols = atom_symbols,
cell = mycell, pbc = my_pbc)
return atoms
def write_dftb(filename, atoms):
"""Method to write atom structure in DFTB+ format
(gen format)
"""
import numpy as np
#sort
atoms.set_masses()
masses = atoms.get_masses()
indexes = np.argsort(masses)
atomsnew = Atoms()
for i in indexes:
atomsnew = atomsnew + atoms[i]
if isinstance(filename, str):
myfile = open(filename, 'w')
else: # Assume it's a 'file-like object'
myfile = filename
ispbc = atoms.get_pbc()
box = atoms.get_cell()
if (any(ispbc)):
myfile.write('%8d %2s \n' %(len(atoms), 'S'))
else:
myfile.write('%8d %2s \n' %(len(atoms), 'C'))
chemsym = atomsnew.get_chemical_symbols()
allchem = ''
for i in chemsym:
if i not in allchem:
allchem = allchem + i + ' '
myfile.write(allchem+' \n')
coords = atomsnew.get_positions()
itype = 1
for iatom, coord in enumerate(coords):
if iatom > 0:
if chemsym[iatom] != chemsym[iatom-1]:
itype = itype+1
myfile.write('%5i%5i %19.16f %19.16f %19.16f \n' \
%(iatom+1, itype,
coords[iatom][0], coords[iatom][1], coords[iatom][2]))
# write box
if (any(ispbc)):
#dftb dummy
myfile.write(' %19.16f %19.16f %19.16f \n' %(0, 0, 0))
myfile.write(' %19.16f %19.16f %19.16f \n'
%( box[0][0], box[0][1], box[0][2]))
myfile.write(' %19.16f %19.16f %19.16f \n'
%( box[1][0], box[1][1], box[1][2]))
myfile.write(' %19.16f %19.16f %19.16f \n'
%( box[2][0], box[2][1], box[2][2]))
if type(filename) == str:
myfile.close()
python-ase-3.6.0.2515/ase/io/cmdft.py 0000644 0001754 0001754 00000001215 11222662616 016031 0 ustar askhl askhl from math import pi, cos, sin, sqrt, acos
import numpy as np
from ase.atom import Atom
from ase.atoms import Atoms
from ase.parallel import paropen
from ase.units import Bohr
def read_I_info(fileobj, index=-1):
if isinstance(fileobj, str):
fileobj = open(fileobj)
lines = fileobj.readlines()
del lines[0]
finished = False
s = Atoms()
while not finished:
w = lines.pop(0).split()
if w[0].startswith('"'):
position = Bohr * np.array([float(w[3]), float(w[4]), float(w[5])])
s.append(Atom(w[0].replace('"',''), position))
else:
finished = True
return s
python-ase-3.6.0.2515/ase/io/vtkxml.py 0000644 0001754 0001754 00000012331 11207220276 016255 0 ustar askhl askhl import numpy as np
#from Numeric import asarray as Numeric_asarray
#from ase.units import Bohr
#from ase.parallel import paropen
fast = False
# -------------------------------------------------------------------
from vtk import vtkStructuredPoints, vtkDoubleArray, vtkXMLImageDataWriter
def write_vti(filename, atoms, data):
#if isinstance(fileobj, str):
# fileobj = paropen(fileobj, 'w')
if isinstance(atoms, list):
if len(atoms) > 1:
raise ValueError('Can only write one configuration to a VTI file!')
atoms = atoms[0]
if data is None:
raise ValueError('VTK XML Image Data (VTI) format requires data!')
data = np.asarray(data)
if data.dtype == complex:
data = np.abs(data)
cell = atoms.get_cell()
assert np.all(cell==np.diag(cell.diagonal())), 'Unit cell must be orthogonal'
bbox = np.array(zip(np.zeros(3),cell.diagonal())).ravel()
# Create a VTK grid of structured points
spts = vtkStructuredPoints()
spts.SetWholeBoundingBox(bbox)
spts.SetDimensions(data.shape)
spts.SetSpacing(cell.diagonal() / data.shape)
#spts.SetSpacing(paw.gd.h_c * Bohr)
#print 'paw.gd.h_c * Bohr=',paw.gd.h_c * Bohr
#print 'atoms.cell.diagonal() / data.shape=', cell.diagonal()/data.shape
#assert np.all(paw.gd.h_c * Bohr==cell.diagonal()/data.shape)
#s = paw.wfs.kpt_u[0].psit_nG[0].copy()
#data = paw.get_pseudo_wave_function(band=0, kpt=0, spin=0, pad=False)
#spts.point_data.scalars = data.swapaxes(0,2).flatten()
#spts.point_data.scalars.name = 'scalars'
# Allocate a VTK array of type double and copy data
da = vtkDoubleArray()
da.SetName('scalars')
da.SetNumberOfComponents(1)
da.SetNumberOfTuples(np.prod(data.shape))
for i,d in enumerate(data.swapaxes(0,2).flatten()):
da.SetTuple1(i,d)
# Assign the VTK array as point data of the grid
spd = spts.GetPointData() # type(spd) is vtkPointData
spd.SetScalars(da)
"""
from vtk.util.vtkImageImportFromArray import vtkImageImportFromArray
iia = vtkImageImportFromArray()
#iia.SetArray(Numeric_asarray(data.swapaxes(0,2).flatten()))
iia.SetArray(Numeric_asarray(data))
ida = iia.GetOutput()
ipd = ida.GetPointData()
ipd.SetName('scalars')
spd.SetScalars(ipd.GetScalars())
"""
# Save the ImageData dataset to a VTK XML file.
w = vtkXMLImageDataWriter()
if fast:
w.SetDataModeToAppend()
w.EncodeAppendedDataOff()
else:
w.SetDataModeToAscii()
w.SetFileName(filename)
w.SetInput(spts)
w.Write()
# -------------------------------------------------------------------
from vtk import vtkStructuredGrid, vtkPoints, vtkXMLStructuredGridWriter
def write_vts(filename, atoms, data=None):
raise NotImplementedError
# -------------------------------------------------------------------
from vtk import vtkUnstructuredGrid, vtkPoints, vtkXMLUnstructuredGridWriter
def write_vtu(filename, atoms, data=None):
#if isinstance(fileobj, str):
# fileobj = paropen(fileobj, 'w')
if isinstance(atoms, list):
if len(atoms) > 1:
raise ValueError('Can only write one configuration to a VTI file!')
atoms = atoms[0]
"""
if data is None:
raise ValueError('VTK XML Unstructured Grid (VTI) format requires data!')
data = np.asarray(data)
if data.dtype == complex:
data = np.abs(data)
"""
cell = atoms.get_cell()
assert np.all(cell==np.diag(cell.diagonal())), 'Unit cell must be orthogonal' #TODO bounding box with general unit cell?!
bbox = np.array(zip(np.zeros(3),cell.diagonal())).ravel()
# Create a VTK grid of structured points
ugd = vtkUnstructuredGrid()
ugd.SetWholeBoundingBox(bbox)
"""
# Allocate a VTK array of type double and copy data
da = vtkDoubleArray()
da.SetName('scalars')
da.SetNumberOfComponents(3)
da.SetNumberOfTuples(len(atoms))
for i,pos in enumerate(atoms.get_positions()):
da.SetTuple3(i,pos[0],pos[1],pos[2])
"""
p = vtkPoints()
p.SetNumberOfPoints(len(atoms))
p.SetDataTypeToDouble()
for i,pos in enumerate(atoms.get_positions()):
p.InsertPoint(i,pos[0],pos[1],pos[2])
ugd.SetPoints(p)
# Assign the VTK array as point data of the grid
#upd = ugd.GetPointData() # type(spd) is vtkPointData
#upd.SetScalars(da)
# Save the UnstructuredGrid dataset to a VTK XML file.
w = vtkXMLUnstructuredGridWriter()
if fast:
w.SetDataModeToAppend()
w.EncodeAppendedDataOff()
else:
w.GetCompressor().SetCompressionLevel(0)
w.SetDataModeToAscii()
w.SetFileName(filename)
w.SetInput(ugd)
w.Write()
# -------------------------------------------------------------------
def read_vti(filename):
raise NotImplementedError
def read_vts(filename):
raise NotImplementedError
def read_vtu(filename):
raise NotImplementedError
# -------------------------------------------------------------------
from vtk import vtkXMLFileReadTester
def probe_vtkxml(filename):
"""something..."""
r = vtkXMLFileReadTester()
r.SetFileName(filename)
if r.TestReadFile():
return r.GetFileDataType()
else:
return None
python-ase-3.6.0.2515/ase/io/gen.py 0000644 0001754 0001754 00000011156 11551032771 015510 0 ustar askhl askhl """Extension to ASE: read and write structures in GEN format
Refer to DFTB+ manual for GEN format description.
Note: GEN format only supports single snapshot.
"""
from ase.atoms import Atoms
from ase.parallel import paropen
def read_gen(fileobj):
"""Read structure in GEN format (refer to DFTB+ manual).
Multiple snapshot are not allowed. """
if isinstance(fileobj, str):
fileobj = open(fileobj)
image = Atoms()
lines = fileobj.readlines()
line = lines[0].split()
natoms = int(line[0])
if line[1] == 'S':
supercell = True
elif line[1] == 'C':
supercell = False
else:
raise IOError('Error in line #1: only C (Cluster) or S (Supercell) ' +
'are valid options')
# Read atomic symbols
line = lines[1].split()
# Define a dictionary with symbols-id
symboldict = dict()
symbolid = 1
for symb in line:
symboldict[symbolid] = symb
symbolid += 1
# Read atoms (GEN format supports only single snapshot)
del lines[:2]
positions = []
symbols = []
for line in lines[:natoms]:
dummy, symbolid, x, y, z = line.split()[:5]
symbols.append(symboldict[int(symbolid)])
positions.append([float(x), float(y), float(z)])
image = Atoms(symbols=symbols, positions=positions)
del lines[:natoms]
# If Supercell, parse periodic vectors
if not supercell:
return image
else:
# Dummy line: line after atom positions is not uniquely defined
# in gen implementations, and not necessary in DFTB package
del lines[:1]
image.set_pbc([True, True, True])
p = []
for i in range(3):
x, y, z = lines[i].split()[:3]
p.append([float(x), float(y), float(z)])
image.set_cell([(p[0][0], p[0][1], p[0][2]), (p[1][0], p[1][1],
p[1][2]), (p[2][0], p[2][1], p[2][2])])
return image
def write_gen(fileobj, images):
"""Write structure in GEN format (refer to DFTB+ manual).
Multiple snapshots are not allowed. """
if isinstance(fileobj, str):
fileobj = paropen(fileobj, 'w')
if not isinstance(images, (list, tuple)):
images = [images]
# Images is kept in a list but a size > 0 is not allowed
# as GEN format doesn't support multiple snapshots.
# Images is used as a list for consistency with the other
# output modules
if len(images) != 1:
raise ValueError('images contains more than one structure\n' +
'GEN format supports only single snapshot output')
symbols = images[0].get_chemical_symbols()
# Define a dictionary with symbols-id
symboldict = dict()
for sym in symbols:
if not (sym in symboldict):
symboldict[sym] = len(symboldict) + 1
# An ordered symbol list is needed as ordered dictionary
# is just available in python 2.7
orderedsymbols = list(['null'] * len(symboldict.keys()))
for sym in symboldict.keys():
orderedsymbols[symboldict[sym] - 1] = sym
# Check whether the structure is periodic
# GEN cannot describe periodicity in one or two direction,
# a periodic structure is considered periodic in all the
# directions. If your structure is not periodical in all
# the directions, be sure you have set big periodicity
# vectors in the non-periodic directions
if images[0].pbc.any():
pb_flag = 'S'
else:
pb_flag = 'C'
natoms = len(symbols)
ind = 0
for atoms in images:
fileobj.write('%d %-5s\n' % (natoms, pb_flag))
for s in orderedsymbols:
fileobj.write('%-5s' % s)
fileobj.write('\n')
for sym, (x, y, z) in zip(symbols, atoms.get_positions()):
ind += 1
symbolid = symboldict[sym]
fileobj.write('%-6d %d %22.15f %22.15f %22.15f\n' % (ind,
symbolid, x, y, z))
if images[0].pbc.any():
fileobj.write('%22.15f %22.15f %22.15f \n' % (0.0, 0.0, 0.0))
fileobj.write('%22.15f %22.15f %22.15f \n' %
(images[0].get_cell()[0][0],
images[0].get_cell()[0][1],
images[0].get_cell()[0][2]))
fileobj.write('%22.15f %22.15f %22.15f \n' %
(images[0].get_cell()[1][0],
images[0].get_cell()[1][1],
images[0].get_cell()[1][2]))
fileobj.write('%22.15f %22.15f %22.15f \n' %
(images[0].get_cell()[2][0],
images[0].get_cell()[2][1],
images[0].get_cell()[2][2]))
python-ase-3.6.0.2515/ase/io/pov.py 0000644 0001754 0001754 00000024341 11543076326 015550 0 ustar askhl askhl """
Module for povray file format support.
See http://www.povray.org/ for details on the format.
"""
import os
import numpy as np
from ase.io.eps import EPS
from ase.data import chemical_symbols
from ase.constraints import FixAtoms
def pa(array):
"""Povray array syntax"""
return '<% 6.2f, % 6.2f, % 6.2f>' % tuple(array)
def pc(array):
"""Povray color syntax"""
if type(array) == str:
return 'color ' + array
if type(array) == float:
return 'rgb <%.2f>*3' % array
if len(array) == 3:
return 'rgb <%.2f, %.2f, %.2f>' % tuple(array)
if len(array) == 4: # filter
return 'rgbf <%.2f, %.2f, %.2f, %.2f>' % tuple(array)
if len(array) == 5: # filter and transmit
return 'rgbft <%.2f, %.2f, %.2f, %.2f, %.2f>' % tuple(array)
def get_bondpairs(atoms, radius=1.1):
"""Get all pairs of bonding atoms
Return all pairs of atoms which are closer than radius times the
sum of their respective covalent radii. The pairs are returned as
tuples::
(a, b, (i1, i2, i3))
so that atoms a bonds to atom b displaced by the vector::
_ _ _
i c + i c + i c ,
1 1 2 2 3 3
where c1, c2 and c3 are the unit cell vectors and i1, i2, i3 are
integers."""
from ase.data import covalent_radii
from ase.calculators.neighborlist import NeighborList
cutoffs = radius * covalent_radii[atoms.numbers]
nl = NeighborList(cutoffs=cutoffs, self_interaction=False)
nl.update(atoms)
bondpairs = []
for a in range(len(atoms)):
indices, offsets = nl.get_neighbors(a)
bondpairs.extend([(a, a2, offset)
for a2, offset in zip(indices, offsets)])
return bondpairs
class POVRAY(EPS):
default_settings = {
# x, y is the image plane, z is *out* of the screen
'display' : True, # Display while rendering
'pause' : True, # Pause when done rendering (only if display)
'transparent' : True, # Transparent background
'canvas_width' : None, # Width of canvas in pixels
'canvas_height' : None, # Height of canvas in pixels
'camera_dist' : 50., # Distance from camera to front atom
'image_plane' : None, # Distance from front atom to image plane
'camera_type' : 'orthographic', # perspective, ultra_wide_angle
'point_lights' : [], # [[loc1, color1], [loc2, color2],...]
'area_light' : [(2., 3., 40.), # location
'White', # color
.7, .7, 3, 3], # width, height, Nlamps_x, Nlamps_y
'background' : 'White', # color
'textures' : None, # Length of atoms list of texture names
'celllinewidth' : 0.05, # Radius of the cylinders representing the cell
'bondlinewidth' : 0.10, # Radius of the cylinders representing the bonds
'bondatoms' : [], # [[atom1, atom2], ... ] pairs of bonding atoms
'exportconstraints' : False} # honour FixAtom requests and mark relevant atoms?
def __init__(self, atoms, scale=1.0, **parameters):
for k, v in self.default_settings.items():
setattr(self, k, parameters.pop(k, v))
EPS.__init__(self, atoms, scale=scale, **parameters)
constr = atoms.constraints
self.constrainatoms = []
for c in constr:
if isinstance(c,FixAtoms):
for n,i in enumerate(c.index):
if i: self.constrainatoms += [n]
def cell_to_lines(self, A):
return np.empty((0, 3)), None, None
def write(self, filename, **settings):
# Determine canvas width and height
ratio = float(self.w) / self.h
if self.canvas_width is None:
if self.canvas_height is None:
self.canvas_width = min(self.w * 15, 640)
else:
self.canvas_width = self.canvas_height * ratio
elif self.canvas_height is not None:
raise RuntimeError, "Can't set *both* width and height!"
# Distance to image plane from camera
if self.image_plane is None:
if self.camera_type == 'orthographic':
self.image_plane = 1 - self.camera_dist
else:
self.image_plane = 0
self.image_plane += self.camera_dist
# Produce the .ini file
if filename.endswith('.pov'):
ini = open(filename[:-4] + '.ini', 'w').write
else:
ini = open(filename + '.ini', 'w').write
ini('Input_File_Name=%s\n' % filename)
ini('Output_to_File=True\n')
ini('Output_File_Type=N\n')
ini('Output_Alpha=%s\n' % self.transparent)
ini('; if you adjust Height, and width, you must preserve the ratio\n')
ini('; Width / Height = %s\n' % repr(ratio))
ini('Width=%s\n' % self.canvas_width)
ini('Height=%s\n' % (self.canvas_width / ratio))
ini('Antialias=True\n')
ini('Antialias_Threshold=0.1\n')
ini('Display=%s\n' % self.display)
ini('Pause_When_Done=%s\n' % self.pause)
ini('Verbose=False\n')
del ini
# Produce the .pov file
w = open(filename, 'w').write
w('#include "colors.inc"\n')
w('#include "finish.inc"\n')
w('\n')
w('global_settings {assumed_gamma 1 max_trace_level 6}\n')
w('background {%s}\n' % pc(self.background))
w('camera {%s\n' % self.camera_type)
w(' right -%.2f*x up %.2f*y\n' % (self.w, self.h))
w(' direction %.2f*z\n' % self.image_plane)
w(' location <0,0,%.2f> look_at <0,0,0>}\n' % self.camera_dist)
for loc, rgb in self.point_lights:
w('light_source {%s %s}\n' % (pa(loc), pc(rgb)))
if self.area_light is not None:
loc, color, width, height, nx, ny = self.area_light
w('light_source {%s %s\n' % (pa(loc), pc(color)))
w(' area_light <%.2f, 0, 0>, <0, %.2f, 0>, %i, %i\n' % (
width, height, nx, ny))
w(' adaptive 1 jitter}\n')
w('\n')
w('#declare simple = finish {phong 0.7}\n')
w('#declare pale = finish {'
'ambient .5 '
'diffuse .85 '
'roughness .001 '
'specular 0.200 }\n')
w('#declare intermediate = finish {'
'ambient 0.3 '
'diffuse 0.6 '
'specular 0.10 '
'roughness 0.04 }\n')
w('#declare vmd = finish {'
'ambient .0 '
'diffuse .65 '
'phong 0.1 '
'phong_size 40. '
'specular 0.500 }\n')
w('#declare jmol = finish {'
'ambient .2 '
'diffuse .6 '
'specular 1 '
'roughness .001 '
'metallic}\n')
w('#declare ase2 = finish {'
'ambient 0.05 '
'brilliance 3 '
'diffuse 0.6 '
'metallic '
'specular 0.70 '
'roughness 0.04 '
'reflection 0.15}\n')
w('#declare ase3 = finish {'
'ambient .15 '
'brilliance 2 '
'diffuse .6 '
'metallic '
'specular 1. '
'roughness .001 '
'reflection .0}\n')
w('#declare glass = finish {'
'ambient .05 '
'diffuse .3 '
'specular 1. '
'roughness .001}\n')
w('#declare Rcell = %.3f;\n' % self.celllinewidth)
w('#declare Rbond = %.3f;\n' % self.bondlinewidth)
w('\n')
w('#macro atom(LOC, R, COL, FIN)\n')
w(' sphere{LOC, R texture{pigment{COL} finish{FIN}}}\n')
w('#end\n')
w('#macro constrain(LOC, R, COL, FIN)\n')
w('union{torus{R, Rcell rotate 45*z texture{pigment{COL} finish{FIN}}}\n')
w(' torus{R, Rcell rotate -45*z texture{pigment{COL} finish{FIN}}}\n')
w(' translate LOC}\n')
w('#end\n')
w('\n')
z0 = self.X[:, 2].max()
self.X -= (self.w / 2, self.h / 2, z0)
# Draw unit cell
if self.C is not None:
self.C -= (self.w / 2, self.h / 2, z0)
self.C.shape = (2, 2, 2, 3)
for c in range(3):
for j in ([0, 0], [1, 0], [1, 1], [0, 1]):
w('cylinder {')
for i in range(2):
j.insert(c, i)
w(pa(self.C[tuple(j)]) + ', ')
del j[c]
w('Rcell pigment {Black}}\n')
# Draw atoms
a = 0
for loc, dia, color in zip(self.X, self.d, self.colors):
tex = 'ase3'
if self.textures is not None:
tex = self.textures[a]
w('atom(%s, %.2f, %s, %s) // #%i \n' % (
pa(loc), dia / 2., pc(color), tex, a))
a += 1
# Draw atom bonds
for pair in self.bondatoms:
if len(pair) == 2:
a, b = pair
offset = (0, 0, 0)
else:
a, b, offset = pair
R = np.dot(offset, self.A)
mida = 0.5 * (self.X[a] + self.X[b] + R)
midb = 0.5 * (self.X[a] + self.X[b] - R)
if self.textures is not None:
texa = self.textures[a]
texb = self.textures[b]
else:
texa = texb = 'ase3'
w('cylinder {%s, %s, Rbond texture{pigment {%s} finish{%s}}}\n' % (
pa(self.X[a]), pa(mida), pc(self.colors[a]), texa))
w('cylinder {%s, %s, Rbond texture{pigment {%s} finish{%s}}}\n' % (
pa(self.X[b]), pa(midb), pc(self.colors[b]), texb))
# Draw constraints if requested
if self.exportconstraints:
for a in self.constrainatoms:
dia = self.d[a]
loc = self.X[a]
w('constrain(%s, %.2f, Black, %s) // #%i \n' % (
pa(loc), dia / 2., tex, a))
def write_pov(filename, atoms, run_povray=False, **parameters):
if isinstance(atoms, list):
assert len(atoms) == 1
atoms = atoms[0]
assert 'scale' not in parameters
POVRAY(atoms, **parameters).write(filename)
if run_povray:
errcode = os.system('povray %s.ini 2> /dev/null' % filename[:-4])
if errcode != 0:
raise OSError('Povray failed with error code %d' % errcode)
python-ase-3.6.0.2515/ase/io/vasp.py 0000644 0001754 0001754 00000032714 11660424243 015713 0 ustar askhl askhl """
This module contains functionality for reading and writing an ASE
Atoms object in VASP POSCAR format.
"""
import os
def get_atomtypes(fname):
"""Given a file name, get the atomic symbols.
The function can get this information from OUTCAR and POTCAR
format files. The files can also be compressed with gzip or
bzip2.
"""
atomtypes=[]
if fname.find('.gz') != -1:
import gzip
f = gzip.open(fname)
elif fname.find('.bz2') != -1:
import bz2
f = bz2.BZ2File(fname)
else:
f = open(fname)
for line in f:
if line.find('TITEL') != -1:
atomtypes.append(line.split()[3].split('_')[0].split('.')[0])
return atomtypes
def atomtypes_outpot(posfname, numsyms):
"""Try to retreive chemical symbols from OUTCAR or POTCAR
If getting atomtypes from the first line in POSCAR/CONTCAR fails, it might
be possible to find the data in OUTCAR or POTCAR, if these files exist.
posfname -- The filename of the POSCAR/CONTCAR file we're trying to read
numsyms -- The number of symbols we must find
"""
import os.path as op
import glob
# First check files with exactly same name except POTCAR/OUTCAR instead
# of POSCAR/CONTCAR.
fnames = [posfname.replace('POSCAR', 'POTCAR').replace('CONTCAR',
'POTCAR')]
fnames.append(posfname.replace('POSCAR', 'OUTCAR').replace('CONTCAR',
'OUTCAR'))
# Try the same but with compressed files
fsc = []
for fn in fnames:
fsc.append(fn + '.gz')
fsc.append(fn + '.bz2')
for f in fsc:
fnames.append(f)
# Finally try anything with POTCAR or OUTCAR in the name
vaspdir = op.dirname(posfname)
fs = glob.glob(vaspdir + '*POTCAR*')
for f in fs:
fnames.append(f)
fs = glob.glob(vaspdir + '*OUTCAR*')
for f in fs:
fnames.append(f)
tried = []
files_in_dir = os.listdir('.')
for fn in fnames:
if fn in files_in_dir:
tried.append(fn)
at = get_atomtypes(fn)
if len(at) == numsyms:
return at
raise IOError('Could not determine chemical symbols. Tried files '
+ str(tried))
def get_atomtypes_from_formula(formula):
"""Return atom types from chemical formula (optionally prepended
with and underscore).
"""
from ase.atoms import string2symbols
symbols = string2symbols(formula.split('_')[0])
atomtypes = [symbols[0]]
for s in symbols[1:]:
if s != atomtypes[-1]: atomtypes.append(s)
return atomtypes
def read_vasp(filename='CONTCAR'):
"""Import POSCAR/CONTCAR type file.
Reads unitcell, atom positions and constraints from the POSCAR/CONTCAR
file and tries to read atom types from POSCAR/CONTCAR header, if this fails
the atom types are read from OUTCAR or POTCAR file.
"""
from ase import Atoms, Atom
from ase.constraints import FixAtoms, FixScaled
from ase.data import chemical_symbols
import numpy as np
if isinstance(filename, str):
f = open(filename)
else: # Assume it's a file-like object
f = filename
# First line should contain the atom symbols , eg. "Ag Ge" in
# the same order
# as later in the file (and POTCAR for the full vasp run)
atomtypes = f.readline().split()
# Sometimes the first line in POSCAR/CONTCAR is of the form
# "CoP3_In-3.pos". Check for this case and extract atom types
if len(atomtypes) == 1 and '_' in atomtypes[0]:
atomtypes = get_atomtypes_from_formula(atomtypes[0])
lattice_constant = float(f.readline().split()[0])
# Now the lattice vectors
a = []
for ii in range(3):
s = f.readline().split()
floatvect = float(s[0]), float(s[1]), float(s[2])
a.append(floatvect)
basis_vectors = np.array(a) * lattice_constant
# Number of atoms. Again this must be in the same order as
# in the first line
# or in the POTCAR or OUTCAR file
atom_symbols = []
numofatoms = f.readline().split()
#vasp5.1 has an additional line which gives the atom types
#the following try statement skips this line
try:
int(numofatoms[0])
except ValueError:
numofatoms = f.readline().split()
# check for comments in numofatoms line and get rid of them if necessary
commentcheck = np.array(['!' in s for s in numofatoms])
if commentcheck.any():
# only keep the elements up to the first including a '!':
numofatoms = numofatoms[:np.arange(len(numofatoms))[commentcheck][0]]
numsyms = len(numofatoms)
if len(atomtypes) < numsyms:
# First line in POSCAR/CONTCAR didn't contain enough symbols.
atomtypes = atomtypes_outpot(f.name, numsyms)
else:
try:
for atype in atomtypes[:numsyms]:
if not atype in chemical_symbols:
raise KeyError
except KeyError:
atomtypes = atomtypes_outpot(f.name, numsyms)
for i, num in enumerate(numofatoms):
numofatoms[i] = int(num)
[atom_symbols.append(atomtypes[i]) for na in xrange(numofatoms[i])]
# Check if Selective dynamics is switched on
sdyn = f.readline()
selective_dynamics = sdyn[0].lower() == "s"
# Check if atom coordinates are cartesian or direct
if selective_dynamics:
ac_type = f.readline()
else:
ac_type = sdyn
cartesian = ac_type[0].lower() == "c" or ac_type[0].lower() == "k"
tot_natoms = sum(numofatoms)
atoms_pos = np.empty((tot_natoms, 3))
if selective_dynamics:
selective_flags = np.empty((tot_natoms, 3), dtype=bool)
for atom in xrange(tot_natoms):
ac = f.readline().split()
atoms_pos[atom] = (float(ac[0]), float(ac[1]), float(ac[2]))
if selective_dynamics:
curflag = []
for flag in ac[3:6]:
curflag.append(flag == 'F')
selective_flags[atom] = curflag
# Done with all reading
if type(filename) == str:
f.close()
if cartesian:
atoms_pos *= lattice_constant
atoms = Atoms(symbols = atom_symbols, cell = basis_vectors, pbc = True)
if cartesian:
atoms.set_positions(atoms_pos)
else:
atoms.set_scaled_positions(atoms_pos)
if selective_dynamics:
constraints = []
indices = []
for ind, sflags in enumerate(selective_flags):
if sflags.any() and not sflags.all():
constraints.append(FixScaled(atoms.get_cell(), ind, sflags))
elif sflags.all():
indices.append(ind)
if indices:
constraints.append(FixAtoms(indices))
if constraints:
atoms.set_constraint(constraints)
return atoms
def read_vasp_out(filename='OUTCAR',index = -1):
"""Import OUTCAR type file.
Reads unitcell, atom positions, energies, and forces from the OUTCAR file
and attempts to read constraints (if any) from CONTCAR/POSCAR, if present.
"""
import os
import numpy as np
from ase.calculators.singlepoint import SinglePointCalculator
from ase import Atoms, Atom
try: # try to read constraints, first from CONTCAR, then from POSCAR
constr = read_vasp('CONTCAR').constraints
except:
try:
constr = read_vasp('POSCAR').constraints
except:
constr = None
if isinstance(filename, str):
f = open(filename)
else: # Assume it's a file-like object
f = filename
data = f.readlines()
natoms = 0
images = []
atoms = Atoms(pbc = True, constraint = constr)
energy = 0
species = []
species_num = []
symbols = []
ecount = 0
poscount = 0
for n,line in enumerate(data):
if 'POTCAR:' in line:
temp = line.split()[2]
for c in ['.','_','1']:
if c in temp:
temp = temp[0:temp.find(c)]
species += [temp]
if 'ions per type' in line:
species = species[:len(species)/2]
temp = line.split()
for ispecies in range(len(species)):
species_num += [int(temp[ispecies+4])]
natoms += species_num[-1]
for iatom in range(species_num[-1]): symbols += [species[ispecies]]
if 'direct lattice vectors' in line:
cell = []
for i in range(3):
temp = data[n+1+i].split()
cell += [[float(temp[0]), float(temp[1]), float(temp[2])]]
atoms.set_cell(cell)
if 'FREE ENERGIE OF THE ION-ELECTRON SYSTEM' in line:
energy = float(data[n+2].split()[4])
if ecount < poscount:
# reset energy for LAST set of atoms, not current one - VASP 5.11? and up
images[-1].calc.energy = energy
ecount += 1
if 'POSITION ' in line:
forces = []
for iatom in range(natoms):
temp = data[n+2+iatom].split()
atoms += Atom(symbols[iatom],[float(temp[0]),float(temp[1]),float(temp[2])])
forces += [[float(temp[3]),float(temp[4]),float(temp[5])]]
atoms.set_calculator(SinglePointCalculator(energy,forces,None,None,atoms))
images += [atoms]
atoms = Atoms(pbc = True, constraint = constr)
poscount += 1
# return requested images, code borrowed from ase/io/trajectory.py
if isinstance(index, int):
return images[index]
else:
step = index.step or 1
if step > 0:
start = index.start or 0
if start < 0:
start += len(images)
stop = index.stop or len(images)
if stop < 0:
stop += len(images)
else:
if index.start is None:
start = len(images) - 1
else:
start = index.start
if start < 0:
start += len(images)
if index.stop is None:
stop = -1
else:
stop = index.stop
if stop < 0:
stop += len(images)
return [images[i] for i in range(start, stop, step)]
def write_vasp(filename, atoms, label='', direct=False, sort=None, symbol_count = None, long_format=True):
"""Method to write VASP position (POSCAR/CONTCAR) files.
Writes label, scalefactor, unitcell, # of various kinds of atoms,
positions in cartesian or scaled coordinates (Direct), and constraints
to file. Cartesian coordiantes is default and default label is the
atomic species, e.g. 'C N H Cu'.
"""
import numpy as np
from ase.constraints import FixAtoms, FixScaled
if isinstance(filename, str):
f = open(filename, 'w')
else: # Assume it's a 'file-like object'
f = filename
if isinstance(atoms, (list, tuple)):
if len(atoms) > 1:
raise RuntimeError("Don't know how to save more than "+
"one image to VASP input")
else:
atoms = atoms[0]
# Write atom positions in scaled or cartesian coordinates
if direct:
coord = atoms.get_scaled_positions()
else:
coord = atoms.get_positions()
if atoms.constraints:
sflags = np.zeros((len(atoms), 3), dtype=bool)
for constr in atoms.constraints:
if isinstance(constr, FixScaled):
sflags[constr.a] = constr.mask
elif isinstance(constr, FixAtoms):
sflags[constr.index] = [True, True, True]
if sort:
ind = np.argsort(atoms.get_chemical_symbols())
symbols = np.array(atoms.get_chemical_symbols())[ind]
coord = coord[ind]
if atoms.constraints:
sflags = sflags[ind]
else:
symbols = atoms.get_chemical_symbols()
# Create a list sc of (symbol, count) pairs
if symbol_count:
sc = symbol_count
else:
sc = []
psym = symbols[0]
count = 0
for sym in symbols:
if sym != psym:
sc.append((psym, count))
psym = sym
count = 1
else:
count += 1
sc.append((psym, count))
# Create the label
if label == '':
for sym, c in sc:
label += '%2s ' % sym
f.write(label + '\n')
# Write unitcell in real coordinates and adapt to VASP convention
# for unit cell
# ase Atoms doesn't store the lattice constant separately, so always
# write 1.0.
f.write('%19.16f\n' % 1.0)
if long_format:
latt_form = ' %21.16f'
else:
latt_form = ' %11.6f'
for vec in atoms.get_cell():
f.write(' ')
for el in vec:
f.write(latt_form % el)
f.write('\n')
# Numbers of each atom
for sym, count in sc:
f.write(' %3i' % count)
f.write('\n')
if atoms.constraints:
f.write('Selective dynamics\n')
if direct:
f.write('Direct\n')
else:
f.write('Cartesian\n')
if long_format:
cform = ' %19.16f'
else:
cform = ' %9.6f'
for iatom, atom in enumerate(coord):
for dcoord in atom:
f.write(cform % dcoord)
if atoms.constraints:
for flag in sflags[iatom]:
if flag:
s = 'F'
else:
s = 'T'
f.write('%4s' % s)
f.write('\n')
if type(filename) == str:
f.close()
python-ase-3.6.0.2515/ase/io/vnl.py 0000644 0001754 0001754 00000002013 11207220276 015523 0 ustar askhl askhl import numpy as np
from ase.atoms import Atoms
class VNL:
def __setstate__(self, data):
self.data = data
def ac(shape, typecode, data, endian):
x = np.fromstring(data, typecode)
try:
x.shape = shape
except ValueError:
x = x[::2].copy()
x.shape = shape
if np.LittleEndian != endian:
return x.byteswap()
else:
return x
class VNLUnpickler(pickle.Unpickler):
def find_class(self, module, name):
if module == 'VNLATKStorage.Core.Sample':
return VNL
if name == 'array_constructor':
return ac
return pickle.Unpickler.find_class(self, module, name)
def read_vnl(filename):
from cStringIO import StringIO
vnl = VNLUnpickler(StringIO(ZipFile(filename).read('0_object'))).load()
conf = vnl.data['__properties__']['Atomic Configuration'].data
numbers = conf['_dataarray_']
positions = conf['_positions_'].data['_dataarray_']
return Atoms(numbers=numbers, positions=positions)
python-ase-3.6.0.2515/ase/io/etsf.py 0000644 0001754 0001754 00000006415 11475647267 015723 0 ustar askhl askhl import numpy as np
from ase.atoms import Atoms
from ase.units import Bohr
from ase.io.pupynere import NetCDFFile
class ETSFReader:
def __init__(self, filename):
self.nc = NetCDFFile(filename, 'r')
def read_atoms(self):
var = self.nc.variables
cell = var['primitive_vectors']
assert cell.units == 'atomic units'
species = var['atom_species'][:]
spos = var['reduced_atom_positions'][:]
numbers = var['atomic_numbers'][:]
return Atoms(numbers=numbers[species - 1],
scaled_positions=spos,
cell=cell[:] * Bohr,
pbc=True)
class ETSFWriter:
def __init__(self, filename):
from Scientific.IO.NetCDF import NetCDFFile
self.nc = NetCDFFile(filename, 'w')
self.nc.file_format = 'ETSF Nanoquanta'
self.nc.file_format_version = np.array([3.3], dtype=np.float32)
self.nc.Conventions = 'http://www.etsf.eu/fileformats/'
self.nc.history = 'File generated by ASE'
def write_atoms(self, atoms):
specie_a = np.empty(len(atoms), np.int32)
nspecies = 0
species = {}
numbers = []
for a, Z in enumerate(atoms.get_atomic_numbers()):
if Z not in species:
species[Z] = nspecies
nspecies += 1
numbers.append(Z)
specie_a[a] = species[Z]
dimensions = [
('character_string_length', 80),
('number_of_atoms', len(atoms)),
('number_of_atom_species', nspecies),
('number_of_cartesian_directions', 3),
('number_of_reduced_dimensions', 3),
('number_of_vectors', 3)]
for name, size in dimensions:
self.nc.createDimension(name, size)
var = self.add_variable
var('primitive_vectors',
('number_of_vectors', 'number_of_cartesian_directions'),
atoms.cell / Bohr, units='atomic units')
var('atom_species', ('number_of_atoms',), specie_a + 1)
var('reduced_atom_positions',
('number_of_atoms', 'number_of_reduced_dimensions'),
atoms.get_scaled_positions())
var('atomic_numbers', ('number_of_atom_species',),
np.array(numbers, dtype=float))
def close(self):
self.nc.close()
def add_variable(self, name, dims, data=None, **kwargs):
if data is None:
char = 'd'
else:
if isinstance(data, np.ndarray):
char = data.dtype.char
elif isinstance(data, float):
char = 'd'
elif isinstance(data, int):
char = 'i'
else:
char = 'c'
var = self.nc.createVariable(name, char, dims)
for attr, value in kwargs.items():
setattr(var, attr, value)
if data is not None:
if len(dims) == 0:
var.assignValue(data)
else:
if char == 'c':
if len(dims) == 1:
var[:len(data)] = data
else:
for i, x in enumerate(data):
var[i, :len(x)] = x
else:
var[:] = data
return var
python-ase-3.6.0.2515/ase/io/turbomole.py 0000644 0001754 0001754 00000012776 11655756254 016776 0 ustar askhl askhl from ase.atoms import Atoms
from ase.units import Bohr
def read_turbomole(filename='coord'):
"""Method to read turbomole coord file
coords in bohr, atom types in lowercase, format:
$coord
x y z atomtype
x y z atomtype f
$end
Above 'f' means a fixed atom.
"""
from ase import Atoms, Atom
from ase.constraints import FixAtoms
if isinstance(filename, str):
f = open(filename)
lines = f.readlines()
atoms_pos = []
atom_symbols = []
myconstraints=[]
# find $coord section;
# does not necessarily have to be the first $ in file...
start = lines.index('$coord') # raises ValueError if not found
for line in lines[start+1:]:
if line.startswith('$'): # start of new section
break
else:
x, y, z, symbolraw = line.split()[:4]
symbolshort=symbolraw.strip()
symbol=symbolshort[0].upper()+symbolshort[1:].lower()
#print symbol
atom_symbols.append(symbol)
atoms_pos.append([float(x)*Bohr, float(y)*Bohr, float(z)*Bohr])
cols = line.split()
if (len(cols) == 5):
fixedstr = line.split()[4].strip()
if (fixedstr == "f"):
myconstraints.append(True)
else:
myconstraints.append(False)
else:
myconstraints.append(False)
if type(filename) == str:
f.close()
atoms = Atoms(positions = atoms_pos, symbols = atom_symbols, pbc = False)
c = FixAtoms(mask = myconstraints)
atoms.set_constraint(c)
#print c
return atoms
def read_turbomole_gradient(filename='gradient', index=-1):
""" Method to read turbomole gradient file """
if isinstance(filename, str):
f = open(filename)
# read entire file
lines = [x.strip() for x in f.readlines()]
# find $grad section
start = end = -1
for i, line in enumerate(lines):
if not line.startswith('$'):
continue
if line.split()[0] == '$grad':
start = i
elif start >= 0:
end = i
break
if end <= start:
raise RuntimeError('File %s does not contain a valid \'$grad\' section' % (filename))
def formatError():
raise RuntimeError('Data format in file %s does not correspond to known Turbomole gradient format' % (filename))
# trim lines to $grad
del lines[:start+1]
del lines[end-1-start:]
# Interpret $grad section
from ase import Atoms, Atom
from ase.calculators.singlepoint import SinglePointCalculator
from ase.units import Bohr
images = []
while len(lines): # loop over optimization cycles
# header line
# cycle = 1 SCF energy = -267.6666811409 |dE/dxyz| = 0.157112
fields = lines[0].split('=')
try:
cycle = int(fields[1].split()[0])
energy = float(fields[2].split()[0])
gradient = float(fields[3].split()[0])
except (IndexError, ValueError):
formatError()
# coordinates/gradient
atoms = Atoms()
forces = []
for line in lines[1:]:
fields = line.split()
if len(fields) == 4: # coordinates
# 0.00000000000000 0.00000000000000 0.00000000000000 c
try:
symbol = fields[3].lower().capitalize()
position = tuple([bohr2angstrom(float(x)) for x in fields[0:3] ])
except ValueError:
formatError()
atoms.append(Atom(symbol, position))
elif len(fields) == 3: # gradients
# -.51654903354681D-07 -.51654903206651D-07 0.51654903169644D-07
try:
grad = [float(x.replace('D', 'E')) * Bohr for x in fields[0:3] ]
except ValueError:
formatError()
forces.append(grad)
else: # next cycle
break
# calculator
calc = SinglePointCalculator(energy, forces, None, None, atoms)
atoms.set_calculator(calc)
# save frame
images.append(atoms)
# delete this frame from data to be handled
del lines[:2*len(atoms)+1]
return images[index]
def write_turbomole(filename, atoms):
"""Method to write turbomole coord file
"""
import numpy as np
from ase.constraints import FixAtoms
if isinstance(filename, str):
f = open(filename, 'w')
else: # Assume it's a 'file-like object'
f = filename
coord = atoms.get_positions()
symbols = atoms.get_chemical_symbols()
printfixed = False
if atoms.constraints:
for constr in atoms.constraints:
if isinstance(constr, FixAtoms):
fix_index=constr.index
printfixed=True
#print sflags
if (printfixed):
fix_str=[]
for i in fix_index:
if i == 1:
fix_str.append("f")
else:
fix_str.append(" ")
f.write("$coord\n")
if (printfixed):
for (x, y, z), s, fix in zip(coord,symbols,fix_str):
f.write('%20.14f %20.14f %20.14f %2s %2s \n'
% (x/Bohr, y/Bohr, z/Bohr, s.lower(), fix))
else:
for (x, y, z), s in zip(coord,symbols):
f.write('%20.14f %20.14f %20.14f %2s \n'
% (x/Bohr, y/Bohr, z/Bohr, s.lower()))
f.write("$end\n")
python-ase-3.6.0.2515/ase/io/sdf.py 0000644 0001754 0001754 00000001117 11417270450 015506 0 ustar askhl askhl from math import pi, cos, sin, sqrt, acos
from ase.atoms import Atoms
from ase.parallel import paropen
def read_sdf(fileobj):
if isinstance(fileobj, str):
fileobj = open(fileobj)
lines = fileobj.readlines()
# first three lines header
del lines[:3]
#
L1 = lines.pop(0).split()
natoms = int(L1[0])
positions = []
symbols = []
for line in lines[:natoms]:
x, y, z, symbol = line.split()[:4]
symbols.append(symbol)
positions.append([float(x), float(y), float(z)])
return Atoms(symbols=symbols, positions=positions)
python-ase-3.6.0.2515/ase/io/dacapo.py 0000644 0001754 0001754 00000004767 11410141252 016165 0 ustar askhl askhl import numpy as np
from ase.calculators.singlepoint import SinglePointCalculator
from ase.atom import Atom
from ase.atoms import Atoms
def read_dacapo_text(fileobj):
if isinstance(fileobj, str):
fileobj = open(fileobj)
lines = fileobj.readlines()
i = lines.index(' Structure: A1 A2 A3\n')
cell = np.array([[float(w) for w in line.split()[2:5]]
for line in lines[i + 1:i + 4]]).transpose()
i = lines.index(' Structure: >> Ionic positions/velocities ' +
'in cartesian coordinates <<\n')
atoms = []
for line in lines[i + 4:]:
words = line.split()
if len(words) != 9:
break
Z, x, y, z = words[2:6]
atoms.append(Atom(int(Z), [float(x), float(y), float(z)]))
atoms = Atoms(atoms, cell=cell.tolist())
try:
i = lines.index(
' DFT: CPU time Total energy\n')
except ValueError:
pass
else:
column = lines[i + 3].split().index('selfcons') - 1
try:
i2 = lines.index(' ANALYSIS PART OF CODE\n', i)
except ValueError:
pass
else:
while i2 > i:
if lines[i2].startswith(' DFT:'):
break
i2 -= 1
energy = float(lines[i2].split()[column])
atoms.set_calculator(SinglePointCalculator(energy, None, None,
None, atoms))
return atoms
def read_dacapo(filename):
from ase.io.pupynere import NetCDFFile
nc = NetCDFFile(filename)
dims = nc.dimensions
vars = nc.variables
cell = vars['UnitCell'][-1]
try:
magmoms = vars['InitialAtomicMagneticMoment'][:]
except KeyError:
magmoms = None
try:
tags = vars['AtomTags'][:]
except KeyError:
tags = None
atoms = Atoms(scaled_positions=vars['DynamicAtomPositions'][-1],
symbols=[(a + b).strip()
for a, b in vars['DynamicAtomSpecies'][:]],
cell=cell,
magmoms=magmoms,
tags=tags,
pbc=True)
try:
energy = vars['TotalEnergy'][-1]
force = vars['DynamicAtomForces'][-1]
except KeyError:
energy = None
force = None
calc = SinglePointCalculator(energy,force,None, None, atoms) ### Fixme magmoms
atoms.set_calculator(calc)
return atoms
python-ase-3.6.0.2515/ase/io/castep.py 0000644 0001754 0001754 00000056611 11636303074 016224 0 ustar askhl askhl # -*- coding: utf-8 -*-
"""This module defines I/O routines with CASTEP files.
The key idea is that all function accept or return atoms objects.
CASTEP specific parameters will be returned through the .calc
attribute.
"""
from numpy import sqrt, radians, sin, cos, matrix, array, cross, float32, dot
import ase
from ase.constraints import FixAtoms, FixCartesian
from ase.parallel import paropen
import os
__all__ = [
'read_castep',
'read_cell',
'read_geom',
'read_param',
'read_seed',
'write_cell',
'write_param',
]
def write_cell(filename, atoms, positions_frac=False, castep_cell=None,
force_write=False):
"""This CASTEP export function write minimal information to
a .cell file. If the atoms object is a trajectory, it will
take the last image.
"""
if atoms is None:
print("Atoms object not initialized")
return False
if isinstance(atoms, list):
if len(atoms) > 1:
atoms = atoms[-1]
if os.path.isfile(filename) and not force_write:
print('ase.io.castep.write_param: Set optional argument')
print('force_write=True to overwrite %s.' % filename)
return False
fd = open(filename, 'w')
fd.write('#######################################################\n')
fd.write('#CASTEP cell file: %s\n' % filename)
fd.write('#Created using the Atomic Simulation Environment (ASE)#\n')
fd.write('#######################################################\n\n')
fd.write('%BLOCK LATTICE_CART\n')
cell = matrix(atoms.get_cell())
for line in atoms.get_cell():
fd.write(' %.10f %.10f %.10f\n' % tuple(line))
fd.write('%ENDBLOCK LATTICE_CART\n\n\n')
if positions_frac:
keyword = 'POSITIONS_FRAC'
positions = array(atoms.get_positions() * cell.I)
else:
keyword = 'POSITIONS_ABS'
positions = atoms.get_positions()
if atoms.get_initial_magnetic_moments().any():
pos_block = [('%s %8.6f %8.6f %8.6f SPIN=%4.2f' %
(x, y[0], y[1], y[2], m)) for (x, y, m)
in zip(atoms.get_chemical_symbols(),
positions,
atoms.get_initial_magnetic_moments())]
else:
pos_block = [('%s %8.6f %8.6f %8.6f' %
(x, y[0], y[1], y[2])) for (x, y)
in zip(atoms.get_chemical_symbols(),
positions)]
fd.write('%%BLOCK %s\n' % keyword)
for line in pos_block:
fd.write(' %s\n' % line)
fd.write('%%ENDBLOCK %s\n\n' % keyword)
# if atoms, has a CASTEP calculator attached, then only
# write constraints if really necessary
if hasattr(atoms, 'calc')\
and hasattr(atoms.calc, 'param')\
and hasattr(atoms.calc.param, 'task'):
task = atoms.calc.param.task
if atoms.calc.param.task.value is None:
suppress_constraints = True
elif task.value.lower() not in [
'geometryoptimization',
'moleculardynamics',
'transitionstatesearch',
'phonon']:
suppress_constraints = True
else:
suppress_constraints = False
else:
suppress_constraints = True
constraints = atoms.constraints
if len(constraints) and not suppress_constraints:
fd.write("%BLOCK IONIC_CONSTRAINTS \n")
count = 0
for constr in constraints:
if not isinstance(constr, FixAtoms)\
and not isinstance(constr, FixCartesian)\
and not suppress_constraints:
print('Warning: you have constraints in your atoms, that are')
print(' not supported by CASTEP')
break
if isinstance(constr, FixAtoms):
# sorry, for this complicated block
# reason is that constraint.index can either
# hold booleans or integers and in both cases
# it is an numpy array, so no simple comparison works
for n, val in enumerate(constr.index):
if val.dtype.name.startswith('bool'):
if not val:
continue
symbol = atoms.get_chemical_symbols()[n]
nis = atoms.calc._get_number_in_species(n)
elif val.dtype.name.startswith('int'):
symbol = atoms.get_chemical_symbols()[val]
nis = atoms.calc._get_number_in_species(val)
else:
raise UserWarning('Unrecognized index in' + \
' constraint %s' % constr)
fd.write("%6d %3s %3d 1 0 0 \n" % (count + 1,
symbol,
nis))
fd.write("%6d %3s %3d 0 1 0 \n" % (count + 2,
symbol,
nis))
fd.write("%6d %3s %3d 0 0 1 \n" % (count + 3,
symbol,
nis))
count += 3
elif isinstance(constr, FixCartesian):
n = constr.a
symbol = atoms.get_chemical_symbols()[n]
nis = atoms.calc._get_number_in_species(n)
fix_cart = - constr.mask + 1
if fix_cart[0]:
count += 1
fd.write("%6d %3s %3d 1 0 0 \n" % (count, symbol, nis))
if fix_cart[1]:
count += 1
fd.write("%6d %3s %3d 0 1 0 \n" % (count, symbol, nis))
if fix_cart[2]:
count += 1
fd.write("%6d %3s %3d 0 0 1 \n" % (count, symbol, nis))
fd.write("%ENDBLOCK IONIC_CONSTRAINTS \n")
if castep_cell is None:
if hasattr(atoms, 'calc') and hasattr(atoms.calc, 'cell'):
castep_cell = atoms.calc.cell
else:
fd.close()
return True
for option in castep_cell._options.values():
if option.value is not None:
if option.type == 'Block':
fd.write('%%BLOCK %s\n' % option.keyword.upper())
fd.write(option.value)
fd.write('\n%%ENDBLOCK %s\n' % option.keyword.upper())
else:
fd.write('%s : %s\n' % (option.keyword.upper(), option.value))
fd.close()
return True
def read_cell(filename, _=None):
"""Read a .cell file and return an atoms object.
Any value found that does not fit the atoms API
will be stored in the atoms.calc attribute.
"""
from ase.calculators.castep import Castep
calc = Castep()
fileobj = open(filename)
lines = fileobj.readlines()
fileobj.close()
def get_tokens(lines, l):
"""Tokenizes one line of a *cell file."""
comment_chars = "#!"
while l < len(lines):
line = lines[l].strip()
if len(line) == 0:
l += 1
continue
elif any([line.startswith(comment_char)
for comment_char in comment_chars]):
l += 1
continue
else:
for c in comment_chars:
if c in line:
icomment = min(line.index(c))
else:
icomment = len(line)
tokens = line[:icomment].split()
return tokens, l + 1
tokens = ""
print("read_cell: Warning - get_tokens has not found any more tokens")
return tokens, l
lat = []
have_lat = False
pos = []
spec = []
constraints = []
raw_constraints = {}
have_pos = False
pos_frac = False
l = 0
while l < len(lines):
tokens, l = get_tokens(lines, l)
if not tokens:
continue
elif tokens[0].upper() == "%BLOCK":
if tokens[1].upper() == "LATTICE_CART" and not have_lat:
tokens, l = get_tokens(lines, l)
if len(tokens) == 1:
print('read_cell: Warning - ignoring unit specifier in')
print('%BLOCK LATTICE_CART (assuming Angstrom instead)')
tokens, l = get_tokens(lines, l)
for _ in range(3):
lat_vec = map(float, tokens[0:3])
lat.append(lat_vec)
tokens, l = get_tokens(lines, l)
if tokens[0].upper() != "%ENDBLOCK":
print('read_cell: Warning - ignoring more than three')
print('lattice vectors in invalid %BLOCK LATTICE_CART')
print('%s ...' % tokens[0].upper())
have_lat = True
elif tokens[1].upper() == "LATTICE_ABC" and not have_lat:
tokens, l = get_tokens(lines, l)
if len(tokens) == 1:
print('read_cell: Warning - ignoring unit specifier in')
print('%BLOCK LATTICE_ABC (assuming Angstrom instead)')
tokens, l = get_tokens(lines, l)
a, b, c = map(float, tokens[0:3])
tokens, l = get_tokens(lines, l)
alpha, beta, gamma = map(lambda phi: radians(float(phi)),
tokens[0:3])
tokens, l = get_tokens(lines, l)
if tokens[0].upper() != "%ENDBLOCK":
print('read_cell: Warning - ignoring additional lines in')
print('invalid %BLOCK LATTICE_ABC')
lat_a = [a, 0, 0]
lat_b = [b * cos(gamma), b * sin(gamma), 0]
lat_c1 = c * cos(beta)
lat_c2 = c * (cos(alpha) - cos(beta) * cos(gamma)) / sin(gamma)
lat_c3 = sqrt(c * c - lat_c1 * lat_c1 - lat_c2 * lat_c2)
lat_c = [lat_c1, lat_c2, lat_c3]
lat = [lat_a, lat_b, lat_c]
have_lat = True
elif tokens[1].upper() == "POSITIONS_ABS" and not have_pos:
tokens, l = get_tokens(lines, l)
if len(tokens) == 1:
print('read_cell: Warning - ignoring unit specifier in')
print('%BLOCK POSITIONS_ABS(assuming Angstrom instead)')
tokens, l = get_tokens(lines, l)
while len(tokens) == 4:
spec.append(tokens[0])
pos.append(map(float, tokens[1:4]))
tokens, l = get_tokens(lines, l)
if tokens[0].upper() != "%ENDBLOCK":
print('read_cell: Warning - ignoring invalid lines in')
print('%%BLOCK POSITIONS_ABS:\n\t %s' % tokens)
have_pos = True
elif tokens[1].upper() == "POSITIONS_FRAC" and not have_pos:
pos_frac = True
tokens, l = get_tokens(lines, l)
while len(tokens) == 4:
spec.append(tokens[0])
pos.append(map(float, tokens[1:4]))
tokens, l = get_tokens(lines, l)
if tokens[0].upper() != "%ENDBLOCK":
print('read_cell: Warning - ignoring invalid lines')
print('%%BLOCK POSITIONS_FRAC:\n\t %s' % tokens)
have_pos = True
elif tokens[1].upper() == 'SPECIES_POT':
tokens, l = get_tokens(lines, l)
while tokens and not tokens[0].upper() == '%ENDBLOCK':
if len(tokens) == 2:
calc.cell.species_pot = tuple(tokens)
tokens, l = get_tokens(lines, l)
elif tokens[1].upper() == 'IONIC_CONSTRAINTS':
while True:
if tokens and tokens[0].upper() == '%ENDBLOCK':
break
tokens, l = get_tokens(lines, l)
if not len(tokens) == 6:
continue
_, species, nic, x, y, z = tokens
nic = int(nic)
if (species, nic) not in raw_constraints:
raw_constraints[(species, nic)] = []
raw_constraints[(species, nic)].append(array(
[x, y, z]))
else:
print('Warning: the keyword %s is not' % tokens[1].upper())
print(' interpreted in cell files')
while not tokens[0].upper() == '%ENDBLOCK':
tokens, l = get_tokens(lines, l)
#raise UserWarning
else:
key = tokens[0]
value = ' '.join(tokens[1:])
try:
calc.__setattr__(key, value)
except:
print("Problem setting calc.cell.%s = %s" % (key, value))
raise
if pos_frac:
atoms = ase.Atoms(
calculator=calc,
cell=lat,
pbc=True,
scaled_positions=pos,
symbols=spec,
)
else:
atoms = ase.Atoms(
calculator=calc,
cell=lat,
pbc=True,
positions=pos,
symbols=spec,
)
fixed_atoms = []
for (species, nic), value in raw_constraints.iteritems():
absolute_nr = atoms.calc._get_absolute_number(species, nic)
if len(value) == 3:
fixed_atoms.append(absolute_nr)
elif len(value) == 2:
constraint = ase.constraints.FixedLine(a=absolute_nr,
direction=cross(value[0], value[1]))
constraints.append(constraint)
elif len(value) == 1:
constraint = ase.constraints.FixedPlane(a=absolute_nr,
direction=array(value[0], dtype=float32))
constraints.append(constraint)
else:
print('Error: Found %s statements attached to atoms %s'
% (len(value), absolute_nr))
constraints.append(ase.constraints.FixAtoms(fixed_atoms))
atoms.set_constraint(constraints)
# needs to go here again to have the constraints in
# atoms.calc.atoms.constraints as well
atoms.calc.atoms = atoms
atoms.calc.push_oldstate()
return atoms
# this actually does not belong here
# think how one could join this with
# the ase.calculators.castep.Castep.read()
# in the future!
def read_castep(filename, _=-1):
"""Reads a .castep file and returns an atoms object.
The calculator information will be stored in the calc attribute.
If more than one SCF step is found, a list of all steps
will be stored in the traj attribute.
Note that the index argument has no effect as of now.
"""
from ase.calculators.singlepoint import SinglePointCalculator
fileobj = open(filename)
lines = fileobj.readlines()
fileobj.close()
traj = []
energy_total = None
energy_0K = None
for i, line in enumerate(lines):
if 'NB est. 0K energy' in line:
energy_0K = float(line.split()[6])
elif 'Final energy, E' in line:
energy_total = float(line.split()[4])
elif 'Unit Cell' in line:
cell = [x.split()[0:3] for x in lines[i + 3:i + 6]]
cell = array([[float(col) for col in row] for row in cell])
elif 'Cell Contents' in line:
geom_starts = i
start_found = False
for j, jline in enumerate(lines[geom_starts:]):
if jline.find('xxxxx') > 0 and start_found:
geom_stop = j + geom_starts
break
if jline.find('xxxx') > 0 and not start_found:
geom_start = j + geom_starts + 4
start_found = True
species = [line.split()[1] for line in lines[geom_start:geom_stop]]
geom = dot(array([[float(col) for col in line.split()[3:6]]
for line in lines[geom_start:geom_stop]]), cell)
elif 'Writing model to' in line:
atoms = ase.Atoms(
cell=cell,
pbc=True,
positions=geom,
symbols=''.join(species),
)
# take 0K energy where available, else total energy
if energy_0K:
energy = energy_0K
else:
energy = energy_total
# generate a minimal single-point calculator
sp_calc = SinglePointCalculator(atoms=atoms,
energy=energy,
forces=None,
magmoms=None,
stress=None,
)
atoms.set_calculator(sp_calc)
traj.append(atoms)
return traj
def read_param(filename, calc=None):
"""Reads a param file. If an Castep object is passed as the
second argument, the parameter setings are merged into
the existing object and returned. Otherwise a new Castep()
calculator instance gets created and returned.
Parameters:
filename: the .param file. Only opens reading
calc: [Optional] calculator object to hang
parameters onto
"""
if calc is None:
calc = ase.calculators.castep.Castep(check_castep_version=False)
calc.merge_param(filename)
return calc
def write_param(filename, param, check_checkfile=False,
force_write=False,
interface_options=None):
"""Writes a CastepParam object to a CASTEP .param file
Parameters:
filename: the location of the file to write to. If it
exists it will be overwritten without warning. If it
doesn't it will be created.
param: a CastepParam instance
check_checkfile : if set to True, write_param will
only write continuation or reuse statement
if a restart file exists in the same directory
"""
if os.path.isfile(filename) and not force_write:
print('ase.io.castep.write_param: Set optional argument')
print('force_write=True to overwrite %s.' % filename)
return False
out = paropen(filename, 'w')
out.write('#######################################################\n')
out.write('#CASTEP param file: %s\n' % filename)
out.write('#Created using the Atomic Simulation Environment (ASE)#\n')
if interface_options is not None:
out.write('# Internal settings of the calculator\n')
out.write('# This can be switched off by settings\n')
out.write('# calc._export_settings = False\n')
out.write('# If stated, this will be automatically processed\n')
out.write('# by ase.io.castep.read_seed()\n')
for option, value in sorted(interface_options.iteritems()):
out.write('# ASE_INTERFACE %s : %s\n' % (option, value))
out.write('#######################################################\n\n')
for keyword, opt in sorted(param._options.iteritems()):
if opt.type == 'Defined':
if opt.value is not None:
out.write('%s\n' % (option))
elif opt.value is not None:
if keyword in ['continuation', 'reuse'] and check_checkfile:
if opt.value == 'default':
if not os.path.exists('%s.%s'\
% (os.path.splitext(filename)[0], 'check')):
continue
elif not os.path.exists(opt.value):
continue
out.write('%s : %s\n'
% (keyword, opt.value))
out.close()
def read_geom(filename, _=-1):
"""Reads a .geom file produced by the CASTEP GeometryOptimization task and
returns an atoms object.
The information about total free energy and forces of each atom for every
relaxation step will be stored for further analysis especially in a
single-point calculator.
Note that everything in the .geom file is in atomic units, which has
been conversed to commonly used unit angstrom(length) and eV (energy).
Note that the index argument has no effect as of now.
Contribution by Wei-Bing Zhang. Thanks!
"""
from ase.calculators.singlepoint import SinglePointCalculator
fileobj = open(filename)
txt = fileobj.readlines()
fileobj.close()
traj = []
# Source: CODATA2002, used by default
# in CASTEP 5.01
# but check with your version in case of error
# ase.units is based on CODATA1986/
# here we hard-code from http://physics.nist.gov/cuu/Document/all_2002.pdf
Hartree = 27.211384565719481
Bohr = 0.5291772108
print('N.B.: Energy in .geom file is not 0K extrapolated.')
for i, line in enumerate(txt):
if line.find("<-- E") > 0:
start_found = True
energy = float(line.split()[0]) * Hartree
cell = [x.split()[0:3] for x in txt[i + 1:i + 4]]
cell = array([[float(col) * Bohr for col in row] for row in
cell])
if line.find('<-- R') > 0 and start_found:
start_found = False
geom_start = i
for i, line in enumerate(txt[geom_start:]):
if line.find('<-- F') > 0:
geom_stop = i + geom_start
break
species = [line.split()[0] for line in
txt[geom_start:geom_stop]]
geom = array([[float(col) * Bohr for col in
line.split()[2:5]] for line in txt[geom_start:geom_stop]])
forces = array([[float(col) * Hartree / Bohr for col in
line.split()[2:5]] for line in
txt[geom_stop:geom_stop + (geom_stop - geom_start)]])
image = ase.Atoms(species, geom, cell=cell, pbc=True)
image.set_calculator(SinglePointCalculator(energy, forces, None,
None, image))
traj.append(image)
return traj
def read_seed(seed, new_seed=None, ignore_internal_keys=False):
"""A wrapper around the CASTEP Calculator in conjunction with
read_cell and read_param. Basically this can be used to reuse
a previous calculation which results in a triple of
cell/param/castep file. The label of the calculation if pre-
fixed with cop_of_ and everything else will be recycled as
much as possible from the addressed calculation.
"""
directory = os.path.abspath(os.path.dirname(seed))
seed = os.path.basename(seed)
paramfile = os.path.join(directory, '%s.param' % seed)
cellfile = os.path.join(directory, '%s.cell' % seed)
castepfile = os.path.join(directory, '%s.castep' % seed)
atoms = read_cell(cellfile)
atoms.calc._directory = directory
atoms.calc._rename_existing_dir = False
atoms.calc._castep_pp_path = directory
atoms.calc.merge_param(paramfile,
ignore_internal_keys=ignore_internal_keys)
if new_seed is None:
atoms.calc._label = 'copy_of_%s' % seed
else:
atoms.calc._label = str(new_seed)
if os.path.isfile(castepfile):
# _set_atoms needs to be True here
# but we set it right back to False
atoms.calc._set_atoms = True
atoms.calc.read(castepfile)
atoms.calc._set_atoms = False
# sync the top-level object with the
# one attached to the calculator
atoms = atoms.calc.atoms
else:
print('Corresponding CASTEP not found.')
atoms.calc.push_oldstate()
return atoms
python-ase-3.6.0.2515/ase/io/siesta.py 0000644 0001754 0001754 00000017542 11676635535 016253 0 ustar askhl askhl from numpy import zeros
from os import fstat
from re import compile
from ase.io.fortranfile import FortranFile
def read_rho(fname):
"Read unformatted Siesta charge density file"
# TODO:
#
# Handle formatted and NetCDF files.
#
# Siesta source code (at least 2.0.2) can possibly also
# save RHO as a _formatted_ file (the source code seems
# prepared, but there seems to be no fdf-options for it though).
# Siesta >= 3 has support for saving RHO as a NetCDF file
# (according to manual)
fh = FortranFile(fname)
# Read (but ignore) unit cell vectors
x = fh.readReals('d')
if len(x) != 3 * 3:
raise IOError('Failed to read cell vectors')
# Read number of grid points and spin components
x = fh.readInts()
if len(x) != 4:
raise IOError('Failed to read grid size')
gpts = x # number of 'X', 'Y', 'Z', 'spin' gridpoints
rho = zeros(gpts)
for ispin in range(gpts[3]):
for n3 in range(gpts[2]):
for n2 in range(gpts[1]):
x = fh.readReals('f')
if len(x) != gpts[0]:
raise IOError('Failed to read RHO[:,%i,%i,%i]' %
(n2, n3, ispin))
rho[:, n2, n3, ispin] = x
fh.close()
return rho
#
# Helper functions for read_fdf
#
_label_strip_re = compile(r'[\s._-]')
def _labelize(raw_label):
# Labels are case insensitive and -_. should be ignored, lower and strip it
return _label_strip_re.sub('', raw_label).lower()
def _is_block(val):
# Tell whether value is a block-value or an ordinary value.
# A block is represented as a list of lists of strings,
# and a ordinary value is represented as a list of strings
if type(val) is list and \
len(val) > 0 and \
type(val[0]) is list:
return True
return False
def _get_stripped_lines(fd):
# Remove comments, leading blanks, and empty lines
return filter(None, [L.split('#')[0].strip() for L in fd])
def _read_fdf_lines(file, inodes=[]):
# Read lines and resolve includes
if type(file) is str:
file = open(file, 'r')
fst = fstat(file.fileno())
inode = (fst.st_dev, fst.st_ino)
if inode in inodes:
raise IOError('Cyclic include in fdf file')
inodes = inodes + [inode]
lbz = _labelize
lines = []
for L in _get_stripped_lines(file):
w0 = lbz(L.split(None, 1)[0])
if w0 == '%include':
# Include the contents of fname
fname = L.split(None, 1)[1].strip()
lines += _read_fdf_lines(fname, inodes)
elif '<' in L:
L, fname = L.split('<', 1)
w = L.split()
fname = fname.strip()
if w0 == '%block':
# "%block label < filename" means that the block contents should be read from filename
if len(w) != 2:
raise IOError('Bad %%block-statement "%s < %s"' % (L, fname))
label = lbz(w[1])
lines.append('%%block %s' % label)
lines += _get_stripped_lines(open(fname))
lines.append('%%endblock %s' % label)
else:
# "label < filename.fdf" means that the label (_only_ that label) is to be resolved from filename.fdf
label = lbz(w[0])
fdf = _read_fdf(fname, inodes)
if label in fdf:
if _is_block(fdf[label]):
lines.append('%%block %s' % label)
lines += [' '.join(x) for x in fdf[label]]
lines.append('%%endblock %s' % label)
else:
lines.append('%s %s' % (label, ' '.join(fdf[label])))
#else: label unresolved! One should possibly issue a warning about this!
else:
# Simple include line L
lines.append(L)
return lines
#
# The reason for creating a separate _read_fdf is simply to hide the inodes-argument
#
def _read_fdf(fname, inodes=[]):
# inodes is used to detect cyclic includes
fdf = {}
lbz = _labelize
lines = _read_fdf_lines(fname, inodes)
while lines:
w = lines.pop(0).split(None, 1)
if lbz(w[0]) == '%block':
# Block value
if len(w) == 2:
label = lbz(w[1])
content = []
while True:
if len(lines) == 0:
raise IOError('Unexpected EOF reached in %s, '
'un-ended block %s' % (fname, label))
w = lines.pop(0).split()
if lbz(w[0]) == '%endblock' and lbz(w[1]) == label:
break
content.append(w)
if not label in fdf:
# Only first appearance of label is to be used
fdf[label] = content
else:
raise IOError('%%block statement without label' )
else:
# Ordinary value
label = lbz(w[0])
if len(w) == 1:
# Siesta interpret blanks as True for logical variables
fdf[label] = []
else:
fdf[label] = w[1].split()
return fdf
def read_fdf(fname):
"""Read a siesta style fdf-file.
The data is returned as a dictionary
( label:value ).
All labels are converted to lower case characters and
are stripped of any '-', '_', or '.'.
Ordinary values are stored as a list of strings (splitted on WS),
and block values are stored as list of lists of strings
(splitted per line, and on WS).
If a label occurres more than once, the first occurrence
takes precedence.
The implementation applies no intelligence, and does not
"understand" the data or the concept of units etc.
Values are never parsed in any way, just stored as
split strings.
The implementation tries to comply with the fdf-format
specification as presented in the siesta 2.0.2 manual.
An fdf-dictionary could e.g. look like this::
{'atomiccoordinatesandatomicspecies': [
['4.9999998', '5.7632392', '5.6095972', '1'],
['5.0000000', '6.5518100', '4.9929091', '2'],
['5.0000000', '4.9746683', '4.9929095', '2']],
'atomiccoordinatesformat': ['Ang'],
'chemicalspecieslabel': [['1', '8', 'O'],
['2', '1', 'H']],
'dmmixingweight': ['0.1'],
'dmnumberpulay': ['5'],
'dmusesavedm': ['True'],
'latticeconstant': ['1.000000', 'Ang'],
'latticevectors': [
['10.00000000', '0.00000000', '0.00000000'],
['0.00000000', '11.52647800', '0.00000000'],
['0.00000000', '0.00000000', '10.59630900']],
'maxscfiterations': ['120'],
'meshcutoff': ['2721.139566', 'eV'],
'numberofatoms': ['3'],
'numberofspecies': ['2'],
'paobasissize': ['dz'],
'solutionmethod': ['diagon'],
'systemlabel': ['H2O'],
'wavefunckpoints': [['0.0', '0.0', '0.0']],
'writedenchar': ['T'],
'xcauthors': ['PBE'],
'xcfunctional': ['GGA']}
"""
return _read_fdf(fname)
def read_struct(fname):
"""Read a siesta struct file"""
from ase.atoms import Atoms, Atom
f = open(fname, 'r')
cell = []
for i in range(3):
cell.append([float(x) for x in f.readline().split()])
natoms = int(f.readline())
atoms = Atoms()
for atom in f:
Z, pos_x, pos_y, pos_z = atom.split()[1:]
atoms.append(Atom(int(Z), position = (float(pos_x), float(pos_y), float(pos_z))))
if len(atoms) != natoms:
raise IOError('Badly structured input file')
atoms.set_cell(cell, scale_atoms = True)
return atoms
python-ase-3.6.0.2515/ase/io/fortranfile.py 0000644 0001754 0001754 00000021110 11531152214 017232 0 ustar askhl askhl # Copyright 2008-2010 Neil Martinsen-Burrell
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""Defines a file-derived class to read/write Fortran unformatted files.
The assumption is that a Fortran unformatted file is being written by
the Fortran runtime as a sequence of records. Each record consists of
an integer (of the default size [usually 32 or 64 bits]) giving the
length of the following data in bytes, then the data itself, then the
same integer as before.
Examples
--------
To use the default endian and precision settings, one can just do:
>>> f = FortranFile('filename')
>>> x = f.readReals()
One can read arrays with varying precisions:
>>> f = FortranFile('filename')
>>> x = f.readInts('h')
>>> y = f.readInts('q')
>>> z = f.readReals('f')
Where the format codes are those used by Python's struct module.
One can change the default endian-ness and header precision:
>>> f = FortranFile('filename', endian='>', header_prec='l')
for a file with little-endian data whose record headers are long
integers.
"""
__docformat__ = "restructuredtext en"
import numpy
try:
file
except NameError:
# For python3 compatibility
from io import FileIO as file
try:
bytes
except NameError:
# For python2.x compatibility, I think it would have been nicer to
# "from __future__ import unicode_literals" and used b'' instead of bytes()
bytes = str
class FortranFile(file):
"""File with methods for dealing with fortran unformatted data files"""
def _get_header_length(self):
return numpy.dtype(self._header_prec).itemsize
_header_length = property(fget=_get_header_length)
def _set_endian(self,c):
"""Set endian to big (c='>') or little (c='<') or native (c='=')
:Parameters:
`c` : string
The endian-ness to use when reading from this file.
"""
if c in '<>@=':
if c == '@':
c = '='
self._endian = c
else:
raise ValueError('Cannot set endian-ness')
def _get_endian(self):
return self._endian
ENDIAN = property(fset=_set_endian,
fget=_get_endian,
doc="Possible endian values are '<', '>', '@', '='"
)
def _set_header_prec(self, prec):
if prec in 'hilq':
self._header_prec = prec
else:
raise ValueError('Cannot set header precision')
def _get_header_prec(self):
return self._header_prec
HEADER_PREC = property(fset=_set_header_prec,
fget=_get_header_prec,
doc="Possible header precisions are 'h', 'i', 'l', 'q'"
)
def __init__(self, fname, endian='@', header_prec='i', *args, **kwargs):
"""Open a Fortran unformatted file for writing.
Parameters
----------
endian : character, optional
Specify the endian-ness of the file. Possible values are
'>', '<', '@' and '='. See the documentation of Python's
struct module for their meanings. The deafult is '>' (native
byte order)
header_prec : character, optional
Specify the precision used for the record headers. Possible
values are 'h', 'i', 'l' and 'q' with their meanings from
Python's struct module. The default is 'i' (the system's
default integer).
"""
file.__init__(self, fname, *args, **kwargs)
self.ENDIAN = endian
self.HEADER_PREC = header_prec
def _read_exactly(self, num_bytes):
"""Read in exactly num_bytes, raising an error if it can't be done."""
data = bytes()
while True:
l = len(data)
if l == num_bytes:
return data
else:
read_data = self.read(num_bytes - l)
if read_data == bytes():
raise IOError('Could not read enough data.'
' Wanted %d bytes, got %d.' % (num_bytes, l))
data += read_data
def _read_check(self):
return numpy.fromstring(self._read_exactly(self._header_length),
dtype=self.ENDIAN+self.HEADER_PREC
)[0]
def _write_check(self, number_of_bytes):
"""Write the header for the given number of bytes"""
self.write(numpy.array(number_of_bytes,
dtype=self.ENDIAN+self.HEADER_PREC,).tostring()
)
def readRecord(self):
"""Read a single fortran record"""
l = self._read_check()
data_str = self._read_exactly(l)
check_size = self._read_check()
if check_size != l:
raise IOError('Error reading record from data file')
return data_str
def writeRecord(self,s):
"""Write a record with the given bytes.
Parameters
----------
s : the string to write
"""
length_bytes = len(s)
self._write_check(length_bytes)
self.write(s)
self._write_check(length_bytes)
def readString(self):
"""Read a string."""
return self.readRecord()
def writeString(self,s):
"""Write a string
Parameters
----------
s : the string to write
"""
self.writeRecord(s)
_real_precisions = 'df'
def readReals(self, prec='f'):
"""Read in an array of real numbers.
Parameters
----------
prec : character, optional
Specify the precision of the array using character codes from
Python's struct module. Possible values are 'd' and 'f'.
"""
_numpy_precisions = {'d': numpy.float64,
'f': numpy.float32
}
if prec not in self._real_precisions:
raise ValueError('Not an appropriate precision')
data_str = self.readRecord()
return numpy.fromstring(data_str, dtype=self.ENDIAN+prec)
def writeReals(self, reals, prec='f'):
"""Write an array of floats in given precision
Parameters
----------
reals : array
Data to write
prec` : string
Character code for the precision to use in writing
"""
if prec not in self._real_precisions:
raise ValueError('Not an appropriate precision')
nums = numpy.array(reals, dtype=self.ENDIAN+prec)
self.writeRecord(nums.tostring())
_int_precisions = 'hilq'
def readInts(self, prec='i'):
"""Read an array of integers.
Parameters
----------
prec : character, optional
Specify the precision of the data to be read using
character codes from Python's struct module. Possible
values are 'h', 'i', 'l' and 'q'
"""
if prec not in self._int_precisions:
raise ValueError('Not an appropriate precision')
data_str = self.readRecord()
return numpy.fromstring(data_str, dtype=self.ENDIAN+prec)
def writeInts(self, ints, prec='i'):
"""Write an array of integers in given precision
Parameters
----------
reals : array
Data to write
prec : string
Character code for the precision to use in writing
"""
if prec not in self._int_precisions:
raise ValueError('Not an appropriate precision')
nums = numpy.array(ints, dtype=self.ENDIAN+prec)
self.writeRecord(nums.tostring())
python-ase-3.6.0.2515/ase/io/xsf.py 0000644 0001754 0001754 00000011644 11714705036 015543 0 ustar askhl askhl import numpy as np
from ase.atoms import Atoms
from ase.units import Hartree
from ase.parallel import paropen
from ase.calculators.singlepoint import SinglePointCalculator
def write_xsf(fileobj, images, data=None):
if isinstance(fileobj, str):
fileobj = paropen(fileobj, 'w')
if not isinstance(images, (list, tuple)):
images = [images]
fileobj.write('ANIMSTEPS %d\n' % len(images))
numbers = images[0].get_atomic_numbers()
pbc = images[0].get_pbc()
if pbc[2]:
fileobj.write('CRYSTAL\n')
elif pbc[1]:
fileobj.write('SLAB\n')
elif pbc[0]:
fileobj.write('POLYMER\n')
else:
fileobj.write('MOLECULE\n')
for n, atoms in enumerate(images):
if pbc.any():
fileobj.write('PRIMVEC %d\n' % (n + 1))
cell = atoms.get_cell()
for i in range(3):
fileobj.write(' %.14f %.14f %.14f\n' % tuple(cell[i]))
fileobj.write('PRIMCOORD %d\n' % (n + 1))
# Get the forces if it's not too expensive:
calc = atoms.get_calculator()
if (calc is not None and
(hasattr(calc, 'calculation_required') and
not calc.calculation_required(atoms,
['energy', 'forces', 'stress']))):
forces = atoms.get_forces()
else:
forces = None
pos = atoms.get_positions()
fileobj.write(' %d 1\n' % len(pos))
for a in range(len(pos)):
fileobj.write(' %2d' % numbers[a])
fileobj.write(' %20.14f %20.14f %20.14f' % tuple(pos[a]))
if forces is None:
fileobj.write('\n')
else:
fileobj.write(' %20.14f %20.14f %20.14f\n' % tuple(forces[a]))
if data is None:
return
fileobj.write('BEGIN_BLOCK_DATAGRID_3D\n')
fileobj.write(' data\n')
fileobj.write(' BEGIN_DATAGRID_3Dgrid#1\n')
data = np.asarray(data)
if data.dtype == complex:
data = np.abs(data)
shape = data.shape
fileobj.write(' %d %d %d\n' % shape)
cell = atoms.get_cell()
origin = np.zeros(3)
for i in range(3):
if not pbc[i]:
origin += cell[i] / shape[i]
fileobj.write(' %f %f %f\n' % tuple(origin))
for i in range(3):
fileobj.write(' %f %f %f\n' %
tuple(cell[i] * (shape[i] + 1) / shape[i]))
for x in range(shape[2]):
for y in range(shape[1]):
fileobj.write(' ')
fileobj.write(' '.join(['%f' % d for d in data[x, y]]))
fileobj.write('\n')
fileobj.write('\n')
fileobj.write(' END_DATAGRID_3D\n')
fileobj.write('END_BLOCK_DATAGRID_3D\n')
def read_xsf(fileobj, index=-1, read_data=True):
if isinstance(fileobj, str):
fileobj = open(fileobj)
readline = fileobj.readline
while True:
line = readline()
if line[0] != '#':
line = line.strip()
break
if 'ANIMSTEPS' in line:
nimages = int(line.split()[1])
line = readline().strip()
else:
nimages = 1
if 'CRYSTAL' in line:
pbc = True
elif 'SLAB' in line:
pbc = (True, True, False)
elif 'POLYMER' in line:
pbc = (True, False, False)
else:
pbc = False
images = []
for n in range(nimages):
cell = None
if pbc:
line = readline().strip()
assert 'PRIMVEC' in line
cell = []
for i in range(3):
cell.append([float(x) for x in readline().split()])
line = readline().strip()
assert 'PRIMCOORD' in line
natoms = int(readline().split()[0])
numbers = []
positions = []
for a in range(natoms):
line = readline().split()
numbers.append(int(line[0]))
positions.append([float(x) for x in line[1:]])
positions = np.array(positions)
if len(positions[0]) == 3:
forces = None
else:
positions = positions[:, :3]
forces = positions[:, 3:] * Hartree
image = Atoms(numbers, positions, cell=cell, pbc=pbc)
if forces is not None:
image.set_calculator(SinglePointCalculator(None, forces, None,
None, image))
images.append(image)
if read_data:
line = readline()
assert 'BEGIN_BLOCK_DATAGRID_3D' in line
line = readline()
assert 'BEGIN_DATAGRID_3D' in line
shape = [int(x) for x in readline().split()]
start = [float(x) for x in readline().split()]
for i in range(3):
readline()
n_data = shape[0]*shape[1]*shape[2]
data = np.array([float(readline())
for s in range(n_data)]).reshape(shape[::-1])
data = np.swapaxes(data, 0, 2)
return data, images[index]
return images[index]
python-ase-3.6.0.2515/ase/io/plt.py 0000644 0001754 0001754 00000003076 11575626453 015554 0 ustar askhl askhl import numpy as np
from ase.atoms import Atoms
def write_plt(filename, atoms, data):
if isinstance(atoms, Atoms):
cell = atoms.get_cell()
else:
cell = np.asarray(atoms, float)
if cell.ndim == 2:
c = cell.copy()
cell = c.diagonal()
c.flat[::4] = 0.0
if c.any():
raise ValueError('Unit cell must be orthorhombic!')
f = open(filename, 'w')
np.array([3, 4], np.int32).tofile(f)
dims = np.array(data.shape, np.int32)
dims[::-1].tofile(f)
for n, L in zip(dims[::-1], cell[::-1]):
if n % 2 == 0:
d = L / n
np.array([0.0, L - d], np.float32).tofile(f)
else:
d = L / (n + 1)
np.array([d, L - d], np.float32).tofile(f)
if data.dtype == complex:
data = np.abs(data)
data.astype(np.float32).T.tofile(f)
f.close()
def read_plt(fileobj):
if isinstance(fileobj, str):
fileobj = open(fileobj, 'rb')
# dummy numbers
np.fromfile(fileobj, dtype=np.int32, count=2)
# read dimensions
dims = np.fromfile(fileobj, dtype=np.int32, count=3)
size = dims[0] * dims[1] * dims[2]
# read cell
cell = np.zeros((3,3), np.float32)
for c in range(3):
beg, Lmd = np.fromfile(fileobj, dtype=np.float32, count=2)
n = dims[c]
if n % 2 == 0:
cell[2 - c, 2 - c] = Lmd / (1 - 1. / n)
else:
cell[2 - c, 2 - c] = Lmd / (1 - 1. / (n + 1))
# read data
data = np.fromfile(fileobj, dtype=np.float32)
return data.reshape(dims).T, cell
python-ase-3.6.0.2515/ase/io/netcdf.py 0000644 0001754 0001754 00000005422 11410141252 016166 0 ustar askhl askhl """Read and write ASE2's netCDF trajectory files."""
from ase.io.pupynere import NetCDFFile
from ase.atoms import Atoms
from ase.calculators.singlepoint import SinglePointCalculator
def read_netcdf(filename, index=-1):
nc = NetCDFFile(filename)
dims = nc.dimensions
vars = nc.variables
positions = vars['CartesianPositions']
numbers = vars['AtomicNumbers'][:]
pbc = vars['BoundaryConditions'][:]
cell = vars['UnitCell']
tags = vars['Tags'][:]
if not tags.any():
tags = None
magmoms = vars['MagneticMoments'][:]
if not magmoms.any():
magmoms = None
nimages = positions.shape[0]
attach_calculator = False
if 'PotentialEnergy' in vars:
energy = vars['PotentialEnergy']
attach_calculator = True
else:
energy = nimages * [None]
if 'CartesianForces' in vars:
forces = vars['CartesianForces']
attach_calculator = True
else:
forces = nimages * [None]
if 'Stress' in vars:
stress = vars['Stress']
attach_calculator = True
else:
stress = nimages * [None]
if isinstance(index, int):
indices = [index]
else:
indices = range(nimages)[index]
images = []
for i in indices:
atoms = Atoms(positions=positions[i],
numbers=numbers,
cell=cell[i],
pbc=pbc,
tags=tags, magmoms=magmoms)
if attach_calculator:
calc = SinglePointCalculator(energy[i], forces[i], stress[i],
None, atoms) ### Fixme magmoms
atoms.set_calculator(calc)
images.append(atoms)
if isinstance(index, int):
return images[0]
else:
return images
class LOA:
def __init__(self, images):
self.set_atoms(images[0])
def __len__(self):
return len(self.atoms)
def set_atoms(self, atoms):
self.atoms = atoms
def GetPotentialEnergy(self):
return self.atoms.get_potential_energy()
def GetCartesianForces(self):
return self.atoms.get_forces()
def GetUnitCell(self):
return self.atoms.get_cell()
def GetAtomicNumbers(self):
return self.atoms.get_atomic_numbers()
def GetCartesianPositions(self):
return self.atoms.get_positions()
def GetBoundaryConditions(self):
return self.atoms.get_pbc()
def write_netcdf(filename, images):
from ASE.Trajectories.NetCDFTrajectory import NetCDFTrajectory
if not isinstance(images, (list, tuple)):
images = [images]
loa = LOA(images)
traj = NetCDFTrajectory(filename, loa)
for atoms in images:
loa.set_atoms(atoms)
traj.Update()
traj.Close()
python-ase-3.6.0.2515/ase/io/wien2k.py 0000644 0001754 0001754 00000013274 11377656100 016145 0 ustar askhl askhl from math import sin, cos, pi, sqrt
import numpy as np
from ase.atoms import Atoms, Atom
from ase.units import Bohr, Ry
def read_scf(filename):
try:
f = open(filename + '.scf', 'r')
pip = f.readlines()
ene = []
for line in pip:
if line[0:4] == ':ENE':
ene.append(float(line[43:59]) * Ry)
f.close()
return ene
except:
return None
def read_struct(filename, ase = True):
f = open(filename, 'r')
pip = f.readlines()
lattice = pip[1][0:3]
nat = int(pip[1][27:30])
cell = np.zeros(6)
for i in range(6):
cell[i] = float(pip[3][0 + i * 10:10 + i * 10])
cell[0:3] = cell[0:3] * Bohr
if lattice == 'P ':
lattice = 'P'
elif lattice == 'H ':
lattice = 'P'
cell[3:6] = [90.0, 90.0, 120.0]
elif lattice == 'R ':
lattice = 'R'
elif lattice == 'F ':
lattice = 'F'
elif lattice == 'B ':
lattice = 'I'
elif lattice == 'CXY':
lattice = 'C'
elif lattice == 'CXZ':
lattice = 'B'
elif lattice == 'CYZ':
lattice = 'A'
else:
print 'TEST needed'
pos = np.array([])
atomtype = []
rmt = []
neq = np.zeros(nat)
iline = 4
indif = 0
for iat in range(nat):
indifini = indif
if len(pos) == 0:
pos = np.array([[float(pip[iline][12:22]),
float(pip[iline][25:35]),
float(pip[iline][38:48])]])
else:
pos = np.append(pos, np.array([[float(pip[iline][12:22]),
float(pip[iline][25:35]),
float(pip[iline][38:48])]]),
axis = 0)
indif += 1
iline += 1
neq[iat] = int(pip[iline][15:17])
iline += 1
for ieq in range(1, int(neq[iat])):
pos = np.append(pos, np.array([[float(pip[iline][12:22]),
float(pip[iline][25:35]),
float(pip[iline][38:48])]]),
axis = 0)
indif += 1
iline += 1
for i in range(indif - indifini):
atomtype.append(pip[iline][0:2].replace(' ', ''))
rmt.append(float(pip[iline][43:48]))
iline += 4
if ase:
cell2 = coorsys(cell)
atoms = Atoms(atomtype, pos, pbc = True)
atoms.set_cell(cell2, scale_atoms = True)
cell2 = np.dot(c2p(lattice), cell2)
if lattice == 'R':
atoms.set_cell(cell2, scale_atoms = True)
else:
atoms.set_cell(cell2)
return atoms
else:
return cell, lattice, pos, atomtype, rmt
def write_struct(filename, atoms2 = None, rmt = None, lattice = 'P'):
atoms=atoms2.copy()
atoms.set_scaled_positions(atoms.get_scaled_positions())
f = file(filename, 'w')
f.write('ASE generated\n')
nat = len(atoms)
if rmt == None:
rmt = [2.0] * nat
f.write(lattice+' LATTICE,NONEQUIV.ATOMS:%3i\nMODE OF CALC=RELA\n'%nat)
cell = atoms.get_cell()
metT = np.dot(cell, np.transpose(cell))
cell2 = cellconst(metT)
cell2[0:3] = cell2[0:3] / Bohr
f.write(('%10.6f' * 6) % tuple(cell2) + '\n')
#print atoms.get_positions()[0]
for ii in range(nat):
f.write('ATOM %3i: ' % (ii + 1))
pos = atoms.get_scaled_positions()[ii]
f.write('X=%10.8f Y=%10.8f Z=%10.8f\n' % tuple(pos))
f.write(' MULT= 1 ISPLIT= 1\n')
zz = atoms.get_atomic_numbers()[ii]
if zz > 71:
ro = 0.000005
elif zz > 36:
ro = 0.00001
elif zz > 18:
ro = 0.00005
else:
ro = 0.0001
f.write('%-10s NPT=%5i R0=%9.8f RMT=%10.4f Z:%10.5f\n' %
(atoms.get_chemical_symbols()[ii], 781, ro, rmt[ii], zz))
f.write('LOCAL ROT MATRIX: %9.7f %9.7f %9.7f\n' % (1.0, 0.0, 0.0))
f.write(' %9.7f %9.7f %9.7f\n' % (0.0, 1.0, 0.0))
f.write(' %9.7f %9.7f %9.7f\n' % (0.0, 0.0, 1.0))
f.write(' 0\n')
def cellconst(metT):
aa = np.sqrt(metT[0, 0])
bb = np.sqrt(metT[1, 1])
cc = np.sqrt(metT[2, 2])
gamma = np.arccos(metT[0, 1] / (aa * bb)) / np.pi * 180.0
beta = np.arccos(metT[0, 2] / (aa * cc)) / np.pi * 180.0
alpha = np.arccos(metT[1, 2] / (bb * cc)) / np.pi * 180.0
return np.array([aa, bb, cc, alpha, beta, gamma])
def coorsys(latconst):
a = latconst[0]
b = latconst[1]
c = latconst[2]
cal = np.cos(latconst[3] * np.pi / 180.0)
cbe = np.cos(latconst[4] * np.pi / 180.0)
cga = np.cos(latconst[5] * np.pi / 180.0)
sal = np.sin(latconst[3] * np.pi / 180.0)
sbe = np.sin(latconst[4] * np.pi / 180.0)
sga = np.sin(latconst[5] * np.pi / 180.0)
return np.array([[a, b * cga, c * cbe],
[0, b * sga, c * (cal - cbe * cga) / sga],
[0, 0, c * np.sqrt(1 - cal**2 - cbe**2 - cga**2 + 2 * cal * cbe * cga) / sga]]).transpose()
def c2p(lattice):
# apply as eg. cell2 = np.dot(ct.c2p('F'), cell)
if lattice == 'P':
cell = np.eye(3)
elif lattice == 'F':
cell = np.array([[0.0, 0.5, 0.5], [0.5, 0.0, 0.5], [0.5, 0.5, 0.0]])
elif lattice == 'I':
cell = np.array([[-0.5, 0.5, 0.5], [0.5, -0.5, 0.5], [0.5, 0.5, -0.5]])
elif lattice == 'C':
cell = np.array([[0.5, 0.5, 0.0], [0.5, -0.5, 0.0], [0.0, 0.0, -1.0]])
elif lattice == 'R':
cell = np.array([[2.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0], [-1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0], [-1.0 / 3.0, -2.0/3.0, 1.0 / 3.0]])
else:
print 'lattice is ' + lattice + '!'
return cell
python-ase-3.6.0.2515/ase/io/pdb.py 0000644 0001754 0001754 00000005233 11656735402 015512 0 ustar askhl askhl import numpy as np
from ase.atoms import Atom, Atoms
from ase.parallel import paropen
"""Module to read and write atoms in PDB file format"""
def read_pdb(fileobj, index=-1):
"""Read PDB files.
The format is assumed to follow the description given in
http://www.wwpdb.org/documentation/format32/sect9.html."""
if isinstance(fileobj, str):
fileobj = open(fileobj)
images = []
atoms = Atoms()
for line in fileobj.readlines():
if line.startswith('ATOM') or line.startswith('HETATM'):
try:
# Atom name is arbitrary and does not necessarily contain the element symbol.
# The specification requires the element symbol to be in columns 77+78.
symbol = line[76:78].strip().lower().capitalize()
words = line[30:55].split()
position = np.array([float(words[0]),
float(words[1]),
float(words[2])])
atoms.append(Atom(symbol, position))
except:
pass
if line.startswith('ENDMDL'):
images.append(atoms)
atoms = Atoms()
if len(images) == 0:
images.append(atoms)
return images[index]
def write_pdb(fileobj, images):
"""Write images to PDB-file.
The format is assumed to follow the description given in
http://www.wwpdb.org/documentation/format32/sect9.html."""
if isinstance(fileobj, str):
fileobj = paropen(fileobj, 'w')
if not isinstance(images, (list, tuple)):
images = [images]
if images[0].get_pbc().any():
from ase.lattice.spacegroup.cell import cell_to_cellpar
cellpar = cell_to_cellpar( images[0].get_cell())
# ignoring Z-value, using P1 since we have all atoms defined explicitly
format = 'CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f P 1\n'
fileobj.write(format % (cellpar[0], cellpar[1], cellpar[2], cellpar[3], cellpar[4], cellpar[5]))
# 1234567 123 6789012345678901 89 67 456789012345678901234567 890
format = 'ATOM %5d %4s MOL 1 %8.3f%8.3f%8.3f 1.00 0.00 %2s \n'
# RasMol complains if the atom index exceeds 100000. There might
# be a limit of 5 digit numbers in this field.
MAXNUM = 100000
symbols = images[0].get_chemical_symbols()
natoms = len(symbols)
for n,atoms in enumerate(images):
fileobj.write('MODEL '+str(n+1)+'\n')
p = atoms.get_positions()
for a in range(natoms):
x, y, z = p[a]
fileobj.write(format % (a % MAXNUM, symbols[a], x, y, z, symbols[a].rjust(2)))
fileobj.write('ENDMDL\n')
python-ase-3.6.0.2515/ase/io/mol.py 0000644 0001754 0001754 00000001117 11207220276 015517 0 ustar askhl askhl from math import pi, cos, sin, sqrt, acos
from ase.atoms import Atoms
from ase.parallel import paropen
def read_mol(fileobj, index=-1):
if isinstance(fileobj, str):
fileobj = open(fileobj)
lines = fileobj.readlines()
del(lines[:3])
L1 = lines[0].split()
del(lines[0])
natoms = int(L1[0])
positions = []
symbols = []
for line in lines[:natoms]:
x, y, z, symbol = line.split()[:4]
symbols.append(symbol)
positions.append([float(x), float(y), float(z)])
return Atoms(symbols=symbols, positions=positions)
python-ase-3.6.0.2515/ase/io/eps.py 0000644 0001754 0001754 00000014320 11604536461 015526 0 ustar askhl askhl import time
from math import sqrt
import numpy as np
from ase.utils import rotate
from ase.data import covalent_radii
from ase.data.colors import jmol_colors
class EPS:
def __init__(self, atoms,
rotation='', show_unit_cell=False, radii=None,
bbox=None, colors=None, scale=20):
self.numbers = atoms.get_atomic_numbers()
self.colors = colors
if colors is None:
self.colors = jmol_colors[self.numbers]
if radii is None:
radii = covalent_radii[self.numbers]
elif type(radii) is float:
radii = covalent_radii[self.numbers] * radii
else:
radii = np.array(radii)
natoms = len(atoms)
if isinstance(rotation, str):
rotation = rotate(rotation)
A = atoms.get_cell()
if show_unit_cell > 0:
L, T, D = self.cell_to_lines(A)
C = np.empty((2, 2, 2, 3))
for c1 in range(2):
for c2 in range(2):
for c3 in range(2):
C[c1, c2, c3] = np.dot([c1, c2, c3], A)
C.shape = (8, 3)
C = np.dot(C, rotation) # Unit cell vertices
else:
L = np.empty((0, 3))
T = None
D = None
C = None
nlines = len(L)
X = np.empty((natoms + nlines, 3))
R = atoms.get_positions()
X[:natoms] = R
X[natoms:] = L
r2 = radii**2
for n in range(nlines):
d = D[T[n]]
if ((((R - L[n] - d)**2).sum(1) < r2) &
(((R - L[n] + d)**2).sum(1) < r2)).any():
T[n] = -1
X = np.dot(X, rotation)
R = X[:natoms]
if bbox is None:
X1 = (R - radii[:, None]).min(0)
X2 = (R + radii[:, None]).max(0)
if show_unit_cell == 2:
X1 = np.minimum(X1, C.min(0))
X2 = np.maximum(X2, C.max(0))
M = (X1 + X2) / 2
S = 1.05 * (X2 - X1)
w = scale * S[0]
if w > 500:
w = 500
scale = w / S[0]
h = scale * S[1]
offset = np.array([scale * M[0] - w / 2, scale * M[1] - h / 2, 0])
else:
w = (bbox[2] - bbox[0]) * scale
h = (bbox[3] - bbox[1]) * scale
offset = np.array([bbox[0], bbox[1], 0]) * scale
self.w = w
self.h = h
X *= scale
X -= offset
if nlines > 0:
D = np.dot(D, rotation)[:, :2] * scale
if C is not None:
C *= scale
C -= offset
A = np.dot(A, rotation)
A *= scale
self.A = A
self.X = X
self.D = D
self.T = T
self.C = C
self.natoms = natoms
self.d = 2 * scale * radii
def cell_to_lines(self, A):
nlines = 0
nn = []
for c in range(3):
d = sqrt((A[c]**2).sum())
n = max(2, int(d / 0.3))
nn.append(n)
nlines += 4 * n
X = np.empty((nlines, 3))
T = np.empty(nlines, int)
D = np.zeros((3, 3))
n1 = 0
for c in range(3):
n = nn[c]
dd = A[c] / (4 * n - 2)
D[c] = dd
P = np.arange(1, 4 * n + 1, 4)[:, None] * dd
T[n1:] = c
for i, j in [(0, 0), (0, 1), (1, 0), (1, 1)]:
n2 = n1 + n
X[n1:n2] = P + i * A[(c + 1) % 3] + j * A[(c + 2) % 3]
n1 = n2
return X, T, D
def write(self, filename):
self.filename = filename
self.write_header()
self.write_body()
self.write_trailer()
def write_header(self):
import matplotlib
if matplotlib.__version__ <= '0.8':
raise RuntimeError('Your version of matplotlib (%s) is too old' %
matplotlib.__version__)
from matplotlib.backends.backend_ps import RendererPS, \
GraphicsContextPS, psDefs
self.fd = open(self.filename, 'w')
self.fd.write('%!PS-Adobe-3.0 EPSF-3.0\n')
self.fd.write('%%Creator: G2\n')
self.fd.write('%%CreationDate: %s\n' % time.ctime(time.time()))
self.fd.write('%%Orientation: portrait\n')
bbox = (0, 0, self.w, self.h)
self.fd.write('%%%%BoundingBox: %d %d %d %d\n' % bbox)
self.fd.write('%%EndComments\n')
Ndict = len(psDefs)
self.fd.write('%%BeginProlog\n')
self.fd.write('/mpldict %d dict def\n' % Ndict)
self.fd.write('mpldict begin\n')
for d in psDefs:
d = d.strip()
for l in d.split('\n'):
self.fd.write(l.strip() + '\n')
self.fd.write('%%EndProlog\n')
self.fd.write('mpldict begin\n')
self.fd.write('%d %d 0 0 clipbox\n' % (self.w, self.h))
self.renderer = RendererPS(self.w, self.h, self.fd)
def write_body(self):
try:
from matplotlib.path import Path
except ImportError:
Path = None
from matplotlib.patches import Circle, Polygon
else:
from matplotlib.patches import Circle, PathPatch
indices = self.X[:, 2].argsort()
for a in indices:
xy = self.X[a, :2]
if a < self.natoms:
r = self.d[a] / 2
if ((xy[1] + r > 0) and (xy[1] - r < self.h) and
(xy[0] + r > 0) and (xy[0] - r < self.w)):
circle = Circle(xy, r, facecolor=self.colors[a])
circle.draw(self.renderer)
else:
a -= self.natoms
c = self.T[a]
if c != -1:
hxy = self.D[c]
if Path is None:
line = Polygon((xy + hxy, xy - hxy))
else:
line = PathPatch(Path((xy + hxy, xy - hxy)))
line.draw(self.renderer)
def write_trailer(self):
self.fd.write('end\n')
self.fd.write('showpage\n')
self.fd.close()
def write_eps(filename, atoms, **parameters):
if isinstance(atoms, list):
assert len(atoms) == 1
atoms = atoms[0]
EPS(atoms, **parameters).write(filename)
python-ase-3.6.0.2515/ase/io/findsym.py 0000644 0001754 0001754 00000002270 11473434675 016421 0 ustar askhl askhl from ase.atoms import Atoms
from ase.parallel import paropen
def write_findsym(fileobj, images):
if isinstance(fileobj, str):
fileobj = paropen(fileobj, 'w')
if not isinstance(images, (list, tuple)):
images = [images]
symbols = images[0].get_chemical_symbols()
natoms = len(symbols)
for atoms in images:
formula = atoms.get_chemical_symbols(True)
accuracy = 1.0e-4
# Write Comment
fileobj.write('%s\n' % formula)
fileobj.write('%f accuracy\n' % accuracy)
fileobj.write('1 vectors in cartesian coordinates\n')
# Write cartesian coordinates of vectors
for x, y, z in atoms.cell:
fileobj.write('%22.15f %22.15f %22.15f\n' % (x, y, z))
fileobj.write('1 no known centering\n')
fileobj.write('1 0 0 \n')
fileobj.write('0 1 0 \n')
fileobj.write('0 0 1 \n')
fileobj.write('%d\n' % natoms)
numbers = atoms.get_atomic_numbers()
for n in numbers:
fileobj.write('%d ' % (n))
fileobj.write('\n')
for x, y, z in atoms.get_positions():
fileobj.write('%22.15f %22.15f %22.15f\n' % (x, y, z))
python-ase-3.6.0.2515/ase/io/ascii.py 0000644 0001754 0001754 00000001067 10712434106 016023 0 ustar askhl askhl from ase.atoms import Atoms
def write_ascii(fileobj, images):
if isinstance(fileobj, str):
fileobj = open(fileobj, 'w')
if not isinstance(images, (list, tuple)):
images = [images]
fileobj.write('atoms = ')
else:
fileobj.write('images = [')
symbols = images[0].get_chemical_symbols()
natoms = len(symbols)
for atoms in images:
fileobj.write('%d\n\n' % natoms)
for s, (x, y, z) in zip(symbols, atoms.get_positions()):
fileobj.write('%-2s %22.15f %22.15f %22.15f\n' % (s, x, y, z))
python-ase-3.6.0.2515/ase/io/png.py 0000644 0001754 0001754 00000002330 11703141460 015510 0 ustar askhl askhl from ase.io.eps import EPS
class PNG(EPS):
def write_header(self):
from matplotlib.backends.backend_agg import RendererAgg
try:
from matplotlib.transforms import Value
except ImportError:
dpi = 72
else:
dpi = Value(72)
self.renderer = RendererAgg(self.w, self.h, dpi)
#self.gc = GraphicsContextBase()
#self.gc.set_linewidth(2)
def write_trailer(self):
renderer = self.renderer
if hasattr(renderer._renderer, 'write_png'):
# Old version of matplotlib:
renderer._renderer.write_png(self.filename)
else:
x = renderer._renderer.buffer_rgba(0, 0)
from matplotlib import _png
_png.write_png(renderer._renderer.buffer_rgba(0, 0),
renderer.width, renderer.height,
self.filename, 72)
def write_png(filename, atoms, **parameters):
if isinstance(atoms, list):
if len(atoms) > 1:
raise RuntimeError("Don't know how to save more than "+
"one image to PNG image!")
else:
atoms = atoms[0]
PNG(atoms, **parameters).write(filename)
python-ase-3.6.0.2515/ase/io/xyz.py 0000644 0001754 0001754 00000002317 11655752304 015576 0 ustar askhl askhl from ase.atoms import Atoms
from ase.parallel import paropen
def read_xyz(fileobj, index=-1):
if isinstance(fileobj, str):
fileobj = open(fileobj)
lines = fileobj.readlines()
L1 = lines[0].split()
if len(L1) == 1:
del lines[:2]
natoms = int(L1[0])
else:
natoms = len(lines)
images = []
while len(lines) >= natoms:
positions = []
symbols = []
for line in lines[:natoms]:
symbol, x, y, z = line.split()[:4]
symbol = symbol.lower().capitalize()
symbols.append(symbol)
positions.append([float(x), float(y), float(z)])
images.append(Atoms(symbols=symbols, positions=positions))
del lines[:natoms + 2]
return images[index]
def write_xyz(fileobj, images):
if isinstance(fileobj, str):
fileobj = paropen(fileobj, 'w')
if not isinstance(images, (list, tuple)):
images = [images]
symbols = images[0].get_chemical_symbols()
natoms = len(symbols)
for atoms in images:
fileobj.write('%d\n\n' % natoms)
for s, (x, y, z) in zip(symbols, atoms.get_positions()):
fileobj.write('%-2s %22.15f %22.15f %22.15f\n' % (s, x, y, z))
python-ase-3.6.0.2515/ase/io/bundletrajectory.py 0000644 0001754 0001754 00000076023 11600331247 020316 0 ustar askhl askhl """bundletrajectory - a module for I/O from large MD simulations.
The BundleTrajectory class writes trajectory into a directory with the
following structure::
filename.bundle (dir)
metadata.pickle Data about the file format, and about which
data is present.
state.pickle The number of frames
F0 (dir) Frame number 0
small.pickle Small data structures in a dictionary
(pbc, cell, ...)
numbers.pickle Atomic numbers
positions.pickle Positions
momenta.pickle Momenta
...
F1 (dir)
"""
import ase.parallel
from ase.parallel import paropen
from ase.calculators.singlepoint import SinglePointCalculator
import numpy as np
import os
import shutil
import time
import cPickle as pickle
class BundleTrajectory:
"""Reads and writes atoms into a .bundle directory.
The BundleTrajectory is an alternative way of storing
trajectories, intended for large-scale molecular dynamics
simulations, where a single flat file becomes unwieldy. Instead,
the data is stored in directory, a 'bundle' (the name bundle is
inspired from bundles in Mac OS, which are really just directories
the user is supposed to think of as a single file-like unit).
Parameters:
filename:
The name of the directory. Preferably ending in .bundle.
mode (optional):
The file opening mode. 'r' means open for reading, 'w' for
writing and 'a' for appending. Default: 'r'. If opening in
write mode, and the filename already exists, the old file is
renamed to .bak (any old .bak file is deleted), except if the
existing file is empty.
atoms (optional):
The atoms that will be written. Can only be specified in
write or append mode. If not specified, the atoms must be
given as an argument to the .write() method instead.
backup=True:
Use backup=False to disable renaming of an existing file.
"""
slavelog = True # Log from all nodes
def __init__(self, filename, mode='r', atoms=None, backup=True):
self.state = 'constructing'
self.filename = filename
self.pre_observers = [] # Callback functions before write is performed
self.post_observers = [] # Callback functions after write is performed
self.master = ase.parallel.rank == 0
self.extra_data = []
self._set_defaults()
self._set_backend()
if mode == 'r':
if atoms is not None:
raise ValueError("You cannot specify atoms in read mode.")
self._open_read()
elif mode == 'w':
self._open_write(atoms, backup)
elif mode == 'a':
self._open_append(atoms)
def _set_defaults(self):
"Set default values for internal parameters."
self.version = 1
self.subtype = 'normal'
self.backend_name = 'pickle'
self.datatypes = {'positions': True,
'numbers': 'once',
'tags': 'once',
'masses': 'once',
'momenta': True,
'forces': True,
'energy': True,
'energies': False,
'stress': False,
'magmoms': True
}
def _set_backend(self, backend=None):
"""Set the backed doing the actual I/O."""
if backend is not None:
self.backend_name = backend
if self.backend_name == 'pickle':
self.backend = PickleBundleBackend(self.master)
else:
raise NotImplementedError(
"This version of ASE cannot use BundleTrajectory with backend '%s'"
% self.backend_name)
def write(self, atoms=None):
"""Write the atoms to the file.
If the atoms argument is not given, the atoms object specified
when creating the trajectory object is used.
"""
# Check that we are in write mode
if self.state == 'prewrite':
self.state = 'write'
assert self.nframes == 0
elif self.state != 'write':
raise RuntimeError('Cannot write in ' + self.state + ' mode.')
if atoms is None:
atoms = self.atoms
if hasattr(atoms, 'interpolate'):
# seems to be a NEB
self.log('Beginning to write NEB data')
neb = atoms
assert not neb.parallel
try:
neb.get_energies_and_forces(all=True)
except AttributeError:
pass
for image in neb.images:
self.write(image)
self.log('Done writing NEB data')
return
# OK, it is a real atoms object. Write it.
self._call_observers(self.pre_observers)
self.log("Beginning to write frame " + str(self.nframes))
framedir = self._make_framedir(self.nframes)
# Check which data should be written the first time:
# Modify datatypes so any element of type 'once' becomes true
# for the first frame but false for subsequent frames.
datatypes = {}
for k, v in self.datatypes.items():
if v == 'once':
v = (self.nframes == 0)
datatypes[k] = v
# Write 'small' data structures. They are written jointly.
smalldata = {'pbc': atoms.get_pbc(),
'cell': atoms.get_cell(),
'natoms': atoms.get_number_of_atoms(),
'constraints': atoms.constraints,
}
if datatypes.get('energy'):
try:
smalldata['energy'] = atoms.get_potential_energy()
except (RuntimeError, NotImplementedError):
self.datatypes['energy'] = False
if datatypes.get('stress'):
try:
smalldata['stress'] = atoms.get_stress()
except NotImplementedError:
self.datatypes['stress'] = False
self.backend.write_small(framedir, smalldata)
# Write the large arrays.
if datatypes.get('positions'):
self.backend.write(framedir, 'positions', atoms.get_positions())
if datatypes.get('numbers'):
self.backend.write(framedir, 'numbers', atoms.get_atomic_numbers())
if datatypes.get('tags'):
if atoms.has('tags'):
self.backend.write(framedir, 'tags', atoms.get_tags())
else:
self.datatypes['tags'] = False
if datatypes.get('masses'):
if atoms.has('masses'):
self.backend.write(framedir, 'masses', atoms.get_masses())
else:
self.datatypes['masses'] = False
if datatypes.get('momenta'):
if atoms.has('momenta'):
self.backend.write(framedir, 'momenta', atoms.get_momenta())
else:
self.datatypes['momenta'] = False
if datatypes.get('magmoms'):
if atoms.has('magmoms'):
self.backend.write(framedir, 'magmoms', atoms.get_magmoms())
else:
self.datatypes['magmoms'] = False
if datatypes.get('forces'):
try:
x = atoms.get_forces()
except (RuntimeError, NotImplementedError):
self.datatypes['forces'] = False
else:
self.backend.write(framedir, 'forces', x)
del x
if datatypes.get('energies'):
try:
x = atoms.get_potential_energies()
except (RuntimeError, NotImplementedError):
self.datatypes['energies'] = False
else:
self.backend.write(framedir, 'energies', x)
del x
# Write any extra data
for (label, source, once) in self.extra_data:
if self.nframes == 0 or not once:
if source is not None:
x = source()
else:
x = atoms.arrays[label]
self.backend.write(framedir, label, x)
del x
if once:
self.datatypes[label] = 'once'
else:
self.datatypes[label] = True
# Finally, write metadata if it is the first frame
if self.nframes == 0:
metadata = {'datatypes': self.datatypes}
self._write_metadata(metadata)
self._write_nframes(self.nframes + 1)
self._call_observers(self.post_observers)
self.log("Done writing frame " + str(self.nframes))
self.nframes += 1
def select_data(self, data, value):
"""Selects if a given data type should be written.
Data can be written in every frame (specify True), in the
first frame only (specify 'only') or not at all (specify
False). Not all data types support the 'only' keyword, if not
supported it is interpreted as True.
The following data types are supported, the letter in parenthesis
indicates the default:
positions (T), numbers (O), tags (O), masses (O), momenta (T),
forces (T), energy (T), energies (F), stress (F), magmoms (T)
If a given property is not present during the first write, it
will be not be saved at all.
"""
if value not in (True, False, 'once'):
raise ValueError("Unknown write mode")
if data not in self.datatypes:
raise ValueError("Unsupported data type: " + data)
self.datatypes[data] = value
def set_extra_data(self, name, source=None, once=False):
"""Adds extra data to be written.
Parameters:
name: The name of the data.
source (optional): If specified, a callable object returning
the data to be written. If not specified it is instead
assumed that the atoms contains the data as an array of the
same name.
once (optional): If specified and True, the data will only be
written to the first frame.
"""
self.extra_data.append((name, source, once))
def close(self):
"Closes the trajectory."
self.state = 'closed'
lf = getattr(self, 'logfile', None)
if lf is not None:
lf.close()
del self.logfile
def log(self, text):
"""Write to the log file in the bundle.
Logging is only possible in write/append mode.
This function is mainly for internal use, but can also be called by
the user.
"""
if not (self.master or self.slavelog):
return
text = time.asctime() + ': ' + text
if hasattr(self, "logfile"):
# Logging enabled
if self.logfile is None:
# Logfile not yet open
try:
self.logdata.append(text)
except AttributeError:
self.logdata = [text]
else:
self.logfile.write(text + '\n')
self.logfile.flush()
else:
raise RuntimeError("Cannot write to log file in mode " + self.state)
# __getitem__ is the main reading method.
def __getitem__(self, n):
return self._read(n)
def _read(self, n):
"Read an atoms object from the BundleTrajectory."
if self.state != 'read':
raise IOError('Cannot read in %s mode' % (self.state,))
if n < 0:
n += self.nframes
if n < 0 or n >= self.nframes:
raise IndexError('Trajectory index %d out of range [0, %d['
% (n, self.nframes))
framedir = os.path.join(self.filename, 'F' + str(n))
framezero = os.path.join(self.filename, 'F0')
smalldata = self.backend.read_small(framedir)
data = {}
data['pbc'] = smalldata['pbc']
data['cell'] = smalldata['cell']
data['constraint'] = smalldata['constraints']
if self.subtype == 'split':
self.backend.set_fragments(smalldata['fragments'])
atom_id = self.backend.read_split(framedir, 'ID')
else:
atom_id = None
atoms = ase.Atoms(**data)
natoms = smalldata['natoms']
for name in ('positions', 'numbers', 'tags', 'masses',
'momenta'):
if self.datatypes.get(name):
atoms.arrays[name] = self._read_data(framezero, framedir,
name, atom_id)
assert len(atoms.arrays[name]) == natoms
# Create the atoms object
if self.datatypes.get('energy'):
if self.datatypes.get('forces'):
forces = self.backend.read(framedir, 'forces')
else:
forces = None
if self.datatypes.get('magmoms'):
magmoms = self.backend.read(framedir, 'magmoms')
else:
magmoms = None
calc = SinglePointCalculator(smalldata.get('energy'),
forces,
smalldata.get('stress'),
magmoms, atoms)
atoms.set_calculator(calc)
return atoms
def read_extra_data(self, name, n=0):
"""Read extra data stored alongside the atoms.
Currently only used to read data stored by an NPT dynamics object.
The data is not associated with individual atoms.
"""
if self.state != 'read':
raise IOError('Cannot read extra data in %s mode' % (self.state,))
# Handle negative n.
if n < 0:
n += self.nframes
if n < 0 or n >= self.nframes:
raise IndexError('Trajectory index %d out of range [0, %d['
% (n, self.nframes))
framedir = os.path.join(self.filename, 'F' + str(n))
return self.backend.read(framedir, name)
def _read_data(self, f0, f, name, atom_id):
"Read single data item."
if self.subtype == 'normal':
if self.datatypes[name] == 'once':
d = self.backend.read(f0, name)
else:
d = self.backend.read(f, name)
elif self.subtype == 'split':
if self.datatypes[name] == 'once':
d = self.backend.read_split(f0, name)
else:
d = self.backend.read_split(f, name)
if atom_id is not None:
assert len(d) == len(atom_id)
d = d[atom_id]
return d
def __len__(self):
return self.nframes
def _open_log(self):
if not (self.master or self.slavelog):
return
if self.master:
lfn = os.path.join(self.filename, "log.txt")
else:
lfn = os.path.join(self.filename, ("log-node%d.txt" %
(ase.parallel.rank,)))
self.logfile = open(lfn, "a") # Append to log if it exists.
if hasattr(self, 'logdata'):
for text in self.logdata:
self.logfile.write(text + '\n')
self.logfile.flush()
del self.logdata
def _open_write(self, atoms, backup):
"Open a bundle trajectory for writing."
self.logfile = None # Enable delayed logging
self.atoms = atoms
if os.path.exists(self.filename):
# The output directory already exists.
if not self.is_bundle(self.filename):
raise IOError("Filename '" + self.filename +
"' already exists, but is not a BundleTrajectory." +
"Cowardly refusing to remove it.")
ase.parallel.barrier() # All must have time to see it exists.
if self.is_empty_bundle(self.filename):
self.log('Deleting old "%s" as it is empty' % (self.filename,))
self.delete_bundle(self.filename)
elif not backup:
self.log('Deleting old "%s" as backup is turned off.' % (self.filename,))
self.delete_bundle(self.filename)
else:
# Make a backup file
bakname = self.filename + '.bak'
if os.path.exists(bakname):
ase.parallel.barrier() # All must see it exists
self.log('Deleting old backup file "%s"' % (bakname,))
self.delete_bundle(bakname)
self.log('Renaming "%s" to "%s"' % (self.filename, bakname))
self._rename_bundle(self.filename, bakname)
# Ready to create a new bundle.
self.log('Creating new "%s"' % (self.filename,))
self._make_bundledir(self.filename)
self.state = 'prewrite'
self._write_metadata({})
self._write_nframes(0) # Mark new bundle as empty
self._open_log()
self.nframes = 0
def _open_read(self):
"Open a bundle trajectory for reading."
if not os.path.exists(self.filename):
raise IOError('File not found: ' + self.filename)
if not self.is_bundle(self.filename):
raise IOError('Not a BundleTrajectory: ' + self.filename)
self.state = 'read'
# Read the metadata
metadata = self._read_metadata()
self.metadata = metadata
if metadata['version'] > self.version:
raise NotImplementedError(
"This version of ASE cannot read a BundleTrajectory version "
+ str(metadata['version']))
if metadata['subtype'] not in ('normal', 'split'):
raise NotImplementedError(
"This version of ASE cannot read BundleTrajectory subtype "
+ metadata['subtype'])
self.subtype = metadata['subtype']
self._set_backend(metadata['backend'])
self.nframes = self._read_nframes()
if self.nframes == 0:
raise IOError("Empty BundleTrajectory")
self.datatypes = metadata['datatypes']
self.state = 'read'
def _write_nframes(self, n):
"Write the number of frames in the bundle."
assert self.state == 'write' or self.state == 'prewrite'
f = paropen(os.path.join(self.filename, "frames"), "w")
f.write(str(n) + '\n')
f.close()
def _read_nframes(self):
"Read the number of frames."
f = open(os.path.join(self.filename, 'frames'))
n = int(f.read())
return n
def _write_metadata(self, metadata):
"""Write the metadata file of the bundle.
Modifies the medadata dictionary!
"""
# Add standard fields that must always be present.
assert self.state == 'write' or self.state == 'prewrite'
metadata['format'] = 'BundleTrajectory'
metadata['version'] = self.version
metadata['subtype'] = self.subtype
metadata['backend'] = self.backend_name
f = paropen(os.path.join(self.filename, "metadata"), "w")
pickle.dump(metadata, f, -1)
f.close()
def _read_metadata(self):
"""Read the metadata."""
assert self.state == 'read'
f = open(os.path.join(self.filename, 'metadata'))
metadata = pickle.load(f)
f.close()
return metadata
@staticmethod
def is_bundle(filename):
"""Check if a filename exists and is a BundleTrajectory."""
if not os.path.isdir(filename):
return False
metaname = os.path.join(filename, 'metadata')
if not os.path.isfile(metaname):
return False
f = open(metaname)
mdata = pickle.load(f)
f.close()
try:
return mdata['format'] == 'BundleTrajectory'
except KeyError:
return False
@staticmethod
def is_empty_bundle(filename):
"""Check if a filename is an empty bundle. Assumes that it is a bundle."""
f = open(os.path.join(filename, "frames"))
nframes = int(f.read())
ase.parallel.barrier() # File may be removed by the master immediately after this.
return nframes == 0
@classmethod
def delete_bundle(cls, filename):
"Deletes a bundle."
if ase.parallel.rank == 0:
# Only the master deletes
if not cls.is_bundle(filename):
raise IOError("Cannot remove '%s' as it is not a bundle trajectory."
% (filename,))
if os.path.islink(filename):
# A symbolic link to a bundle. Only remove the link.
os.remove(filename)
else:
# A real bundle
shutil.rmtree(filename)
else:
# All other tasks wait for the directory to go away.
while os.path.exists(filename):
time.sleep(1)
# The master may not proceed before all tasks have seen the
# directory go away, as it might otherwise create a new bundle
# with the same name, fooling the wait loop in _make_bundledir.
ase.parallel.barrier()
def _rename_bundle(self, oldname, newname):
"Rename a bundle. Used to create the .bak"
if self.master:
os.rename(oldname, newname)
else:
while os.path.exists(oldname):
time.sleep(1)
# The master may not proceed before all tasks have seen the
# directory go away.
ase.parallel.barrier()
def _make_bundledir(self, filename):
"""Make the main bundle directory.
Since all MPI tasks might write to it, all tasks must wait for
the directory to appear.
"""
self.log("Making directory " + filename)
assert not os.path.isdir(filename)
ase.parallel.barrier()
if self.master:
os.mkdir(filename)
else:
i = 0
while not os.path.isdir(filename):
time.sleep(1)
i += 1
if i > 10:
self.log("Waiting %d seconds for %s to appear!"
% (i, filename))
def _make_framedir(self, frame):
"""Make subdirectory for the frame.
As only the master writes to it, no synchronization between
MPI tasks is necessary.
"""
framedir = os.path.join(self.filename, "F" + str(frame))
if self.master:
os.mkdir(framedir)
return framedir
def pre_write_attach(self, function, interval=1, *args, **kwargs):
"""Attach a function to be called before writing begins.
function: The function or callable object to be called.
interval: How often the function is called. Default: every time (1).
All other arguments are stored, and passed to the function.
"""
if not callable(function):
raise ValueError("Callback object must be callable.")
self.pre_observers.append((function, interval, args, kwargs))
def post_write_attach(self, function, interval=1, *args, **kwargs):
"""Attach a function to be called after writing ends.
function: The function or callable object to be called.
interval: How often the function is called. Default: every time (1).
All other arguments are stored, and passed to the function.
"""
if not callable(function):
raise ValueError("Callback object must be callable.")
self.post_observers.append((function, interval, args, kwargs))
def _call_observers(self, obs):
"Call pre/post write observers."
for function, interval, args, kwargs in obs:
if (self.nframes + 1) % interval == 0:
function(*args, **kwargs)
class PickleBundleBackend:
"""Backend for writing BundleTrajectories stored as pickle files."""
def __init__(self, master):
# Store if this backend will actually write anything
self.writesmall = master
self.writelarge = master
def write_small(self, framedir, smalldata):
"Write small data to be written jointly."
if self.writesmall:
f = open(os.path.join(framedir, "smalldata.pickle"), "w")
pickle.dump(smalldata, f, -1)
f.close()
def write(self, framedir, name, data):
"Write data to separate file."
if self.writelarge:
fn = os.path.join(framedir, name + '.pickle')
f = open(fn, "w")
try:
info = (data.shape, str(data.dtype))
except AttributeError:
info = None
pickle.dump(info, f, -1)
pickle.dump(data, f, -1)
f.close()
def read_small(self, framedir):
"Read small data."
f = open(os.path.join(framedir, "smalldata.pickle"))
data = pickle.load(f)
f.close()
return data
def read(self, framedir, name):
"Read data from separate file."
fn = os.path.join(framedir, name + '.pickle')
f = open(fn)
pickle.load(f) # Discarded.
data = pickle.load(f)
f.close()
return data
def read_info(self, framedir, name, split=None):
"Read information about file contents without reading the data."
fn = os.path.join(framedir, name + '.pickle')
if split is None or os.path.exists(fn):
f = open(fn)
info = pickle.load(f)
f.close()
return info
else:
for i in range(split):
fn = os.path.join(framedir, name + '_' + str(i) + '.pickle')
f = open(fn)
info = pickle.load(f)
f.close()
if i == 0:
shape = list(info[0])
dtype = info[1]
else:
shape[0] += info[0][0]
assert dtype == info[1]
return (tuple(shape), dtype)
def set_fragments(self, nfrag):
self.nfrag = nfrag
def read_split(self, framedir, name):
"Read data from multiple files."
data = []
for i in range(self.nfrag):
suf = "_%d" % (i,)
fn = os.path.join(framedir, name + suf + '.pickle')
f = open(fn)
shape = pickle.load(f) # Discarded.
data.append(pickle.load(f))
f.close()
return np.concatenate(data)
def read_bundletrajectory(filename, index=-1):
"""Reads one or more atoms objects from a BundleTrajectory.
Arguments:
filename: str
The name of the bundle (really a directory!)
index: int
An integer specifying which frame to read, or an index object
for reading multiple frames. Default: -1 (reads the last
frame).
"""
traj = BundleTrajectory(filename, mode='r')
if isinstance(index, int):
return traj[index]
else:
# Here, we try to read only the configurations we need to read
# and len(traj) should only be called if we need to as it will
# read all configurations!
# XXX there must be a simpler way?
step = index.step or 1
if step > 0:
start = index.start or 0
if start < 0:
start += len(traj)
stop = index.stop or len(traj)
if stop < 0:
stop += len(traj)
else:
if index.start is None:
start = len(traj) - 1
else:
start = index.start
if start < 0:
start += len(traj)
if index.stop is None:
stop = -1
else:
stop = index.stop
if stop < 0:
stop += len(traj)
return [traj[i] for i in range(start, stop, step)]
def write_bundletrajectory(filename, images):
"""Write image(s) to a BundleTrajectory.
Write also energy, forces, and stress if they are already
calculated.
"""
traj = BundleTrajectory(filename, mode='w')
if not isinstance(images, (list, tuple)):
images = [images]
for atoms in images:
# Avoid potentially expensive calculations:
calc = atoms.get_calculator()
if hasattr(calc, 'calculation_required'):
for quantity in ('energy', 'forces', 'stress', 'magmoms'):
traj.select_data(quantity,
not calc.calculation_required(atoms, [quantity]))
traj.write(atoms)
traj.close()
def print_bundletrajectory_info(filename):
"""Prints information about a BundleTrajectory.
Mainly intended to be called from a command line tool.
"""
if not BundleTrajectory.is_bundle(filename):
raise ValueError, "Not a BundleTrajectory!"
if BundleTrajectory.is_empty_bundle(filename):
print filename, "is an empty BundleTrajectory."
return
# Read the metadata
f = open(os.path.join(filename, 'metadata'))
metadata = pickle.load(f)
f.close()
print "Metadata information of BundleTrajectory '%s':" % (filename,)
for k, v in metadata.items():
if k != 'datatypes':
print " %s: %s" % (k, v)
f = open(os.path.join(filename, 'frames'))
nframes = int(f.read())
print "Number of frames: %i" % (nframes,)
print "Data types:"
for k, v in metadata['datatypes'].items():
if v == 'once':
print " %s: First frame only." % (k,)
elif v:
print " %s: All frames." % (k,)
# Look at first frame
if metadata['backend'] == 'pickle':
backend = PickleBundleBackend(True)
else:
raise NotImplementedError("Backend %s not supported."
% (metadata['backend'],))
frame = os.path.join(filename, "F0")
small = backend.read_small(frame)
print "Contents of first frame:"
for k, v in small.items():
if k == 'constraints':
if v:
print " %i constraints are present"
else:
print " Constraints are absent."
elif k == 'pbc':
print " Periodic boundary conditions: %s" % (str(v),)
elif k == 'natoms':
print " Number of atoms: %i" % (v,)
elif hasattr(v, 'shape'):
print " %s: shape = %s, type = %s" % (k, str(v.shape), str(v.dtype))
else:
print " %s: %s" % (k, str(v))
# Read info from separate files.
for k, v in metadata['datatypes'].items():
if v and not k in small:
info = backend.read_info(frame, k)
if info and isinstance(info[0], tuple):
shape, dtype = info
else:
shape = info
dtype = 'unknown'
print " %s: shape = %s, type = %s" % (k, str(shape), dtype)
if __name__ == '__main__':
from ase.lattice.cubic import FaceCenteredCubic
from ase.io import read, write
atoms = FaceCenteredCubic(size=(5, 5, 5), symbol='Au')
write('test.bundle', atoms)
atoms2 = read('test.bundle')
assert (atoms.get_positions() == atoms2.get_positions()).all()
assert (atoms.get_atomic_numbers() == atoms2.get_atomic_numbers()).all()
python-ase-3.6.0.2515/ase/io/iwm.py 0000644 0001754 0001754 00000002211 11222662616 015525 0 ustar askhl askhl from math import pi, cos, sin, sqrt, acos
import numpy as np
from ase.data import chemical_symbols
from ase.atoms import Atoms
from ase.parallel import paropen
iwm_symbols = {'1' : 'C',
'2' : 'Au',
'5' : 'Ag'}
def read_iwm(fileobj, index=-1):
if isinstance(fileobj, str):
fileobj = open(fileobj)
lines = fileobj.readlines()
L1 = lines[1].split()
if len(L1) == 1:
del lines[:3]
natoms = int(L1[0])
else:
natoms = len(lines)
images = []
positions = []
symbols = []
for line in lines[:natoms]:
symbol, mass, x, y, z = line.split()[:5]
if symbol in iwm_symbols:
symbols.append(iwm_symbols[symbol])
else:
symbols.append(chemical_symbols[int(symbol)])
positions.append([float(x), float(y), float(z)])
del(lines[natoms:3 * natoms + 3])
cell = []
for line in lines[natoms:natoms+3]:
x, y, z = line.split()[:3]
cell.append(np.array([float(x), float(y), float(z)]))
images.append(Atoms(symbols=symbols, positions=positions, cell=cell))
return images[index]
python-ase-3.6.0.2515/ase/xrdebye.py 0000644 0001754 0001754 00000007111 11401133550 015755 0 ustar askhl askhl from math import exp, pi, sin, sqrt, cos, acos
import numpy as np
from ase.data import atomic_numbers
# Table (1) of
# D. WAASMAIER AND A. KIRFEL, Acta Cryst. (1995). A51, 416-431
waasmaier = {
# a1 b1 a2 b2 a3 b3 a4 b4 a5 b5 c
'C' : [2.657506, 14.780758, 1.078079, 0.776775, 1.490909, 42.086843, -4.241070, -0.000294, 0.713791, 0.239535, 4.297983],
'S' : [6.372157, 1.514347, 5.154568, 22.092528, 1.473732, 0.061373, 1.635073, 55.445176, 1.209372, 0.646925, 0.154722],
'Pd': [6.121511, 0.062549, 4.784063, 0.784031, 16.631683, 8.751391, 4.318258, 34.489983, 13.246773, 0.784031, 0.883099],
'Ag': [6.073874, 0.055333, 17.155437, 7.896512, 4.173344, 28.443739, 0.852238, 110.376108, 17.988685, 0.716809, 0.756603],
'Au': [16.777389, 0.122737, 19.317156, 8.621570, 32.979682, 1.256902, 5.595453, 38.008821, 10.576854, 0.000601, -6.279078],
'P' : [1.950541, 0.908139, 4.146930, 27.044953, 1.494560, 0.071280, 1.522042, 67.520190, 5.729711, 1.981173, 0.155233],
'Cl': [1.446071, 0.052357, 6.870609, 1.193165, 6.151801, 18.343416, 1.750347, 46.398394, 0.634168, 0.401005, 0.146773],
}
class XrDebye:
def __init__(self, wavelength, alpha=1.01, damping=0.04, warn=True,
method='Iwasa'):
"""
Obtain powder x-ray spectra.
wavelength in Angstrom
damping in Angstrom**2
"""
self.wavelength = wavelength
self.damping = damping
self.alpha = alpha
self.warn = warn
self.method = method
def set_damping(self, damping):
self.damping = damping
def get(self, atoms, s):
"""Get the powder x-ray (XRD) pattern using the Debye-Formula.
After: T. Iwasa and K. Nobusada, J. Phys. Chem. C 111 (2007) 45
s is assumed to be in 1/Angstrom
"""
sinth = self.wavelength * s / 2.
costh = sqrt(1. - sinth**2)
cos2th = cos(2. * acos(costh))
pre = exp(- self.damping * s**2 / 2)
if self.method == 'Iwasa':
pre *= costh / (1. + self.alpha * cos2th**2)
f = {}
def atomic(symbol):
if not f.has_key(symbol):
if self.method == 'Iwasa':
f[symbol] = self.get_waasmaier(symbol, s)
else:
f[symbol] = atomic_numbers[symbol]
return f[symbol]
def sinc(x):
if x < 1.e-6:
x2 = x * x
return 1 - x2 / 6. + x2 * x2 / 120.
else:
return sin(x) / x
I = 0.
for a in atoms:
fa = atomic(a.symbol)
# print a.symbol, fa
for b in atoms:
fb = atomic(b.symbol)
if a == b:
twopis = 0.
else:
vrij = a.position - b.position
rij = np.sqrt(np.dot(vrij, vrij))
twopisr = 2 * pi * s * rij
I += fa * fb * sinc(twopisr)
return pre * I
def get_waasmaier(self, symbol, s):
"""Scattering factor for free atoms."""
if symbol == 'H':
# XXXX implement analytical H
return 0
elif waasmaier.has_key(symbol):
abc = waasmaier[symbol]
f = abc[10]
s2 = s*s
for i in range(5):
f += abc[2 * i] * exp(-abc[2 * i + 1] * s2)
return f
if self.warn:
print ' Element', symbol, 'not available'
return 0
python-ase-3.6.0.2515/ase/lattice/ 0000755 0001754 0001754 00000000000 11757245036 015407 5 ustar askhl askhl python-ase-3.6.0.2515/ase/lattice/general_surface.py 0000644 0001754 0001754 00000006473 11632115555 021112 0 ustar askhl askhl import numpy as np
from numpy.linalg import norm, solve
from ase.utils import gcd
from ase.lattice.bulk import bulk
def surface(lattice, indices, layers, vacuum=0.0, tol=1e-10):
"""Create surface from a given lattice and Miller indices.
lattice: Atoms object or str
Bulk lattice structure of alloy or pure metal. One can also
give the chemical symbol as a string, in which case the
correct bulk lattice will be generated automatically.
indices: sequence of three int
Surface normal in Miller indices (h,k,l).
layers: int
Number of equivalent layers of the slab.
vacuum: float
Amount of vacuum added on both sides of the slab.
"""
indices = np.asarray(indices)
if indices.shape != (3,) or not indices.any() or indices.dtype != int:
raise ValueError('%s is an invalid surface type' % indices)
if isinstance(lattice, str):
lattice = bulk(lattice, cubic=True)
h, k, l = indices
h0, k0, l0 = (indices == 0)
if h0 and k0 or h0 and l0 or k0 and l0: # if two indices are zero
if not h0:
c1, c2, c3 = [(0, 1, 0), (0, 0, 1), (1, 0, 0)]
if not k0:
c1, c2, c3 = [(1, 0, 0), (0, 0, 1), (0, 1, 0)]
if not l0:
c1, c2, c3 = [(1, 0, 0), (0, 1, 0), (0, 0, 1)]
else:
p, q = ext_gcd(k, l)
a1, a2, a3 = lattice.cell
# constants describing the dot product of basis c1 and c2:
# dot(c1,c2) = k1+i*k2, i in Z
k1 = np.dot(p * (k * a1 - h * a2) + q * (l * a1 - h * a3),
l * a2 - k * a3)
k2 = np.dot(l * (k * a1 - h * a2) - k * (l * a1 - h * a3),
l * a2 - k * a3)
if abs(k2) > tol:
i = -int(round(k1 / k2)) # i corresponding to the optimal basis
p, q = p + i * l, q - i * k
a, b = ext_gcd(p * k + q * l, h)
c1 = (p * k + q * l, -p * h, -q * h)
c2 = np.array((0, l, -k)) // abs(gcd(l, k))
c3 = (b, a * p, a * q)
surf = build(lattice, np.array([c1, c2, c3]), layers, tol)
surf.center(vacuum=vacuum, axis=2)
return surf
def build(lattice, basis, layers, tol):
surf = lattice.copy()
scaled = solve(basis.T, surf.get_scaled_positions().T).T
scaled -= np.floor(scaled + tol)
surf.set_scaled_positions(scaled)
surf.set_cell(np.dot(basis, surf.cell), scale_atoms=True)
surf *= (1, 1, layers)
a1, a2, a3 = surf.cell
surf.set_cell([a1, a2,
np.cross(a1, a2) * np.dot(a3, np.cross(a1, a2)) /
norm(np.cross(a1, a2))**2])
# Change unit cell to have the x-axis parallel with a surface vector
# and z perpendicular to the surface:
a1, a2, a3 = surf.cell
surf.set_cell([(norm(a1), 0, 0),
(np.dot(a1, a2) / norm(a1),
np.sqrt(norm(a2)**2 - (np.dot(a1, a2) / norm(a1))**2), 0),
(0, 0, -norm(a3))],
scale_atoms=True)
surf.pbc = (True, True, False)
# Move atoms into the unit cell:
scaled = surf.get_scaled_positions()
scaled[:, :2] %= 1
surf.set_scaled_positions(scaled)
return surf
def ext_gcd(a, b):
if b == 0:
return 1, 0
elif a % b == 0:
return 0, 1
else:
x, y = ext_gcd(b, a % b)
return y, x - y * (a / b)
python-ase-3.6.0.2515/ase/lattice/surface.py 0000644 0001754 0001754 00000030474 11652200253 017403 0 ustar askhl askhl """Helper functions for creating the most common surfaces and related tasks.
The helper functions can create the most common low-index surfaces,
add vacuum layers and add adsorbates.
"""
from math import sqrt
import numpy as np
from ase.atom import Atom
from ase.atoms import Atoms
from ase.data import reference_states, atomic_numbers
from ase.lattice.general_surface import surface
def fcc100(symbol, size, a=None, vacuum=None):
"""FCC(100) surface.
Supported special adsorption sites: 'ontop', 'bridge', 'hollow'."""
return _surface(symbol, 'fcc', '100', size, a, None, vacuum)
def fcc110(symbol, size, a=None, vacuum=None):
"""FCC(110) surface.
Supported special adsorption sites: 'ontop', 'longbridge',
'shortbridge','hollow'."""
return _surface(symbol, 'fcc', '110', size, a, None, vacuum)
def bcc100(symbol, size, a=None, vacuum=None):
"""BCC(100) surface.
Supported special adsorption sites: 'ontop', 'bridge', 'hollow'."""
return _surface(symbol, 'bcc', '100', size, a, None, vacuum)
def bcc110(symbol, size, a=None, vacuum=None, orthogonal=False):
"""BCC(110) surface.
Supported special adsorption sites: 'ontop', 'longbridge',
'shortbridge', 'hollow'.
Use *orthogonal=True* to get an orthogonal unit cell - works only
for size=(i,j,k) with j even."""
return _surface(symbol, 'bcc', '110', size, a, None, vacuum, orthogonal)
def bcc111(symbol, size, a=None, vacuum=None, orthogonal=False):
"""BCC(111) surface.
Supported special adsorption sites: 'ontop'.
Use *orthogonal=True* to get an orthogonal unit cell - works only
for size=(i,j,k) with j even."""
return _surface(symbol, 'bcc', '111', size, a, None, vacuum, orthogonal)
def fcc111(symbol, size, a=None, vacuum=None, orthogonal=False):
"""FCC(111) surface.
Supported special adsorption sites: 'ontop', 'bridge', 'fcc' and 'hcp'.
Use *orthogonal=True* to get an orthogonal unit cell - works only
for size=(i,j,k) with j even."""
return _surface(symbol, 'fcc', '111', size, a, None, vacuum, orthogonal)
def hcp0001(symbol, size, a=None, c=None, vacuum=None, orthogonal=False):
"""HCP(0001) surface.
Supported special adsorption sites: 'ontop', 'bridge', 'fcc' and 'hcp'.
Use *orthogonal=True* to get an orthogonal unit cell - works only
for size=(i,j,k) with j even."""
return _surface(symbol, 'hcp', '0001', size, a, c, vacuum, orthogonal)
def hcp10m10(symbol, size, a=None, c=None, vacuum=None):
"""HCP(10m10) surface.
Supported special adsorption sites: 'ontop'.
Works only for size=(i,j,k) with j even."""
return _surface(symbol, 'hcp', '10m10', size, a, c, vacuum)
def diamond100(symbol, size, a=None, vacuum=None):
"""DIAMOND(100) surface.
Supported special adsorption sites: 'ontop'."""
return _surface(symbol, 'diamond', '100', size, a, None, vacuum)
def diamond111(symbol, size, a=None, vacuum=None, orthogonal=False):
"""DIAMOND(111) surface.
Supported special adsorption sites: 'ontop'."""
if orthogonal:
raise NotImplementedError("Can't do orthogonal cell yet!")
return _surface(symbol, 'diamond', '111', size, a, None, vacuum, orthogonal)
def add_adsorbate(slab, adsorbate, height, position=(0, 0), offset=None,
mol_index=0):
"""Add an adsorbate to a surface.
This function adds an adsorbate to a slab. If the slab is
produced by one of the utility functions in ase.lattice.surface, it
is possible to specify the position of the adsorbate by a keyword
(the supported keywords depend on which function was used to
create the slab).
If the adsorbate is a molecule, the atom indexed by the mol_index
optional argument is positioned on top of the adsorption position
on the surface, and it is the responsibility of the user to orient
the adsorbate in a sensible way.
This function can be called multiple times to add more than one
adsorbate.
Parameters:
slab: The surface onto which the adsorbate should be added.
adsorbate: The adsorbate. Must be one of the following three types:
A string containing the chemical symbol for a single atom.
An atom object.
An atoms object (for a molecular adsorbate).
height: Height above the surface.
position: The x-y position of the adsorbate, either as a tuple of
two numbers or as a keyword (if the surface is produced by one
of the functions in ase.lattice.surfaces).
offset (default: None): Offsets the adsorbate by a number of unit
cells. Mostly useful when adding more than one adsorbate.
mol_index (default: 0): If the adsorbate is a molecule, index of
the atom to be positioned above the location specified by the
position argument.
Note *position* is given in absolute xy coordinates (or as
a keyword), whereas offset is specified in unit cells. This
can be used to give the positions in units of the unit cell by
using *offset* instead.
"""
info = slab.adsorbate_info
if 'cell' not in info:
info['cell'] = slab.get_cell()[:2, :2]
pos = np.array([0.0, 0.0]) # (x, y) part
spos = np.array([0.0, 0.0]) # part relative to unit cell
if offset is not None:
spos += np.asarray(offset, float)
if isinstance(position, str):
# A site-name:
if 'sites' not in info:
raise TypeError('If the atoms are not made by an ' +
'ase.lattice.surface function, ' +
'position cannot be a name.')
if position not in info['sites']:
raise TypeError('Adsorption site %s not supported.' % position)
spos += info['sites'][position]
else:
pos += position
pos += np.dot(spos, info['cell'])
# Convert the adsorbate to an Atoms object
if isinstance(adsorbate, Atoms):
ads = adsorbate
elif isinstance(adsorbate, Atom):
ads = Atoms([adsorbate])
else:
# Hope it is a useful string or something like that
ads = Atoms(adsorbate)
# Get the z-coordinate:
try:
a = info['top layer atom index']
except KeyError:
a = slab.positions[:, 2].argmax()
info['top layer atom index'] = a
z = slab.positions[a, 2] + height
# Move adsorbate into position
ads.translate([pos[0], pos[1], z] - ads.positions[mol_index])
# Attach the adsorbate
slab.extend(ads)
def _surface(symbol, structure, face, size, a, c, vacuum, orthogonal=True):
"""Function to build often used surfaces.
Don't call this function directly - use fcc100, fcc110, bcc111, ..."""
Z = atomic_numbers[symbol]
if a is None:
sym = reference_states[Z]['symmetry']
if sym != structure:
raise ValueError("Can't guess lattice constant for %s-%s!" %
(structure, symbol))
a = reference_states[Z]['a']
if structure == 'hcp' and c is None:
if reference_states[Z]['symmetry'] == 'hcp':
c = reference_states[Z]['c/a'] * a
else:
c = sqrt(8 / 3.0) * a
positions = np.empty((size[2], size[1], size[0], 3))
positions[..., 0] = np.arange(size[0]).reshape((1, 1, -1))
positions[..., 1] = np.arange(size[1]).reshape((1, -1, 1))
positions[..., 2] = np.arange(size[2]).reshape((-1, 1, 1))
numbers = np.ones(size[0] * size[1] * size[2], int) * Z
tags = np.empty((size[2], size[1], size[0]), int)
tags[:] = np.arange(size[2], 0, -1).reshape((-1, 1, 1))
slab = Atoms(numbers,
tags=tags.ravel(),
pbc=(True, True, False),
cell=size)
surface_cell = None
sites = {'ontop': (0, 0)}
surf = structure + face
if surf == 'fcc100':
cell = (sqrt(0.5), sqrt(0.5), 0.5)
positions[-2::-2, ..., :2] += 0.5
sites.update({'hollow': (0.5, 0.5), 'bridge': (0.5, 0)})
elif surf == 'diamond100':
cell = (sqrt(0.5), sqrt(0.5), 0.5 / 2)
positions[-4::-4, ..., :2] += (0.5, 0.5)
positions[-3::-4, ..., :2] += (0.0, 0.5)
positions[-2::-4, ..., :2] += (0.0, 0.0)
positions[-1::-4, ..., :2] += (0.5, 0.0)
elif surf == 'fcc110':
cell = (1.0, sqrt(0.5), sqrt(0.125))
positions[-2::-2, ..., :2] += 0.5
sites.update({'hollow': (0.5, 0.5), 'longbridge': (0.5, 0),
'shortbridge': (0, 0.5)})
elif surf == 'bcc100':
cell = (1.0, 1.0, 0.5)
positions[-2::-2, ..., :2] += 0.5
sites.update({'hollow': (0.5, 0.5), 'bridge': (0.5, 0)})
else:
if orthogonal and size[1] % 2 == 1:
raise ValueError(("Can't make orthorhombic cell with size=%r. " %
(tuple(size),)) +
'Second number in size must be even.')
if surf == 'fcc111':
cell = (sqrt(0.5), sqrt(0.375), 1 / sqrt(3))
if orthogonal:
positions[-1::-3, 1::2, :, 0] += 0.5
positions[-2::-3, 1::2, :, 0] += 0.5
positions[-3::-3, 1::2, :, 0] -= 0.5
positions[-2::-3, ..., :2] += (0.0, 2.0 / 3)
positions[-3::-3, ..., :2] += (0.5, 1.0 / 3)
else:
positions[-2::-3, ..., :2] += (-1.0 / 3, 2.0 / 3)
positions[-3::-3, ..., :2] += (1.0 / 3, 1.0 / 3)
sites.update({'bridge': (0.5, 0), 'fcc': (1.0 / 3, 1.0 / 3),
'hcp': (2.0 / 3, 2.0 / 3)})
elif surf == 'diamond111':
cell = (sqrt(0.5), sqrt(0.375), 1 / sqrt(3) / 2)
assert not orthogonal
positions[-1::-6, ..., :3] += (0.0, 0.0, 0.5)
positions[-2::-6, ..., :2] += (0.0, 0.0)
positions[-3::-6, ..., :3] += (-1.0 / 3, 2.0 / 3, 0.5)
positions[-4::-6, ..., :2] += (-1.0 / 3, 2.0 / 3)
positions[-5::-6, ..., :3] += (1.0 / 3, 1.0 / 3, 0.5)
positions[-6::-6, ..., :2] += (1.0 / 3, 1.0 / 3)
elif surf == 'hcp0001':
cell = (1.0, sqrt(0.75), 0.5 * c / a)
if orthogonal:
positions[:, 1::2, :, 0] += 0.5
positions[-2::-2, ..., :2] += (0.0, 2.0 / 3)
else:
positions[-2::-2, ..., :2] += (-1.0 / 3, 2.0 / 3)
sites.update({'bridge': (0.5, 0), 'fcc': (1.0 / 3, 1.0 / 3),
'hcp': (2.0 / 3, 2.0 / 3)})
elif surf == 'hcp10m10':
cell = (1.0, 0.5 * c / a, sqrt(0.75))
assert orthogonal
positions[-2::-2, ..., 0] += 0.5
positions[:, ::2, :, 2] += 2.0 / 3
elif surf == 'bcc110':
cell = (1.0, sqrt(0.5), sqrt(0.5))
if orthogonal:
positions[:, 1::2, :, 0] += 0.5
positions[-2::-2, ..., :2] += (0.0, 1.0)
else:
positions[-2::-2, ..., :2] += (-0.5, 1.0)
sites.update({'shortbridge': (0, 0.5),
'longbridge': (0.5, 0),
'hollow': (0.375, 0.25)})
elif surf == 'bcc111':
cell = (sqrt(2), sqrt(1.5), sqrt(3) / 6)
if orthogonal:
positions[-1::-3, 1::2, :, 0] += 0.5
positions[-2::-3, 1::2, :, 0] += 0.5
positions[-3::-3, 1::2, :, 0] -= 0.5
positions[-2::-3, ..., :2] += (0.0, 2.0 / 3)
positions[-3::-3, ..., :2] += (0.5, 1.0 / 3)
else:
positions[-2::-3, ..., :2] += (-1.0 / 3, 2.0 / 3)
positions[-3::-3, ..., :2] += (1.0 / 3, 1.0 / 3)
sites.update({'hollow': (1.0 / 3, 1.0 / 3)})
else:
2 / 0
surface_cell = a * np.array([(cell[0], 0),
(cell[0] / 2, cell[1])])
if not orthogonal:
cell = np.array([(cell[0], 0, 0),
(cell[0] / 2, cell[1], 0),
(0, 0, cell[2])])
if surface_cell is None:
surface_cell = a * np.diag(cell[:2])
if isinstance(cell, tuple):
cell = np.diag(cell)
slab.set_positions(positions.reshape((-1, 3)))
slab.set_cell([a * v * n for v, n in zip(cell, size)], scale_atoms=True)
if vacuum is not None:
slab.center(vacuum=vacuum, axis=2)
slab.adsorbate_info['cell'] = surface_cell
slab.adsorbate_info['sites'] = sites
return slab
python-ase-3.6.0.2515/ase/lattice/monoclinic.py 0000644 0001754 0001754 00000003216 11005621507 020100 0 ustar askhl askhl """Function-like object creating monoclinic lattices.
The following lattice creator is defined:
SimpleMonoclinic
BaseCenteredMonoclinic
"""
from ase.lattice.triclinic import TriclinicFactory
import numpy as np
from ase.data import reference_states as _refstate
class SimpleMonoclinicFactory(TriclinicFactory):
"A factory for creating simple monoclinic lattices."
# The name of the crystal structure in ChemicalElements
xtal_name = "monoclinic"
def make_crystal_basis(self):
"Make the basis matrix for the crystal unit cell and the system unit cell."
# First convert the basis specification to a triclinic one
if type(self.latticeconstant) == type({}):
self.latticeconstant['beta'] = 90
self.latticeconstant['gamma'] = 90
else:
if len(self.latticeconstant) == 4:
self.latticeconstant = self.latticeconstant + (90,90)
else:
raise ValueError, "Improper lattice constants for monoclinic crystal."
TriclinicFactory.make_crystal_basis(self)
SimpleMonoclinic = SimpleMonoclinicFactory()
class BaseCenteredMonoclinicFactory(SimpleMonoclinicFactory):
# The natural basis vectors of the crystal structure
int_basis = np.array([[1, -1, 0],
[1, 1, 0],
[0, 0, 2]])
basis_factor = 0.5
# Converts the natural basis back to the crystallographic basis
inverse_basis = np.array([[1, 1, 0],
[-1, 1, 0],
[0, 0, 1]])
inverse_basis_factor = 1.0
BaseCenteredMonoclinic = BaseCenteredMonoclinicFactory()
python-ase-3.6.0.2515/ase/lattice/__init__.py 0000644 0001754 0001754 00000000042 11632077176 017514 0 ustar askhl askhl from ase.lattice.bulk import bulk
python-ase-3.6.0.2515/ase/lattice/bulk.py 0000644 0001754 0001754 00000013722 11652200253 016705 0 ustar askhl askhl from math import sqrt
from ase.atoms import Atoms, string2symbols
from ase.data import reference_states, atomic_numbers, chemical_symbols
def bulk(name, crystalstructure=None, a=None, c=None, covera=None,
orthorhombic=False, cubic=False):
"""Creating bulk systems.
Crystal structure and lattice constant(s) will be guessed if not
provided.
name: str
Chemical symbol or symbols as in 'MgO' or 'NaCl'.
crystalstructure: str
Must be one of sc, fcc, bcc, hcp, diamond, zincblende or
rocksalt.
a: float
Lattice constant.
c: float
Lattice constant.
covera: float
c/a raitio used for hcp. Use sqrt(8/3.0) for ideal ratio.
orthorhombic: bool
Construct orthorhombic unit cell instead of primitive cell
which is the default.
cubic: bool
Construct cubic unit cell if possible.
"""
if a is not None:
a = float(a)
if c is not None:
c = float(c)
if covera is not None and c is not None:
raise ValueError("Don't specify both c and c/a!")
if name in chemical_symbols:
Z = atomic_numbers[name]
ref = reference_states[Z]
if ref is not None:
xref = ref['symmetry']
else:
xref = None
if crystalstructure is None:
crystalstructure = xref
if a is None:
assert xref == crystalstructure
a = ref['a']
if crystalstructure == 'hcp':
cubic = False
if c is not None:
covera = c / a
elif covera is None:
if xref == 'hcp':
covera = ref['c/a']
else:
covera = sqrt(8.0 / 3.0)
if orthorhombic and crystalstructure != 'sc':
return _orthorhombic_bulk(name, crystalstructure, a, covera)
if cubic and crystalstructure == 'bcc':
return _orthorhombic_bulk(name, crystalstructure, a, covera)
if cubic and crystalstructure != 'sc':
return _cubic_bulk(name, crystalstructure, a)
if crystalstructure == 'sc':
atoms = Atoms(name, cell=(a, a, a), pbc=True)
elif crystalstructure == 'fcc':
b = a / 2
atoms = Atoms(name, cell=[(0, b, b), (b, 0, b), (b, b, 0)], pbc=True)
elif crystalstructure == 'bcc':
b = a / 2
atoms = Atoms(name, cell=[(-b, b, b), (b, -b, b), (b, b, -b)],
pbc=True)
elif crystalstructure == 'hcp':
atoms = Atoms(2 * name,
scaled_positions=[(0, 0, 0),
(1.0 / 3.0, 2.0 / 3.0, 0.5)],
cell=[(a, 0, 0),
(-a / 2, a * sqrt(3) / 2, 0),
(0, 0, covera * a)],
pbc=True)
elif crystalstructure == 'diamond':
atoms = bulk(2 * name, 'zincblende', a)
elif crystalstructure == 'zincblende':
s1, s2 = string2symbols(name)
atoms = bulk(s1, 'fcc', a) + bulk(s2, 'fcc', a)
atoms.positions[1] += a / 4
elif crystalstructure == 'rocksalt':
s1, s2 = string2symbols(name)
atoms = bulk(s1, 'fcc', a) + bulk(s2, 'fcc', a)
atoms.positions[1, 0] += a / 2
else:
raise ValueError('Unknown crystal structure: ' + crystalstructure)
return atoms
def _orthorhombic_bulk(name, crystalstructure, a, covera=None):
if crystalstructure == 'fcc':
b = a / sqrt(2)
atoms = Atoms(2 * name, cell=(b, b, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)])
elif crystalstructure == 'bcc':
atoms = Atoms(2 * name, cell=(a, a, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)])
elif crystalstructure == 'hcp':
atoms = Atoms(4 * name,
cell=(a, a * sqrt(3), covera * a),
scaled_positions=[(0, 0, 0),
(0.5, 0.5, 0),
(0.5, 1.0 / 6.0, 0.5),
(0, 2.0 / 3.0, 0.5)],
pbc=True)
elif crystalstructure == 'diamond':
atoms = _orthorhombic_bulk(2 * name, 'zincblende', a)
elif crystalstructure == 'zincblende':
s1, s2 = string2symbols(name)
b = a / sqrt(2)
atoms = Atoms(2 * name, cell=(b, b, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.5, 0, 0.25),
(0.5, 0.5, 0.5), (0, 0.5, 0.75)])
elif crystalstructure == 'rocksalt':
s1, s2 = string2symbols(name)
b = a / sqrt(2)
atoms = Atoms(2 * name, cell=(b, b, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.5, 0.5, 0),
(0.5, 0.5, 0.5), (0, 0, 0.5)])
else:
raise RuntimeError
return atoms
def _cubic_bulk(name, crystalstructure, a):
if crystalstructure == 'fcc':
atoms = Atoms(4 * name, cell=(a, a, a), pbc=True,
scaled_positions=[(0, 0, 0), (0, 0.5, 0.5),
(0.5, 0, 0.5), (0.5, 0.5, 0)])
elif crystalstructure == 'diamond':
atoms = _cubic_bulk(2 * name, 'zincblende', a)
elif crystalstructure == 'zincblende':
atoms = Atoms(4 * name, cell=(a, a, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.25, 0.25, 0.25),
(0, 0.5, 0.5), (0.25, 0.75, 0.75),
(0.5, 0, 0.5), (0.75, 0.25, 0.75),
(0.5, 0.5, 0), (0.75, 0.75, 0.25)])
elif crystalstructure == 'rocksalt':
atoms = Atoms(4 * name, cell=(a, a, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.5, 0, 0),
(0, 0.5, 0.5), (0.5, 0.5, 0.5),
(0.5, 0, 0.5), (0, 0, 0.5),
(0.5, 0.5, 0), (0, 0.5, 0)])
else:
raise RuntimeError
return atoms
python-ase-3.6.0.2515/ase/lattice/tetragonal.py 0000644 0001754 0001754 00000002656 11005152646 020120 0 ustar askhl askhl """Function-like objects creating tetragonal lattices.
The following lattice creators are defined:
SimleTetragonal
CenteredTetragonal
"""
from ase.lattice.orthorhombic import SimpleOrthorhombicFactory,\
BodyCenteredOrthorhombicFactory
import numpy as np
from ase.data import reference_states as _refstate
class _Tetragonalize:
"A mixin class for implementing tetragonal crystals as orthorhombic ones."
# The name of the crystal structure in ChemicalElements
xtal_name = "tetragonal"
def make_crystal_basis(self):
lattice = self.latticeconstant
if type(lattice) == type({}):
lattice['b/a'] = 1.0
else:
if len(lattice) == 2:
lattice = (lattice[0], lattice[0], lattice[1])
else:
raise ValueError, "Improper lattice constants for tetragonal crystal."
self.latticeconstant = lattice
self.orthobase.make_crystal_basis(self)
class SimpleTetragonalFactory(_Tetragonalize, SimpleOrthorhombicFactory):
"A factory for creating simple tetragonal lattices."
orthobase = SimpleOrthorhombicFactory
SimpleTetragonal = SimpleTetragonalFactory()
class CenteredTetragonalFactory(_Tetragonalize,
BodyCenteredOrthorhombicFactory):
"A factory for creating centered tetragonal lattices."
orthobase = BodyCenteredOrthorhombicFactory
CenteredTetragonal = CenteredTetragonalFactory()
python-ase-3.6.0.2515/ase/lattice/orthorhombic.py 0000644 0001754 0001754 00000012457 11652200253 020453 0 ustar askhl askhl """Function-like objects creating orthorhombic lattices.
The following lattice creators are defined:
SimleOrthorhombic
BaseCenteredOrthorhombic
BodyCenteredOrthorhombic
FaceCenteredOrthorhombic
"""
from ase.lattice.bravais import Bravais
import numpy as np
from ase.data import reference_states as _refstate
class SimpleOrthorhombicFactory(Bravais):
"A factory for creating simple orthorhombic lattices."
# The name of the crystal structure in ChemicalElements
xtal_name = "orthorhombic"
# The natural basis vectors of the crystal structure
int_basis = np.array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
basis_factor = 1.0
# Converts the natural basis back to the crystallographic basis
inverse_basis = np.array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
inverse_basis_factor = 1.0
def get_lattice_constant(self):
"Get the lattice constant of an element with orhtorhombic crystal structure."
if _refstate[self.atomicnumber]['symmetry'] != self.xtal_name:
raise ValueError, (("Cannot guess the %s lattice constant of"
+ " an element with crystal structure %s.")
% (self.xtal_name,
_refstate[self.atomicnumber]['symmetry']))
return _refstate[self.atomicnumber].copy()
def make_crystal_basis(self):
"Make the basis matrix for the crystal unit cell and the system unit cell."
lattice = self.latticeconstant
if type(lattice) == type({}):
a = lattice['a']
try:
b = lattice['b']
except KeyError:
b = a * lattice['b/a']
try:
c = lattice['c']
except KeyError:
c = a * lattice['c/a']
else:
if len(lattice) == 3:
(a,b,c) = lattice
else:
raise ValueError, "Improper lattice constants for orthorhombic crystal."
lattice = np.array([[a,0,0],[0,b,0],[0,0,c]])
self.latticeconstant = lattice
self.miller_basis = lattice
self.crystal_basis = (self.basis_factor *
np.dot(self.int_basis, lattice))
self.basis = np.dot(self.directions, self.crystal_basis)
self.check_basis_volume()
def check_basis_volume(self):
"Check the volume of the unit cell."
vol1 = abs(np.linalg.det(self.basis))
vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant)
if self.bravais_basis is not None:
vol2 /= len(self.bravais_basis)
if abs(vol1-vol2) > 1e-5:
print "WARNING: Got volume %f, expected %f" % (vol1, vol2)
SimpleOrthorhombic = SimpleOrthorhombicFactory()
class BaseCenteredOrthorhombicFactory(SimpleOrthorhombicFactory):
"A factory for creating base-centered orthorhombic lattices."
# The natural basis vectors of the crystal structure
int_basis = np.array([[1, -1, 0],
[1, 1, 0],
[0, 0, 2]])
basis_factor = 0.5
# Converts the natural basis back to the crystallographic basis
inverse_basis = np.array([[1, 1, 0],
[-1, 1, 0],
[0, 0, 1]])
inverse_basis_factor = 1.0
def check_basis_volume(self):
"Check the volume of the unit cell."
vol1 = abs(np.linalg.det(self.basis))
vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 2.0
if abs(vol1-vol2) > 1e-5:
print "WARNING: Got volume %f, expected %f" % (vol1, vol2)
BaseCenteredOrthorhombic = BaseCenteredOrthorhombicFactory()
class BodyCenteredOrthorhombicFactory(SimpleOrthorhombicFactory):
"A factory for creating body-centered orthorhombic lattices."
int_basis = np.array([[-1, 1, 1],
[1, -1, 1],
[1, 1, -1]])
basis_factor = 0.5
inverse_basis = np.array([[0, 1, 1],
[1, 0, 1],
[1, 1, 0]])
inverse_basis_factor = 1.0
def check_basis_volume(self):
"Check the volume of the unit cell."
vol1 = abs(np.linalg.det(self.basis))
vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 2.0
if abs(vol1-vol2) > 1e-5:
print "WARNING: Got volume %f, expected %f" % (vol1, vol2)
BodyCenteredOrthorhombic = BodyCenteredOrthorhombicFactory()
class FaceCenteredOrthorhombicFactory(SimpleOrthorhombicFactory):
"A factory for creating face-centered orthorhombic lattices."
int_basis = np.array([[0, 1, 1],
[1, 0, 1],
[1, 1, 0]])
basis_factor = 0.5
inverse_basis = np.array([[-1, 1, 1],
[1, -1, 1],
[1, 1, -1]])
inverse_basis_factor = 1.0
def check_basis_volume(self):
"Check the volume of the unit cell."
vol1 = abs(np.linalg.det(self.basis))
vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 4.0
if abs(vol1-vol2) > 1e-5:
print "WARNING: Got volume %f, expected %f" % (vol1, vol2)
FaceCenteredOrthorhombic = FaceCenteredOrthorhombicFactory()
python-ase-3.6.0.2515/ase/lattice/compounds.py 0000644 0001754 0001754 00000015742 11465024127 017771 0 ustar askhl askhl """Function-like objects creating lattices with more than one element.
These lattice creators are mainly intended as examples for how to build you
own. The following crystal structures are defined:
B1 = NaCl = Rocksalt
B2 = CsCl
B3 = ZnS = Zincblende
L1_2 = AuCu3
L1_0 = AuCu
TRI_Fe2O3
HEX_Fe2O3
"""
from ase.lattice.cubic import FaceCenteredCubicFactory, \
BodyCenteredCubicFactory, DiamondFactory, SimpleCubicFactory
from ase.lattice.tetragonal import SimpleTetragonalFactory
from ase.lattice.triclinic import TriclinicFactory
from ase.lattice.hexagonal import HexagonalFactory
import numpy as np
from ase.data import reference_states as _refstate
# To prevent a layer of element one on one side, and a layer of
# element two on the other side, NaCl is based on SimpleCubic instead
# of on FaceCenteredCubic
class NaClFactory(SimpleCubicFactory):
"A factory for creating NaCl (B1, Rocksalt) lattices."
bravais_basis = [[0, 0, 0], [0, 0, 0.5], [0, 0.5, 0], [0, 0.5, 0.5],
[0.5, 0, 0], [0.5, 0, 0.5], [0.5, 0.5, 0],
[0.5, 0.5, 0.5]]
element_basis = (0, 1, 1, 0, 1, 0, 0, 1)
B1 = NaCl = Rocksalt = NaClFactory()
class CsClFactory(SimpleCubicFactory):
"A factory for creating CsCl (B2) lattices."
bravais_basis = [[0, 0, 0], [0.5, 0.5, 0.5]]
element_basis = (0, 1)
B2 = CsCl = CsClFactory()
#The zincblende structure is easily derived from Diamond, which
#already has the right basis.
class ZnSFactory(DiamondFactory):
"A factory for creating ZnS (B3, Zincblende) lattices."
element_basis = (0, 1)
B3 = ZnS = Zincblende = ZnSFactory()
# The L1_0 structure is "based on FCC", but is a tetragonal distortion
# of fcc. It must therefore be derived from the base-centered
# tetragonal structure. That structure, however, does not exist,
# since it is equivalent to a simple tetragonal structure rotated 45
# degrees along the z-axis. Basing L1_2 on that would however give
# unexpected miller indices. L1_2 will therefore be based on a simple
# tetragonal structure, but with a basis corresponding to a
# base-centered tetragonal.
class AuCuFactory(SimpleTetragonalFactory):
"A factory for creating AuCu (L1_0) lattices (tetragonal symmetry)."
bravais_basis = [[0, 0, 0], [0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]
element_basis = (0, 1, 1, 0)
AuCu = L1_0 = AuCuFactory()
# The L1_2 structure is "based on FCC", but is really simple cubic
# with a basis.
class AuCu3Factory(SimpleCubicFactory):
"A factory for creating AuCu3 (L1_2) lattices."
bravais_basis = [[0, 0, 0], [0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]
element_basis = (0, 1, 1, 1)
AuCu3 = L1_2 = AuCu3Factory()
class TriclinicFe2O3Factory(TriclinicFactory):
"""A factory for creating hematite (Fe2O3) lattices.
Rhombohedral unit cell.
Pauling L, Hendricks S B
Journal of the American Chemical Society 47 (1925) 781-790
Example::
#!/usr/bin/env python
from ase.lattice.hexagonal import *
from ase.lattice.compounds import *
import ase.io as io
from ase import Atoms, Atom
index1=3
index2=3
index3=3
mya = 5.42
myb = 5.42
myc = 5.42
myalpha = 55.28
mybeta = 55.28
mygamma = 55.28
gra = TRI_Fe2O3(symbol = ('Fe', 'O'),
latticeconstant={'a':mya,'b':myb, 'c':myc,
'alpha':myalpha,
'beta':mybeta,
'gamma':mygamma},
size=(index1,index2,index3))
io.write('rhombohedralUC_Fe2O3.xyz', gra, format='xyz')
"""
bravais_basis = [[0.10534, 0.10534, 0.10534], [0.39466, 0.39466, 0.39466],
[0.60534, 0.60534, 0.60534], [0.89466, 0.89466, 0.89466],
[0.30569, 0.69431, 0.00000], [0.69431, 0.00000, 0.30569],
[0.00000, 0.30569, 0.69431], [0.19431, 0.80569, 0.50000],
[0.80569, 0.50000, 0.19431], [0.50000, 0.19431, 0.80569]]
element_basis = (0, 0, 0, 0, 1, 1, 1, 1, 1, 1)
TRI_Fe2O3 = TriclinicFe2O3Factory()
class HexagonalFe2O3Factory(HexagonalFactory):
"""A factory for creating hematite (Fe2O3) lattices.
With hexagonal unit cell.
Blake R L, Hessevick R E, Zoltai T, Finger L W
American Mineralogist 51 (1966) 123-129
5.038 5.038 13.772 90 90 120 R-3c
Fe 0 0 .3553 .0080 .0080 .00029 .0040 0 0
O .3059 0 1/4 .0068 .0083 .00046 .0042 .00058 .0012
Example:
#!/usr/bin/env python
from ase.lattice.hexagonal import *
from ase.lattice.compounds import *
import ase.io as io
from ase import Atoms, Atom
index1=1
index2=1
index3=1
mya = 5.038
myb = 5.038
myc = 13.772
myalpha = 90
mybeta = 90
mygamma = 120
gra = HEX_Fe2O3(symbol = ('Fe', 'O'),
latticeconstant={'a':mya,'b':myb, 'c':myc,
'alpha':myalpha,
'beta':mybeta,
'gamma':mygamma},
size=(index1,index2,index3))
io.write('hexaFe2O3.xyz', gra, format='xyz')
"""
bravais_basis = [[0.000000, 0.000000, 0.355300],
[0.000000, 0.000000, 0.144700],
[0.000000, 0.000000, 0.644700],
[0.000000, 0.000000, 0.855300],
[0.666667, 0.333333, 0.688633],
[0.666667, 0.333333, 0.478033],
[0.666667, 0.333333, 0.978033],
[0.666667, 0.333333, 0.188633],
[0.333333, 0.666667, 0.021967],
[0.333333, 0.666667, 0.811367],
[0.333333, 0.666667, 0.311367],
[0.333333, 0.666667, 0.521967],
#Fe to O here
[0.305900, 0.000000, 0.250000],
[0.000000, 0.305900, 0.250000],
[0.694100, 0.694100, 0.250000],
[0.694100, 0.000000, 0.750000],
[0.000000, 0.694100, 0.750000],
[0.305900, 0.305900, 0.750000],
[0.972567, 0.333333, 0.583333],
[0.666667, 0.639233, 0.583333],
[0.360767, 0.027433, 0.583333],
[0.360767, 0.333333, 0.083333],
[0.666667, 0.027433, 0.083333],
[0.972567, 0.639233, 0.083333],
[0.639233, 0.666667, 0.916667],
[0.333333, 0.972567, 0.916667],
[0.027433, 0.360767, 0.916667],
[0.027433, 0.666667, 0.416667],
[0.333333, 0.360767, 0.416667],
[0.639233, 0.972567, 0.416667]]
element_basis = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
HEX_Fe2O3 = HexagonalFe2O3Factory()
python-ase-3.6.0.2515/ase/lattice/bravais.py 0000644 0001754 0001754 00000044334 11632077176 017420 0 ustar askhl askhl """Bravais.py - class for generating Bravais lattices etc.
This is a base class for numerous classes setting up pieces of crystal.
"""
import math
import numpy as np
from ase.atoms import Atoms
from ase.utils import gcd
import ase.data
class Bravais:
"""Bravais lattice factory.
This is a base class for the objects producing various lattices
(SC, FCC, ...).
"""
# The following methods are NOT defined here, but must be defined
# in classes inhering from Bravais:
# get_lattice_constant
# make_crystal_basis
# The following class attributes are NOT defined here, but must be defined
# in classes inhering from Bravais:
# int_basis
# inverse_basis
other = {0:(1,2), 1:(2,0), 2:(0,1)}
# For Bravais lattices with a basis, set the basis here. Leave as
# None if no basis is present.
bravais_basis = None
# If more than one type of element appear in the crystal, give the
# order here. For example, if two elements appear in a 3:1 ratio,
# bravais_basis could contain four vectors, and element_basis
# could be (0,0,1,0) - the third atom in the basis is different
# from the other three. Leave as None if all atoms are of the
# same type.
element_basis = None
# How small numbers should be considered zero in the unit cell?
chop_tolerance = 1e-10
def __call__(self, symbol,
directions=(None,None,None), miller=(None,None,None),
size=(1,1,1), latticeconstant=None,
pbc=True, align=True, debug=0):
"Create a lattice."
self.size = size
self.pbc = pbc
self.debug = debug
self.process_element(symbol)
self.find_directions(directions, miller)
if self.debug:
self.print_directions_and_miller()
self.convert_to_natural_basis()
if self.debug >= 2:
self.print_directions_and_miller(" (natural basis)")
if latticeconstant is None:
if self.element_basis is None:
self.latticeconstant = self.get_lattice_constant()
else:
raise ValueError,\
"A lattice constant must be specified for a compound"
else:
self.latticeconstant = latticeconstant
if self.debug:
print "Expected number of atoms in unit cell:", self.calc_num_atoms()
if self.debug >= 2:
print "Bravais lattice basis:", self.bravais_basis
if self.bravais_basis is not None:
print " ... in natural basis:", self.natural_bravais_basis
self.make_crystal_basis()
self.make_unit_cell()
if align:
self.align()
return self.make_list_of_atoms()
def align(self):
"Align the first axis along x-axis and the second in the x-y plane."
degree = 180/np.pi
if self.debug >= 2:
print "Basis before alignment:"
print self.basis
if self.basis[0][0]**2 + self.basis[0][2]**2 < 0.01 * self.basis[0][1]**2:
# First basis vector along y axis - rotate 90 deg along z
t = np.array([[0, -1, 0],
[1, 0, 0],
[0, 0, 1]], np.float)
self.basis = np.dot(self.basis, t)
transf = t
if self.debug >= 2:
print "Rotating -90 degrees around z axis for numerical stability."
print self.basis
else:
transf = np.identity(3, np.float)
assert abs(np.linalg.det(transf) - 1) < 1e-6
# Rotate first basis vector into xy plane
theta = math.atan2(self.basis[0,2], self.basis[0,0])
t = np.array([[np.cos(theta), 0, -np.sin(theta)],
[ 0, 1, 0 ],
[np.sin(theta), 0, np.cos(theta) ]])
self.basis = np.dot(self.basis, t)
transf = np.dot(transf, t)
if self.debug >= 2:
print "Rotating %f degrees around y axis." % (-theta*degree,)
print self.basis
assert abs(np.linalg.det(transf) - 1) < 1e-6
# Rotate first basis vector to point along x axis
theta = math.atan2(self.basis[0,1], self.basis[0,0])
t = np.array([[np.cos(theta), -np.sin(theta), 0],
[np.sin(theta), np.cos(theta), 0],
[ 0, 0, 1]])
self.basis = np.dot(self.basis, t)
transf = np.dot(transf, t)
if self.debug >= 2:
print "Rotating %f degrees around z axis." % (-theta*degree,)
print self.basis
assert abs(np.linalg.det(transf) - 1) < 1e-6
# Rotate second basis vector into xy plane
theta = math.atan2(self.basis[1,2], self.basis[1,1])
t = np.array([[1, 0, 0],
[0, np.cos(theta), -np.sin(theta)],
[0, np.sin(theta), np.cos(theta)]])
self.basis = np.dot(self.basis, t)
transf = np.dot(transf, t)
if self.debug >= 2:
print "Rotating %f degrees around x axis." % (-theta*degree,)
print self.basis
assert abs(np.linalg.det(transf) - 1) < 1e-6
# Now we better rotate the atoms as well
self.atoms = np.dot(self.atoms, transf)
# ... and rotate miller_basis
self.miller_basis = np.dot(self.miller_basis, transf)
def make_list_of_atoms(self):
"Repeat the unit cell."
nrep = self.size[0] * self.size[1] * self.size[2]
if nrep <= 0:
raise ValueError, "Cannot create a non-positive number of unit cells"
# Now the unit cells must be merged.
a2 = []
e2 = []
for i in xrange(self.size[0]):
offset = self.basis[0] * i
a2.append(self.atoms + offset[np.newaxis,:])
e2.append(self.elements)
atoms = np.concatenate(a2)
elements = np.concatenate(e2)
a2 = []
e2 = []
for j in xrange(self.size[1]):
offset = self.basis[1] * j
a2.append(atoms + offset[np.newaxis,:])
e2.append(elements)
atoms = np.concatenate(a2)
elements = np.concatenate(e2)
a2 = []
e2 = []
for k in xrange(self.size[2]):
offset = self.basis[2] * k
a2.append(atoms + offset[np.newaxis,:])
e2.append(elements)
atoms = np.concatenate(a2)
elements = np.concatenate(e2)
del a2, e2
assert len(atoms) == nrep * len(self.atoms)
basis = np.array([[self.size[0],0,0],
[0,self.size[1],0],
[0,0,self.size[2]]])
basis = np.dot(basis, self.basis)
# Tiny elements should be replaced by zero. The cutoff is
# determined by chop_tolerance which is a class attribute.
basis = np.where(np.abs(basis) < self.chop_tolerance,
0.0, basis)
# None should be replaced, and memory should be freed.
lattice = Lattice(positions=atoms, cell=basis, numbers=elements,
pbc=self.pbc)
lattice.millerbasis = self.miller_basis
# Add info for lattice.surface.AddAdsorbate
lattice._addsorbate_info_size = np.array(self.size[:2])
return lattice
def process_element(self, element):
"Extract atomic number from element"
# The types that can be elements: integers and strings
if self.element_basis is None:
if isinstance(element, type("string")):
self.atomicnumber = ase.data.atomic_numbers[element]
elif isinstance(element, int):
self.atomicnumber = element
else:
raise TypeError("The symbol argument must be a string or an atomic number.")
else:
atomicnumber = []
try:
if len(element) != max(self.element_basis) + 1:
oops = True
else:
oops = False
except TypeError:
oops = True
if oops:
raise TypeError(
("The symbol argument must be a sequence of length %d"
+" (one for each kind of lattice position")
% (max(self.element_basis)+1,))
for e in element:
if isinstance(e, type("string")):
atomicnumber.append(ase.data.atomic_numbers[e])
elif isinstance(e, int):
atomicnumber.append(e)
else:
raise TypeError("The symbols argument must be a sequence of strings or atomic numbers.")
self.atomicnumber = [atomicnumber[i] for i in self.element_basis]
assert len(self.atomicnumber) == len(self.bravais_basis)
def convert_to_natural_basis(self):
"Convert directions and miller indices to the natural basis."
self.directions = np.dot(self.directions, self.inverse_basis)
if self.bravais_basis is not None:
self.natural_bravais_basis = np.dot(self.bravais_basis,
self.inverse_basis)
for i in (0,1,2):
self.directions[i] = reduceindex(self.directions[i])
for i in (0,1,2):
(j,k) = self.other[i]
self.miller[i] = reduceindex(self.handedness *
cross(self.directions[j],
self.directions[k]))
def calc_num_atoms(self):
v = int(round(abs(np.linalg.det(self.directions))))
if self.bravais_basis is None:
return v
else:
return v * len(self.bravais_basis)
def make_unit_cell(self):
"Make the unit cell."
# Make three loops, and find the positions in the integral
# lattice. Each time a position is found, the atom is placed
# in the real unit cell by put_atom().
self.natoms = self.calc_num_atoms()
self.nput = 0
self.atoms = np.zeros((self.natoms,3), np.float)
self.elements = np.zeros(self.natoms, np.int)
self.farpoint = farpoint = sum(self.directions)
#printprogress = self.debug and (len(self.atoms) > 250)
percent = 0
# Find the radius of the sphere containing the whole system
sqrad = 0
for i in (0,1):
for j in (0,1):
for k in (0,1):
vect = (i * self.directions[0] +
j * self.directions[1] +
k * self.directions[2])
if np.dot(vect,vect) > sqrad:
sqrad = np.dot(vect,vect)
del i,j,k
# Loop along first crystal axis (i)
for (istart, istep) in ((0,1), (-1,-1)):
i = istart
icont = True
while icont:
nj = 0
for (jstart, jstep) in ((0,1), (-1,-1)):
j = jstart
jcont = True
while jcont:
nk = 0
for (kstart, kstep) in ((0,1), (-1,-1)):
k = kstart
#print "Starting line i=%d, j=%d, k=%d, step=(%d,%d,%d)" % (i,j,k,istep,jstep,kstep)
kcont = True
while kcont:
# Now (i,j,k) loops over Z^3, except that
# the loops can be cut off when we get outside
# the unit cell.
point = np.array((i,j,k))
if self.inside(point):
self.put_atom(point)
nk += 1
nj += 1
# Is k too high?
if np.dot(point,point) > sqrad:
assert not self.inside(point)
kcont = False
k += kstep
# Is j too high?
if i*i+j*j > sqrad:
jcont = False
j += jstep
# Is i too high?
if i*i > sqrad:
icont = False
i += istep
#if printprogress:
# perce = int(100*self.nput / len(self.atoms))
# if perce > percent + 10:
# print ("%d%%" % perce),
# percent = perce
assert(self.nput == self.natoms)
def inside(self, point):
"Is a point inside the unit cell?"
return (np.dot(self.miller[0], point) >= 0 and
np.dot(self.miller[0], point - self.farpoint) < 0 and
np.dot(self.miller[1], point) >= 0 and
np.dot(self.miller[1], point - self.farpoint) < 0 and
np.dot(self.miller[2], point) >= 0 and
np.dot(self.miller[2], point - self.farpoint) < 0)
def put_atom(self, point):
"Place an atom given its integer coordinates."
if self.bravais_basis is None:
# No basis - just place a single atom
pos = np.dot(point, self.crystal_basis)
if self.debug >= 2:
print ("Placing an atom at (%d,%d,%d) ~ (%.3f, %.3f, %.3f)."
% (tuple(point) + tuple(pos)))
self.atoms[self.nput] = pos
self.elements[self.nput] = self.atomicnumber
self.nput += 1
else:
for i, offset in enumerate(self.natural_bravais_basis):
pos = np.dot(point + offset, self.crystal_basis)
if self.debug >= 2:
print ("Placing an atom at (%d+%f, %d+%f, %d+%f) ~ (%.3f, %.3f, %.3f)."
% (point[0], offset[0], point[1], offset[1],
point[2], offset[2], pos[0], pos[1], pos[2]))
self.atoms[self.nput] = pos
if self.element_basis is None:
self.elements[self.nput] = self.atomicnumber
else:
self.elements[self.nput] = self.atomicnumber[i]
self.nput += 1
def find_directions(self, directions, miller):
"Find missing directions and miller indices from the specified ones."
directions = list(directions)
miller = list(miller)
# If no directions etc are specified, use a sensible default.
if directions == [None, None, None] and miller == [None, None, None]:
directions = [[1,0,0], [0,1,0], [0,0,1]]
# Now fill in missing directions and miller indices. This is an
# iterative process.
change = 1
while change:
change = False
missing = 0
for i in (0,1,2):
(j,k) = self.other[i]
if directions[i] is None:
missing += 1
if miller[j] is not None and miller[k] is not None:
directions[i] = reduceindex(cross(miller[j],
miller[k]))
change = True
if self.debug >= 2:
print "Calculating directions[%d] from miller indices" % i
if miller[i] is None:
missing += 1
if directions[j] is not None and directions[k] is not None:
miller[i] = reduceindex(cross(directions[j],
directions[k]))
change = True
if self.debug >= 2:
print "Calculating miller[%d] from directions" % i
if missing:
raise ValueError, "Specification of directions and miller indices is incomplete."
# Make sure that everything is Numeric arrays
self.directions = np.array(directions)
self.miller = np.array(miller)
# Check for left-handed coordinate system
if np.linalg.det(self.directions) < 0:
print "WARNING: Creating a left-handed coordinate system!"
self.miller = -self.miller
self.handedness = -1
else:
self.handedness = 1
# Now check for consistency
for i in (0,1,2):
(j,k) = self.other[i]
m = reduceindex(self.handedness *
cross(self.directions[j], self.directions[k]))
if sum(np.not_equal(m, self.miller[i])):
print "ERROR: Miller index %s is inconsisten with directions %d and %d" % (i,j,k)
print "Miller indices:"
print str(self.miller)
print "Directions:"
print str(self.directions)
raise ValueError, "Inconsistent specification of miller indices and directions."
def print_directions_and_miller(self, txt=""):
"Print direction vectors and Miller indices."
print "Direction vectors of unit cell%s:" % (txt,)
for i in (0,1,2):
print " ", self.directions[i]
print "Miller indices of surfaces%s:" % (txt,)
for i in (0,1,2):
print " ", self.miller[i]
class MillerInfo:
"""Mixin class to provide information about Miller indices."""
def miller_to_direction(self, miller):
"""Returns the direction corresponding to a given Miller index."""
return np.dot(miller, self.millerbasis)
class Lattice(Atoms, MillerInfo):
"""List of atoms initially containing a regular lattice of atoms.
A part from the usual list of atoms methods this list of atoms type
also has a method, `miller_to_direction`, used to convert from Miller
indices to directions in the coordinate system of the lattice.
"""
pass
# Helper functions
def cross(a, b):
"""The cross product of two vectors."""
return np.array((a[1]*b[2] - b[1]*a[2],
a[2]*b[0] - b[2]*a[0],
a[0]*b[1] - b[0]*a[1]))
def reduceindex(M):
"Reduce Miller index to the lowest equivalent integers."
oldM = M
g = gcd(M[0], M[1])
h = gcd(g, M[2])
while h != 1:
M = M/h
g = gcd(M[0], M[1])
h = gcd(g, M[2])
if np.dot(oldM, M) > 0:
return M
else:
return -M
python-ase-3.6.0.2515/ase/lattice/triclinic.py 0000644 0001754 0001754 00000006216 11652200253 017730 0 ustar askhl askhl """Function-like object creating triclinic lattices.
The following lattice creator is defined:
Triclinic
"""
from ase.lattice.bravais import Bravais
import numpy as np
from ase.data import reference_states as _refstate
class TriclinicFactory(Bravais):
"A factory for creating triclinic lattices."
# The name of the crystal structure in ChemicalElements
xtal_name = "triclinic"
# The natural basis vectors of the crystal structure
int_basis = np.array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
basis_factor = 1.0
# Converts the natural basis back to the crystallographic basis
inverse_basis = np.array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
inverse_basis_factor = 1.0
def get_lattice_constant(self):
"Get the lattice constant of an element with triclinic crystal structure."
if _refstate[self.atomicnumber]['symmetry'] != self.xtal_name:
raise ValueError(('Cannot guess the %s lattice constant of'
+ ' an element with crystal structure %s.')
% (self.xtal_name,
_refstate[self.atomicnumber]['symmetry']))
return _refstate[self.atomicnumber].copy()
def make_crystal_basis(self):
"Make the basis matrix for the crystal unit cell and the system unit cell."
lattice = self.latticeconstant
if type(lattice) == type({}):
a = lattice['a']
try:
b = lattice['b']
except KeyError:
b = a * lattice['b/a']
try:
c = lattice['c']
except KeyError:
c = a * lattice['c/a']
alpha = lattice['alpha']
beta = lattice['beta']
gamma = lattice['gamma']
else:
if len(lattice) == 6:
(a,b,c,alpha,beta,gamma) = lattice
else:
raise ValueError, "Improper lattice constants for triclinic crystal."
degree = np.pi / 180.0
cosa = np.cos(alpha*degree)
cosb = np.cos(beta*degree)
sinb = np.sin(beta*degree)
cosg = np.cos(gamma*degree)
sing = np.sin(gamma*degree)
lattice = np.array([[a,0,0],
[b*cosg, b*sing,0],
[c*cosb, c*(cosa-cosb*cosg)/sing,
c*np.sqrt(sinb**2 - ((cosa-cosb*cosg)/sing)**2)]])
self.latticeconstant = lattice
self.miller_basis = lattice
self.crystal_basis = (self.basis_factor *
np.dot(self.int_basis, lattice))
self.basis = np.dot(self.directions, self.crystal_basis)
assert abs(np.dot(lattice[0],lattice[1]) - a*b*cosg) < 1e-5
assert abs(np.dot(lattice[0],lattice[2]) - a*c*cosb) < 1e-5
assert abs(np.dot(lattice[1],lattice[2]) - b*c*cosa) < 1e-5
assert abs(np.dot(lattice[0],lattice[0]) - a*a) < 1e-5
assert abs(np.dot(lattice[1],lattice[1]) - b*b) < 1e-5
assert abs(np.dot(lattice[2],lattice[2]) - c*c) < 1e-5
Triclinic = TriclinicFactory()
python-ase-3.6.0.2515/ase/lattice/hexagonal.py 0000644 0001754 0001754 00000007603 11452317126 017725 0 ustar askhl askhl """Function-like object creating hexagonal lattices.
The following lattice creators are defined:
* Hexagonal
* HexagonalClosedPacked
* Graphite
* Graphene
Example for using Graphene to create atoms object gra::
from ase.lattice.hexagonal import *
import ase.io as io
from ase import Atoms, Atom
index1=6
index2=7
mya = 2.45
myc = 20.0
gra = Graphene(symbol = 'C',latticeconstant={'a':mya,'c':myc},
size=(index1,index2,1))
io.write('test.xyz', gra, format='xyz')
"""
from ase.lattice.triclinic import TriclinicFactory
import numpy as np
from ase.data import reference_states as _refstate
class HexagonalFactory(TriclinicFactory):
"A factory for creating simple hexagonal lattices."
# The name of the crystal structure in ChemicalElements
xtal_name = "hexagonal"
def make_crystal_basis(self):
"Make the basis matrix for the crystal unit cell and the system unit cell."
# First convert the basis specification to a triclinic one
if type(self.latticeconstant) == type({}):
self.latticeconstant['alpha'] = 90
self.latticeconstant['beta'] = 90
self.latticeconstant['gamma'] = 120
self.latticeconstant['b/a'] = 1.0
else:
if len(self.latticeconstant) == 2:
a,c = self.latticeconstant
self.latticeconstant = (a,a,c,90,90,120)
else:
raise ValueError, "Improper lattice constants for hexagonal crystal."
TriclinicFactory.make_crystal_basis(self)
def find_directions(self, directions, miller):
"""Find missing directions and miller indices from the specified ones.
Also handles the conversion of hexagonal-style 4-index notation to
the normal 3-index notation.
"""
directions = list(directions)
miller = list(miller)
for obj in (directions,miller):
for i in range(3):
if obj[i] is not None:
(a,b,c,d) = obj[i]
if a + b + c != 0:
raise ValueError(
("(%d,%d,%d,%d) is not a valid hexagonal Miller " +
"index, as the sum of the first three numbers " +
"should be zero.") % (a,b,c,d))
x = 4*a + 2*b
y = 2*a + 4*b
z = 3*d
obj[i] = (x,y,z)
TriclinicFactory.find_directions(self, directions, miller)
def print_directions_and_miller(self, txt=""):
"Print direction vectors and Miller indices."
print "Direction vectors of unit cell%s:" % (txt,)
for i in (0,1,2):
self.print_four_vector("[]", self.directions[i])
print "Miller indices of surfaces%s:" % (txt,)
for i in (0,1,2):
self.print_four_vector("()", self.miller[i])
def print_four_vector(self, bracket, numbers):
bra, ket = bracket
(x,y,z) = numbers
a = 2*x - y
b = -x + 2*y
c = -x -y
d = 2*z
print " %s%d, %d, %d%s ~ %s%d, %d, %d, %d%s" % \
(bra,x,y,z,ket, bra,a,b,c,d,ket)
Hexagonal = HexagonalFactory()
class HexagonalClosedPackedFactory(HexagonalFactory):
"A factory for creating HCP lattices."
xtal_name = "hcp"
bravais_basis = [[0,0,0], [1.0/3.0, 2.0/3.0, 0.5]]
HexagonalClosedPacked = HexagonalClosedPackedFactory()
class GraphiteFactory(HexagonalFactory):
"A factory for creating graphite lattices."
xtal_name = "graphite"
bravais_basis = [[0,0,0], [1.0/3.0, 2.0/3.0, 0], [1.0/3.0,2.0/3.0,0.5], [2.0/3.0,1.0/3.0,0.5]]
Graphite = GraphiteFactory()
class GrapheneFactory(HexagonalFactory):
"A factory for creating graphene lattices."
xtal_name = "graphene"
bravais_basis = [[0,0,0], [1.0/3.0, 2.0/3.0, 0]]
Graphene = GrapheneFactory()
python-ase-3.6.0.2515/ase/lattice/cubic.py 0000644 0001754 0001754 00000010551 11652200253 017032 0 ustar askhl askhl """Function-like objects creating cubic lattices (SC, FCC, BCC and Diamond).
The following lattice creators are defined:
SimpleCubic
FaceCenteredCubic
BodyCenteredCubic
Diamond
"""
from ase.lattice.bravais import Bravais
import numpy as np
from ase.data import reference_states as _refstate
class SimpleCubicFactory(Bravais):
"A factory for creating simple cubic lattices."
# The name of the crystal structure in ChemicalElements
xtal_name = "sc"
# The natural basis vectors of the crystal structure
int_basis = np.array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
basis_factor = 1.0
# Converts the natural basis back to the crystallographic basis
inverse_basis = np.array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
inverse_basis_factor = 1.0
# For checking the basis volume
atoms_in_unit_cell = 1
def get_lattice_constant(self):
"Get the lattice constant of an element with cubic crystal structure."
if _refstate[self.atomicnumber]['symmetry'] != self.xtal_name:
raise ValueError, (("Cannot guess the %s lattice constant of"
+ " an element with crystal structure %s.")
% (self.xtal_name,
_refstate[self.atomicnumber]['symmetry']))
return _refstate[self.atomicnumber]['a']
def make_crystal_basis(self):
"Make the basis matrix for the crystal unit cell and the system unit cell."
self.crystal_basis = (self.latticeconstant * self.basis_factor
* self.int_basis)
self.miller_basis = self.latticeconstant * np.identity(3)
self.basis = np.dot(self.directions, self.crystal_basis)
self.check_basis_volume()
def check_basis_volume(self):
"Check the volume of the unit cell."
vol1 = abs(np.linalg.det(self.basis))
cellsize = self.atoms_in_unit_cell
if self.bravais_basis is not None:
cellsize *= len(self.bravais_basis)
vol2 = (self.calc_num_atoms() * self.latticeconstant**3 / cellsize)
assert abs(vol1-vol2) < 1e-5
def find_directions(self, directions, miller):
"Find missing directions and miller indices from the specified ones."
directions = list(directions)
miller = list(miller)
# Process keyword "orthogonal"
self.find_ortho(directions)
self.find_ortho(miller)
Bravais.find_directions(self, directions, miller)
def find_ortho(self, idx):
"Replace keyword 'ortho' or 'orthogonal' with a direction."
for i in range(3):
if isinstance(idx[i], str) and (idx[i].lower() == "ortho" or
idx[i].lower() == "orthogonal"):
if self.debug:
print "Calculating orthogonal direction", i
print idx[i-2], "X", idx[i-1],
idx[i] = reduceindex(cross(idx[i-2], idx[i-1]))
if self.debug:
print "=", idx[i]
SimpleCubic = SimpleCubicFactory()
class FaceCenteredCubicFactory(SimpleCubicFactory):
"A factory for creating face-centered cubic lattices."
xtal_name = "fcc"
int_basis = np.array([[0, 1, 1],
[1, 0, 1],
[1, 1, 0]])
basis_factor = 0.5
inverse_basis = np.array([[-1, 1, 1],
[1, -1, 1],
[1, 1, -1]])
inverse_basis_factor = 1.0
atoms_in_unit_cell = 4
FaceCenteredCubic = FaceCenteredCubicFactory()
class BodyCenteredCubicFactory(SimpleCubicFactory):
"A factory for creating body-centered cubic lattices."
xtal_name = "bcc"
int_basis = np.array([[-1, 1, 1],
[1, -1, 1],
[1, 1, -1]])
basis_factor = 0.5
inverse_basis = np.array([[0, 1, 1],
[1, 0, 1],
[1, 1, 0]])
inverse_basis_factor = 1.0
atoms_in_unit_cell = 2
BodyCenteredCubic = BodyCenteredCubicFactory()
class DiamondFactory(FaceCenteredCubicFactory):
"A factory for creating diamond lattices."
xtal_name = "diamond"
bravais_basis = [[0,0,0], [0.25, 0.25, 0.25]]
Diamond = DiamondFactory()
python-ase-3.6.0.2515/ase/lattice/spacegroup/ 0000755 0001754 0001754 00000000000 11757245036 017557 5 ustar askhl askhl python-ase-3.6.0.2515/ase/lattice/spacegroup/__init__.py 0000644 0001754 0001754 00000000143 11345166042 021656 0 ustar askhl askhl from spacegroup import Spacegroup
from crystal import crystal
__all__ = ['Spacegroup', 'crystal']
python-ase-3.6.0.2515/ase/lattice/spacegroup/spacegroup.dat 0000644 0001754 0001754 00001120273 11345166042 022417 0 ustar askhl askhl 1 P 1
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
1 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
2 P -1
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
1 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
3 P 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
3 P 2
setting 2
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
4 P 21
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
4 P 21
setting 2
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
5 C 2
setting 1
centrosymmetric 0
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
5 A 2
setting 2
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 -0.5000000000
0.0000000000 0.5000000000 0.5000000000
1.0000000000 0.0000000000 0.0000000000
reciprocal primitive cell
0 1 -1
0 1 1
1 0 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
6 P m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
6 P m
setting 2
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
7 P c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
7 P n
setting 2
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
8 C m
setting 1
centrosymmetric 0
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
8 A m
setting 2
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 -0.5000000000
0.0000000000 0.5000000000 0.5000000000
1.0000000000 0.0000000000 0.0000000000
reciprocal primitive cell
0 1 -1
0 1 1
1 0 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
9 C c
setting 1
centrosymmetric 0
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
9 A n
setting 2
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 -0.5000000000
0.0000000000 0.5000000000 0.5000000000
1.0000000000 0.0000000000 0.0000000000
reciprocal primitive cell
0 1 -1
0 1 1
1 0 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
10 P 2/m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
10 P 2/m
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
11 P 21/m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
11 P 21/m
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
12 C 2/m
setting 1
centrosymmetric 1
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
12 A 2/m
setting 2
centrosymmetric 1
primitive cell
0.0000000000 0.5000000000 -0.5000000000
0.0000000000 0.5000000000 0.5000000000
1.0000000000 0.0000000000 0.0000000000
reciprocal primitive cell
0 1 -1
0 1 1
1 0 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
13 P 2/c
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
13 P 2/n
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
14 P 21/c
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
14 P 21/n
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
15 C 2/c
setting 1
centrosymmetric 1
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
15 A 2/n
setting 2
centrosymmetric 1
primitive cell
0.0000000000 0.5000000000 -0.5000000000
0.0000000000 0.5000000000 0.5000000000
1.0000000000 0.0000000000 0.0000000000
reciprocal primitive cell
0 1 -1
0 1 1
1 0 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
2 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
16 P 2 2 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
17 P 2 2 21
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
18 P 21 21 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
19 P 21 21 21
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
20 C 2 2 21
setting 1
centrosymmetric 0
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
21 C 2 2 2
setting 1
centrosymmetric 0
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
22 F 2 2 2
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
23 I 2 2 2
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
24 I 21 21 21
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
25 P m m 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
26 P m c 21
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
27 P c c 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
28 P m a 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
29 P c a 21
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
30 P n c 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
31 P m n 21
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
32 P b a 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
33 P n a 21
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
34 P n n 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
35 C m m 2
setting 1
centrosymmetric 0
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
36 C m c 21
setting 1
centrosymmetric 0
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
37 C c c 2
setting 1
centrosymmetric 0
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
38 A m m 2
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 -0.5000000000
0.0000000000 0.5000000000 0.5000000000
1.0000000000 0.0000000000 0.0000000000
reciprocal primitive cell
0 1 -1
0 1 1
1 0 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
39 A b m 2
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 -0.5000000000
0.0000000000 0.5000000000 0.5000000000
1.0000000000 0.0000000000 0.0000000000
reciprocal primitive cell
0 1 -1
0 1 1
1 0 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.5000000000 0.0000000000
40 A m a 2
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 -0.5000000000
0.0000000000 0.5000000000 0.5000000000
1.0000000000 0.0000000000 0.0000000000
reciprocal primitive cell
0 1 -1
0 1 1
1 0 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
41 A b a 2
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 -0.5000000000
0.0000000000 0.5000000000 0.5000000000
1.0000000000 0.0000000000 0.0000000000
reciprocal primitive cell
0 1 -1
0 1 1
1 0 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
42 F m m 2
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
43 F d d 2
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.2500000000 0.2500000000 0.2500000000
-1 0 0 0 1 0 0 0 1 0.2500000000 0.2500000000 0.2500000000
44 I m m 2
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
45 I b a 2
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
46 I m a 2
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
47 P m m m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
48 P n n n
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
48 P n n n
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
49 P c c m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
50 P b a n
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
50 P b a n
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
51 P m m a
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.0000000000
52 P n n a
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
53 P m n a
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
54 P c c A
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
55 P b a m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
56 P c c n
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
57 P b c m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
58 P n n m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
59 P m m n
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
59 P m m n
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.0000000000
60 P b c n
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
61 P b c a
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
62 P n m a
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
63 C m c m
setting 1
centrosymmetric 1
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
64 C m c a
setting 1
centrosymmetric 1
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
65 C m m m
setting 1
centrosymmetric 1
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
66 C c c m
setting 1
centrosymmetric 1
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
67 C m m a
setting 1
centrosymmetric 1
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
68 C c c a
setting 1
centrosymmetric 0
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
68 C c c a
setting 2
centrosymmetric 1
primitive cell
0.5000000000 -0.5000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 -1 0
1 1 0
0 0 1
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
69 F m m m
setting 1
centrosymmetric 1
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
70 F d d d
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.2500000000 0.2500000000 0.2500000000
1 0 0 0 1 0 0 0 -1 0.2500000000 0.2500000000 0.2500000000
1 0 0 0 -1 0 0 0 1 0.2500000000 0.2500000000 0.2500000000
-1 0 0 0 1 0 0 0 1 0.2500000000 0.2500000000 0.2500000000
70 F d d d
setting 2
centrosymmetric 1
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.7500000000 0.7500000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.7500000000 0.0000000000 0.7500000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.7500000000 0.7500000000
71 I m m m
setting 1
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
72 I b a m
setting 1
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
73 I b c a
setting 1
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
74 I m m a
setting 1
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
75 P 4
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
76 P 41
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.7500000000
77 P 42
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
78 P 43
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.7500000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.2500000000
79 I 4
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
80 I 41
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.5000000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.7500000000
81 P -4
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
82 I -4
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
83 P 4/m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
84 P 42/m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
85 P 4/n
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
85 P 4/n
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.0000000000
86 P 42/n
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
86 P 42/n
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
87 I 4/m
setting 1
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
88 I 41/a
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.5000000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.7500000000
-1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.2500000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.7500000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
88 I 41/a
setting 2
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
4 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.7500000000 0.2500000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.7500000000 0.7500000000 0.7500000000
89 P 4 2 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
90 P 4 21 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
91 P 41 2 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.7500000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.7500000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.2500000000
92 P 41 21 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.7500000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.2500000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.7500000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
93 P 42 2 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
94 P 42 21 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
95 P 43 2 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.7500000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.2500000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.2500000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.7500000000
96 P 43 21 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.7500000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.2500000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.7500000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.2500000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
97 I 4 2 2
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
98 I 41 2 2
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.5000000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.7500000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.7500000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.2500000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
99 P 4 m m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
100 P 4 b n
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
101 P 42 c m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
102 P 42 n m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
103 P 4 c c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
104 P 4 n c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
105 P 42 m c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
106 P 42 b c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
107 I 4 m m
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
108 I 4 c m
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
109 I 41 m d
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.5000000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.7500000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.2500000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.7500000000
110 I 41 c d
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.5000000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.7500000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.7500000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.2500000000
111 P -4 2 m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
112 P -4 2 c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
113 P -4 21 m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
114 P -4 21 c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
115 P -4 m 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
116 P -4 c 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
117 P -4 b 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
118 P -4 n 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
119 I -4 m 2
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
120 I -4 c 2
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
121 I -4 2 m
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
122 I -4 2 d
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.7500000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.7500000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.7500000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.7500000000
123 P 4/m m m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
124 P 4/m c c
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
125 P 4/n b m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
16 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
125 P 4/n b m
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
126 P 4/n n c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
16 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
126 P 4/n n c
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
127 P 4/m b m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
128 P 4/m n c
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
129 P 4/n m m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
16 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
129 P 4/n m m
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
130 P 4/n c c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
16 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
130 P 4/n c c
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
131 P 42/m m c
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
132 P 42/m c m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
133 P 42/n b c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
16 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
133 P 42/n b c
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
134 P 42/n n m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
16 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
134 P 42/n n m
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
135 P 42/m b c
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
136 P 42/m n m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
137 P 42/n m c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
16 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
137 P 42/n m c
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
138 P 42/n c m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
16 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
138 P 42/n c m
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
139 I 4/m m m
setting 1
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
140 I 4/m c m
setting 1
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
141 I 41/a m d
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
16 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.5000000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.7500000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.7500000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.2500000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.2500000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.7500000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.7500000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.5000000000 0.2500000000
141 I 41/a m d
setting 2
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.2500000000 0.7500000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.2500000000 0.2500000000 0.7500000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.2500000000 0.7500000000 0.2500000000
0 -1 0 -1 0 0 0 0 -1 0.2500000000 0.2500000000 0.7500000000
142 I 41/a c d
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
16 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.5000000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.7500000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.2500000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.7500000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.2500000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.7500000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.2500000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.5000000000 0.7500000000
142 I 41/a c d
setting 2
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
8 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.2500000000 0.7500000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.2500000000 0.2500000000 0.7500000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.2500000000 0.7500000000 0.7500000000
0 -1 0 -1 0 0 0 0 -1 0.2500000000 0.2500000000 0.2500000000
143 P 3
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
3 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
144 P 31
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
3 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
145 P 32
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
3 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
146 R 3
setting 1
centrosymmetric 0
primitive cell
0.6666666667 0.3333333333 0.3333333333
-0.3333333333 0.3333333333 0.3333333333
-0.3333333333 -0.6666666667 0.3333333333
reciprocal primitive cell
1 1 0
-1 1 1
0 -1 1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.6666666667 0.3333333333 0.3333333333
0.3333333333 0.6666666667 0.6666666667
3 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
146 R 3
setting 2
centrosymmetric 0
primitive cell
0.3333333333 0.6666666667 -0.3333333333
0.3333333333 -0.3333333333 -0.3333333333
-0.6666666667 -0.3333333333 -0.3333333333
reciprocal primitive cell
1 1 0
1 -1 -1
-1 0 -1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.3333333333 0.6666666667 0.3333333333
0.6666666667 0.3333333333 0.6666666667
3 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
147 P -3
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
3 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
148 R -3
setting 1
centrosymmetric 1
primitive cell
0.6666666667 0.3333333333 0.3333333333
-0.3333333333 0.3333333333 0.3333333333
-0.3333333333 -0.6666666667 0.3333333333
reciprocal primitive cell
1 1 0
-1 1 1
0 -1 1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.6666666667 0.3333333333 0.3333333333
0.3333333333 0.6666666667 0.6666666667
3 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
148 R -3
setting 2
centrosymmetric 1
primitive cell
0.3333333333 0.6666666667 -0.3333333333
0.3333333333 -0.3333333333 -0.3333333333
-0.6666666667 -0.3333333333 -0.3333333333
reciprocal primitive cell
1 1 0
1 -1 -1
-1 0 -1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.3333333333 0.6666666667 0.3333333333
0.6666666667 0.3333333333 0.6666666667
3 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
149 P 3 1 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
150 P 3 2 1
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
151 P 31 1 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.6666666667
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.3333333333
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
152 P 31 2 1
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.6666666667
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.3333333333
153 P 32 1 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.3333333333
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.6666666667
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
154 P 32 2 1
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.3333333333
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.6666666667
155 R 3 2
setting 1
centrosymmetric 0
primitive cell
0.6666666667 0.3333333333 0.3333333333
-0.3333333333 0.3333333333 0.3333333333
-0.3333333333 -0.6666666667 0.3333333333
reciprocal primitive cell
1 1 0
-1 1 1
0 -1 1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.6666666667 0.3333333333 0.3333333333
0.3333333333 0.6666666667 0.6666666667
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
155 R 3 2
setting 2
centrosymmetric 0
primitive cell
0.3333333333 0.6666666667 -0.3333333333
0.3333333333 -0.3333333333 -0.3333333333
-0.6666666667 -0.3333333333 -0.3333333333
reciprocal primitive cell
1 1 0
1 -1 -1
-1 0 -1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.3333333333 0.6666666667 0.3333333333
0.6666666667 0.3333333333 0.6666666667
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
156 P 3 m 1
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
157 P 3 1 m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
158 P 3 c 1
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 1 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
159 P 3 1 c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
160 R 3 m
setting 1
centrosymmetric 0
primitive cell
0.6666666667 0.3333333333 0.3333333333
-0.3333333333 0.3333333333 0.3333333333
-0.3333333333 -0.6666666667 0.3333333333
reciprocal primitive cell
1 1 0
-1 1 1
0 -1 1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.6666666667 0.3333333333 0.3333333333
0.3333333333 0.6666666667 0.6666666667
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
160 R 3 m
setting 2
centrosymmetric 0
primitive cell
0.3333333333 0.6666666667 -0.3333333333
0.3333333333 -0.3333333333 -0.3333333333
-0.6666666667 -0.3333333333 -0.3333333333
reciprocal primitive cell
1 1 0
1 -1 -1
-1 0 -1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.3333333333 0.6666666667 0.3333333333
0.6666666667 0.3333333333 0.6666666667
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
161 R 3 c
setting 1
centrosymmetric 0
primitive cell
0.6666666667 0.3333333333 0.3333333333
-0.3333333333 0.3333333333 0.3333333333
-0.3333333333 -0.6666666667 0.3333333333
reciprocal primitive cell
1 1 0
-1 1 1
0 -1 1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.6666666667 0.3333333333 0.3333333333
0.3333333333 0.6666666667 0.6666666667
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 1 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
161 R 3 c
setting 2
centrosymmetric 0
primitive cell
0.3333333333 0.6666666667 -0.3333333333
0.3333333333 -0.3333333333 -0.3333333333
-0.6666666667 -0.3333333333 -0.3333333333
reciprocal primitive cell
1 1 0
1 -1 -1
-1 0 -1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.3333333333 0.6666666667 0.3333333333
0.6666666667 0.3333333333 0.6666666667
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 1 0 1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
162 P -3 1 m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
163 P -3 1 c
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
164 P -3 m 1
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
165 P -3 c 1
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
166 R -3 m
setting 1
centrosymmetric 1
primitive cell
0.6666666667 0.3333333333 0.3333333333
-0.3333333333 0.3333333333 0.3333333333
-0.3333333333 -0.6666666667 0.3333333333
reciprocal primitive cell
1 1 0
-1 1 1
0 -1 1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.6666666667 0.3333333333 0.3333333333
0.3333333333 0.6666666667 0.6666666667
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
166 R -3 m
setting 2
centrosymmetric 1
primitive cell
0.3333333333 0.6666666667 -0.3333333333
0.3333333333 -0.3333333333 -0.3333333333
-0.6666666667 -0.3333333333 -0.3333333333
reciprocal primitive cell
1 1 0
1 -1 -1
-1 0 -1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.3333333333 0.6666666667 0.3333333333
0.6666666667 0.3333333333 0.6666666667
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
167 R -3 c
setting 1
centrosymmetric 1
primitive cell
0.6666666667 0.3333333333 0.3333333333
-0.3333333333 0.3333333333 0.3333333333
-0.3333333333 -0.6666666667 0.3333333333
reciprocal primitive cell
1 1 0
-1 1 1
0 -1 1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.6666666667 0.3333333333 0.3333333333
0.3333333333 0.6666666667 0.6666666667
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
167 R -3 c
setting 2
centrosymmetric 1
primitive cell
0.3333333333 0.6666666667 -0.3333333333
0.3333333333 -0.3333333333 -0.3333333333
-0.6666666667 -0.3333333333 -0.3333333333
reciprocal primitive cell
1 1 0
1 -1 -1
-1 0 -1
3 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.3333333333 0.6666666667 0.3333333333
0.6666666667 0.3333333333 0.6666666667
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 -1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 -1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
168 P 6
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
169 P 61
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.8333333333
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.1666666667
170 P 65
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.1666666667
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.8333333333
171 P 62
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
172 P 64
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
173 P 63
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
174 P -6
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
175 P 6/m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
176 P 63/m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
6 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
177 P 6 2 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
178 P 61 2 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.8333333333
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.1666666667
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.3333333333
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.6666666667
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.8333333333
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.1666666667
179 P 65 2 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.1666666667
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.8333333333
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.6666666667
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.3333333333
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.1666666667
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.8333333333
180 P 62 2 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.6666666667
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.3333333333
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.6666666667
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.3333333333
181 P 64 2 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.3333333333
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.6666666667
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.3333333333
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.6666666667
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.3333333333
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.6666666667
182 P 63 2 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
183 P 6 m m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
184 P 6 c c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 1 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
185 P 63 c m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 1 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
186 P 63 m c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
187 P -6 m 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
188 P -6 c 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 1 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 0 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
189 P -6 2 m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
190 P -6 2 c
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
191 P 6/m m m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
192 P 6/m c c
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
193 P 63/m c m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
194 P 63/m m c
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 -1 1 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
1 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 -1 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 -1 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 1 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
1 0 0 1 -1 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
195 P 2 3
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
196 F 2 3
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
197 I 2 3
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
198 P 21 3
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.0000000000 0.5000000000
199 I 21 3
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.0000000000 0.5000000000
200 P m -3
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
201 P n -3
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 0 -1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 1 0 0 0 1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 1 0 0 0 -1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 -1 0 0 0 1 0 0.5000000000 0.5000000000 0.5000000000
0 -1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 -1 0 0 0 1 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 -1 0 0 0.5000000000 0.5000000000 0.5000000000
201 P n -3
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.5000000000 0.0000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.5000000000 0.0000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.5000000000 0.0000000000
202 F m -3
setting 1
centrosymmetric 1
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
203 F d -3
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.2500000000 0.2500000000 0.2500000000
1 0 0 0 1 0 0 0 -1 0.2500000000 0.2500000000 0.2500000000
1 0 0 0 -1 0 0 0 1 0.2500000000 0.2500000000 0.2500000000
-1 0 0 0 1 0 0 0 1 0.2500000000 0.2500000000 0.2500000000
0 0 -1 -1 0 0 0 -1 0 0.2500000000 0.2500000000 0.2500000000
0 0 -1 1 0 0 0 1 0 0.2500000000 0.2500000000 0.2500000000
0 0 1 1 0 0 0 -1 0 0.2500000000 0.2500000000 0.2500000000
0 0 1 -1 0 0 0 1 0 0.2500000000 0.2500000000 0.2500000000
0 -1 0 0 0 -1 -1 0 0 0.2500000000 0.2500000000 0.2500000000
0 1 0 0 0 -1 1 0 0 0.2500000000 0.2500000000 0.2500000000
0 -1 0 0 0 1 1 0 0 0.2500000000 0.2500000000 0.2500000000
0 1 0 0 0 1 -1 0 0 0.2500000000 0.2500000000 0.2500000000
203 F d -3
setting 2
centrosymmetric 1
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.2500000000 0.2500000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.2500000000 0.0000000000 0.2500000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.2500000000 0.2500000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.2500000000 0.2500000000
0 0 -1 -1 0 0 0 1 0 0.2500000000 0.2500000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.2500000000 0.0000000000 0.2500000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.2500000000 0.0000000000 0.2500000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.2500000000 0.2500000000
0 -1 0 0 0 -1 1 0 0 0.2500000000 0.2500000000 0.0000000000
204 I m -3
setting 1
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
205 P a -3
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.0000000000 0.5000000000
206 I a -3
setting 1
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
12 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.0000000000 0.5000000000
207 P 4 3 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
208 P 42 3 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 1 0 1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 -1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 -1 0 1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 -1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 -1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
209 F 4 3 2
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
210 F 41 3 2
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.5000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.0000000000 0.5000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.7500000000 0.2500000000 0.7500000000
0 -1 0 -1 0 0 0 0 -1 0.2500000000 0.2500000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.2500000000 0.7500000000 0.7500000000
0 -1 0 1 0 0 0 0 1 0.7500000000 0.7500000000 0.2500000000
1 0 0 0 0 1 0 -1 0 0.7500000000 0.2500000000 0.7500000000
-1 0 0 0 0 1 0 1 0 0.7500000000 0.7500000000 0.2500000000
-1 0 0 0 0 -1 0 -1 0 0.2500000000 0.2500000000 0.2500000000
1 0 0 0 0 -1 0 1 0 0.2500000000 0.7500000000 0.7500000000
0 0 1 0 1 0 -1 0 0 0.7500000000 0.2500000000 0.7500000000
0 0 1 0 -1 0 1 0 0 0.2500000000 0.7500000000 0.7500000000
0 0 -1 0 1 0 1 0 0 0.7500000000 0.7500000000 0.2500000000
0 0 -1 0 -1 0 -1 0 0 0.2500000000 0.2500000000 0.2500000000
211 I 4 3 2
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
212 P 43 3 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.2500000000 0.7500000000 0.7500000000
0 -1 0 -1 0 0 0 0 -1 0.2500000000 0.2500000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.7500000000 0.7500000000 0.2500000000
0 -1 0 1 0 0 0 0 1 0.7500000000 0.2500000000 0.7500000000
1 0 0 0 0 1 0 -1 0 0.2500000000 0.7500000000 0.7500000000
-1 0 0 0 0 1 0 1 0 0.7500000000 0.2500000000 0.7500000000
-1 0 0 0 0 -1 0 -1 0 0.2500000000 0.2500000000 0.2500000000
1 0 0 0 0 -1 0 1 0 0.7500000000 0.7500000000 0.2500000000
0 0 1 0 1 0 -1 0 0 0.2500000000 0.7500000000 0.7500000000
0 0 1 0 -1 0 1 0 0 0.7500000000 0.7500000000 0.2500000000
0 0 -1 0 1 0 1 0 0 0.7500000000 0.2500000000 0.7500000000
0 0 -1 0 -1 0 -1 0 0 0.2500000000 0.2500000000 0.2500000000
213 P 41 3 2
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.7500000000 0.2500000000 0.2500000000
0 -1 0 -1 0 0 0 0 -1 0.7500000000 0.7500000000 0.7500000000
0 1 0 -1 0 0 0 0 1 0.2500000000 0.2500000000 0.7500000000
0 -1 0 1 0 0 0 0 1 0.2500000000 0.7500000000 0.2500000000
1 0 0 0 0 1 0 -1 0 0.7500000000 0.2500000000 0.2500000000
-1 0 0 0 0 1 0 1 0 0.2500000000 0.7500000000 0.2500000000
-1 0 0 0 0 -1 0 -1 0 0.7500000000 0.7500000000 0.7500000000
1 0 0 0 0 -1 0 1 0 0.2500000000 0.2500000000 0.7500000000
0 0 1 0 1 0 -1 0 0 0.7500000000 0.2500000000 0.2500000000
0 0 1 0 -1 0 1 0 0 0.2500000000 0.2500000000 0.7500000000
0 0 -1 0 1 0 1 0 0 0.2500000000 0.7500000000 0.2500000000
0 0 -1 0 -1 0 -1 0 0 0.7500000000 0.7500000000 0.7500000000
214 I 41 3 2
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.7500000000 0.2500000000 0.2500000000
0 -1 0 -1 0 0 0 0 -1 0.7500000000 0.7500000000 0.7500000000
0 1 0 -1 0 0 0 0 1 0.2500000000 0.2500000000 0.7500000000
0 -1 0 1 0 0 0 0 1 0.2500000000 0.7500000000 0.2500000000
1 0 0 0 0 1 0 -1 0 0.7500000000 0.2500000000 0.2500000000
-1 0 0 0 0 1 0 1 0 0.2500000000 0.7500000000 0.2500000000
-1 0 0 0 0 -1 0 -1 0 0.7500000000 0.7500000000 0.7500000000
1 0 0 0 0 -1 0 1 0 0.2500000000 0.2500000000 0.7500000000
0 0 1 0 1 0 -1 0 0 0.7500000000 0.2500000000 0.2500000000
0 0 1 0 -1 0 1 0 0 0.2500000000 0.2500000000 0.7500000000
0 0 -1 0 1 0 1 0 0 0.2500000000 0.7500000000 0.2500000000
0 0 -1 0 -1 0 -1 0 0 0.7500000000 0.7500000000 0.7500000000
215 P -4 3 m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
216 F -4 3 m
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
217 I -4 3 m
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
218 P -4 3 n
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 1 0 1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 -1 0 1 0 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 -1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 -1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 -1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
219 F -4 3 c
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 1 0 1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 -1 0 1 0 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 -1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 -1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 -1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
220 I -4 3 d
setting 1
centrosymmetric 0
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.2500000000 0.2500000000 0.2500000000
0 -1 0 -1 0 0 0 0 1 0.2500000000 0.7500000000 0.7500000000
0 1 0 -1 0 0 0 0 -1 0.7500000000 0.2500000000 0.7500000000
0 -1 0 1 0 0 0 0 -1 0.7500000000 0.7500000000 0.2500000000
1 0 0 0 0 1 0 1 0 0.2500000000 0.2500000000 0.2500000000
-1 0 0 0 0 1 0 -1 0 0.7500000000 0.7500000000 0.2500000000
-1 0 0 0 0 -1 0 1 0 0.2500000000 0.7500000000 0.7500000000
1 0 0 0 0 -1 0 -1 0 0.7500000000 0.2500000000 0.7500000000
0 0 1 0 1 0 1 0 0 0.2500000000 0.2500000000 0.2500000000
0 0 1 0 -1 0 -1 0 0 0.7500000000 0.2500000000 0.7500000000
0 0 -1 0 1 0 -1 0 0 0.7500000000 0.7500000000 0.2500000000
0 0 -1 0 -1 0 1 0 0 0.2500000000 0.7500000000 0.7500000000
221 P m -3 m
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
222 P n -3 n
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
48 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 0 -1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 1 0 0 0 1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 1 0 0 0 -1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 -1 0 0 0 1 0 0.5000000000 0.5000000000 0.5000000000
0 -1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 -1 0 0 0 1 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 -1 0 1 0 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 -1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 1 0 1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 -1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 -1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
222 P n -3 n
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.5000000000 0.0000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.5000000000 0.0000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 0 1 0 1 0 0.5000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 -1 0 1 0 0.0000000000 0.5000000000 0.0000000000
0 0 1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.5000000000
0 0 1 0 -1 0 1 0 0 0.0000000000 0.5000000000 0.0000000000
0 0 -1 0 1 0 1 0 0 0.5000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
223 P m -3 n
setting 1
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 1 0 1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 -1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 -1 0 1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 -1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 -1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
224 P n -3 m
setting 1
centrosymmetric 0
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
48 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 1 0 1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 -1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 -1 0 1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 -1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 -1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 0 -1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 1 0 0 0 1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 1 0 0 0 -1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 -1 0 0 0 1 0 0.5000000000 0.5000000000 0.5000000000
0 -1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 -1 0 0 0 1 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
224 P n -3 m
setting 2
centrosymmetric 1
primitive cell
1.0000000000 0.0000000000 0.0000000000
0.0000000000 1.0000000000 0.0000000000
0.0000000000 0.0000000000 1.0000000000
reciprocal primitive cell
1 0 0
0 1 0
0 0 1
1 subtranslations
0.0000000000 0.0000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.5000000000 0.0000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.5000000000 0.0000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 0 1 0 -1 0 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 0 1 0 1 0 0.0000000000 0.5000000000 0.5000000000
-1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 1 0 0.5000000000 0.0000000000 0.5000000000
0 0 1 0 1 0 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 0 1 0 -1 0 1 0 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 0 1 0 1 0 0 0.0000000000 0.5000000000 0.5000000000
0 0 -1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
225 F m -3 m
setting 1
centrosymmetric 1
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
226 F m -3 c
setting 1
centrosymmetric 1
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 1 0 1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 -1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 -1 0 1 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 1 0 -1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
0 0 -1 0 -1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
227 F d -3 m
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
48 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.5000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.0000000000 0.5000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.7500000000 0.2500000000 0.7500000000
0 -1 0 -1 0 0 0 0 -1 0.2500000000 0.2500000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.2500000000 0.7500000000 0.7500000000
0 -1 0 1 0 0 0 0 1 0.7500000000 0.7500000000 0.2500000000
1 0 0 0 0 1 0 -1 0 0.7500000000 0.2500000000 0.7500000000
-1 0 0 0 0 1 0 1 0 0.7500000000 0.7500000000 0.2500000000
-1 0 0 0 0 -1 0 -1 0 0.2500000000 0.2500000000 0.2500000000
1 0 0 0 0 -1 0 1 0 0.2500000000 0.7500000000 0.7500000000
0 0 1 0 1 0 -1 0 0 0.7500000000 0.2500000000 0.7500000000
0 0 1 0 -1 0 1 0 0 0.2500000000 0.7500000000 0.7500000000
0 0 -1 0 1 0 1 0 0 0.7500000000 0.7500000000 0.2500000000
0 0 -1 0 -1 0 -1 0 0 0.2500000000 0.2500000000 0.2500000000
-1 0 0 0 -1 0 0 0 -1 0.2500000000 0.2500000000 0.2500000000
1 0 0 0 1 0 0 0 -1 0.2500000000 0.7500000000 0.7500000000
1 0 0 0 -1 0 0 0 1 0.7500000000 0.7500000000 0.2500000000
-1 0 0 0 1 0 0 0 1 0.7500000000 0.2500000000 0.7500000000
0 0 -1 -1 0 0 0 -1 0 0.2500000000 0.2500000000 0.2500000000
0 0 -1 1 0 0 0 1 0 0.7500000000 0.2500000000 0.7500000000
0 0 1 1 0 0 0 -1 0 0.2500000000 0.7500000000 0.7500000000
0 0 1 -1 0 0 0 1 0 0.7500000000 0.7500000000 0.2500000000
0 -1 0 0 0 -1 -1 0 0 0.2500000000 0.2500000000 0.2500000000
0 1 0 0 0 -1 1 0 0 0.7500000000 0.7500000000 0.2500000000
0 -1 0 0 0 1 1 0 0 0.7500000000 0.2500000000 0.7500000000
0 1 0 0 0 1 -1 0 0 0.2500000000 0.7500000000 0.7500000000
0 -1 0 -1 0 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
-1 0 0 0 0 -1 0 1 0 0.5000000000 0.0000000000 0.5000000000
1 0 0 0 0 -1 0 -1 0 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 0 -1 0 -1 0 1 0 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 0 1 0 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 0 1 0 -1 0 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 0 1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
227 F d -3 m
setting 2
centrosymmetric 1
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.7500000000 0.2500000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.2500000000 0.5000000000 0.7500000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.7500000000 0.2500000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.7500000000 0.2500000000
0 0 -1 -1 0 0 0 1 0 0.7500000000 0.2500000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.2500000000 0.5000000000 0.7500000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.2500000000 0.5000000000 0.7500000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.7500000000 0.2500000000
0 -1 0 0 0 -1 1 0 0 0.7500000000 0.2500000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.7500000000 0.2500000000 0.5000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.2500000000 0.5000000000 0.7500000000
0 -1 0 1 0 0 0 0 1 0.5000000000 0.7500000000 0.2500000000
1 0 0 0 0 1 0 -1 0 0.7500000000 0.2500000000 0.5000000000
-1 0 0 0 0 1 0 1 0 0.5000000000 0.7500000000 0.2500000000
-1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 1 0 0.2500000000 0.5000000000 0.7500000000
0 0 1 0 1 0 -1 0 0 0.7500000000 0.2500000000 0.5000000000
0 0 1 0 -1 0 1 0 0 0.2500000000 0.5000000000 0.7500000000
0 0 -1 0 1 0 1 0 0 0.5000000000 0.7500000000 0.2500000000
0 0 -1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
228 F d -3 c
setting 1
centrosymmetric 0
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
48 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.5000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.0000000000 0.5000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.5000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.0000000000 0.5000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.7500000000 0.2500000000 0.7500000000
0 -1 0 -1 0 0 0 0 -1 0.2500000000 0.2500000000 0.2500000000
0 1 0 -1 0 0 0 0 1 0.2500000000 0.7500000000 0.7500000000
0 -1 0 1 0 0 0 0 1 0.7500000000 0.7500000000 0.2500000000
1 0 0 0 0 1 0 -1 0 0.7500000000 0.2500000000 0.7500000000
-1 0 0 0 0 1 0 1 0 0.7500000000 0.7500000000 0.2500000000
-1 0 0 0 0 -1 0 -1 0 0.2500000000 0.2500000000 0.2500000000
1 0 0 0 0 -1 0 1 0 0.2500000000 0.7500000000 0.7500000000
0 0 1 0 1 0 -1 0 0 0.7500000000 0.2500000000 0.7500000000
0 0 1 0 -1 0 1 0 0 0.2500000000 0.7500000000 0.7500000000
0 0 -1 0 1 0 1 0 0 0.7500000000 0.7500000000 0.2500000000
0 0 -1 0 -1 0 -1 0 0 0.2500000000 0.2500000000 0.2500000000
-1 0 0 0 -1 0 0 0 -1 0.7500000000 0.7500000000 0.7500000000
1 0 0 0 1 0 0 0 -1 0.7500000000 0.2500000000 0.2500000000
1 0 0 0 -1 0 0 0 1 0.2500000000 0.2500000000 0.7500000000
-1 0 0 0 1 0 0 0 1 0.2500000000 0.7500000000 0.2500000000
0 0 -1 -1 0 0 0 -1 0 0.7500000000 0.7500000000 0.7500000000
0 0 -1 1 0 0 0 1 0 0.2500000000 0.7500000000 0.2500000000
0 0 1 1 0 0 0 -1 0 0.7500000000 0.2500000000 0.2500000000
0 0 1 -1 0 0 0 1 0 0.2500000000 0.2500000000 0.7500000000
0 -1 0 0 0 -1 -1 0 0 0.7500000000 0.7500000000 0.7500000000
0 1 0 0 0 -1 1 0 0 0.2500000000 0.2500000000 0.7500000000
0 -1 0 0 0 1 1 0 0 0.2500000000 0.7500000000 0.2500000000
0 1 0 0 0 1 -1 0 0 0.7500000000 0.2500000000 0.2500000000
0 -1 0 -1 0 0 0 0 1 0.0000000000 0.5000000000 0.0000000000
0 1 0 1 0 0 0 0 1 0.5000000000 0.5000000000 0.5000000000
0 -1 0 1 0 0 0 0 -1 0.5000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.5000000000
-1 0 0 0 0 -1 0 1 0 0.0000000000 0.5000000000 0.0000000000
1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.5000000000
1 0 0 0 0 1 0 1 0 0.5000000000 0.5000000000 0.5000000000
-1 0 0 0 0 1 0 -1 0 0.5000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 1 0 0 0.0000000000 0.5000000000 0.0000000000
0 0 -1 0 1 0 -1 0 0 0.5000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.5000000000
0 0 1 0 1 0 1 0 0 0.5000000000 0.5000000000 0.5000000000
228 F d -3 c
setting 2
centrosymmetric 1
primitive cell
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
reciprocal primitive cell
-1 1 1
1 -1 1
1 1 -1
4 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.0000000000 0.5000000000 0.5000000000
0.5000000000 0.0000000000 0.5000000000
0.5000000000 0.5000000000 0.0000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.2500000000 0.7500000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.7500000000 0.5000000000 0.2500000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.2500000000 0.7500000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.2500000000 0.7500000000
0 0 -1 -1 0 0 0 1 0 0.2500000000 0.7500000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.7500000000 0.5000000000 0.2500000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.7500000000 0.5000000000 0.2500000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.2500000000 0.7500000000
0 -1 0 0 0 -1 1 0 0 0.2500000000 0.7500000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.7500000000 0.2500000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.5000000000 0.5000000000 0.5000000000
0 1 0 -1 0 0 0 0 1 0.2500000000 0.0000000000 0.7500000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.7500000000 0.2500000000
1 0 0 0 0 1 0 -1 0 0.7500000000 0.2500000000 0.0000000000
-1 0 0 0 0 1 0 1 0 0.0000000000 0.7500000000 0.2500000000
-1 0 0 0 0 -1 0 -1 0 0.5000000000 0.5000000000 0.5000000000
1 0 0 0 0 -1 0 1 0 0.2500000000 0.0000000000 0.7500000000
0 0 1 0 1 0 -1 0 0 0.7500000000 0.2500000000 0.0000000000
0 0 1 0 -1 0 1 0 0 0.2500000000 0.0000000000 0.7500000000
0 0 -1 0 1 0 1 0 0 0.0000000000 0.7500000000 0.2500000000
0 0 -1 0 -1 0 -1 0 0 0.5000000000 0.5000000000 0.5000000000
229 I m -3 m
setting 1
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 -1 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 0 0 -1 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 1 0 1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 -1 0 0 0 0 -1 0.0000000000 0.0000000000 0.0000000000
0 1 0 -1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
0 -1 0 1 0 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 1 0 1 0 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 0 -1 0 -1 0 0.0000000000 0.0000000000 0.0000000000
1 0 0 0 0 -1 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 0 -1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 1 0 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 0 -1 0 -1 0 -1 0 0 0.0000000000 0.0000000000 0.0000000000
230 I a -3 d
setting 1
centrosymmetric 1
primitive cell
-0.5000000000 0.5000000000 0.5000000000
0.5000000000 -0.5000000000 0.5000000000
0.5000000000 0.5000000000 -0.5000000000
reciprocal primitive cell
0 1 1
1 0 1
1 1 0
2 subtranslations
0.0000000000 0.0000000000 0.0000000000
0.5000000000 0.5000000000 0.5000000000
24 symmetry operations (rot+trans)
1 0 0 0 1 0 0 0 1 0.0000000000 0.0000000000 0.0000000000
-1 0 0 0 -1 0 0 0 1 0.5000000000 0.0000000000 0.5000000000
-1 0 0 0 1 0 0 0 -1 0.0000000000 0.5000000000 0.5000000000
1 0 0 0 -1 0 0 0 -1 0.5000000000 0.5000000000 0.0000000000
0 0 1 1 0 0 0 1 0 0.0000000000 0.0000000000 0.0000000000
0 0 1 -1 0 0 0 -1 0 0.5000000000 0.5000000000 0.0000000000
0 0 -1 -1 0 0 0 1 0 0.5000000000 0.0000000000 0.5000000000
0 0 -1 1 0 0 0 -1 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 1 1 0 0 0.0000000000 0.0000000000 0.0000000000
0 -1 0 0 0 1 -1 0 0 0.0000000000 0.5000000000 0.5000000000
0 1 0 0 0 -1 -1 0 0 0.5000000000 0.5000000000 0.0000000000
0 -1 0 0 0 -1 1 0 0 0.5000000000 0.0000000000 0.5000000000
0 1 0 1 0 0 0 0 -1 0.7500000000 0.2500000000 0.2500000000
0 -1 0 -1 0 0 0 0 -1 0.7500000000 0.7500000000 0.7500000000
0 1 0 -1 0 0 0 0 1 0.2500000000 0.2500000000 0.7500000000
0 -1 0 1 0 0 0 0 1 0.2500000000 0.7500000000 0.2500000000
1 0 0 0 0 1 0 -1 0 0.7500000000 0.2500000000 0.2500000000
-1 0 0 0 0 1 0 1 0 0.2500000000 0.7500000000 0.2500000000
-1 0 0 0 0 -1 0 -1 0 0.7500000000 0.7500000000 0.7500000000
1 0 0 0 0 -1 0 1 0 0.2500000000 0.2500000000 0.7500000000
0 0 1 0 1 0 -1 0 0 0.7500000000 0.2500000000 0.2500000000
0 0 1 0 -1 0 1 0 0 0.2500000000 0.2500000000 0.7500000000
0 0 -1 0 1 0 1 0 0 0.2500000000 0.7500000000 0.2500000000
0 0 -1 0 -1 0 -1 0 0 0.7500000000 0.7500000000 0.7500000000
python-ase-3.6.0.2515/ase/lattice/spacegroup/spacegroup.py 0000644 0001754 0001754 00000062405 11647744227 022314 0 ustar askhl askhl # Copyright (C) 2010, Jesper Friis
# (see accompanying license files for details).
"""Definition of the Spacegroup class.
This module only depends on NumPy and the space group database.
"""
import os
import warnings
import numpy as np
__all__ = ['Spacegroup']
class SpacegroupError(Exception):
"""Base exception for the spacegroup module."""
pass
class SpacegroupNotFoundError(SpacegroupError):
"""Raised when given space group cannot be found in data base."""
pass
class SpacegroupValueError(SpacegroupError):
"""Raised when arguments have invalid value."""
pass
class Spacegroup(object):
"""A space group class.
The instances of Spacegroup describes the symmetry operations for
the given space group.
Example:
>>> from ase.lattice.spacegroup import Spacegroup
>>>
>>> sg = Spacegroup(225)
>>> print 'Space group', sg.no, sg.symbol
Space group 225 F m -3 m
>>> sg.scaled_primitive_cell
array([[ 0. , 0.5, 0.5],
[ 0.5, 0. , 0.5],
[ 0.5, 0.5, 0. ]])
>>> sites, kinds = sg.equivalent_sites([[0,0,0]])
>>> sites
array([[ 0. , 0. , 0. ],
[ 0. , 0.5, 0.5],
[ 0.5, 0. , 0.5],
[ 0.5, 0.5, 0. ]])
"""
no = property(
lambda self: self._no,
doc='Space group number in International Tables of Crystallography.')
symbol = property(
lambda self: self._symbol,
doc='Hermann-Mauguin (or international) symbol for the space group.')
setting = property(
lambda self: self._setting,
doc='Space group setting. Either one or two.')
lattice = property(
lambda self: self._symbol[0],
doc="""Lattice type:
P primitive
I body centering, h+k+l=2n
F face centering, h,k,l all odd or even
A,B,C single face centering, k+l=2n, h+l=2n, h+k=2n
R rhombohedral centering, -h+k+l=3n (obverse); h-k+l=3n (reverse)
""")
centrosymmetric = property(
lambda self: self._centrosymmetric,
doc='Whether a center of symmetry exists.')
scaled_primitive_cell = property(
lambda self: self._scaled_primitive_cell,
doc='Primitive cell in scaled coordinates as a matrix with the '
'primitive vectors along the rows.')
reciprocal_cell = property(
lambda self: self._reciprocal_cell,
doc='Tree Miller indices that span all kinematically non-forbidden '
'reflections as a matrix with the Miller indices along the rows.')
nsubtrans = property(
lambda self: len(self._subtrans),
doc='Number of cell-subtranslation vectors.')
def _get_nsymop(self):
"""Returns total number of symmetry operations."""
if self.centrosymmetric:
return 2 * len(self._rotations) * len(self._subtrans)
else:
return len(self._rotations) * len(self._subtrans)
nsymop = property(_get_nsymop, doc='Total number of symmetry operations.')
subtrans = property(
lambda self: self._subtrans,
doc='Translations vectors belonging to cell-sub-translations.')
rotations = property(
lambda self: self._rotations,
doc='Symmetry rotation matrices. The invertions are not included '
'for centrosymmetrical crystals.')
translations = property(
lambda self: self._translations,
doc='Symmetry translations. The invertions are not included '
'for centrosymmetrical crystals.')
def __init__(self, spacegroup, setting=1, datafile=None):
"""Returns a new Spacegroup instance.
Parameters:
spacegroup : int | string | Spacegroup instance
The space group number in International Tables of
Crystallography or its Hermann-Mauguin symbol. E.g.
spacegroup=225 and spacegroup='F m -3 m' are equivalent.
setting : 1 | 2
Some space groups have more than one setting. `setting`
determines Which of these should be used.
datafile : None | string
Path to database file. If `None`, the the default database
will be used.
"""
if isinstance(spacegroup, Spacegroup):
for k, v in spacegroup.__dict__.iteritems():
setattr(self, k, v)
return
if not datafile:
datafile = get_datafile()
f = open(datafile, 'r')
try:
_read_datafile(self, spacegroup, setting, f)
finally:
f.close()
def __repr__(self):
return 'Spacegroup(%d, setting=%d)' % (self.no, self.setting)
def __str__(self):
"""Return a string representation of the space group data in
the same format as found the database."""
retval = []
# no, symbol
retval.append('%-3d %s\n' % (self.no, self.symbol))
# setting
retval.append(' setting %d\n' % (self.setting))
# centrosymmetric
retval.append(' centrosymmetric %d\n' % (self.centrosymmetric))
# primitive vectors
retval.append(' primitive vectors\n')
for i in range(3):
retval.append(' ')
for j in range(3):
retval.append(' %13.10f' % (self.scaled_primitive_cell[i, j]))
retval.append('\n')
# primitive reciprocal vectors
retval.append(' reciprocal vectors\n')
for i in range(3):
retval.append(' ')
for j in range(3):
retval.append(' %3d' % (self.reciprocal_cell[i, j]))
retval.append('\n')
# sublattice
retval.append(' %d subtranslations\n' % self.nsubtrans)
for i in range(self.nsubtrans):
retval.append(' ')
for j in range(3):
retval.append(' %13.10f' % (self.subtrans[i, j]))
retval.append('\n')
# symmetry operations
nrot = len(self.rotations)
retval.append(' %d symmetry operations (rot+trans)\n' % nrot)
for i in range(nrot):
retval.append(' ')
for j in range(3):
retval.append(' ')
for k in range(3):
retval.append(' %2d' % (self.rotations[i, j, k]))
retval.append(' ')
for j in range(3):
retval.append(' %13.10f' % self.translations[i, j])
retval.append('\n')
retval.append('\n')
return ''.join(retval)
def __eq__(self, other):
"""Chech whether *self* and *other* refer to the same
spacegroup number and setting."""
if not isinstance(other, Spacegroup):
other = Spacegroup(other)
return self.no == other.no and self.setting == other.setting
def __index__(self):
return self.no
def get_symop(self):
"""Returns all symmetry operations (including inversions and
subtranslations) as a sequence of (rotation, translation)
tuples."""
symop = []
parities = [1]
if self.centrosymmetric:
parities.append(-1)
for parity in parities:
for subtrans in self.subtrans:
for rot, trans in zip(self.rotations, self.translations):
newtrans = np.mod(trans + subtrans, 1)
symop.append((parity*rot, newtrans))
return symop
def get_op(self):
"""Returns all symmetry operations (including inversions and
subtranslations), but unlike get_symop(), they are returned as
two ndarrays."""
if self.centrosymmetric:
rot = np.tile(np.vstack((self.rotations, -self.rotations)),
(self.nsubtrans, 1, 1))
trans = np.repeat(self.subtrans, 2*len(self.rotations), axis=0)
else:
rot = np.tile(self.rotations, (self.nsubtrans, 1, 1))
trans = np.repeat(self.subtrans, len(self.rotations), axis=0)
return rot, trans
def get_rotations(self):
"""Return all rotations, including inversions for
centrosymmetric crystals."""
if self.centrosymmetric:
return np.vstack((self.rotations, -self.rotations))
else:
return self.rotations
def equivalent_reflections(self, hkl):
"""Return all equivalent reflections to the list of Miller indices
in hkl.
Example:
>>> from ase.lattice.spacegroup import Spacegroup
>>> sg = Spacegroup(225) # fcc
>>> sg.equivalent_reflections([[0, 0, 2]])
array([[ 0, 0, -2],
[ 0, -2, 0],
[-2, 0, 0],
[ 2, 0, 0],
[ 0, 2, 0],
[ 0, 0, 2]])
"""
hkl = np.array(hkl, dtype='int', ndmin=2)
rot = self.get_rotations()
n, nrot = len(hkl), len(rot)
R = rot.transpose(0, 2, 1).reshape((3*nrot, 3)).T
refl = np.dot(hkl, R).reshape((n*nrot, 3))
ind = np.lexsort(refl.T)
refl = refl[ind]
diff = np.diff(refl, axis=0)
mask = np.any(diff, axis=1)
return np.vstack((refl[mask], refl[-1,:]))
def symmetry_normalised_reflections(self, hkl):
"""Returns an array of same size as *hkl*, containing the
corresponding symmetry-equivalent reflections of lowest
indices.
Example:
>>> from ase.lattice.spacegroup import Spacegroup
>>> sg = Spacegroup(225) # fcc
>>> sg.symmetry_normalised_reflections([[2, 0, 0], [0, 2, 0]])
array([[ 0, 0, -2],
[ 0, 0, -2]])
"""
hkl = np.array(hkl, dtype=int, ndmin=2)
normalised = np.empty(hkl.shape, int)
R = self.get_rotations().transpose(0, 2, 1)
for i, g in enumerate(hkl):
gsym = np.dot(R, g)
j = np.lexsort(gsym.T)[0]
normalised[i,:] = gsym[j]
return normalised
def unique_reflections(self, hkl):
"""Returns a subset *hkl* containing only the symmetry-unique
reflections.
Example:
>>> from ase.lattice.spacegroup import Spacegroup
>>> sg = Spacegroup(225) # fcc
>>> sg.unique_reflections([[ 2, 0, 0],
... [ 0, -2, 0],
... [ 2, 2, 0],
... [ 0, -2, -2]])
array([[2, 0, 0],
[2, 2, 0]])
"""
hkl = np.array(hkl, dtype=int, ndmin=2)
hklnorm = self.symmetry_normalised_reflections(hkl)
perm = np.lexsort(hklnorm.T)
iperm = perm.argsort()
xmask = np.abs(np.diff(hklnorm[perm], axis=0)).any(axis=1)
mask = np.concatenate(([True], xmask))
imask = mask[iperm]
return hkl[imask]
def equivalent_sites(self, scaled_positions, ondublicates='error',
symprec=1e-3):
"""Returns the scaled positions and all their equivalent sites.
Parameters:
scaled_positions: list | array
List of non-equivalent sites given in unit cell coordinates.
ondublicates : 'keep' | 'replace' | 'warn' | 'error'
Action if `scaled_positions` contain symmetry-equivalent
positions:
'keep'
ignore additional symmetry-equivalent positions
'replace'
replace
'warn'
like 'keep', but issue an UserWarning
'error'
raises a SpacegroupValueError
symprec: float
Minimum "distance" betweed two sites in scaled coordinates
before they are counted as the same site.
Returns:
sites: array
A NumPy array of equivalent sites.
kinds: list
A list of integer indices specifying which input site is
equivalent to the corresponding returned site.
Example:
>>> from ase.lattice.spacegroup import Spacegroup
>>> sg = Spacegroup(225) # fcc
>>> sites, kinds = sg.equivalent_sites([[0, 0, 0], [0.5, 0.0, 0.0]])
>>> sites
array([[ 0. , 0. , 0. ],
[ 0. , 0.5, 0.5],
[ 0.5, 0. , 0.5],
[ 0.5, 0.5, 0. ],
[ 0.5, 0. , 0. ],
[ 0. , 0.5, 0. ],
[ 0. , 0. , 0.5],
[ 0.5, 0.5, 0.5]])
>>> kinds
[0, 0, 0, 0, 1, 1, 1, 1]
"""
kinds = []
sites = []
symprec2 = symprec**2
scaled = np.array(scaled_positions, ndmin=2)
for kind, pos in enumerate(scaled):
for rot, trans in self.get_symop():
site = np.mod(np.dot(rot, pos) + trans, 1.)
if not sites:
sites.append(site)
kinds.append(kind)
continue
t = site - sites
mask = np.sum(t*t, 1) < symprec2
if np.any(mask):
ind = np.argwhere(mask)[0][0]
if kinds[ind] == kind:
pass
elif ondublicates == 'keep':
pass
elif ondublicates == 'replace':
kinds[ind] = kind
elif ondublicates == 'warn':
warnings.warn('scaled_positions %d and %d '
'are equivalent'%(kinds[ind], kind))
elif ondublicates == 'error':
raise SpacegroupValueError(
'scaled_positions %d and %d are equivalent'%(
kinds[ind], kind))
else:
raise SpacegroupValueError(
'Argument "ondublicates" must be one of: '
'"keep", "replace", "warn" or "error".')
else:
sites.append(site)
kinds.append(kind)
return np.array(sites), kinds
def symmetry_normalised_sites(self, scaled_positions):
"""Returns an array of same size as *scaled_positions*,
containing the corresponding symmetry-equivalent sites within
the unit cell of lowest indices.
Example:
>>> from ase.lattice.spacegroup import Spacegroup
>>> sg = Spacegroup(225) # fcc
>>> sg.symmetry_normalised_sites([[0.0, 0.5, 0.5], [1.0, 1.0, 0.0]])
array([[ 0., 0., 0.],
[ 0., 0., 0.]])
"""
scaled = np.array(scaled_positions, ndmin=2)
normalised = np.empty(scaled.shape, np.float)
rot, trans = self.get_op()
for i, pos in enumerate(scaled):
sympos = np.dot(rot, pos) + trans
# Must be done twice, see the scaled_positions.py test
sympos %= 1.0
sympos %= 1.0
j = np.lexsort(sympos.T)[0]
normalised[i,:] = sympos[j]
return normalised
def unique_sites(self, scaled_positions, symprec=1e-3, output_mask=False):
"""Returns a subset of *scaled_positions* containing only the
symmetry-unique positions. If *output_mask* is True, a boolean
array masking the subset is also returned.
Example:
>>> from ase.lattice.spacegroup import Spacegroup
>>> sg = Spacegroup(225) # fcc
>>> sg.unique_sites([[0.0, 0.0, 0.0],
... [0.5, 0.5, 0.0],
... [1.0, 0.0, 0.0],
... [0.5, 0.0, 0.0]])
array([[ 0. , 0. , 0. ],
[ 0.5, 0. , 0. ]])
"""
scaled = np.array(scaled_positions, ndmin=2)
symnorm = self.symmetry_normalised_sites(scaled)
perm = np.lexsort(symnorm.T)
iperm = perm.argsort()
xmask = np.abs(np.diff(symnorm[perm], axis=0)).max(axis=1) > symprec
mask = np.concatenate(([True], xmask))
imask = mask[iperm]
if output_mask:
return scaled[imask], imask
else:
return scaled[imask]
def tag_sites(self, scaled_positions, symprec=1e-3):
"""Returns an integer array of the same length as *scaled_positions*,
tagging all equivalent atoms with the same index.
Example:
>>> from ase.lattice.spacegroup import Spacegroup
>>> sg = Spacegroup(225) # fcc
>>> sg.tag_sites([[0.0, 0.0, 0.0],
... [0.5, 0.5, 0.0],
... [1.0, 0.0, 0.0],
... [0.5, 0.0, 0.0]])
array([0, 0, 0, 1])
"""
scaled = np.array(scaled_positions, ndmin=2)
scaled %= 1.0
scaled %= 1.0
tags = -np.ones((len(scaled), ), dtype=int)
mask = np.ones((len(scaled), ), dtype=np.bool)
rot, trans = self.get_op()
i = 0
while mask.any():
pos = scaled[mask][0]
sympos = np.dot(rot, pos) + trans
# Must be done twice, see the scaled_positions.py test
sympos %= 1.0
sympos %= 1.0
m = ~np.all(np.any(np.abs(scaled[np.newaxis,:,:] -
sympos[:,np.newaxis,:]) > symprec,
axis=2), axis=0)
assert not np.any((~mask) & m)
tags[m] = i
mask &= ~m
i += 1
return tags
def get_datafile():
"""Return default path to datafile."""
return os.path.join(os.path.dirname(__file__), 'spacegroup.dat')
def format_symbol(symbol):
"""Returns well formatted Hermann-Mauguin symbol as extected by
the database, by correcting the case and adding missing or
removing dublicated spaces."""
fixed = []
s = symbol.strip()
s = s[0].upper() + s[1:].lower()
for c in s:
if c.isalpha():
fixed.append(' ' + c + ' ')
elif c.isspace():
fixed.append(' ')
elif c.isdigit():
fixed.append(c)
elif c == '-':
fixed.append(' ' + c)
elif c == '/':
fixed.append(' ' + c)
s = ''.join(fixed).strip()
return ' '.join(s.split())
#-----------------------------------------------------------------
# Functions for parsing the database. They are moved outside the
# Spacegroup class in order to make it easier to later implement
# caching to avoid reading the database each time a new Spacegroup
# instance is created.
#-----------------------------------------------------------------
def _skip_to_blank(f, spacegroup, setting):
"""Read lines from f until a blank line is encountered."""
while True:
line = f.readline()
if not line:
raise SpacegroupNotFoundError(
'invalid spacegroup %s, setting %i not found in data base' %
( spacegroup, setting ) )
if not line.strip():
break
def _skip_to_nonblank(f, spacegroup, setting):
"""Read lines from f until a nonblank line not starting with a
hash (#) is encountered and returns this and the next line."""
while True:
line1 = f.readline()
if not line1:
raise SpacegroupNotFoundError(
'invalid spacegroup %s, setting %i not found in data base' %
( spacegroup, setting ) )
line1.strip()
if line1 and not line1.startswith('#'):
line2 = f.readline()
break
return line1, line2
def _read_datafile_entry(spg, no, symbol, setting, f):
"""Read space group data from f to spg."""
spg._no = no
spg._symbol = symbol.strip()
spg._setting = setting
spg._centrosymmetric = bool(int(f.readline().split()[1]))
# primitive vectors
f.readline()
spg._scaled_primitive_cell = np.array([map(float, f.readline().split())
for i in range(3)],
dtype=np.float)
# primitive reciprocal vectors
f.readline()
spg._reciprocal_cell = np.array([map(int, f.readline().split())
for i in range(3)],
dtype=np.int)
# subtranslations
spg._nsubtrans = int(f.readline().split()[0])
spg._subtrans = np.array([map(float, f.readline().split())
for i in range(spg._nsubtrans)],
dtype=np.float)
# symmetry operations
nsym = int(f.readline().split()[0])
symop = np.array([map(float, f.readline().split()) for i in range(nsym)],
dtype=np.float)
spg._nsymop = nsym
spg._rotations = np.array(symop[:,:9].reshape((nsym,3,3)), dtype=np.int)
spg._translations = symop[:,9:]
def _read_datafile(spg, spacegroup, setting, f):
if isinstance(spacegroup, int):
pass
elif isinstance(spacegroup, basestring):
#spacegroup = ' '.join(spacegroup.strip().split())
spacegroup = format_symbol(spacegroup)
else:
raise SpacegroupValueError('`spacegroup` must be of type int or str')
while True:
line1, line2 = _skip_to_nonblank(f, spacegroup, setting)
_no,_symbol = line1.strip().split(None, 1)
_symbol = format_symbol(_symbol)
_setting = int(line2.strip().split()[1])
_no = int(_no)
if ((isinstance(spacegroup, int) and _no == spacegroup) or
(isinstance(spacegroup, basestring) and
_symbol == spacegroup)) and _setting == setting:
_read_datafile_entry(spg, _no, _symbol, _setting, f)
break
else:
_skip_to_blank(f, spacegroup, setting)
def parse_sitesym(symlist, sep=','):
"""Parses a sequence of site symmetries in the form used by
International Tables and returns corresponding rotation and
translation arrays.
Example:
>>> symlist = [
... 'x,y,z',
... '-y+1/2,x+1/2,z',
... '-y,-x,-z',
... ]
>>> rot, trans = parse_sitesym(symlist)
>>> rot
array([[[ 1, 0, 0],
[ 0, 1, 0],
[ 0, 0, 1]],
[[ 0, -1, 0],
[ 1, 0, 0],
[ 0, 0, 1]],
[[ 0, -1, 0],
[-1, 0, 0],
[ 0, 0, -1]]])
>>> trans
array([[ 0. , 0. , 0. ],
[ 0.5, 0.5, 0. ],
[ 0. , 0. , 0. ]])
"""
nsym = len(symlist)
rot = np.zeros((nsym, 3, 3), dtype='int')
trans = np.zeros((nsym, 3))
for i, sym in enumerate(symlist):
for j, s in enumerate (sym.split(sep)):
s = s.lower().strip()
while s:
sign = 1
if s[0] in '+-':
if s[0] == '-':
sign = -1
s = s[1:]
if s[0] in 'xyz':
k = ord(s[0]) - ord('x')
rot[i, j, k] = sign
s = s[1:]
elif s[0].isdigit() or s[0] == '.':
n = 0
while n < len(s) and (s[n].isdigit() or s[n] in '/.'):
n += 1
t = s[:n]
s = s[n:]
if '/' in t:
q, r = t.split('/')
trans[i,j] = float(q)/float(r)
else:
trans[i,j] = float(t)
else:
raise SpacegroupValueError(
'Error parsing %r. Invalid site symmetry: %s' %
(s, sym))
return rot, trans
def spacegroup_from_data(no=None, symbol=None, setting=1,
centrosymmetric=None, scaled_primitive_cell=None,
reciprocal_cell=None, subtrans=None, sitesym=None,
rotations=None, translations=None, datafile=None):
"""Manually create a new space group instance. This might be
usefull when reading crystal data with its own spacegroup
definitions."""
if no is not None:
spg = Spacegroup(no, setting, datafile)
elif symbol is not None:
spg = Spacegroup(symbol, setting, datafile)
else:
raise SpacegroupValueError('either *no* or *symbol* must be given')
have_sym = False
if centrosymmetric is not None:
spg._centrosymmetric = bool(centrosymmetric)
if scaled_primitive_cell is not None:
spg._scaled_primitive_cell = np.array(scaled_primitive_cell)
if reciprocal_cell is not None:
spg._reciprocal_cell = np.array(reciprocal_cell)
if subtrans is not None:
spg._subtrans = np.atleast_2d(subtrans)
spg._nsubtrans = spg._subtrans.shape[0]
if sitesym is not None:
spg._rotations, spg._translations = parse_sitesym(sitesym)
have_sym = True
if rotations is not None:
spg._rotations = np.atleast_3d(rotations)
have_sym = True
if translations is not None:
spg._translations = np.atleast_2d(translations)
have_sym = True
if have_sym:
if spg._rotations.shape[0] != spg._translations.shape[0]:
raise SpacegroupValueError('inconsistent number of rotations and '
'translations')
spg._nsymop = spg._rotations.shape[0]
return spg
#-----------------------------------------------------------------
# Self test
if __name__ == '__main__':
# Import spacegroup in order to ensure that __file__ is defined
# such that the data base can be found.
import spacegroup
import doctest
print 'doctest: ', doctest.testmod()
python-ase-3.6.0.2515/ase/lattice/spacegroup/cell.py 0000644 0001754 0001754 00000006561 11454152657 021060 0 ustar askhl askhl # Copyright (C) 2010, Jesper Friis
# (see accompanying license files for details).
import numpy as np
from numpy import pi, sin, cos, tan, arcsin, arccos, arctan, sqrt
from numpy import dot
from numpy.linalg import norm
import ase
__all__ = ['cell_to_cellpar', 'cellpar_to_cell', 'metric_from_cell']
def unit_vector(x):
"""Return a unit vector in the same direction as x."""
y = np.array(x, dtype='float')
return y/norm(y)
def angle(x, y):
"""Return the angle between vectors a and b in degrees."""
return arccos(dot(x, y)/(norm(x)*norm(y)))*180./pi
def cell_to_cellpar(cell):
"""Returns the cell parameters [a, b, c, alpha, beta, gamma] as a
numpy array."""
va, vb, vc = cell
a = np.linalg.norm(va)
b = np.linalg.norm(vb)
c = np.linalg.norm(vc)
alpha = 180.0/pi*arccos(dot(vb, vc)/(b*c))
beta = 180.0/pi*arccos(dot(vc, va)/(c*a))
gamma = 180.0/pi*arccos(dot(va, vb)/(a*b))
return np.array([a, b, c, alpha, beta, gamma])
def cellpar_to_cell(cellpar, ab_normal=(0,0,1), a_direction=None):
"""Return a 3x3 cell matrix from `cellpar` = [a, b, c, alpha,
beta, gamma]. The returned cell is orientated such that a and b
are normal to `ab_normal` and a is parallel to the projection of
`a_direction` in the a-b plane.
Default `a_direction` is (1,0,0), unless this is parallel to
`ab_normal`, in which case default `a_direction` is (0,0,1).
The returned cell has the vectors va, vb and vc along the rows. The
cell will be oriented such that va and vb are normal to `ab_normal`
and va will be along the projection of `a_direction` onto the a-b
plane.
Example:
>>> cell = cellpar_to_cell([1, 2, 4, 10, 20, 30], (0,1,1), (1,2,3))
>>> np.round(cell, 3)
array([[ 0.816, -0.408, 0.408],
[ 1.992, -0.13 , 0.13 ],
[ 3.859, -0.745, 0.745]])
"""
if a_direction is None:
if np.linalg.norm(np.cross(ab_normal, (1,0,0))) < 1e-5:
a_direction = (0,0,1)
else:
a_direction = (1,0,0)
# Define rotated X,Y,Z-system, with Z along ab_normal and X along
# the projection of a_direction onto the normal plane of Z.
ad = np.array(a_direction)
Z = unit_vector(ab_normal)
X = unit_vector(ad - dot(ad, Z)*Z)
Y = np.cross(Z, X)
# Express va, vb and vc in the X,Y,Z-system
alpha, beta, gamma = 90., 90., 90.
if isinstance(cellpar, (int, long, float)):
a = b = c = cellpar
elif len(cellpar) == 1:
a = b = c = cellpar[0]
elif len(cellpar) == 3:
a, b, c = cellpar
alpha, beta, gamma = 90., 90., 90.
else:
a, b, c, alpha, beta, gamma = cellpar
alpha *= pi/180.0
beta *= pi/180.0
gamma *= pi/180.0
va = a * np.array([1, 0, 0])
vb = b * np.array([cos(gamma), sin(gamma), 0])
cx = cos(beta)
cy = (cos(alpha) - cos(beta)*cos(gamma))/sin(gamma)
cz = sqrt(1. - cx*cx - cy*cy)
vc = c * np.array([cx, cy, cz])
# Convert to the Cartesian x,y,z-system
abc = np.vstack((va, vb, vc))
T = np.vstack((X, Y, Z))
cell = dot(abc, T)
return cell
def metric_from_cell(cell):
"""Calculates the metric matrix from cell, which is given in the
Cartesian system."""
cell = np.asarray(cell, dtype=float)
return np.dot(cell, cell.T)
if __name__ == '__main__':
import doctest
print 'doctest: ', doctest.testmod()
python-ase-3.6.0.2515/ase/lattice/spacegroup/crystal.py 0000644 0001754 0001754 00000013642 11636312743 021614 0 ustar askhl askhl # Copyright (C) 2010, Jesper Friis
# (see accompanying license files for details).
"""
A module for ASE for simple creation of crystalline structures from
knowledge of the space group.
"""
import numpy as np
import ase
from ase.atoms import string2symbols
from spacegroup import Spacegroup
from cell import cellpar_to_cell
__all__ = ['crystal']
def crystal(symbols=None, basis=None, spacegroup=1, setting=1,
cell=None, cellpar=None,
ab_normal=(0,0,1), a_direction=None, size=(1,1,1),
ondublicates='warn', symprec=0.001,
pbc=True, primitive_cell=False, **kwargs):
"""Create an Atoms instance for a conventional unit cell of a
space group.
Parameters:
symbols : str | sequence of str | sequence of Atom | Atoms
Element symbols of the unique sites. Can either be a string
formula or a sequence of element symbols. E.g. ('Na', 'Cl')
and 'NaCl' are equivalent. Can also be given as a sequence of
Atom objects or an Atoms object.
basis : list of scaled coordinates
Positions of the unique sites corresponding to symbols given
either as scaled positions or through an atoms instance. Not
needed if *symbols* is a sequence of Atom objects or an Atoms
object.
spacegroup : int | string | Spacegroup instance
Space group given either as its number in International Tables
or as its Hermann-Mauguin symbol.
setting : 1 | 2
Space group setting.
cell : 3x3 matrix
Unit cell vectors.
cellpar : [a, b, c, alpha, beta, gamma]
Cell parameters with angles in degree. Is not used when `cell`
is given.
ab_normal : vector
Is used to define the orientation of the unit cell relative
to the Cartesian system when `cell` is not given. It is the
normal vector of the plane spanned by a and b.
a_direction : vector
Defines the orientation of the unit cell a vector. a will be
parallel to the projection of `a_direction` onto the a-b plane.
size : 3 positive integers
How many times the conventional unit cell should be repeated
in each direction.
ondublicates : 'keep' | 'replace' | 'warn' | 'error'
Action if `basis` contain symmetry-equivalent positions:
'keep' - ignore additional symmetry-equivalent positions
'replace' - replace
'warn' - like 'keep', but issue an UserWarning
'error' - raises a SpacegroupValueError
symprec : float
Minimum "distance" betweed two sites in scaled coordinates
before they are counted as the same site.
pbc : one or three bools
Periodic boundary conditions flags. Examples: True,
False, 0, 1, (1, 1, 0), (True, False, False). Default
is True.
primitive_cell : bool
Wheter to return the primitive instead of the conventional
unit cell.
Keyword arguments:
All additional keyword arguments are passed on to the Atoms
constructor. Currently, probably the most useful additional
keyword arguments are `info`, `constraint` and `calculator`.
Examples:
Two diamond unit cells (space group number 227)
>>> diamond = crystal('C', [(0,0,0)], spacegroup=227,
... cellpar=[3.57, 3.57, 3.57, 90, 90, 90], size=(2,1,1))
>>> ase.view(diamond) # doctest: +SKIP
A CoSb3 skutterudite unit cell containing 32 atoms
>>> skutterudite = crystal(('Co', 'Sb'),
... basis=[(0.25,0.25,0.25), (0.0, 0.335, 0.158)],
... spacegroup=204, cellpar=[9.04, 9.04, 9.04, 90, 90, 90])
>>> len(skutterudite)
32
"""
sg = Spacegroup(spacegroup, setting)
if (not isinstance(symbols, str) and
hasattr(symbols, '__getitem__') and
len(symbols) > 0 and
isinstance(symbols[0], ase.Atom)):
symbols = ase.Atoms(symbols)
if isinstance(symbols, ase.Atoms):
basis = symbols
symbols = basis.get_chemical_symbols()
if isinstance(basis, ase.Atoms):
basis_coords = basis.get_scaled_positions()
if cell is None and cellpar is None:
cell = basis.cell
if symbols is None:
symbols = basis.get_chemical_symbols()
else:
basis_coords = np.array(basis, dtype=float, copy=False, ndmin=2)
sites, kinds = sg.equivalent_sites(basis_coords,
ondublicates=ondublicates,
symprec=symprec)
symbols = parse_symbols(symbols)
symbols = [symbols[i] for i in kinds]
if cell is None:
cell = cellpar_to_cell(cellpar, ab_normal, a_direction)
info = dict(spacegroup=sg)
if primitive_cell:
info['unit_cell'] = 'primitive'
else:
info['unit_cell'] = 'conventional'
if 'info' in kwargs:
info.update(kwargs['info'])
kwargs['info'] = info
atoms = ase.Atoms(symbols,
scaled_positions=sites,
cell=cell,
pbc=pbc,
**kwargs)
if isinstance(basis, ase.Atoms):
for name in basis.arrays:
if not atoms.has(name):
array = basis.get_array(name)
atoms.new_array(name, [array[i] for i in kinds],
dtype=array.dtype, shape=array.shape[1:])
if primitive_cell:
from ase.utils.geometry import cut
prim_cell = sg.scaled_primitive_cell
atoms = cut(atoms, a=prim_cell[0], b=prim_cell[1], c=prim_cell[2])
if size != (1, 1, 1):
atoms = atoms.repeat(size)
return atoms
def parse_symbols(symbols):
"""Return `sumbols` as a sequence of element symbols."""
if isinstance(symbols, basestring):
symbols = string2symbols(symbols)
return symbols
#-----------------------------------------------------------------
# Self test
if __name__ == '__main__':
import doctest
print 'doctest: ', doctest.testmod()
python-ase-3.6.0.2515/ase/vibrations.py 0000644 0001754 0001754 00000030031 11602445437 016505 0 ustar askhl askhl # -*- coding: utf-8 -*-
"""Vibrational modes."""
import pickle
from math import sin, pi, sqrt
from os import remove
from os.path import isfile
import sys
import numpy as np
import ase.units as units
from ase.io.trajectory import PickleTrajectory
from ase.parallel import rank, paropen
from ase.utils import opencew
class Vibrations:
"""Class for calculating vibrational modes using finite difference.
The vibrational modes are calculated from a finite difference
approximation of the Hessian matrix.
The *summary()*, *get_energies()* and *get_frequencies()* methods all take
an optional *method* keyword. Use method='Frederiksen' to use the method
described in:
T. Frederiksen, M. Paulsson, M. Brandbyge, A. P. Jauho:
"Inelastic transport theory from first-principles: methodology and
applications for nanoscale devices", Phys. Rev. B 75, 205413 (2007)
atoms: Atoms object
The atoms to work on.
indices: list of int
List of indices of atoms to vibrate. Default behavior is
to vibrate all atoms.
name: str
Name to use for files.
delta: float
Magnitude of displacements.
nfree: int
Number of displacements per atom and cartesian coordinate, 2 and 4 are
supported. Default is 2 which will displace each atom +delta and
-delta for each cartesian coordinate.
Example:
>>> from ase import Atoms
>>> from ase.calculators import EMT
>>> from ase.optimize import BFGS
>>> from ase.vibrations import Vibrations
>>> n2 = Atoms('N2', [(0, 0, 0), (0, 0, 1.1)],
... calculator=EMT())
>>> BFGS(n2).run(fmax=0.01)
BFGS: 0 16:01:21 0.440339 3.2518
BFGS: 1 16:01:21 0.271928 0.8211
BFGS: 2 16:01:21 0.263278 0.1994
BFGS: 3 16:01:21 0.262777 0.0088
>>> vib = Vibrations(n2)
>>> vib.run()
Writing vib.eq.pckl
Writing vib.0x-.pckl
Writing vib.0x+.pckl
Writing vib.0y-.pckl
Writing vib.0y+.pckl
Writing vib.0z-.pckl
Writing vib.0z+.pckl
Writing vib.1x-.pckl
Writing vib.1x+.pckl
Writing vib.1y-.pckl
Writing vib.1y+.pckl
Writing vib.1z-.pckl
Writing vib.1z+.pckl
>>> vib.summary()
---------------------
# meV cm^-1
---------------------
0 0.0 0.0
1 0.0 0.0
2 0.0 0.0
3 2.5 20.4
4 2.5 20.4
5 152.6 1230.8
---------------------
Zero-point energy: 0.079 eV
>>> vib.write_mode(-1) # write last mode to trajectory file
"""
def __init__(self, atoms, indices=None, name='vib', delta=0.01, nfree=2):
assert nfree in [2, 4]
self.atoms = atoms
if indices is None:
indices = range(len(atoms))
self.indices = np.asarray(indices)
self.name = name
self.delta = delta
self.nfree = nfree
self.H = None
self.ir = None
def run(self):
"""Run the vibration calculations.
This will calculate the forces for 6 displacements per atom +/-x,
+/-y, +/-z. Only those calculations that are not already done will be
started. Be aware that an interrupted calculation may produce an empty
file (ending with .pckl), which must be deleted before restarting the
job. Otherwise the forces will not be calculated for that
displacement.
Note that the calculations for the different displacements can be done
simultaneously by several independent processes. This feature relies
on the existence of files and the subsequent creation of the file in
case it is not found.
"""
filename = self.name + '.eq.pckl'
fd = opencew(filename)
if fd is not None:
self.calculate(filename, fd)
p = self.atoms.positions.copy()
for a in self.indices:
for i in range(3):
for sign in [-1, 1]:
for ndis in range(1, self.nfree // 2 + 1):
filename = ('%s.%d%s%s.pckl' %
(self.name, a, 'xyz'[i],
ndis * ' +-'[sign]))
fd = opencew(filename)
if fd is not None:
disp = ndis * sign * self.delta
self.atoms.positions[a, i] = p[a, i] + disp
self.calculate(filename, fd)
self.atoms.positions[a, i] = p[a, i]
def calculate(self, filename, fd):
forces = self.atoms.get_forces()
if self.ir:
dipole = self.calc.get_dipole_moment(self.atoms)
if rank == 0:
if self.ir:
pickle.dump([forces, dipole], fd)
sys.stdout.write(
'Writing %s, dipole moment = (%.6f %.6f %.6f)\n' %
(filename, dipole[0], dipole[1], dipole[2]))
else:
pickle.dump(forces, fd)
sys.stdout.write('Writing %s\n' % filename)
fd.close()
sys.stdout.flush()
def clean(self):
if isfile(self.name + '.eq.pckl'):
remove(self.name + '.eq.pckl')
for a in self.indices:
for i in 'xyz':
for sign in '-+':
for ndis in range(1, self.nfree // 2 + 1):
name = '%s.%d%s%s.pckl' % (self.name, a, i,
ndis * sign)
if isfile(name):
remove(name)
def read(self, method='standard', direction='central'):
self.method = method.lower()
self.direction = direction.lower()
assert self.method in ['standard', 'frederiksen']
assert self.direction in ['central', 'forward', 'backward']
n = 3 * len(self.indices)
H = np.empty((n, n))
r = 0
if direction != 'central':
feq = pickle.load(open(self.name + '.eq.pckl'))
for a in self.indices:
for i in 'xyz':
name = '%s.%d%s' % (self.name, a, i)
fminus = pickle.load(open(name + '-.pckl'))
fplus = pickle.load(open(name + '+.pckl'))
if self.method == 'frederiksen':
fminus[a] -= fminus.sum(0)
fplus[a] -= fplus.sum(0)
if self.nfree == 4:
fminusminus = pickle.load(open(name + '--.pckl'))
fplusplus = pickle.load(open(name + '++.pckl'))
if self.method == 'frederiksen':
fminusminus[a] -= fminusminus.sum(0)
fplusplus[a] -= fplusplus.sum(0)
if self.direction == 'central':
if self.nfree == 2:
H[r] = .5 * (fminus - fplus)[self.indices].ravel()
else:
H[r] = H[r] = (-fminusminus +
8 * fminus -
8 * fplus +
fplusplus)[self.indices].ravel() / 12.0
elif self.direction == 'forward':
H[r] = (feq - fplus)[self.indices].ravel()
else:
assert self.direction == 'backward'
H[r] = (fminus - feq)[self.indices].ravel()
H[r] /= 2 * self.delta
r += 1
H += H.copy().T
self.H = H
m = self.atoms.get_masses()
if 0 in [m[index] for index in self.indices]:
raise RuntimeError('Zero mass encountered in one or more of '
'the vibrated atoms. Use Atoms.set_masses()'
' to set all masses to non-zero values.')
self.im = np.repeat(m[self.indices] ** -0.5, 3)
omega2, modes = np.linalg.eigh(self.im[:, None] * H * self.im)
self.modes = modes.T.copy()
# Conversion factor:
s = units._hbar * 1e10 / sqrt(units._e * units._amu)
self.hnu = s * omega2.astype(complex) ** 0.5
def get_energies(self, method='standard', direction='central'):
"""Get vibration energies in eV."""
if (self.H is None or method.lower() != self.method or
direction.lower() != self.direction):
self.read(method, direction)
return self.hnu
def get_frequencies(self, method='standard', direction='central'):
"""Get vibration frequencies in cm^-1."""
s = 0.01 * units._e / units._c / units._hplanck
return s * self.get_energies(method, direction)
def summary(self, method='standard', direction='central', freq=None,
log=sys.stdout):
"""Print a summary of the vibrational frequencies.
Parameters:
method : string
Can be 'standard'(default) or 'Frederiksen'.
direction: string
Direction for finite differences. Can be one of 'central'
(default), 'forward', 'backward'.
freq : numpy array
Optional. Can be used to create a summary on a set of known
frequencies.
log : if specified, write output to a different location than
stdout. Can be an object with a write() method or the name of a
file to create.
"""
if isinstance(log, str):
log = paropen(log, 'a')
write = log.write
s = 0.01 * units._e / units._c / units._hplanck
if freq != None:
hnu = freq / s
else:
hnu = self.get_energies(method, direction)
write('---------------------\n')
write(' # meV cm^-1\n')
write('---------------------\n')
for n, e in enumerate(hnu):
if e.imag != 0:
c = 'i'
e = e.imag
else:
c = ' '
e = e.real
write('%3d %6.1f%s %7.1f%s\n' % (n, 1000 * e, c, s * e, c))
write('---------------------\n')
write('Zero-point energy: %.3f eV\n' %
self.get_zero_point_energy(freq=freq))
def get_zero_point_energy(self, freq=None):
if freq is None:
return 0.5 * self.hnu.real.sum()
else:
s = 0.01 * units._e / units._c / units._hplanck
return 0.5 * freq.real.sum() / s
def get_mode(self, n):
mode = np.zeros((len(self.atoms), 3))
mode[self.indices] = (self.modes[n] * self.im).reshape((-1, 3))
return mode
def write_mode(self, n, kT=units.kB * 300, nimages=30):
"""Write mode to trajectory file."""
mode = self.get_mode(n) * sqrt(kT / abs(self.hnu[n]))
p = self.atoms.positions.copy()
n %= 3 * len(self.indices)
traj = PickleTrajectory('%s.%d.traj' % (self.name, n), 'w')
calc = self.atoms.get_calculator()
self.atoms.set_calculator()
for x in np.linspace(0, 2 * pi, nimages, endpoint=False):
self.atoms.set_positions(p + sin(x) * mode)
traj.write(self.atoms)
self.atoms.set_positions(p)
self.atoms.set_calculator(calc)
traj.close()
def write_jmol(self):
"""Writes file for viewing of the modes with jmol."""
fd = open(self.name + '.xyz', 'w')
symbols = self.atoms.get_chemical_symbols()
f = self.get_frequencies()
for n in range(3 * len(self.indices)):
fd.write('%6d\n' % len(self.atoms))
if f[n].imag != 0:
c = 'i'
f[n] = f[n].imag
else:
c = ' '
fd.write('Mode #%d, f = %.1f%s cm^-1' % (n, f[n], c))
if self.ir:
fd.write(', I = %.4f (D/Ã…)^2 amu^-1.\n' % self.intensities[n])
else:
fd.write('.\n')
mode = self.get_mode(n)
for i, pos in enumerate(self.atoms.positions):
fd.write('%2s %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f \n' %
(symbols[i], pos[0], pos[1], pos[2],
mode[i, 0], mode[i, 1], mode[i, 2]))
fd.close()
python-ase-3.6.0.2515/ase/phonons.py 0000644 0001754 0001754 00000066017 11670114554 016024 0 ustar askhl askhl """Module for calculating phonons of periodic systems."""
import sys
import pickle
from math import sin, pi, sqrt
from os import remove
from os.path import isfile
import numpy as np
import numpy.linalg as la
import numpy.fft as fft
has_spglib = False
try:
from pyspglib import spglib
has_spglib = True
except ImportError:
pass
import ase.units as units
from ase.parallel import rank, barrier
from ase.dft import monkhorst_pack
from ase.io.trajectory import PickleTrajectory
class Displacement:
"""Abstract base class for phonon and el-ph supercell calculations.
Both phonons and the electron-phonon interaction in periodic systems can be
calculated with the so-called finite-displacement method where the
derivatives of the total energy and effective potential are obtained from
finite-difference approximations, i.e. by displacing the atoms. This class
provides the required functionality for carrying out the calculations for
the different displacements in its ``run`` member function.
Derived classes must overwrite the ``__call__`` member function which is
called for each atomic displacement.
"""
def __init__(self, atoms, calc=None, supercell=(1, 1, 1), name=None,
delta=0.01, refcell=None):
"""Init with an instance of class ``Atoms`` and a calculator.
Parameters
----------
atoms: Atoms object
The atoms to work on.
calc: Calculator
Calculator for the supercell calculation.
supercell: tuple
Size of supercell given by the number of repetitions (l, m, n) of
the small unit cell in each direction.
name: str
Base name to use for files.
delta: float
Magnitude of displacement in Ang.
refcell: str
Reference cell in which the atoms will be displaced. If ``None``,
corner cell in supercell is used. If ``str``, cell in the center of
the supercell is used.
"""
# Store atoms and calculator
self.atoms = atoms
self.calc = calc
# Displace all atoms in the unit cell by default
self.indices = range(len(atoms))
self.name = name
self.delta = delta
self.N_c = supercell
# Reference cell offset
if refcell is None:
# Corner cell
self.offset = 0
else:
# Center cell
N_c = self.N_c
self.offset = N_c[0] // 2 * (N_c[1] * N_c[2]) + N_c[1] // \
2 * N_c[2] + N_c[2] // 2
def __call__(self, *args, **kwargs):
"""Member function called in the ``run`` function."""
raise NotImplementedError("Implement in derived classes!.")
def set_atoms(self, atoms):
"""Set the atoms to vibrate.
Parameters
----------
atoms: list
Can be either a list of strings, ints or ...
"""
assert isinstance(atoms, list)
assert len(atoms) <= len(self.atoms)
if isinstance(atoms[0], str):
assert np.all([isinstance(atom, str) for atom in atoms])
sym_a = self.atoms.get_chemical_symbols()
# List for atomic indices
indices = []
for type in atoms:
indices.extend([a for a, atom in enumerate(sym_a)
if atom == type])
else:
assert np.all([isinstance(atom, int) for atom in atoms])
indices = atoms
self.indices = indices
def lattice_vectors(self):
"""Return lattice vectors for cells in the supercell."""
# Lattice vectors relevative to the reference cell
R_cN = np.indices(self.N_c).reshape(3, -1)
N_c = np.array(self.N_c)[:, np.newaxis]
if self.offset == 0:
R_cN += N_c // 2
R_cN %= N_c
R_cN -= N_c // 2
return R_cN
def run(self):
"""Run the calculations for the required displacements.
This will do a calculation for 6 displacements per atom, +-x, +-y, and
+-z. Only those calculations that are not already done will be
started. Be aware that an interrupted calculation may produce an empty
file (ending with .pckl), which must be deleted before restarting the
job. Otherwise the calculation for that displacement will not be done.
"""
# Atoms in the supercell -- repeated in the lattice vector directions
# beginning with the last
atoms_N = self.atoms * self.N_c
# Set calculator if provided
assert self.calc is not None, "Provide calculator in __init__ method"
atoms_N.set_calculator(self.calc)
# Do calculation on equilibrium structure
filename = self.name + '.eq.pckl'
if not isfile(filename):
# Wait for all ranks to enter
barrier()
# Create file
if rank == 0:
fd = open(filename, 'w')
fd.close()
# Call derived class implementation of __call__
output = self.__call__(atoms_N)
# Write output to file
if rank == 0:
fd = open(filename, 'w')
pickle.dump(output, fd)
sys.stdout.write('Writing %s\n' % filename)
fd.close()
sys.stdout.flush()
# Positions of atoms to be displaced in the reference cell
natoms = len(self.atoms)
offset = natoms * self.offset
pos = atoms_N.positions[offset: offset + natoms].copy()
# Loop over all displacements
for a in self.indices:
for i in range(3):
for sign in [-1, 1]:
# Filename for atomic displacement
filename = '%s.%d%s%s.pckl' % \
(self.name, a, 'xyz'[i], ' +-'[sign])
# Wait for ranks before checking for file
# barrier()
if isfile(filename):
# Skip if already done
continue
# Wait for ranks
barrier()
if rank == 0:
fd = open(filename, 'w')
fd.close()
# Update atomic positions
atoms_N.positions[offset + a, i] = \
pos[a, i] + sign * self.delta
# Call derived class implementation of __call__
output = self.__call__(atoms_N)
# Write output to file
if rank == 0:
fd = open(filename, 'w')
pickle.dump(output, fd)
sys.stdout.write('Writing %s\n' % filename)
fd.close()
sys.stdout.flush()
# Return to initial positions
atoms_N.positions[offset + a, i] = pos[a, i]
def clean(self):
"""Delete generated pickle files."""
if isfile(self.name + '.eq.pckl'):
remove(self.name + '.eq.pckl')
for a in self.indices:
for i in 'xyz':
for sign in '-+':
name = '%s.%d%s%s.pckl' % (self.name, a, i, sign)
if isfile(name):
remove(name)
class Phonons(Displacement):
"""Class for calculating phonon modes using the finite displacement method.
The matrix of force constants is calculated from the finite difference
approximation to the first-order derivative of the atomic forces as::
2 nbj nbj
nbj d E F- - F+
C = ------------ ~ ------------- ,
mai dR dR 2 * delta
mai nbj
where F+/F- denotes the force in direction j on atom nb when atom ma is
displaced in direction +i/-i. The force constants are related by various
symmetry relations. From the definition of the force constants it must
be symmetric in the three indices mai::
nbj mai bj ai
C = C -> C (R ) = C (-R ) .
mai nbj ai n bj n
As the force constants can only depend on the difference between the m and
n indices, this symmetry is more conveniently expressed as shown on the
right hand-side.
The acoustic sum-rule::
_ _
aj \ bj
C (R ) = - ) C (R )
ai 0 /__ ai m
(m, b)
!=
(0, a)
Ordering of the unit cells illustrated here for a 1-dimensional system (in
case ``refcell=None`` in constructor!):
::
m = 0 m = 1 m = -2 m = -1
-----------------------------------------------------
| | | | |
| * b | * | * | * |
| | | | |
| * a | * | * | * |
| | | | |
-----------------------------------------------------
Example:
>>> from ase.structure import bulk
>>> from ase.phonons import Phonons
>>> from gpaw import GPAW, FermiDirac
>>> atoms = bulk('Si', 'diamond', a=5.4)
>>> calc = GPAW(kpts=(5, 5, 5),
h=0.2,
occupations=FermiDirac(0.))
>>> ph = Phonons(atoms, calc, supercell=(5, 5, 5))
>>> ph.run()
>>> ph.read(method='frederiksen', acoustic=True)
"""
def __init__(self, *args, **kwargs):
"""Initialize with base class args and kwargs."""
if 'name' not in kwargs.keys():
kwargs['name'] = "phonon"
Displacement.__init__(self, *args, **kwargs)
# Attributes for force constants and dynamical matrix in real space
self.C_N = None # in units of eV / Ang**2
self.D_N = None # in units of eV / Ang**2 / amu
# Attributes for born charges and static dielectric tensor
self.Z_avv = None
self.eps_vv = None
def __call__(self, atoms_N):
"""Calculate forces on atoms in supercell."""
# Calculate forces
forces = atoms_N.get_forces()
return forces
def check_eq_forces(self):
"""Check maximum size of forces in the equilibrium structure."""
fname = '%s.eq.pckl' % self.name
feq_av = pickle.load(open(fname))
fmin = feq_av.max()
fmax = feq_av.min()
i_min = np.where(feq_av == fmin)
i_max = np.where(feq_av == fmax)
return fmin, fmax, i_min, i_max
def read_born_charges(self, name=None, neutrality=True):
"""Read Born charges and dieletric tensor from pickle file.
The charge neutrality sum-rule::
_ _
\ a
) Z = 0
/__ ij
a
Parameters
----------
neutrality: bool
Restore charge neutrality condition on calculated Born effective
charges.
"""
# Load file with Born charges and dielectric tensor for atoms in the
# unit cell
if name is None:
filename = '%s.born.pckl' % self.name
else:
filename = name
fd = open(filename)
Z_avv, eps_vv = pickle.load(fd)
fd.close()
# Neutrality sum-rule
if neutrality:
Z_mean = Z_avv.sum(0) / len(Z_avv)
Z_avv -= Z_mean
self.Z_avv = Z_avv[self.indices]
self.eps_vv = eps_vv
def read(self, method='Frederiksen', symmetrize=3, acoustic=True,
cutoff=None, born=False, **kwargs):
"""Read forces from pickle files and calculate force constants.
Extra keyword arguments will be passed to ``read_born_charges``.
Parameters
----------
method: str
Specify method for evaluating the atomic forces.
symmetrize: int
Symmetrize force constants (see doc string at top) when
``symmetrize != 0`` (default: 3). Since restoring the acoustic sum
rule breaks the symmetry, the symmetrization must be repeated a few
times until the changes a insignificant. The integer gives the
number of iterations that will be carried out.
acoustic: bool
Restore the acoustic sum rule on the force constants.
cutoff: None or float
Zero elements in the dynamical matrix between atoms with an
interatomic distance larger than the cutoff.
born: bool
Read in Born effective charge tensor and high-frequency static
dielelctric tensor from file.
"""
method = method.lower()
assert method in ['standard', 'frederiksen']
if cutoff is not None:
cutoff = float(cutoff)
# Read Born effective charges and optical dielectric tensor
if born:
self.read_born_charges(**kwargs)
# Number of atoms
natoms = len(self.indices)
# Number of unit cells
N = np.prod(self.N_c)
# Matrix of force constants as a function of unit cell index in units
# of eV / Ang**2
C_xNav = np.empty((natoms * 3, N, natoms, 3), dtype=float)
# Loop over all atomic displacements and calculate force constants
for i, a in enumerate(self.indices):
for j, v in enumerate('xyz'):
# Atomic forces for a displacement of atom a in direction v
basename = '%s.%d%s' % (self.name, a, v)
fminus_av = pickle.load(open(basename + '-.pckl'))
fplus_av = pickle.load(open(basename + '+.pckl'))
if method == 'frederiksen':
fminus_av[a] -= fminus_av.sum(0)
fplus_av[a] -= fplus_av.sum(0)
# Finite difference derivative
C_av = fminus_av - fplus_av
C_av /= 2 * self.delta
# Slice out included atoms
C_Nav = C_av.reshape((N, len(self.atoms), 3))[:, self.indices]
index = 3*i + j
C_xNav[index] = C_Nav
# Make unitcell index the first and reshape
C_N = C_xNav.swapaxes(0 ,1). reshape((N,) + (3 * natoms, 3 * natoms))
# Cut off before symmetry and acoustic sum rule are imposed
if cutoff is not None:
self.apply_cutoff(C_N, cutoff)
# Symmetrize force constants
if symmetrize:
for i in range(symmetrize):
# Symmetrize
C_N = self.symmetrize(C_N)
# Restore acoustic sum-rule
if acoustic:
self.acoustic(C_N)
else:
break
# Store force constants and dynamical matrix
self.C_N = C_N
self.D_N = C_N.copy()
# Add mass prefactor
m_a = self.atoms.get_masses()
self.m_inv_x = np.repeat(m_a[self.indices]**-0.5, 3)
M_inv = np.outer(self.m_inv_x, self.m_inv_x)
for D in self.D_N:
D *= M_inv
def symmetrize(self, C_N):
"""Symmetrize force constant matrix."""
# Number of atoms
natoms = len(self.indices)
# Number of unit cells
N = np.prod(self.N_c)
# Reshape force constants to (l, m, n) cell indices
C_lmn = C_N.reshape(self.N_c + (3 * natoms, 3 * natoms))
# Shift reference cell to center index
if self.offset == 0:
C_lmn = fft.fftshift(C_lmn, axes=(0, 1, 2)).copy()
# Make force constants symmetric in indices -- in case of an even
# number of unit cells don't include the first
i, j, k = np.asarray(self.N_c) % 2 - 1
C_lmn[i:, j:, k:] *= 0.5
C_lmn[i:, j:, k:] += \
C_lmn[i:, j:, k:][::-1, ::-1, ::-1].transpose(0, 1, 2, 4, 3).copy()
if self.offset == 0:
C_lmn = fft.ifftshift(C_lmn, axes=(0, 1, 2)).copy()
# Change to single unit cell index shape
C_N = C_lmn.reshape((N, 3 * natoms, 3 * natoms))
return C_N
def acoustic(self, C_N):
"""Restore acoustic sumrule on force constants."""
# Number of atoms
natoms = len(self.indices)
# Copy force constants
C_N_temp = C_N.copy()
# Correct atomic diagonals of R_m = (0, 0, 0) matrix
for C in C_N_temp:
for a in range(natoms):
for a_ in range(natoms):
C_N[self.offset, 3*a: 3*a + 3, 3*a: 3*a + 3] -= \
C[3*a: 3*a+3, 3*a_: 3*a_+3]
def apply_cutoff(self, D_N, r_c):
"""Zero elements for interatomic distances larger than the cutoff.
Parameters
----------
D_N: ndarray
Dynamical/force constant matrix.
r_c: float
Cutoff in Angstrom.
"""
# Number of atoms and primitive cells
natoms = len(self.indices)
N = np.prod(self.N_c)
# Lattice vectors
R_cN = self.lattice_vectors()
# Reshape matrix to individual atomic and cartesian dimensions
D_Navav = D_N.reshape((N, natoms, 3, natoms, 3))
# Cell vectors
cell_vc = self.atoms.cell.transpose()
# Atomic positions in reference cell
pos_av = self.atoms.get_positions()
# Zero elements with a distance to atoms in the reference cell
# larger than the cutoff
for n in range(N):
# Lattice vector to cell
R_v = np.dot(cell_vc, R_cN[:, n])
# Atomic positions in cell
posn_av = pos_av + R_v
# Loop over atoms and zero elements
for i, a in enumerate(self.indices):
dist_a = np.sqrt(np.sum((pos_av[a] - posn_av)**2, axis=-1))
# Atoms where the distance is larger than the cufoff
i_a = dist_a > r_c #np.where(dist_a > r_c)
# Zero elements
D_Navav[n, i, :, i_a, :] = 0.0
# print ""
def get_force_constant(self):
"""Return matrix of force constants."""
assert self.C_N is not None
return self.C_N
def band_structure(self, path_kc, modes=False, born=False, verbose=True):
"""Calculate phonon dispersion along a path in the Brillouin zone.
The dynamical matrix at arbitrary q-vectors is obtained by Fourier
transforming the real-space force constants. In case of negative
eigenvalues (squared frequency), the corresponding negative frequency
is returned.
Eigenvalues and modes are in units of eV and Ang/sqrt(amu),
respectively.
Parameters
----------
path_kc: ndarray
List of k-point coordinates (in units of the reciprocal lattice
vectors) specifying the path in the Brillouin zone for which the
dynamical matrix will be calculated.
modes: bool
Returns both frequencies and modes when True.
born: bool
Include non-analytic part given by the Born effective charges and
the static part of the high-frequency dielectric tensor. This
contribution to the force constant accounts for the splitting
between the LO and TO branches for q -> 0.
verbose: bool
Print warnings when imaginary frequncies are detected.
"""
assert self.D_N is not None
if born:
assert self.Z_avv is not None
assert self.eps_vv is not None
# Lattice vectors -- ordered as illustrated in class docstring
R_cN = self.lattice_vectors()
# Dynamical matrix in real-space
D_N = self.D_N
# Lists for frequencies and modes along path
omega_kl = []
u_kl = []
# Reciprocal basis vectors for use in non-analytic contribution
reci_vc = 2 * pi * la.inv(self.atoms.cell)
# Unit cell volume in Bohr^3
vol = abs(la.det(self.atoms.cell)) / units.Bohr**3
for q_c in path_kc:
# Add non-analytic part
if born:
# q-vector in cartesian coordinates
q_v = np.dot(reci_vc, q_c)
# Non-analytic contribution to force constants in atomic units
qdotZ_av = np.dot(q_v, self.Z_avv).ravel()
C_na = 4 * pi * np.outer(qdotZ_av, qdotZ_av) / \
np.dot(q_v, np.dot(self.eps_vv, q_v)) / vol
self.C_na = C_na / units.Bohr**2 * units.Hartree
# Add mass prefactor and convert to eV / (Ang^2 * amu)
M_inv = np.outer(self.m_inv_x, self.m_inv_x)
D_na = C_na * M_inv / units.Bohr**2 * units.Hartree
self.D_na = D_na
D_N = self.D_N + D_na / np.prod(self.N_c)
## if np.prod(self.N_c) == 1:
##
## q_av = np.tile(q_v, len(self.indices))
## q_xx = np.vstack([q_av]*len(self.indices)*3)
## D_m += q_xx
# Evaluate fourier sum
phase_N = np.exp(-2.j * pi * np.dot(q_c, R_cN))
D_q = np.sum(phase_N[:, np.newaxis, np.newaxis] * D_N, axis=0)
if modes:
omega2_l, u_xl = la.eigh(D_q, UPLO='U')
# Sort eigenmodes according to eigenvalues (see below) and
# multiply with mass prefactor
u_lx = (self.m_inv_x[:, np.newaxis] *
u_xl[:, omega2_l.argsort()]).T.copy()
u_kl.append(u_lx.reshape((-1, len(self.indices), 3)))
else:
omega2_l = la.eigvalsh(D_q, UPLO='U')
# Sort eigenvalues in increasing order
omega2_l.sort()
# Use dtype=complex to handle negative eigenvalues
omega_l = np.sqrt(omega2_l.astype(complex))
# Take care of imaginary frequencies
if not np.all(omega2_l >= 0.):
indices = np.where(omega2_l < 0)[0]
if verbose:
print ("WARNING, %i imaginary frequencies at "
"q = (% 5.2f, % 5.2f, % 5.2f) ; (omega_q =% 5.3e*i)"
% (len(indices), q_c[0], q_c[1], q_c[2],
omega_l[indices][0].imag))
omega_l[indices] = -1 * np.sqrt(np.abs(omega2_l[indices].real))
omega_kl.append(omega_l.real)
# Conversion factor: sqrt(eV / Ang^2 / amu) -> eV
s = units._hbar * 1e10 / sqrt(units._e * units._amu)
omega_kl = s * np.asarray(omega_kl)
if modes:
return omega_kl, np.asarray(u_kl)
return omega_kl
def dos(self, kpts=(10, 10, 10), npts=1000, delta=1e-3, indices=None):
"""Calculate phonon dos as a function of energy.
Parameters
----------
qpts: tuple
Shape of Monkhorst-Pack grid for sampling the Brillouin zone.
npts: int
Number of energy points.
delta: float
Broadening of Lorentzian line-shape in eV.
indices: list
If indices is not None, the atomic-partial dos for the specified
atoms will be calculated.
"""
# Monkhorst-Pack grid
kpts_kc = monkhorst_pack(kpts)
N = np.prod(kpts)
# Get frequencies
omega_kl = self.band_structure(kpts_kc)
# Energy axis and dos
omega_e = np.linspace(0., np.amax(omega_kl) + 5e-3, num=npts)
dos_e = np.zeros_like(omega_e)
# Sum up contribution from all q-points and branches
for omega_l in omega_kl:
diff_el = (omega_e[:, np.newaxis] - omega_l[np.newaxis, :])**2
dos_el = 1. / (diff_el + (0.5 * delta)**2)
dos_e += dos_el.sum(axis=1)
dos_e *= 1./(N * pi) * 0.5*delta
return omega_e, dos_e
def write_modes(self, q_c, branches=0, kT=units.kB*300, born=False,
repeat=(1, 1, 1), nimages=30, center=False):
"""Write modes to trajectory file.
Parameters
----------
q_c: ndarray
q-vector of modes.
branches: int or list
Branch index of modes.
kT: float
Temperature in units of eV. Determines the amplitude of the atomic
displacements in the modes.
born: bool
Include non-analytic contribution to the force constants at q -> 0.
repeat: tuple
Repeat atoms (l, m, n) times in the directions of the lattice
vectors. Displacements of atoms in repeated cells carry a Bloch
phase factor given by the q-vector and the cell lattice vector R_m.
nimages: int
Number of images in an oscillation.
center: bool
Center atoms in unit cell if True (default: False).
"""
if isinstance(branches, int):
branch_l = [branches]
else:
branch_l = list(branches)
# Calculate modes
omega_l, u_l = self.band_structure([q_c], modes=True, born=born)
# Repeat atoms
atoms = self.atoms * repeat
# Center
if center:
atoms.center()
# Here ``Na`` refers to a composite unit cell/atom dimension
pos_Nav = atoms.get_positions()
# Total number of unit cells
N = np.prod(repeat)
# Corresponding lattice vectors R_m
R_cN = np.indices(repeat).reshape(3, -1)
# Bloch phase
phase_N = np.exp(2.j * pi * np.dot(q_c, R_cN))
phase_Na = phase_N.repeat(len(self.atoms))
for l in branch_l:
omega = omega_l[0, l]
u_av = u_l[0, l]
# Mean displacement of a classical oscillator at temperature T
u_av *= sqrt(kT) / abs(omega)
mode_av = np.zeros((len(self.atoms), 3), dtype=complex)
# Insert slice with atomic displacements for the included atoms
mode_av[self.indices] = u_av
# Repeat and multiply by Bloch phase factor
mode_Nav = (np.vstack(N * [mode_av]) * phase_Na[:, np.newaxis]).real
traj = PickleTrajectory('%s.mode.%d.traj' % (self.name, l), 'w')
for x in np.linspace(0, 2*pi, nimages, endpoint=False):
atoms.set_positions(pos_Nav + sin(x) * mode_Nav)
traj.write(atoms)
traj.close()
python-ase-3.6.0.2515/ase/old.py 0000644 0001754 0001754 00000015074 11207220276 015106 0 ustar askhl askhl import numpy as np
try:
import Numeric as num
except ImportError:
pass
else:
def npy2num(a, typecode=num.Float):
return num.array(a, typecode)
if num.__version__ <= '23.8':
#def npy2num(a, typecode=num.Float):
# return num.array(a.tolist(), typecode)
def npy2num(a, typecode=num.Float):
b = num.fromstring(a.tostring(), typecode)
b.shape = a.shape
return b
from ase.data import chemical_symbols
class OldASEListOfAtomsWrapper:
def __init__(self, atoms):
self.atoms = atoms
self.constraints = []
def get_positions(self):
return np.array(self.atoms.GetCartesianPositions())
def get_calculator(self):
calc = self.atoms.GetCalculator()
if calc is not None:
return OldASECalculatorWrapper(calc)
def get_potential_energy(self):
return self.atoms.GetPotentialEnergy()
def get_forces(self):
return np.array(self.atoms.GetCartesianForces())
def get_stress(self):
return np.array(self.atoms.GetStress())
def get_atomic_numbers(self):
return np.array(self.atoms.GetAtomicNumbers())
def get_tags(self):
return np.array(self.atoms.GetTags())
def get_momenta(self):
return np.array(self.atoms.GetCartesianMomenta())
def get_masses(self):
return np.array(self.atoms.GetMasses())
def get_initial_magnetic_moments(self):
return np.array(self.atoms.GetMagneticMoments())
def get_magnetic_moments(self):
return None
def get_charges(self):
return np.zeros(len(self))
def has(self, name):
return True
def get_cell(self):
return np.array(self.atoms.GetUnitCell())
def get_pbc(self):
return np.array(self.atoms.GetBoundaryConditions(), bool)
def __len__(self):
return len(self.atoms)
def copy(self):
from ase.atoms import Atoms
return Atoms(positions=self.get_positions(),
numbers=self.get_atomic_numbers(),
tags=self.get_tags(),
momenta=self.get_momenta(),
masses=self.get_masses(),
magmoms=self.get_initial_magnetic_moments(),
charges=self.get_charges(),
cell=self.get_cell(),
pbc=self.get_pbc(),
constraint=None,
calculator=None) # Don't copy the calculator
class OldASECalculatorWrapper:
def __init__(self, calc, atoms=None):
self.calc = calc
if atoms is None:
try:
self.atoms = calc.GetListOfAtoms()
except AttributeError:
self.atoms = None
else:
from ASE import Atom, ListOfAtoms
numbers = atoms.get_atomic_numbers()
positions = atoms.get_positions()
magmoms = atoms.get_initial_magnetic_moments()
self.atoms = ListOfAtoms(
[Atom(Z=numbers[a], position=positions[a], magmom=magmoms[a])
for a in range(len(atoms))],
cell=npy2num(atoms.get_cell()),
periodic=tuple(atoms.get_pbc()))
self.atoms.SetCalculator(calc)
def get_atoms(self):
return OldASEListOfAtomsWrapper(self.atoms)
def get_potential_energy(self, atoms):
self.atoms.SetCartesianPositions(npy2num(atoms.get_positions()))
self.atoms.SetUnitCell(npy2num(atoms.get_cell()), fix=True)
return self.calc.GetPotentialEnergy()
def get_forces(self, atoms):
self.atoms.SetCartesianPositions(npy2num(atoms.get_positions()))
self.atoms.SetUnitCell(npy2num(atoms.get_cell()), fix=True)
return np.array(self.calc.GetCartesianForces())
def get_stress(self, atoms):
self.atoms.SetCartesianPositions(npy2num(atoms.get_positions()))
self.atoms.SetUnitCell(npy2num(atoms.get_cell()), fix=True)
return np.array(self.calc.GetStress())
def get_number_of_bands(self):
return self.calc.GetNumberOfBands()
def get_kpoint_weights(self):
return np.array(self.calc.GetIBZKPointWeights())
def get_number_of_spins(self):
return 1 + int(self.calc.GetSpinPolarized())
def get_eigenvalues(self, kpt=0, spin=0):
return np.array(self.calc.GetEigenvalues(kpt, spin))
def get_fermi_level(self):
return self.calc.GetFermiLevel()
def get_number_of_grid_points(self):
return np.array(self.get_pseudo_wave_function(0, 0, 0).shape)
def get_pseudo_wave_function(self, n=0, k=0, s=0, pad=True):
kpt = self.get_bz_k_points()[k]
state = self.calc.GetElectronicStates().GetState(band=n, spin=s,
kptindex=k)
# Get wf, without bolch phase (Phase = True doesn't do anything!)
wave = state.GetWavefunctionOnGrid(phase=False)
# Add bloch phase if this is not the Gamma point
if np.all(kpt == 0):
return wave
coord = state.GetCoordinates()
phase = coord[0] * kpt[0] + coord[1] * kpt[1] + coord[2] * kpt[2]
return np.array(wave) * np.exp(-2.j * np.pi * phase) # sign! XXX
#return np.array(self.calc.GetWaveFunctionArray(n, k, s)) # No phase!
def get_bz_k_points(self):
return np.array(self.calc.GetBZKPoints())
def get_ibz_k_points(self):
return np.array(self.calc.GetIBZKPoints())
def get_wannier_localization_matrix(self, nbands, dirG, kpoint,
nextkpoint, G_I, spin):
return np.array(self.calc.GetWannierLocalizationMatrix(
G_I=G_I.tolist(), nbands=nbands, dirG=dirG.tolist(),
kpoint=kpoint, nextkpoint=nextkpoint, spin=spin))
def initial_wannier(self, initialwannier, kpointgrid, fixedstates,
edf, spin):
# Use initial guess to determine U and C
init = self.calc.InitialWannier(initialwannier, self.atoms,
npy2num(kpointgrid, num.Int))
states = self.calc.GetElectronicStates()
waves = [[state.GetWaveFunction()
for state in states.GetStatesKPoint(k, spin)]
for k in self.calc.GetIBZKPoints()]
init.SetupMMatrix(waves, self.calc.GetBZKPoints())
c, U = init.GetListOfCoefficientsAndRotationMatrices(
(self.calc.GetNumberOfBands(), fixedstates, edf))
U = np.array(U)
for k in range(len(c)):
c[k] = np.array(c[k])
return c, U
python-ase-3.6.0.2515/ase/examples/ 0000755 0001754 0001754 00000000000 11757245036 015600 5 ustar askhl askhl python-ase-3.6.0.2515/ase/examples/plot-ase-atoms.py 0000644 0001754 0001754 00000002400 11121465775 021012 0 ustar askhl askhl from ase import Atoms, Atom, view
from gpaw import GPAW
logo = """\
H HH HHH
H H H H
HHH H HH
H H H H
H H HH HHH"""
d = 0.8
atoms = Atoms()
for y, line in enumerate(logo.split('\n')):
for x, c in enumerate(line):
if c == 'H':
atoms.append(Atom('H', [d * x, -d * y, 0]))
atoms.center(vacuum=2.0)
view(atoms)
if 0:
calc = GPAW(nbands=30)
atoms.set_calculator(calc)
atoms.get_potential_energy()
calc.write('ase-logo.gpw')
else:
calc = GPAW('ase-logo.gpw', txt=None)
density = calc.get_pseudo_density()
image = density[..., density.shape[2] // 2]
if 1: # scale colors to wiki background / foreground
import numpy as np
background = np.array([[[19., 63., 82.]]]).T / 255 # 1c4e63 blueish
foreground = np.array([[[1., 1., 1.]]]).T # white
image = background + image / image.max() * (foreground - background)
image = image.T
else: # Use a standard color scheme
image = pl.cm.hot(image.T)
import pylab as pl
x, y, z = atoms.cell.diagonal()
pl.figure(1, figsize=(8, 8 * y / x), dpi=80)
pl.axes([0, 0, 1, 1])
pl.imshow(image,
origin='lower',
extent=[0, x, 0, y],
aspect='equal',
interpolation='spline16')
pl.axis('off')
pl.savefig('ase-logo.png', dpi=80)
pl.show()
python-ase-3.6.0.2515/ase/examples/__init__.py 0000644 0001754 0001754 00000000000 11523745043 017671 0 ustar askhl askhl python-ase-3.6.0.2515/ase/examples/COCu111.py 0000644 0001754 0001754 00000003571 11410152653 017160 0 ustar askhl askhl from math import sqrt
from ase import Atoms, Atom
from ase.constraints import FixAtoms
from ase.optimize import QuasiNewton
from ase.io import PickleTrajectory
from ase.neb import NEB
from ase.calculators.emt import EMT
# Distance between Cu atoms on a (111) surface:
a = 3.6
d = a / sqrt(2)
y = d * sqrt(3) / 2
fcc111 = Atoms('Cu',
cell=[(d, 0, 0),
(d / 2, y, 0),
(d / 2, y / 3, -a / sqrt(3))],
pbc=True)
slab = fcc111 * (2, 2, 4)
slab.set_cell([2 * d, 2 * y, 1])
slab.set_pbc((1, 1, 0))
slab.set_calculator(EMT())
Z = slab.get_positions()[:, 2]
indices = [i for i, z in enumerate(Z) if z < Z.mean()]
constraint = FixAtoms(indices=indices)
slab.set_constraint(constraint)
dyn = QuasiNewton(slab)
dyn.run(fmax=0.05)
Z = slab.get_positions()[:, 2]
print Z[0] - Z[1]
print Z[1] - Z[2]
print Z[2] - Z[3]
b = 1.2
h = 2.0
slab += Atom('C', (d, 2 * y / 3, h))
slab += Atom('O', (3 * d / 2, y / 3, h))
traj = PickleTrajectory('initial.traj', 'w', slab)
dyn = QuasiNewton(slab)
dyn.attach(traj.write)
dyn.run(fmax=0.05)
#view(slab)
# Make band:
images = [slab.copy() for i in range(6)]
neb = NEB(images, climb=True)
# Set constraints and calculator:
for image in images:
image.set_calculator(EMT())
image.set_constraint(constraint)
# Displace last image:
images[-1].positions[-1] = (2 * d, 2 * y / 3, h)
traj = PickleTrajectory('final.traj', 'w', images[-1])
dyn = QuasiNewton(images[-1])
dyn.attach(traj.write)
dyn.run(fmax=0.05)
# Interpolate positions between initial and final states:
neb.interpolate()
for image in images:
print image.positions[-1], image.get_potential_energy()
traj = PickleTrajectory('mep.traj', 'w')
#dyn = MDMin(neb, dt=0.4)
#dyn = FIRE(neb, dt=0.4)
dyn = QuasiNewton(neb)
dyn.attach(neb.writer(traj))
dyn.run(fmax=0.05)
for image in images:
print image.positions[-1], image.get_potential_energy()
python-ase-3.6.0.2515/ase/examples/Pt_island.py 0000644 0001754 0001754 00000004240 11410150314 020043 0 ustar askhl askhl import numpy as np
from math import sqrt
from ase import Atom, Atoms
from ase.optimize import QuasiNewton, FIRE
from ase.constraints import FixAtoms
from ase.neb import NEB
from ase.io import write, PickleTrajectory
from ase.calculators.emt import ASAP
# Distance between Cu atoms on a (100) surface:
d = 2.74
h1 = d * sqrt(3) / 2
h2 = d * sqrt(2.0 / 3)
initial = Atoms(symbols='Pt',
positions=[(0, 0, 0)],#(1.37,0.79,2.24),(2.74,1.58,4.48),(0,0,6.72),(1.37,0.79,8.96),(2.74,1.58,11.2)],
cell=([(d,0,0),(d/2,h1,0),(d/2,h1/3,-h2)]),
pbc=(True, True, True))
initial *= (7, 8, 6) # 5x5 (100) surface-cell
cell = initial.get_cell()
cell[2] = (0, 0, 22)
initial.set_cell(cell)
#initial.set_pbc((True,True,False))
# Approximate height of Ag atom on Cu(100) surfece:
h0 = 2.2373
initial += Atom('Pt', (10.96, 11.074, h0))
initial += Atom('Pt', (13.7, 11.074, h0))
initial += Atom('Pt', (9.59, 8.701, h0))
initial += Atom('Pt', (12.33, 8.701, h0))
initial += Atom('Pt', (15.07, 8.701, h0))
initial += Atom('Pt', (10.96, 6.328, h0))
initial += Atom('Pt', (13.7, 6.328, h0))
if 0:
view(initial)
# Make band:
images = [initial.copy() for i in range(7)]
neb = NEB(images)
# Set constraints and calculator:
indices = np.compress(initial.positions[:, 2] < -5.0, range(len(initial)))
constraint = FixAtoms(indices)
for image in images:
image.set_calculator(ASAP())
image.constraints.append(constraint)
# Displace last image:
for i in xrange(1,8,1):
images[-1].positions[-i] += (d/2, -h1/3, 0)
write('initial.traj', images[0])
# Relax height of Ag atom for initial and final states:
for image in [images[0], images[-1]]:
QuasiNewton(image).run(fmax=0.01)
if 0:
write('initial.pckl', image[0])
write('finial.pckl', image[-1])
# Interpolate positions between initial and final states:
neb.interpolate()
for image in images:
print image.positions[-1], image.get_potential_energy()
traj = PickleTrajectory('mep.traj', 'w')
dyn = FIRE(neb, dt=0.1)
#dyn = MDMin(neb, dt=0.1)
#dyn = QuasiNewton(neb)
dyn.attach(neb.writer(traj))
dyn.run(fmax=0.01,steps=150)
for image in images:
print image.positions[-1], image.get_potential_energy()
python-ase-3.6.0.2515/ase/examples/Al100.py 0000644 0001754 0001754 00000000360 11410162316 016707 0 ustar askhl askhl from ase import Atom, Atoms
from gpaw import GPAW
a = 4.0
b = a / 2**.5
L = 7.0
al = Atoms([Atom('Al')], cell=(b, b, L), pbc=True)
calc = GPAW(kpts=(4, 4, 1))
al.set_calculator(calc)
al.get_potential_energy()
calc.write('Al100.gpw', 'all')
python-ase-3.6.0.2515/ase/examples/stm.py 0000644 0001754 0001754 00000000325 11410162316 016736 0 ustar askhl askhl from ase import Atoms
from ase.dft import STM
from gpaw import GPAW
calc = GPAW('Al100.gpw')
a0 = calc.get_atoms()
stm = STM(calc, [0, 1, 2])
c = stm.get_averaged_current(2.5)
h = stm.scan(c)
print h[8]-h[:, 8]
python-ase-3.6.0.2515/ase/examples/neb1.py 0000644 0001754 0001754 00000002502 10741426561 016772 0 ustar askhl askhl from ase import *
from math import sqrt
a = 4.0614
b = a / sqrt(2)
h = b / 2
initial = Atoms([Atom('Al', (0, 0, 0)),
Atom('Al', (a / 2, b / 2, -h))],
pbc=(1, 1, 0),
cell=(a, b, 2 * h))
initial *= (2, 2, 2)
initial.append(Atom('Al', (a / 2, b / 2, 3 * h)))
#view(initial)
#initial.set_cell((2*2,2*b,)
final = initial.copy()
final.positions[-1, 1] += b
# Construct a list of images:
images = [initial]
for i in range(5):
images.append(initial.copy())
images.append(final)
# Make a mask of zeros and ones that select the dynamic atoms (the
# three topmost layers):
mask = initial.positions[:, 2] < 0.5 * h
constraint = FixAtoms(mask=mask)
print mask
print 'Fixed atoms:', constraint.fixed
for image in images:
# Let all images use an EMT calculator:
image.set_calculator(EMT())
image.set_constraint(constraint)
# Relax the initial and final states:
QuasiNewton(initial).run(fmax=0.05)
QuasiNewton(final).run(fmax=0.05)
# Create a Nudged Elastic Band:
neb = NEB(images)
# Mak a starting guess for the minimum energy path (a straight line
# from the initial to the final state):
neb.interpolate()
# Use MDMin to relax the path:
minimizer = QuasiNewton(neb)
minimizer.run(fmax=0.05)
# Write the path to a trajectory:
traj = PickleTrajectory('jump1.traj', 'w')
neb.write(traj)
python-ase-3.6.0.2515/ase/all.py 0000644 0001754 0001754 00000002555 11632077176 015113 0 ustar askhl askhl """This module imports many important modules at once."""
from ase.atom import Atom
from ase.atoms import Atoms
from ase.units import *
from ase.io import read, write
from ase.io.trajectory import PickleTrajectory
from ase.dft import STM, monkhorst_pack, DOS
from ase.optimize.mdmin import MDMin
from ase.optimize.lbfgs import HessLBFGS
from ase.optimize.fire import FIRE
from ase.optimize.lbfgs import LBFGS, LBFGSLineSearch
from ase.optimize.bfgs import BFGS
from ase.optimize import QuasiNewton
from ase.md.verlet import VelocityVerlet
from ase.md.langevin import Langevin
from ase.constraints import *
from ase.calculators.lj import LennardJones
from ase.calculators.emt import EMT
from ase.calculators.siesta import Siesta
from ase.calculators.dacapo import Dacapo
from ase.calculators.vasp import Vasp
from ase.calculators.aims import Aims, AimsCube
from ase.calculators.turbomole import Turbomole
from ase.calculators.dftb import Dftb
from ase.neb import NEB, SingleCalculatorNEB
from ase.dimer import DimerControl, DimerAtoms, DimerTranslate, \
MinModeAtoms, MinModeTranslate
from ase.visualize import view
from ase.data import chemical_symbols, atomic_numbers, atomic_names, \
atomic_masses, covalent_radii, reference_states
from ase.data.molecules import molecule
from ase.structure import *
#from ase.lattice import bulk
from math import pi, sqrt
import numpy as np
python-ase-3.6.0.2515/ase/structure.py 0000644 0001754 0001754 00000032453 11650327031 016367 0 ustar askhl askhl """Atomic structure.
This mudule contains helper functions for setting up nanotubes and
graphene nanoribbons."""
import warnings
from math import sqrt
import numpy as np
from ase.atoms import Atoms, string2symbols
from ase.data import covalent_radii
from ase.utils import gcd
def nanotube(n, m, length=1, bond=1.42, symbol='C', verbose=False):
if n < m:
m, n = n, m
sign = -1
else:
sign = 1
nk = 6000
sq3 = sqrt(3.0)
a = sq3 * bond
l2 = n * n + m * m + n * m
l = sqrt(l2)
dt = a * l / np.pi
nd = gcd(n ,m)
if (n - m) % (3 * nd ) == 0:
ndr = 3 * nd
else:
ndr = nd
nr = (2 * m + n) / ndr
ns = -(2 * n + m) / ndr
nt2 = 3 * l2 / ndr / ndr
nt = np.floor(sqrt(nt2))
nn = 2 * l2 / ndr
ichk = 0
if nr == 0:
n60 = 1
else:
n60 = nr * 4
absn = abs(n60)
nnp = []
nnq = []
for i in range(-absn, absn + 1):
for j in range(-absn, absn + 1):
j2 = nr * j - ns * i
if j2 == 1:
j1 = m * i - n * j
if j1 > 0 and j1 < nn:
ichk += 1
nnp.append(i)
nnq.append(j)
if ichk == 0:
raise RuntimeError('not found p, q strange!!')
if ichk >= 2:
raise RuntimeError('more than 1 pair p, q strange!!')
nnnp = nnp[0]
nnnq = nnq[0]
if verbose:
print 'the symmetry vector is', nnnp, nnnq
lp = nnnp * nnnp + nnnq * nnnq + nnnp * nnnq
r = a * sqrt(lp)
c = a * l
t = sq3 * c / ndr
if 2 * nn > nk:
raise RuntimeError('parameter nk is too small!')
rs = c / (2.0 * np.pi)
if verbose:
print 'radius=', rs, t
q1 = np.arctan((sq3 * m) / (2 * n + m))
q2 = np.arctan((sq3 * nnnq) / (2 * nnnp + nnnq))
q3 = q1 - q2
q4 = 2.0 * np.pi / nn
q5 = bond * np.cos((np.pi / 6.0) - q1) / c * 2.0 * np.pi
h1 = abs(t) / abs(np.sin(q3))
h2 = bond * np.sin((np.pi / 6.0) - q1)
ii = 0
x, y, z = [], [], []
for i in range(nn):
x1, y1, z1 = 0, 0, 0
k = np.floor(i * abs(r) / h1)
x1 = rs * np.cos(i * q4)
y1 = rs * np.sin(i * q4)
z1 = (i * abs(r) - k * h1) * np.sin(q3)
kk2 = abs(np.floor((z1 + 0.0001) / t))
if z1 >= t - 0.0001:
z1 -= t * kk2
elif z1 < 0:
z1 += t * kk2
ii += 1
x.append(x1)
y.append(y1)
z.append(z1)
z3 = (i * abs(r) - k * h1) * np.sin(q3) - h2
ii += 1
if z3 >= 0 and z3 < t:
x2 = rs * np.cos(i * q4 + q5)
y2 = rs * np.sin(i * q4 + q5)
z2 = (i * abs(r) - k * h1) * np.sin(q3) - h2
x.append(x2)
y.append(y2)
z.append(z2)
else:
x2 = rs * np.cos(i * q4 + q5)
y2 = rs * np.sin(i * q4 + q5)
z2 = (i * abs(r) - (k + 1) * h1) * np.sin(q3) - h2
kk = abs(np.floor(z2 / t))
if z2 >= t - 0.0001:
z2 -= t * kk
elif z2 < 0:
z2 += t * kk
x.append(x2)
y.append(y2)
z.append(z2)
ntotal = 2 * nn
X = []
for i in range(ntotal):
X.append([x[i], y[i], sign * z[i]])
if length > 1:
xx = X[:]
for mnp in range(2, length + 1):
for i in range(len(xx)):
X.append(xx[i][:2] + [xx[i][2] + (mnp - 1) * t])
TransVec = t
NumAtom = ntotal * length
Diameter = rs * 2
ChiralAngle = np.arctan((sq3 * n) / (2 * m + n)) / (np.pi * 180)
cell = [Diameter * 2, Diameter * 2, length * t]
atoms = Atoms(symbol + str(NumAtom), positions=X, cell=cell,
pbc=[False, False, True])
atoms.center()
if verbose:
print 'translation vector =', TransVec
print 'diameter = ', Diameter
print 'chiral angle = ', ChiralAngle
return atoms
def graphene_nanoribbon(n, m, type='zigzag', saturated=False, C_H=1.09,
C_C=1.42, vacuum=2.5, magnetic=None, initial_mag=1.12,
sheet=False, main_element='C', saturate_element='H',
vacc=None):
"""Create a graphene nanoribbon.
Creates a graphene nanoribbon in the x-z plane, with the nanoribbon
running along the z axis.
Parameters:
n: The width of the nanoribbon
m: The length of the nanoribbon.
type ('zigzag'): The orientation of the ribbon. Must be either 'zigzag'
or 'armchair'.
saturated (Falsi): If true, hydrogen atoms are placed along the edge.
C_H: Carbon-hydrogen bond length. Default: 1.09 Angstrom
C_C: Carbon-carbon bond length. Default: 1.42 Angstrom.
vacuum: Amount of vacuum added to both sides. Default 2.5 Angstrom.
magnetic: Make the edges magnetic.
initial_mag: Magnitude of magnetic moment if magnetic=True.
sheet: If true, make an infinite sheet instead of a ribbon.
"""
#This function creates the coordinates for a graphene nanoribbon,
#n is width, m is length
if vacc is not None:
warnings.warn('Use vacuum=%f' % (0.5 * vacc))
vacuum = 0.5 * vacc
assert vacuum > 0
b = sqrt(3) * C_C / 4
arm_unit = Atoms(main_element+'4', pbc=(1,0,1),
cell = [4 * b, 2 * vacuum, 3 * C_C])
arm_unit.positions = [[0, 0, 0],
[b * 2, 0, C_C / 2.],
[b * 2, 0, 3 * C_C / 2.],
[0, 0, 2 * C_C]]
zz_unit = Atoms(main_element+'2', pbc=(1,0,1),
cell = [3 * C_C /2., 2 * vacuum, b * 4])
zz_unit.positions = [[0, 0, 0],
[C_C / 2., 0, b * 2]]
atoms = Atoms()
tol = 1e-4
if sheet:
vacuum2 = 0.0
else:
vacuum2 = vacuum
if type == 'zigzag':
edge_index0 = np.arange(m) * 2 + 1
edge_index1 = (n - 1) * m * 2 + np.arange(m) * 2
if magnetic:
mms = np.zeros(m * n * 2)
for i in edge_index0:
mms[i] = initial_mag
for i in edge_index1:
mms[i] = -initial_mag
for i in range(n):
layer = zz_unit.repeat((1, 1, m))
layer.positions[:, 0] -= 3 * C_C / 2 * i
if i % 2 == 1:
layer.positions[:, 2] += 2 * b
layer[-1].position[2] -= b * 4 * m
atoms += layer
if magnetic:
atoms.set_initial_magnetic_moments(mms)
if saturated:
H_atoms0 = Atoms(saturate_element + str(m))
H_atoms0.positions = atoms[edge_index0].positions
H_atoms0.positions[:, 0] += C_H
H_atoms1 = Atoms(saturate_element + str(m))
H_atoms1.positions = atoms[edge_index1].positions
H_atoms1.positions[:, 0] -= C_H
atoms += H_atoms0 + H_atoms1
atoms.cell = [n * 3 * C_C / 2 + 2 * vacuum2, 2 * vacuum, m * 4 * b]
elif type == 'armchair':
for i in range(n):
layer = arm_unit.repeat((1, 1, m))
layer.positions[:, 0] -= 4 * b * i
atoms += layer
atoms.cell = [b * 4 * n + 2 * vacuum2, 2 * vacuum, 3 * C_C * m]
atoms.center()
atoms.set_pbc([sheet, False, True])
return atoms
def molecule(name, data=None, **kwargs):
"""Create formula base on data. If data is None assume G2 set.
kwargs currently not used. """
if data is None:
from ase.data.g2 import data
if name not in data.keys():
raise NotImplementedError('%s not in data.' % (name))
args = data[name].copy()
# accept only the following Atoms constructor arguments
# XXX: should we accept all Atoms arguments?
for k in args.keys():
if k not in [
'symbols', 'positions', 'numbers',
'tags', 'masses',
'magmoms', 'charges',
'info',
]:
args.pop(k)
# kwargs overwrites data
args.update(kwargs)
return Atoms(**args)
def bulk(name, crystalstructure, a=None, c=None, covera=None,
orthorhombic=False, cubic=False):
"""Helper function for creating bulk systems.
name: str
Chemical symbol or symbols as in 'MgO' or 'NaCl'.
crystalstructure: str
Must be one of sc, fcc, bcc, hcp, diamond, zincblende or
rocksalt.
a: float
Lattice constant.
c: float
Lattice constant.
covera: float
c/a raitio used for hcp. Defaults to ideal ratio.
orthorhombic: bool
Construct orthorhombic unit cell instead of primitive cell
which is the default.
cubic: bool
Construct cubic unit cell.
"""
#warnings.warn('This function is deprecated. Use the ' +
# 'ase.lattice.bulk.bulk() function instead.')
if a is not None:
a = float(a)
if c is not None:
c = float(c)
if covera is not None and c is not None:
raise ValueError("Don't specify both c and c/a!")
if covera is None and c is None:
covera = sqrt(8.0 / 3.0)
if a is None:
a = estimate_lattice_constant(name, crystalstructure, covera)
if covera is None and c is not None:
covera = c / a
x = crystalstructure.lower()
if orthorhombic and x != 'sc':
return _orthorhombic_bulk(name, x, a, covera)
if cubic and x == 'bcc':
return _orthorhombic_bulk(name, x, a, covera)
if cubic and x != 'sc':
return _cubic_bulk(name, x, a)
if x == 'sc':
atoms = Atoms(name, cell=(a, a, a), pbc=True)
elif x == 'fcc':
b = a / 2
atoms = Atoms(name, cell=[(0, b, b), (b, 0, b), (b, b, 0)], pbc=True)
elif x == 'bcc':
b = a / 2
atoms = Atoms(name, cell=[(-b, b, b), (b, -b, b), (b, b, -b)],
pbc=True)
elif x == 'hcp':
atoms = Atoms(2 * name,
scaled_positions=[(0, 0, 0),
(1.0 / 3.0, 1.0 / 3.0, 0.5)],
cell=[(a, 0, 0),
(a / 2, a * sqrt(3) / 2, 0),
(0, 0, covera * a)],
pbc=True)
elif x == 'diamond':
atoms = bulk(2 * name, 'zincblende', a)
elif x == 'zincblende':
s1, s2 = string2symbols(name)
atoms = bulk(s1, 'fcc', a) + bulk(s2, 'fcc', a)
atoms.positions[1] += a / 4
elif x == 'rocksalt':
s1, s2 = string2symbols(name)
atoms = bulk(s1, 'fcc', a) + bulk(s2, 'fcc', a)
atoms.positions[1, 0] += a / 2
else:
raise ValueError('Unknown crystal structure: ' + crystalstructure)
return atoms
def estimate_lattice_constant(name, crystalstructure, covera):
atoms = bulk(name, crystalstructure, 1.0, covera)
v0 = atoms.get_volume()
v = 0.0
for Z in atoms.get_atomic_numbers():
r = covalent_radii[Z]
v += 4 * np.pi / 3 * r**3 * 1.5
return (v / v0)**(1.0 / 3)
def _orthorhombic_bulk(name, x, a, covera=None):
if x == 'fcc':
b = a / sqrt(2)
atoms = Atoms(2 * name, cell=(b, b, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)])
elif x == 'bcc':
atoms = Atoms(2 * name, cell=(a, a, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)])
elif x == 'hcp':
atoms = Atoms(4 * name,
cell=(a, a * sqrt(3), covera * a),
scaled_positions=[(0, 0, 0),
(0.5, 0.5, 0),
(0.5, 1.0 / 6.0, 0.5),
(0, 2.0 / 3.0, 0.5)],
pbc=True)
elif x == 'diamond':
atoms = _orthorhombic_bulk(2 * name, 'zincblende', a)
elif x == 'zincblende':
s1, s2 = string2symbols(name)
b = a / sqrt(2)
atoms = Atoms(2 * name, cell=(b, b, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.5, 0, 0.25),
(0.5, 0.5, 0.5), (0, 0.5, 0.75)])
elif x == 'rocksalt':
s1, s2 = string2symbols(name)
b = a / sqrt(2)
atoms = Atoms(2 * name, cell=(b, b, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.5, 0.5, 0),
(0.5, 0.5, 0.5), (0, 0, 0.5)])
else:
raise RuntimeError
return atoms
def _cubic_bulk(name, x, a):
if x == 'fcc':
atoms = Atoms(4 * name, cell=(a, a, a), pbc=True,
scaled_positions=[(0, 0, 0), (0, 0.5, 0.5),
(0.5, 0, 0.5), (0.5, 0.5, 0)])
elif x == 'diamond':
atoms = _cubic_bulk(2 * name, 'zincblende', a)
elif x == 'zincblende':
atoms = Atoms(4 * name, cell=(a, a, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.25, 0.25, 0.25),
(0, 0.5, 0.5), (0.25, 0.75, 0.75),
(0.5, 0, 0.5), (0.75, 0.25, 0.75),
(0.5, 0.5, 0), (0.75, 0.75, 0.25)])
elif x == 'rocksalt':
atoms = Atoms(4 * name, cell=(a, a, a), pbc=True,
scaled_positions=[(0, 0, 0), (0.5, 0, 0),
(0, 0.5, 0.5), (0.5, 0.5, 0.5),
(0.5, 0, 0.5), (0, 0, 0.5),
(0.5, 0.5, 0), (0, 0.5, 0)])
else:
raise RuntimeError
return atoms
python-ase-3.6.0.2515/ase/parallel.py 0000644 0001754 0001754 00000006727 11717212003 016124 0 ustar askhl askhl import sys
import time
import atexit
import numpy as np
def paropen(name, mode='r', buffering=0):
"""MPI-safe version of open function.
In read mode, the file is opened on all nodes. In write and
append mode, the file is opened on the master only, and /dev/null
is opened on all other nodes.
"""
if rank > 0 and mode[0] != 'r':
name = '/dev/null'
return open(name, mode, buffering)
def parprint(*args, **kwargs):
"""MPI-safe print - prints only from master.
Tries to adopt python 3 behaviour.
"""
if rank > 0:
return
defaults = {'end': '\n',
'file': sys.stdout }
for key in defaults:
if not key in kwargs:
kwargs[key] = defaults[key]
for arg in args[:-1]:
print >> kwargs['file'], arg,
if len(args):
last = args[-1]
else:
last = ''
if kwargs['end'] == '\n':
print >> kwargs['file'], last
else:
print >> kwargs['file'], last,
class DummyMPI:
rank = 0
size = 1
def sum(self, a):
if isinstance(a, np.ndarray) and a.ndim > 0:
pass
else:
return a
def barrier(self):
pass
def broadcast(self, a, rank):
pass
class MPI4PY:
def __init__(self):
from mpi4py import MPI
self.comm = MPI.COMM_WORLD
self.rank = self.comm.rank
self.size = self.comm.size
def sum(self, a):
return self.comm.allreduce(a)
def barrier(self):
self.comm.barrier()
def broadcast(self, a, rank):
a[:] = self.comm.bcast(a, rank)
# Check for special MPI-enabled Python interpreters:
if '_gpaw' in sys.modules:
# http://wiki.fysik.dtu.dk/gpaw
from gpaw.mpi import world
elif 'asapparallel3' in sys.modules:
# http://wiki.fysik.dtu.dk/Asap
# We cannot import asap3.mpi here, as that creates an import deadlock
#from asap3.mpi import world
import asapparallel3
world = asapparallel3.Communicator()
elif 'Scientific_mpi' in sys.modules:
from Scientific.MPI import world
elif 'mpi4py' in sys.modules:
world = MPI4PY()
else:
# This is a standard Python interpreter:
world = DummyMPI()
rank = world.rank
size = world.size
barrier = world.barrier
def register_parallel_cleanup_function():
"""Call MPI_Abort if python crashes.
This will terminate the processes on the other nodes."""
if size == 1:
return
def cleanup(sys=sys, time=time, world=world):
error = getattr(sys, 'last_type', None)
if error:
sys.stdout.flush()
sys.stderr.write(('ASE CLEANUP (node %d): %s occurred. ' +
'Calling MPI_Abort!\n') % (world.rank, error))
sys.stderr.flush()
# Give other nodes a moment to crash by themselves (perhaps
# producing helpful error messages):
time.sleep(3)
world.abort(42)
atexit.register(cleanup)
def distribute_cpus(parsize_calculator, comm):
"""Distribute cpus to tasks and calculators"""
assert parsize_calculator <= comm.size
assert comm.size % parsize_calculator == 0
tasks_rank = comm.rank // parsize_calculator
r0 = tasks_rank * parsize_calculator
ranks = np.arange(r0, r0 + parsize_calculator)
calc_comm = comm.new_communicator(ranks)
# print 'comm.rank, ranks=', comm.rank, ranks
tasks_comm = np.arange(0, comm.size, parsize_calculator)
return calc_comm, tasks_comm, tasks_rank
python-ase-3.6.0.2515/ase/cluster/ 0000755 0001754 0001754 00000000000 11757245034 015441 5 ustar askhl askhl python-ase-3.6.0.2515/ase/cluster/__init__.py 0000644 0001754 0001754 00000000672 11701263043 017544 0 ustar askhl askhl "Module for creating clusters."
from ase.cluster.cluster import Cluster
from ase.cluster.wulff import wulff_construction
from ase.cluster.cubic import SimpleCubic, BodyCenteredCubic,\
FaceCenteredCubic
from ase.cluster.octahedron import Octahedron
from ase.cluster.hexagonal import Hexagonal, HexagonalClosedPacked
from ase.cluster.icosahedron import Icosahedron
from ase.cluster.decahedron import Decahedron
python-ase-3.6.0.2515/ase/cluster/wulff.py 0000644 0001754 0001754 00000016311 11531736072 017135 0 ustar askhl askhl import numpy as np
import ase.cluster
from ase.cluster.cubic import FaceCenteredCubic
from ase.data import atomic_numbers, reference_states
delta = 1e-10
_debug = None
def wulff_construction(symbol, surfaces, energies, size, structure,
rounding="closest", latticeconstant=None, debug=0):
"""Create a cluster using the Wulff construction.
A cluster is created with approximately the number of atoms
specified, following the Wulff construction, i.e. minimizing the
surface energy of the cluster.
Parameters:
-----------
symbol: The chemical symbol (or atomic number) of the desired element.
surfaces: A list of surfaces.
energies: A list of surface energies for the surfaces.
size: The desired number of atoms.
structure: The desired crystal structure. Either one of the strings
"fcc", "bcc", "sc", "hcp", "graphite"; or one of the cluster factory
objects from the ase.cluster.XXX modules.
rounding (optional): Specifies what should be done if no Wulff
construction corresponds to exactly the requested number of atoms.
Should be a string, either "above", "below" or "closest" (the
default), meaning that the nearest cluster above or below - or the
closest one - is created instead.
latticeconstant (optional): The lattice constant. If not given,
extracted from ase.data.
debug (optional): If non-zero, information about the iteration towards
the right cluster size is printed.
"""
global _debug
_debug = debug
if debug:
print "Wulff: Aiming for cluster with %i atoms (%s)" % (size, rounding)
if rounding not in ["above", "below", "closest"]:
raise ValueError("Invalid rounding: "+rounding)
# Interpret symbol
if isinstance(symbol, str):
atomic_number = atomic_numbers[symbol]
else:
atomic_number = symbol
# Interpret structure, if it is a string.
if isinstance(structure, str):
if structure == 'fcc':
from ase.cluster.cubic import FaceCenteredCubic as structure
elif structure == 'bcc':
from ase.cluster.cubic import BodyCenteredCubic as structure
elif structure == 'sc':
from ase.cluster.cubic import SimpleCubic as structure
elif structure == 'hcp':
from ase.cluster.hexagonal import HexagonalClosedPacked as structure
elif structure == 'graphite':
from ase.cluster.hexagonal import Graphite as structure
else:
raise NotImplementedError("Crystal structure "+structure+
" is not supported.")
# Check number of surfaces
nsurf = len(surfaces)
if len(energies) != nsurf:
raise ValueError("The energies array should contain %d values."
% (nsurf,))
# We should check that for each direction, the surface energy plus
# the energy in the opposite direction is positive. But this is
# very difficult in the general case!
# Before starting, make a fake cluster just to extract the
# interlayer distances in the relevant directions, and use these
# to "renormalize" the surface energies such that they can be used
# to convert to number of layers instead of to distances.
atoms = structure(symbol, surfaces, 5*np.ones(len(surfaces), int),
latticeconstant=latticeconstant)
for i, s in enumerate(surfaces):
d = atoms.get_layer_distance(s)
energies[i] /= d
# First guess a size that is not too large.
wanted_size = size**(1.0/3.0)
max_e = max(energies)
factor = wanted_size / max_e
#layers = np.array([int(round(factor * e)) for e in energies])
atoms, layers = make_atoms(symbol, surfaces, energies, factor, structure,
latticeconstant)
if len(atoms) == 0:
# Probably the cluster is very flat
if debug:
print "First try made an empty cluster, trying again."
factor = 1 / energies_sum.min()
atoms, layers = make_atoms(symbol, surfaces, energies, factor,
structure, latticeconstant)
if len(atoms) == 0:
raise RuntimeError("Failed to create a finite cluster.")
# Second guess: scale to get closer.
old_factor = factor
old_layers = layers
old_atoms = atoms
factor *= (size / len(atoms))**(1.0/3.0)
atoms, layers = make_atoms(symbol, surfaces, energies, factor,
structure, latticeconstant)
if len(atoms) == 0:
print "Second guess gave an empty cluster, discarding it."
atoms = old_atoms
factor = old_factor
layers = old_layers
else:
del old_atoms
# Find if the cluster is too small or too large (both means perfect!)
below = above = None
if len(atoms) <= size:
below = atoms
if len(atoms) >= size:
above = atoms
# Now iterate towards the right cluster
iter = 0
while (below is None or above is None):
if len(atoms) < size:
# Find a larger cluster
if debug:
print "Making a larger cluster."
factor = ((layers + 0.5 + delta) / energies).min()
atoms, new_layers = make_atoms(symbol, surfaces, energies, factor,
structure, latticeconstant)
assert (new_layers - layers).max() == 1
assert (new_layers - layers).min() >= 0
layers = new_layers
else:
# Find a smaller cluster
if debug:
print "Making a smaller cluster."
factor = ((layers - 0.5 - delta) / energies).max()
atoms, new_layers = make_atoms(symbol, surfaces, energies, factor,
structure, latticeconstant)
assert (new_layers - layers).max() <= 0
assert (new_layers - layers).min() == -1
layers = new_layers
if len(atoms) <= size:
below = atoms
if len(atoms) >= size:
above = atoms
iter += 1
if iter == 100:
raise RuntimeError("Runaway iteration.")
if rounding == "below":
if debug:
print "Choosing smaller cluster with %i atoms" % (len(below),)
return below
elif rounding == "above":
if debug:
print "Choosing larger cluster with %i atoms" % (len(above),)
return above
else:
assert rounding == "closest"
if (len(above) - size) < (size - len(below)):
atoms = above
else:
atoms = below
if debug:
print "Choosing closest cluster with %i atoms" % (len(atoms),)
return atoms
def make_atoms(symbol, surfaces, energies, factor, structure, latticeconstant):
layers1 = factor * np.array(energies)
layers = np.round(layers1).astype(int)
#layers = np.array([int(round(factor * e)) for e in energies])
atoms = structure(symbol, surfaces, layers,
latticeconstant=latticeconstant)
if _debug:
print "Created a cluster with %i atoms: %s" % (len(atoms),
str(layers))
#print layers1
return (atoms, layers)
python-ase-3.6.0.2515/ase/cluster/compounds.py 0000644 0001754 0001754 00000000745 11627645303 020027 0 ustar askhl askhl import numpy as np
from ase.cluster.cubic import SimpleCubicFactory
# The L1_2 structure is "based on FCC", but is really simple cubic
# with a basis.
class AuCu3Factory(SimpleCubicFactory):
"A factory for creating AuCu3 (L1_2) lattices."
atomic_basis = np.array([[0., 0., 0.],
[0., .5, .5],
[.5, 0., .5],
[.5, .5, 0.]])
element_basis = [0, 1, 1, 1]
AuCu3 = L1_2 = AuCu3Factory()
python-ase-3.6.0.2515/ase/cluster/decahedron.py 0000644 0001754 0001754 00000006722 11536365721 020117 0 ustar askhl askhl import numpy as np
from ase import Atoms
from ase.data import atomic_numbers, reference_states
def Decahedron(symbol, p, q, r, latticeconstant=None):
"""
Returns a cluster in the decahedra class.
Prameters
---------
symbol: Chemical symbol (or atomic number) of the element.
p: Number of atoms on the (100) facets perpendicular to the five
fold axis.
q: Number of atoms on the (100) facets parallel to the five fold
axis. q = 1 corresponds to no visible (100) facets.
r: Depth of the Marks re-entrence at the pentagon corners. r = 0
corresponds to no re-entrence.
latticeconstant (optional): The lattice constant. If not given,
then it is extracted form ase.data.
"""
# Interpret symbol
if isinstance(symbol, str):
atomic_number = atomic_numbers[symbol]
else:
atomic_number = symbol
# Interpret lattice constant
if latticeconstant is None:
if reference_states[atomic_number]['symmetry'] in ['fcc', 'bcc', 'sc']:
lattice_constant = reference_states[atomic_number]['a']
else:
raise NotImplementedError(("Cannot guess lattice constant of a %s element." %
(reference_states[atomic_number]['symmetry'],)))
else:
if isinstance(latticeconstant, (int, float)):
lattice_constant = latticeconstant
else:
raise ValueError("Lattice constant must be of type int or float.")
# Check values of p, q, r
if p < 1 or q < 1:
raise ValueError("p and q must be greater than 0.")
if r < 0:
raise ValueError("r must be greater than or equal to 0.")
# Defining constants
t = 2.0*np.pi/5.0
b = lattice_constant/np.sqrt(2.0)
a = b*np.sqrt(3.0)/2.0
verticies = a * np.array([[np.cos(np.pi/2.), np.sin(np.pi/2.), 0.],
[np.cos(t*1. + np.pi/2.), np.sin(t*1. + np.pi/2.), 0.],
[np.cos(t*2. + np.pi/2.), np.sin(t*2. + np.pi/2.), 0.],
[np.cos(t*3. + np.pi/2.), np.sin(t*3. + np.pi/2.), 0.],
[np.cos(t*4. + np.pi/2.), np.sin(t*4. + np.pi/2.), 0.]])
# Number of atoms on the five fold axis and a nice constant
h = p + q + 2*r - 1
g = h - q + 1 # p + 2*r
positions = []
# Make the five fold axis
for j in range(h):
pos = np.array([0.0, 0.0, j*b - (h-1)*b/2.0])
positions.append(pos)
# Make pentagon rings around the five fold axis
for n in range(1, h):
# Condition for (100)-planes
if n < g:
for m in range(5):
v1 = verticies[m-1]
v2 = verticies[m]
for i in range(n):
# Condition for marks re-entrence
if n - i < g - r and i < g - r:
for j in range(h-n):
pos = (n-i)*v1 + i*v2
pos += np.array([0.0, 0.0, j*b - (h-n-1)*b/2.0])
positions.append(pos)
# Fit the cell, so it only just consist the atoms
min = np.zeros(3)
max = np.zeros(3)
axes = np.array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
for i in range(3):
r = np.dot(positions, axes[i])
min[i] = r.min()
max[i] = r.max()
cell = max - min
positions = np.array(positions) - min
symbols = [atomic_number] * len(positions)
return Atoms(symbols=symbols, positions=positions, cell=cell)
python-ase-3.6.0.2515/ase/cluster/cluster.py 0000644 0001754 0001754 00000010105 11712735707 017473 0 ustar askhl askhl import os
import math
import numpy as np
import cPickle as pickle
from ase import Atoms
from ase.data import chemical_symbols
from ase.cluster.base import ClusterBase
class Cluster(Atoms, ClusterBase):
symmetry = None
surfaces = None
lattice_basis = None
resiproc_basis = None
atomic_basis = None
def copy(self):
cluster = Atoms.copy(self)
cluster.symmetry = self.symmetry
cluster.surfaces = self.surfaces.copy()
cluster.lattice_basis = self.lattice_basis.copy()
cluster.atomic_basis = self.atomic_basis.copy()
cluster.resiproc_basis = self.resiproc_basis.copy()
return cluster
def get_surfaces(self):
"""Returns the miller indexs of the stored surfaces of the cluster."""
if not self.surfaces is None:
return self.surfaces.copy()
else:
return None
def get_layers(self):
"""Return number of atomic layers in stored surfaces directions."""
layers = []
for s in self.surfaces:
n = self.miller_to_direction(s)
c = self.get_positions().mean(axis=0)
r = np.dot(self.get_positions() - c, n).max()
d = self.get_layer_distance(s, 2)
l = 2 * np.round(r / d).astype(int)
ls = np.arange(l - 1, l + 2)
ds = np.array([self.get_layer_distance(s, i) for i in ls])
mask = (np.abs(ds - r) < 1e-10)
layers.append(ls[mask][0])
return np.array(layers, int)
def get_diameter(self, method='volume'):
"""Returns an estimate of the cluster diameter based on two different
methods.
method = 'volume': Returns the diameter of a sphere with the
same volume as the atoms. (Default)
method = 'shape': Returns the averaged diameter calculated from the
directions given by the defined surfaces.
"""
if method == 'shape':
cen = self.get_positions().mean(axis=0)
pos = self.get_positions() - cen
d = 0.0
for s in self.surfaces:
n = self.miller_to_direction(s)
r = np.dot(pos, n)
d += r.max() - r.min()
return d / len(self.surfaces)
elif method == 'volume':
V_cell = np.abs(np.linalg.det(self.lattice_basis))
N_cell = len(self.atomic_basis)
N = len(self)
return 2.0 * (3.0 * N * V_cell /
(4.0 * math.pi * N_cell)) ** (1.0 / 3.0)
else:
return 0.0
#Functions to store the cluster
def write(self, filename=None):
if not isinstance(filename, str):
raise Warning('You must specify a valid filename.')
if os.path.isfile(filename):
os.rename(filename, filename + '.bak')
d = {'symmetry': self.symmetry,
'surfaces': self.surfaces,
'lattice_basis': self.lattice_basis,
'resiproc_basis': self.resiproc_basis,
'atomic_basis': self.atomic_basis,
'cell': self.get_cell(),
'pbc': self.get_pbc()}
f = open(filename, 'w')
f.write('Cluster')
pickle.dump(d, f)
pickle.dump(self.arrays, f)
f.close()
def read(self, filename):
if not os.path.isfile(filename):
raise Warning('The file specified do not exist.')
f = open(filename, 'r')
try:
if f.read(len('Cluster')) != 'Cluster':
raise Warning('This is not a compatible file.')
d = pickle.load(f)
self.arrays = pickle.load(f)
except EOFError:
raise Warinig('Bad file.')
f.close()
self.symmetry = d['symmetry']
self.surfaces = d['surfaces']
self.lattice_basis = d['lattice_basis']
self.resiproc_basis = d['resiproc_basis']
self.atomic_basis = d['atomic_basis']
self.set_cell(d['cell'])
self.set_pbc(d['pbc'])
self.set_constraint()
self.adsorbate_info = {}
self.calc = None
python-ase-3.6.0.2515/ase/cluster/factory.py 0000644 0001754 0001754 00000020645 11712735707 017473 0 ustar askhl askhl import numpy as np
from ase.data import atomic_numbers as ref_atomic_numbers
from ase.lattice.spacegroup import Spacegroup
from ase.cluster.base import ClusterBase
from ase.cluster.cluster import Cluster
class ClusterFactory(ClusterBase):
directions = [[1, 0, 0],
[0, 1, 0],
[0, 0, 1]]
atomic_basis = np.array([[0., 0., 0.]])
element_basis = None
def __call__(self, symbols, surfaces, layers, latticeconstant=None,
center=None, vacuum=0.0, debug=0):
self.debug = debug
# Interpret symbol
self.set_atomic_numbers(symbols)
# Interpret lattice constant
if latticeconstant is None:
if self.element_basis is None:
self.lattice_constant = self.get_lattice_constant()
else:
raise ValueError("A lattice constant must be specified for a compound")
else:
self.lattice_constant = latticeconstant
self.set_basis()
if self.debug:
print "Lattice constant(s):", self.lattice_constant
print "Lattice basis:\n", self.lattice_basis
print "Resiprocal basis:\n", self.resiproc_basis
print "Atomic basis:\n", self.atomic_basis
self.set_surfaces_layers(surfaces, layers)
self.set_lattice_size(center)
if self.debug:
print "Center position:", self.center.round(2)
print "Base lattice size:", self.size
cluster = self.make_cluster(vacuum)
cluster.symmetry = self.xtal_name
cluster.surfaces = self.surfaces.copy()
cluster.lattice_basis = self.lattice_basis.copy()
cluster.atomic_basis = self.atomic_basis.copy()
cluster.resiproc_basis = self.resiproc_basis.copy()
return cluster
def make_cluster(self, vacuum):
# Make the base crystal by repeating the unit cell
size = np.array(self.size)
translations = np.zeros((size.prod(), 3))
for h in range(size[0]):
for k in range(size[1]):
for l in range(size[2]):
i = h * (size[1] * size[2]) + k * size[2] + l
translations[i] = np.dot([h, k, l], self.lattice_basis)
atomic_basis = np.dot(self.atomic_basis, self.lattice_basis)
positions = np.zeros((len(translations) * len(atomic_basis), 3))
numbers = np.zeros(len(positions))
n = len(atomic_basis)
for i, trans in enumerate(translations):
positions[n*i:n*(i+1)] = atomic_basis + trans
numbers[n*i:n*(i+1)] = self.atomic_numbers
# Remove all atoms that is outside the defined surfaces
for s, l in zip(self.surfaces, self.layers):
n = self.miller_to_direction(s)
rmax = self.get_layer_distance(s, l + 0.1)
r = np.dot(positions - self.center, n)
mask = np.less(r, rmax)
if self.debug > 1:
print "Cutting %s at %i layers ~ %.3f A" % (s, l, rmax)
positions = positions[mask]
numbers = numbers[mask]
# Fit the cell, so it only just consist the atoms
min = np.zeros(3)
max = np.zeros(3)
for i in range(3):
v = self.directions[i]
r = np.dot(positions, v)
min[i] = r.min()
max[i] = r.max()
cell = max - min + vacuum
positions = positions - min + vacuum / 2.0
self.center = self.center - min + vacuum / 2.0
return Cluster(symbols=numbers, positions=positions, cell=cell)
def set_atomic_numbers(self, symbols):
"Extract atomic number from element"
# The types that can be elements: integers and strings
atomic_numbers = []
if self.element_basis is None:
if isinstance(symbols, str):
atomic_numbers.append(ref_atomic_numbers[symbols])
elif isinstance(symbols, int):
atomic_numbers.append(symbols)
else:
raise TypeError("The symbol argument must be a " +
"string or an atomic number.")
element_basis = [0] * len(self.atomic_basis)
else:
if isinstance(symbols, (list, tuple)):
nsymbols = len(symbols)
else:
nsymbols = 0
nelement_basis = max(self.element_basis) + 1
if nsymbols != nelement_basis:
raise TypeError("The symbol argument must be a sequence " +
"of length %d" % (nelement_basis,) +
" (one for each kind of lattice position")
for s in symbols:
if isinstance(s, str):
atomic_numbers.append(ref_atomic_numbers[s])
elif isinstance(s, int):
atomic_numbers.append(s)
else:
raise TypeError("The symbol argument must be a " +
"string or an atomic number.")
element_basis = self.element_basis
self.atomic_numbers = [atomic_numbers[n] for n in element_basis]
assert len(self.atomic_numbers) == len(self.atomic_basis)
def set_lattice_size(self, center):
if center is None:
offset = np.zeros(3)
else:
offset = np.array(center)
if (offset > 1.0).any() or (offset < 0.0).any():
raise ValueError("Center offset must lie within the lattice unit \
cell.")
max = np.ones(3)
min = -np.ones(3)
v = np.linalg.inv(self.lattice_basis.T)
for s, l in zip(self.surfaces, self.layers):
n = self.miller_to_direction(s) * self.get_layer_distance(s, l)
k = np.round(np.dot(v, n), 2)
for i in range(3):
if k[i] > 0.0:
k[i] = np.ceil(k[i])
elif k[i] < 0.0:
k[i] = np.floor(k[i])
if self.debug > 1:
print "Spaning %i layers in %s in lattice basis ~ %s" % (l, s, k)
max[k > max] = k[k > max]
min[k < min] = k[k < min]
self.center = np.dot(offset - min, self.lattice_basis)
self.size = (max - min + np.ones(3)).astype(int)
def set_surfaces_layers(self, surfaces, layers):
if len(surfaces) != len(layers):
raise ValueError("Improper size of surface and layer arrays: %i != %i"
% (len(surfaces), len(layers)))
sg = Spacegroup(self.spacegroup)
surfaces = np.array(surfaces)
layers = np.array(layers)
for i, s in enumerate(surfaces):
s = reduce_miller(s)
surfaces[i] = s
surfaces_full = surfaces.copy()
layers_full = layers.copy()
for s, l in zip(surfaces, layers):
equivalent_surfaces = sg.equivalent_reflections(s.reshape(-1, 3))
for es in equivalent_surfaces:
# If the equivalent surface (es) is not in the surface list,
# then append it.
if not np.equal(es, surfaces_full).all(axis=1).any():
surfaces_full = np.append(surfaces_full, es.reshape(1, 3), axis=0)
layers_full = np.append(layers_full, l)
self.surfaces = surfaces_full.copy()
self.layers = layers_full.copy()
def get_resiproc_basis(self, basis):
"""Returns the resiprocal basis to a given lattice (crystal) basis"""
k = 1 / np.dot(basis[0], cross(basis[1], basis[2]))
# The same as the inversed basis matrix transposed
return k * np.array([cross(basis[1], basis[2]),
cross(basis[2], basis[0]),
cross(basis[0], basis[1])])
# Helping functions
def cross(a, b):
"""The cross product of two vectors."""
return np.array([a[1]*b[2] - b[1]*a[2],
a[2]*b[0] - b[2]*a[0],
a[0]*b[1] - b[0]*a[1]])
def GCD(a,b):
"""Greatest Common Divisor of a and b."""
#print "--"
while a != 0:
#print a,b,">",
a,b = b%a,a
#print a,b
return b
def reduce_miller(hkl):
"""Reduce Miller index to the lowest equivalent integers."""
hkl = np.array(hkl)
old = hkl.copy()
d = GCD(GCD(hkl[0], hkl[1]), hkl[2])
while d != 1:
hkl = hkl / d
d = GCD(GCD(hkl[0], hkl[1]), hkl[2])
if np.dot(old, hkl) > 0:
return hkl
else:
return -hkl
python-ase-3.6.0.2515/ase/cluster/octahedron.py 0000644 0001754 0001754 00000003415 11700335744 020140 0 ustar askhl askhl """
Function-like objects that creates cubic clusters.
"""
import numpy as np
from ase.cluster.cubic import FaceCenteredCubic
from ase.cluster.compounds import L1_2
def Octahedron(symbol, length, cutoff=0, latticeconstant=None, alloy=False):
"""
Returns Face Centered Cubic clusters of the octahedral class depending
on the choice of cutoff.
Type Condition
---- ---------
Regular octahedron cutoff = 0
Truncated octahedron cutoff > 0
Regular truncated octahedron length = 3 * cutoff + 1
Cuboctahedron length = 2 * cutoff + 1
Parameters
----------
symbol: The chemical symbol or atomic number of the element(s).
length: Number of atoms on the square edges of the complete octahedron.
cutoff (optional): Number of layers cut at each vertex.
latticeconstant (optional): The lattice constant. If not given,
then it is extracted form ase.data.
alloy (optional): If true the L1_2 structure is used. Default is False.
"""
# Check length and cutoff
if length < 2:
raise ValueError("The lenght must be greater than one.")
if cutoff < 0 or length < 2 * cutoff + 1:
raise ValueError("The cutoff must fullfill: > 0 and <= (length - 1) / 2.")
# Create cluster
surfaces = [(1,1,1), (1,0,0)]
if length % 2 == 0:
center = np.array([0.5, 0.5, 0.5])
layers = [length/2, length - 1 - cutoff]
else:
center = np.array([0.0, 0.0, 0.0])
layers = [(length - 1)/2, length - 1 - cutoff]
if not alloy:
return FaceCenteredCubic(symbol, surfaces, layers, latticeconstant, center)
else:
return L1_2(symbol, surfaces, layers, latticeconstant, center)
python-ase-3.6.0.2515/ase/cluster/data/ 0000755 0001754 0001754 00000000000 11757245034 016352 5 ustar askhl askhl python-ase-3.6.0.2515/ase/cluster/data/__init__.py 0000644 0001754 0001754 00000000357 11374446650 020472 0 ustar askhl askhl from ase.data import atomic_numbers, chemical_symbols, reference_states
from ase.units import *
import fcc
import hcp
import au
lattice = {'fcc': fcc.data,
'hcp': hcp.data,
}
element = {79: au.data, #Au
}
python-ase-3.6.0.2515/ase/cluster/data/fcc.py 0000644 0001754 0001754 00000024044 11401652206 017450 0 ustar askhl askhl """Lattice data - Face Centered Cubic"""
import numpy as np
from math import sqrt
from symmetry import *
#Definition of symmetries
basesymmetries = [np.matrix([[-1, 0, 0], #Mirror x-axis
[0, 1, 0],
[0, 0, 1]]),
np.matrix([[1, 0, 0], #Mirror y-axis
[0, -1, 0],
[0, 0, 1]]),
np.matrix([[1, 0, 0], #Mirror z-axis
[0, 1, 0],
[0, 0, -1]]),
np.matrix([[1, 0, 0], #Rotation x-axis (4-fold)
[0, 0, -1],
[0, 1, 0]]),
np.matrix([[0, 0, -1], #Rotation y-axis (4-fold)
[0, 1, 0],
[1, 0, 0]]),
np.matrix([[0, 1, 0], #Rotation z-axis (4-fold)
[-1, 0, 0],
[0, 0, 1]]),
np.matrix([[0, 0, 1], #Rotation (111)-axis (3-fold)
[1, 0, 0],
[0, 1, 0]]),
np.matrix([[0, 0, -1], #Rotation (11-1)-axis (3-fold)
[1, 0, 0],
[0, -1, 0]]),
np.matrix([[0, 0, 1], #Rotation (1-11)-axis (3-fold)
[-1, 0, 0],
[0, -1, 0]]),
np.matrix([[0, 0, -1], #Rotation (-111)-axis (3-fold)
[-1, 0, 0],
[0, 1, 0]])]
symmetries = get_all_symmetries(basesymmetries, 48)
#Definition of used surfaces
surface_names = [(1,0,0), (-1,0,0),
(0,1,0), (0,-1,0),
(0,0,1), (0,0,-1),
(1,1,0), (-1,-1,0),
(1,0,1), (-1,0,-1),
(0,1,1), (0,-1,-1),
(1,-1,0), (-1,1,0),
(1,0,-1), (-1,0,1),
(0,1,-1), (0,-1,1),
(1,1,1), (-1,-1,-1),
(-1,1,1), (1,-1,-1),
(1,-1,1), (-1,1,-1),
(1,1,-1), (-1,-1,1)]
surface_numbers = {}
for i, s in enumerate(surface_names):
surface_numbers[s] = i
surface_count = len(surface_names)
surface_mapping = {0: 1, 1: 0, 2: 3, 3: 2, 4: 5, 5: 4,
6: 7, 7: 6, 8: 9, 9: 8, 10: 11, 11: 10,
12: 13, 13: 12, 14: 15, 15: 14, 16: 17, 17: 16,
18: 19, 19: 18, 20: 21, 21: 20, 22: 23, 23: 22,
24: 25, 25: 24}
surface_data = ([{'l': 1.0, 'd': 0.5}] * 6 +
[{'l': 1.5, 'd': 1.0 / 4.0}] * 12 +
[{'l': 1.0, 'd': 1.0 / 3.0}] * 8)
surface_symmetries = get_surface_symmetries(symmetries, surface_names, surface_numbers)
def surface_fitting(surfaces):
for i, n1 in enumerate(np.array(surface_names)):
d1 = surface_data[i]['d']
a1 = surfaces[i] * d1
for j, n2 in enumerate(np.array(surface_names)):
d2 = surface_data[j]['d']
a2 = surfaces[j] * d2
nd = np.dot(n1, n2) / (np.linalg.norm(n1) * np.linalg.norm(n2))
if a2 * nd > a1:
surfaces[j] = int(round(a1 / (nd * d2)))
return surfaces
def surface_centering(surfaces, basis='100', debug=0):
if basis == '100':
#Centering within the basis {[1,0,0], [0,1,0], [0,0,1]}
dx = (surfaces[0] - surfaces[1]) // 2
dy = (surfaces[2] - surfaces[3]) // 2
dz = (surfaces[4] - surfaces[5]) // 2
if (dx + dy + dz) % 2 == 1:
dx -= 1
if debug:
print '(%i, %i, %i)' % (dx, dy, dz)
elif basis == '110':
#Centering within the basis {[1,1,0], [1,0,1], [0,1,1]}
dl1 = ((surfaces[6] - surfaces[7]) // 4) * 2
dl2 = ((surfaces[8] - surfaces[9]) // 4) * 2
dl3 = ((surfaces[10] - surfaces[11]) // 4) * 2
#Correction for the none orthogonality of the basis
t1 = (dl1 != 0 and dl2 != 0 and dl3 == 0)
t2 = (dl1 != 0 and dl2 == 0 and dl3 != 0)
t3 = (dl1 != 0 and dl2 == 0 and dl3 != 0)
if t1 or t2 or t3:
d1 = (3 * dl1) // 2 - dl2 // 2 - dl3 // 2
d2 = (3 * dl2) // 2 - dl1 // 2 - dl3 // 2
d3 = (3 * dl3) // 2 - dl1 // 2 - dl2 // 2
else:
d1, d2, d3 = 0, 0, 0
#Converting to '100' basis
dx = (d1 + d2) // 2
dy = (d1 + d3) // 2
dz = (d2 + d3) // 2
if debug:
print ('(%i, %i, %i) -> (%i, %i, %i) -> (%i, %i, %i)' %
(dl1, dl2, dl3, d1, d2, d3, dx, dy, dz))
else:
dx, dy, dz = 0
s = np.array(surfaces, int)
ds = np.array([- dx, dx,
- dy, dy,
- dz, dz,
- dx - dy, dx + dy,
- dx - dz, dx + dz,
- dy - dz, dy + dz,
- dx + dy, dx - dy,
- dx + dz, dx - dz,
- dy + dz, dy - dz,
(-dx - dy - dz) // 2, (dx + dy + dz) // 2,
(dx - dy - dz) // 2, (-dx + dy + dz) // 2,
(-dx + dy - dz) // 2, (dx - dy + dz) // 2,
(-dx - dy + dz) // 2, (dx + dy - dz) // 2], int)
if (s + ds >= 0).all():
surfaces = s + ds
return surfaces
#Definition of the neighbor environment
neighbor_names = [(0.5, 0.5, 0), (-0.5, -0.5, 0),
(0.5, 0, 0.5), (-0.5, 0, -0.5),
(0, 0.5, 0.5), (0, -0.5, -0.5),
(0.5, -0.5, 0), (-0.5, 0.5, 0),
(0.5, 0, -0.5), (-0.5, 0, 0.5),
(0, 0.5, -0.5), (0, -0.5, 0.5)]
neighbor_numbers = {}
for i, n in enumerate(neighbor_names):
neighbor_numbers[n] = i
neighbor_positions = np.array(neighbor_names, dtype=float)
neighbor_cutoff = 0.8
neighbor_count = 12
neighbor_mapping = {0: 1, 1: 0, 2: 3, 3: 2, 4: 5, 5: 4,
6: 7, 7: 6, 8: 9, 9: 8, 10: 11, 11: 10}
neighbor_symmetries = get_neighbor_symmetries(symmetries,
neighbor_positions,
neighbor_numbers)
#Definition of the atom types that is used based on the neighborlist
basetype_names = [(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
(0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1),
(0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1),
(0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
(0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1),
(0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1),
(0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1),
(0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1),
(0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0),
(1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0),
(0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0),
(1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0),
(0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1),
(1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1),
(0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1),
]
basetype_data = [{'type': 0,
'coordination': 0,
'name': 'Free atom, Unknown'},
{'type': 1,
'coordination': 12,
'name': 'bulk'},
{'type': 2,
'coordination': 8,
'name': '100 surface'},
{'type': 3,
'coordination': 7,
'name': '110 surface (top), 111-111 edge, 110-111 edge'},
{'type': 4,
'coordination': 11,
'name': '110 surface (bottom)'},
{'type': 5,
'coordination': 9,
'name': '111 surface'},
{'type': 6,
'coordination': 6,
'name': '100-110 edge'},
{'type': 7,
'coordination': 7,
'name': '100-111 edge'},
{'type': 8,
'coordination': 6,
'name': '111-111-100 corner'},
{'type': 9,
'coordination': 4,
'name': '100 surface ad-atom'},
{'type': 10,
'coordination': 5,
'name': '110 surface ad-atom (bottom), A5 site'},
{'type': 11,
'coordination': 3,
'name': '111 surface ad-atom'},
{'type': 12,
'coordination': 9,
'name': '100 surface with ad-atom'},
{'type': 13,
'coordination': 8,
'name': '110 surface with ad-atom'},
{'type': 14,
'coordination': 10,
'name': '111 surface with ad-atom'},
{'type': 15,
'coordination': 5,
'name': 'B5 site'},
]
type_count = len(basetype_names)
type_names = []
type_data = []
for i, n in enumerate(basetype_names):
type_names.append(n)
type_data.append(basetype_data[i])
for sym in neighbor_symmetries:
new_type = apply_neighbor_symmetry(n, sym)
if not new_type in type_names:
type_names.append(new_type)
type_data.append(basetype_data[i])
type_numbers = {}
for i, n in enumerate(type_names):
type_numbers[n] = i
data = {'symmetries': symmetries,
'surface_names': surface_names,
'surface_numbers': surface_numbers,
'surface_data': surface_data,
'surface_count': surface_count,
'surface_mapping': surface_mapping,
'surface_symmetries': surface_symmetries,
'neighbor_positions': neighbor_positions,
'neighbor_numbers': neighbor_numbers,
'neighbor_count': neighbor_count,
'neighbor_cutoff': neighbor_cutoff,
'neighbor_mapping': neighbor_mapping,
'neighbor_symmetries': neighbor_symmetries,
'type_names': type_names,
'type_numbers': type_numbers,
'type_data': type_data,
'type_count': type_count,
}
python-ase-3.6.0.2515/ase/cluster/data/hcp.py 0000644 0001754 0001754 00000010271 11374446650 017501 0 ustar askhl askhl """Structure data - Hexagonal Closed Packed"""
import numpy as np
from math import sqrt
from symmetry import *
#Definition of symmetries (in hcp basis)
basesymmetries = [np.matrix([[1, 0, 0], #Mirror y-axis
[0, 1, 0],
[0, 0, -1]]),
np.matrix([[0, 1, 0], #Rotation z-axix (3-fold)
[-1, -1, 0],
[0, 0, 1]]),
np.matrix([[1, 0, 0], #Rotation a-axis (2-fold)
[-1, -1, 0],
[0, 0, -1]]),
np.matrix([[-1, -1, 0], #Rotation b-axis (2-fold)
[0, 1, 0],
[0, 0, -1]]),
np.matrix([[0, 1, 0], #Rotation ab-axis (2-fold)
[1, 0, 0],
[0, 0, -1]]),
]
symmetries = get_all_symmetries(basesymmetries, 12)
#Definition of surfaces
surface_names = [(0,0,1), (0,0,-1), #(001)
(1,-1,0), (-1,1,0), #
(2,1,0), (-2,-1,0),
(1,2,0), (-1,-2,0),
(5,-5,3), (5,-5,-3), #
(-5,5,3), (-5,5,-3),
(5,10,3), (5,10,-3),
(10,5,3), (10,5,-3),
(-5,-10,3), (-5,-10,-3),
(-10,-5,3), (-10,-5,-3),
]
surface_numbers = {}
for i, s in enumerate(surface_names):
surface_numbers[s] = i
surface_count = len(surface_names)
surface_mapping = {0:1, 1:0, 2:3, 3:2, 4:5, 5:4, 6:7, 7:6,
}
surface_data = ([{'d': 0.5}] * 2 +
[{'d': 0.5}] * 6 +
[{'d': 1.0/13.0}] * 12)
surface_symmetries = get_surface_symmetries(symmetries, surface_names, surface_numbers)
#Definition of neighbor environment
neighbor_names = [(1,0,0), (-1,0,0),
(0,1,0), (0,-1,0),
(1,1,0), (-1,-1,0),
(1.0/3.0,2.0/3.0,1.0/2.0), (1.0/3.0,-1.0/3.0,1.0/2.0), (-2.0/3.0,-1.0/3.0,1.0/2.0),
(1.0/3.0,2.0/3.0,-1.0/2.0), (1.0/3.0,-1.0/3.0,-1.0/2.0), (-2.0/3.0,-1.0/3.0,-1.0/2.0),
(2.0/3.0,1.0/3.0,1.0/2.0), (-1.0/3.0,-2.0/3.0,1.0/2.0), (-1.0/3.0,1.0/3.0,1.0/2.0),
(2.0/3.0,1.0/3.0,-1.0/2.0), (-1.0/3.0,-2.0/3.0,-1.0/2.0), (-1.0/3.0,1.0/3.0,-1.0/2.0),
]
neighbor_numbers = {}
for i, n in enumerate(neighbor_names):
neighbor_numbers[n] = i
neighbor_positions = np.array(neighbor_names, dtype=float)
neighbor_cutoff = 1.2
neighbor_count = 16
neighbor_mapping = {0:1, 1:0, 2:3, 3:2, 4:5, 5:4,
6:16, 7:17, 8:15, 9:13, 10:14, 11:12,
12:11, 13:9, 14:10, 15:8, 16:6, 17:7,
}
neighbor_symmetries = get_neighbor_symmetries(symmetries,
neighbor_positions,
neighbor_numbers)
#Definition of the atom types that is used based on the neighborlist
basetype_names = []
basetype_data = []
type_count = len(basetype_names)
type_names = []
type_data = []
for i, n in enumerate(basetype_names):
type_names.append(n)
type_data.append(basetype_data[i])
for sym in neighbor_symmetries:
new_type = apply_neighbor_symmetry(n, sym)
if not new_type in type_names:
type_names.append(new_type)
type_data.append(basetype_data[i])
type_numbers = {}
for i, n in enumerate(type_names):
type_numbers[n] = i
#Collect all data
data = {'symmetries': symmetries,
'surface_names': surface_names,
'surface_numbers': surface_numbers,
'surface_data': surface_data,
'surface_count': surface_count,
'surface_mapping': surface_mapping,
'surface_symmetries': surface_symmetries,
'neighbor_positions': neighbor_positions,
'neighbor_numbers': neighbor_numbers,
'neighbor_count': neighbor_count,
'neighbor_cutoff': neighbor_cutoff,
'neighbor_mapping': neighbor_mapping,
'neighbor_symmetries': neighbor_symmetries,
'type_names': type_names,
'type_numbers': type_numbers,
'type_data': type_data,
'type_count': type_count,
}
python-ase-3.6.0.2515/ase/cluster/data/au.py 0000644 0001754 0001754 00000001241 11326132263 017316 0 ustar askhl askhl """Element data - 79 Au Gold"""
name = 'Gold'
symbol = 'Au'
symmetry = 'fcc'
energy_slope = -0.090
energy_intersection = -1.537
energy_types = {1: -2.618, #bulk
2: -2.237, #100 surface
3: -2.343, #110 surface (top) or 111-111 edge
4: -2.369, #110 surface (bottom)
5: -2.352, #111 surface
6: -2.028, #100-110 edge
7: -2.215, #100-111 edge
}
data = {'name': name,
'symbol': symbol,
'symmetry': symmetry,
'energy_slope': energy_slope,
'energy_intersection': energy_intersection,
'energy_types': energy_types,
}
python-ase-3.6.0.2515/ase/cluster/data/symmetry.py 0000644 0001754 0001754 00000005404 11326132263 020607 0 ustar askhl askhl from fcc import *
import numpy as np
def get_all_symmetries(symmetries=None, max=99):
if symmetries is None:
raise Warning('Some unique symmetries are needed to start.')
symmetries_all = symmetries[:]
for i, l in enumerate(symmetries):
for j, m, in enumerate(symmetries):
if len(symmetries_all) == max: break
v = l * m
exist = False
for w in symmetries_all:
if (v == w).all():
exist = True
break
if not exist:
#print 'New added: %i x %i' % (i, j)
symmetries_all.append(v)
for i, l in enumerate(symmetries):
for j, m, in enumerate(symmetries):
for k, n in enumerate(symmetries):
if len(symmetries_all) == max: break
v = l * m * n
exist = False
for w in symmetries_all:
if (v == w).all():
exist = True
break
if not exist:
#print 'New added: %i x %i x %i' % (i, j, k)
symmetries_all.append(v)
#print 'There are %i symmetry operations.' % len(symmetries_all)
return symmetries_all
def get_neighbor_symmetries(symmetries=None, neighbor_positions=None, neighbor_numbers=None):
if symmetries is None or neighbor_positions is None or neighbor_numbers is None:
raise Warning('Both symmetries, positions and numbers for the neighbors are needed.')
neighbor_symmetries = []
for s in symmetries:
neighbor_symmetry = []
for p in neighbor_positions:
new_p = np.array(np.matrix(p) * s)
neighbor_symmetry.append(neighbor_numbers[tuple(new_p[0])])
neighbor_symmetries.append(neighbor_symmetry)
return neighbor_symmetries
def get_surface_symmetries(symmetries=None, surface_names=None, surface_numbers=None):
if symmetries is None or surface_names is None or surface_numbers is None:
raise Warning('Both symmetries, names and numbers for the surfaces are needed.')
surface_symmetries = []
for sym in symmetries:
surface_symmetry = []
for s in surface_names:
ns = np.array(np.matrix(s) * sym)
surface_symmetry.append(surface_numbers[tuple(ns[0])])
surface_symmetries.append(surface_symmetry)
return np.array(surface_symmetries, int)
def apply_neighbor_symmetry(neighbors=None, symmetry=None):
if neighbors is None or symmetry is None:
raise Warning('Both neighbor list and symmetry list are needed.')
new_neighbors = [0] * len(symmetry)
for i, n in enumerate(symmetry):
new_neighbors[i] = neighbors[n]
return tuple(new_neighbors)
python-ase-3.6.0.2515/ase/cluster/base.py 0000644 0001754 0001754 00000003661 11527425577 016742 0 ustar askhl askhl import numpy as np
class ClusterBase:
def get_layer_distance(self, miller, layers=1):
"""Returns the distance between planes defined by the given miller
index.
"""
n = self.miller_to_direction(miller)
d1 = d2 = 0.0
d = np.abs(np.sum(n * self.lattice_basis, axis=1))
mask = np.greater(d, 1e-10)
if mask.sum() > 0:
d1 = np.min(d[mask])
if len(self.atomic_basis) > 1:
atomic_basis = np.dot(self.atomic_basis, self.lattice_basis)
d = np.sum(n * atomic_basis, axis=1)
s = np.sign(d)
d = np.abs(d)
mask = np.greater(d, 1e-10)
if mask.sum() > 0:
d2 = np.min(d[mask])
s2 = s[mask][np.argmin(d[mask])]
if d2 > 1e-10:
if s2 < 0 and d1 - d2 > 1e-10:
d2 = d1 - d2
elif s2 < 0 and d2 - d1 > 1e-10:
d2 = 2 * d1 - d2
elif s2 > 0 and d2 - d1 > 1e-10:
d2 = d2 - d1
if np.abs(d1 - d2) < 1e-10:
ld = np.array([d1])
elif np.abs(d1 - 2 * d2) < 1e-10:
ld = np.array([d2])
else:
assert d1 > d2, "Something is wrong with the layer distance."
ld = np.array([d2, d1 - d2])
else:
ld = np.array([d1])
if len(ld) > 1:
if layers < 0:
ld = np.array([-ld[1], -ld[0]])
layers *= -1
map = np.arange(layers - (layers % 1), dtype=int) % len(ld)
r = ld[map].sum() + (layers % 1) * ld[np.abs(map[-1] - 1)]
else:
r = ld[0] * layers
return r
def miller_to_direction(self, miller, norm=True):
"""Returns the direction corresponding to a given Miller index."""
d = np.dot(miller, self.resiproc_basis)
if norm:
d = d / np.linalg.norm(d)
return d
python-ase-3.6.0.2515/ase/cluster/hexagonal.py 0000644 0001754 0001754 00000005267 11652200253 017757 0 ustar askhl askhl """
Function-like objects that creates cubic clusters.
"""
import numpy as np
from ase.cluster.factory import ClusterFactory
from ase.data import reference_states as _refstate
class HexagonalFactory(ClusterFactory):
spacegroup = 191
xtal_name = 'hexagonal'
def get_lattice_constant(self, latticeconstant):
"Get the lattice constant of an element with cubic crystal structure."
symmetry = _refstate[self.atomic_numbers[0]]['symmetry']
if symmetry != self.xtal_name:
raise ValueError, ("Cannot guess the %s " % (self.xtal_name,) +
"lattice constant of an element with crystal " +
"structure %s." % (symmetry,))
return _refstate[self.atomic_numbers[0]].copy()
def set_basis(self):
lattice = self.lattice_constant
if isinstance(lattice, dict):
a = lattice['a']
try:
c = lattice['c']
except KeyError:
c = a * lattice['c/a']
else:
if len(lattice) == 2:
(a, c) = lattice
else:
raise ValueError("Improper lattice constants for %s crystal." % (self.xtal_name,))
self.lattice_constant = (a, c)
self.lattice_basis = np.array([[a, 0., 0.],
[-a/2., a*np.sqrt(3.)/2., 0.],
[0., 0., c]])
self.resiproc_basis = self.get_resiproc_basis(self.lattice_basis)
def set_surfaces_layers(self, surfaces, layers):
for i, s in enumerate(surfaces):
if len(s) == 4:
(a, b, c, d) = s
if a + b + c != 0:
raise ValueError(("(%d,%d,%d,%d) is not a valid hexagonal Miller " +
"index, as the sum of the first three numbers " +
"should be zero.") % (a,b,c,d))
surfaces[i] = [a, b, d]
ClusterFactory.set_surfaces_layers(self, surfaces, layers)
Hexagonal = HexagonalFactory()
class HexagonalClosedPackedFactory(HexagonalFactory):
"""A factory for creating HCP clusters."""
spacegroup = 194
xtal_name = 'hcp'
atomic_basis = np.array([[0., 0., 0.],
[2./3., 1./3., .5]])
HexagonalClosedPacked = HexagonalClosedPackedFactory()
class GraphiteFactory(HexagonalFactory):
"""A factory for creating graphite clusters."""
xtal_name = "graphite"
atomic_basis = np.array([[0., 0., 0.],
[1./3., 2./3., 0.],
[1./3., 2./3., .5],
[2./3., 1./3., .5]])
Graphite = GraphiteFactory()
python-ase-3.6.0.2515/ase/cluster/icosahedron.py 0000644 0001754 0001754 00000010431 11631137252 020301 0 ustar askhl askhl import numpy as np
from ase import Atoms
from ase.data import atomic_numbers, reference_states
def Icosahedron(symbol, noshells, latticeconstant=None):
"""
Returns a cluster with the icosahedra symmetry.
Parameters
----------
symbol: The chemical symbol (or atomic number) of the element.
noshells: The number of shells (>= 1).
latticeconstant (optional): The lattice constant. If not given,
then it is extracted form ase.data.
"""
# Interpret symbol
if isinstance(symbol, str):
atomic_number = atomic_numbers[symbol]
else:
atomic_number = symbol
# Interpret noshells
if noshells < 1:
raise ValueError("The number of shells must be equal to or greater than one.")
# Interpret lattice constant
if latticeconstant is None:
if reference_states[atomic_number]['symmetry'] in ['fcc', 'bcc', 'sc']:
lattice_constant = reference_states[atomic_number]['a']
else:
raise NotImplementedError(("Cannot guess lattice constant of a %s element." %
(reference_states[atomic_number]['symmetry'],)))
else:
if isinstance(latticeconstant, (int, float)):
lattice_constant = latticeconstant
else:
raise ValueError("Lattice constant must be of type int or float.")
t = 0.5 + np.sqrt(5)/2.0
verticies = np.array([[t, 0., 1.],
[t, 0., -1.],
[-t, 0., 1.],
[-t, 0., -1.],
[1., t, 0.],
[-1., t, 0.],
[1., -t, 0.],
[-1., -t, 0.],
[0., 1., t],
[0., -1., t],
[0., 1., -t],
[0., -1., -t]])
positions = []
tags = []
positions.append(np.zeros(3))
tags.append(1)
for n in range(1, noshells):
#Construct square edges (6)
for k in range(0, 12, 2):
v1 = verticies[k]
v2 = verticies[k+1]
for i in range(n+1):
pos = i*v1 + (n-i)*v2
positions.append(pos)
tags.append(n + 1)
#Construct triangle planes (12)
if n > 1:
map = {0: (8, 9), 1: (10, 11),
2: (8, 9), 3: (10, 11),
4: (0, 1), 5: (2, 3),
6: (0, 1), 7: (2, 3),
8: (4, 5), 9: (6, 7),
10: (4, 5), 11: (6, 7)}
for k in range(0, 12):
v0 = n*verticies[k]
v1 = (verticies[map[k][0]] - verticies[k])
v2 = (verticies[map[k][1]] - verticies[k])
for i in range(n):
for j in range(n-i):
if i == 0 and j == 0:
continue
pos = v0 + i*v1 + j*v2
positions.append(pos)
tags.append(n + 1)
#Fill missing triangle planes (8)
if n > 2:
map = {0: (9, 6, 8, 4,),
1: (11, 6, 10, 4),
2: (9, 7, 8, 5,),
3: (11, 7, 10, 5)}
for k in range(0, 4):
v0 = n*verticies[k]
v1 = (verticies[map[k][0]] - verticies[k])
v2 = (verticies[map[k][1]] - verticies[k])
v3 = (verticies[map[k][2]] - verticies[k])
v4 = (verticies[map[k][3]] - verticies[k])
for i in range(1, n):
for j in range(1, n-i):
pos = v0 + i*v1 + j*v2
positions.append(pos)
tags.append(n + 1)
pos = v0 + i*v3 + j*v4
positions.append(pos)
tags.append(n + 1)
# Scale the positions
scaling_factor = lattice_constant / np.sqrt(2*(1 + t**2))
positions = np.array(positions) * scaling_factor
# Fit the cell, so it only just consist the atoms
min = positions.min(axis=0)
max = positions.max(axis=0)
cell = max - min
positions = positions - min
symbols = [atomic_number] * len(positions)
return Atoms(symbols=symbols, positions=positions, tags=tags, cell=cell)
python-ase-3.6.0.2515/ase/cluster/cubic.py 0000644 0001754 0001754 00000003277 11700335744 017105 0 ustar askhl askhl """
Function-like objects that creates cubic clusters.
"""
import numpy as np
from ase.data import reference_states as _refstate
from ase.cluster.factory import ClusterFactory
class SimpleCubicFactory(ClusterFactory):
spacegroup = 221
xtal_name = 'sc'
def get_lattice_constant(self):
"Get the lattice constant of an element with cubic crystal structure."
symmetry = _refstate[self.atomic_numbers[0]]['symmetry']
if symmetry != self.xtal_name:
raise ValueError, ("Cannot guess the %s " % (self.xtal_name,) +
"lattice constant of an element with crystal " +
"structure %s." % (symmetry,))
return _refstate[self.atomic_numbers[0]]['a']
def set_basis(self):
a = self.lattice_constant
if not isinstance(a, (int, float)):
raise ValueError("Improper lattice constant for %s crystal." % (xtal_name,))
self.lattice_basis = np.array([[a, 0., 0.],
[0., a, 0.],
[0., 0., a]])
self.resiproc_basis = self.get_resiproc_basis(self.lattice_basis)
SimpleCubic = SimpleCubicFactory()
class BodyCenteredCubicFactory(SimpleCubicFactory):
xtal_name = 'bcc'
atomic_basis = np.array([[0., 0., 0.],
[.5, .5, .5]])
BodyCenteredCubic = BodyCenteredCubicFactory()
class FaceCenteredCubicFactory(SimpleCubicFactory):
xtal_name = 'fcc'
atomic_basis = np.array([[0., 0., 0.],
[0., .5, .5],
[.5, 0., .5],
[.5, .5, 0.]])
FaceCenteredCubic = FaceCenteredCubicFactory()
python-ase-3.6.0.2515/ase/atoms.py 0000644 0001754 0001754 00000144250 11712217646 015462 0 ustar askhl askhl # Copyright 2008, 2009 CAMd
# (see accompanying license files for details).
"""Definition of the Atoms class.
This module defines the central object in the ASE package: the Atoms
object.
"""
from math import cos, sin
import numpy as np
from ase.atom import Atom
from ase.data import atomic_numbers, chemical_symbols, atomic_masses
import ase.units as units
class Atoms(object):
"""Atoms object.
The Atoms object can represent an isolated molecule, or a
periodically repeated structure. It has a unit cell and
there may be periodic boundary conditions along any of the three
unit cell axes.
Information about the atoms (atomic numbers and position) is
stored in ndarrays. Optionally, there can be information about
tags, momenta, masses, magnetic moments and charges.
In order to calculate energies, forces and stresses, a calculator
object has to attached to the atoms object.
Parameters:
symbols: str (formula) or list of str
Can be a string formula, a list of symbols or a list of
Atom objects. Examples: 'H2O', 'COPt12', ['H', 'H', 'O'],
[Atom('Ne', (x, y, z)), ...].
positions: list of xyz-positions
Atomic positions. Anything that can be converted to an
ndarray of shape (n, 3) will do: [(x1,y1,z1), (x2,y2,z2),
...].
scaled_positions: list of scaled-positions
Like positions, but given in units of the unit cell.
Can not be set at the same time as positions.
numbers: list of int
Atomic numbers (use only one of symbols/numbers).
tags: list of int
Special purpose tags.
momenta: list of xyz-momenta
Momenta for all atoms.
masses: list of float
Atomic masses in atomic units.
magmoms: list of float or list of xyz-values
Magnetic moments. Can be either a single value for each atom
for collinear calculations or three numbers for each atom for
non-collinear calculations.
charges: list of float
Atomic charges.
cell: 3x3 matrix
Unit cell vectors. Can also be given as just three
numbers for orthorhombic cells. Default value: [1, 1, 1].
pbc: one or three bool
Periodic boundary conditions flags. Examples: True,
False, 0, 1, (1, 1, 0), (True, False, False). Default
value: False.
constraint: constraint object(s)
Used for applying one or more constraints during structure
optimization.
calculator: calculator object
Used to attach a calculator for calculating energies and atomic
forces.
info: dict of key-value pairs
Dictionary of key-value pairs with additional information
about the system. The following keys may be used by ase:
- spacegroup: Spacegroup instance
- unit_cell: 'conventional' | 'primitive' | int | 3 ints
- adsorbate_info:
Items in the info attribute survives copy and slicing and can
be store to and retrieved from trajectory files given that the
key is a string, the value is picklable and, if the value is a
user-defined object, its base class is importable. One should
not make any assumptions about the existence of keys.
Examples:
These three are equivalent:
>>> d = 1.104 # N2 bondlength
>>> a = Atoms('N2', [(0, 0, 0), (0, 0, d)])
>>> a = Atoms(numbers=[7, 7], positions=[(0, 0, 0), (0, 0, d)])
>>> a = Atoms([Atom('N', (0, 0, 0)), Atom('N', (0, 0, d)])
FCC gold:
>>> a = 4.05 # Gold lattice constant
>>> b = a / 2
>>> fcc = Atoms('Au',
... cell=[(0, b, b), (b, 0, b), (b, b, 0)],
... pbc=True)
Hydrogen wire:
>>> d = 0.9 # H-H distance
>>> L = 7.0
>>> h = Atoms('H', positions=[(0, L / 2, L / 2)],
... cell=(d, L, L),
... pbc=(1, 0, 0))
"""
def __init__(self, symbols=None,
positions=None, numbers=None,
tags=None, momenta=None, masses=None,
magmoms=None, charges=None,
scaled_positions=None,
cell=None, pbc=None,
constraint=None,
calculator=None,
info=None):
atoms = None
if hasattr(symbols, 'GetUnitCell'):
from ase.old import OldASEListOfAtomsWrapper
atoms = OldASEListOfAtomsWrapper(symbols)
symbols = None
elif hasattr(symbols, 'get_positions'):
atoms = symbols
symbols = None
elif (isinstance(symbols, (list, tuple)) and
len(symbols) > 0 and isinstance(symbols[0], Atom)):
# Get data from a list or tuple of Atom objects:
data = [[atom.get_raw(name) for atom in symbols]
for name in
['position', 'number', 'tag', 'momentum',
'mass', 'magmom', 'charge']]
atoms = self.__class__(None, *data)
symbols = None
if atoms is not None:
# Get data from another Atoms object:
if scaled_positions is not None:
raise NotImplementedError
if symbols is None and numbers is None:
numbers = atoms.get_atomic_numbers()
if positions is None:
positions = atoms.get_positions()
if tags is None and atoms.has('tags'):
tags = atoms.get_tags()
if momenta is None and atoms.has('momenta'):
momenta = atoms.get_momenta()
if magmoms is None and atoms.has('magmoms'):
magmoms = atoms.get_initial_magnetic_moments()
if masses is None and atoms.has('masses'):
masses = atoms.get_masses()
if charges is None and atoms.has('charges'):
charges = atoms.get_charges()
if cell is None:
cell = atoms.get_cell()
if pbc is None:
pbc = atoms.get_pbc()
if constraint is None:
constraint = [c.copy() for c in atoms.constraints]
if calculator is None:
calculator = atoms.get_calculator()
self.arrays = {}
if symbols is None:
if numbers is None:
if positions is not None:
natoms = len(positions)
elif scaled_positions is not None:
natoms = len(scaled_positions)
else:
natoms = 0
numbers = np.zeros(natoms, int)
self.new_array('numbers', numbers, int)
else:
if numbers is not None:
raise ValueError(
'Use only one of "symbols" and "numbers".')
else:
self.new_array('numbers', symbols2numbers(symbols), int)
if cell is None:
cell = np.eye(3)
self.set_cell(cell)
if positions is None:
if scaled_positions is None:
positions = np.zeros((len(self.arrays['numbers']), 3))
else:
positions = np.dot(scaled_positions, self._cell)
else:
if scaled_positions is not None:
raise RuntimeError('Both scaled and cartesian positions set!')
self.new_array('positions', positions, float, (3,))
self.set_constraint(constraint)
self.set_tags(default(tags, 0))
self.set_momenta(default(momenta, (0.0, 0.0, 0.0)))
self.set_masses(default(masses, None))
self.set_initial_magnetic_moments(default(magmoms, 0.0))
self.set_charges(default(charges, 0.0))
if pbc is None:
pbc = False
self.set_pbc(pbc)
if info is None:
self.info = {}
else:
self.info = dict(info)
self.adsorbate_info = {}
self.set_calculator(calculator)
def set_calculator(self, calc=None):
"""Attach calculator object."""
if hasattr(calc, '_SetListOfAtoms'):
from ase.old import OldASECalculatorWrapper
calc = OldASECalculatorWrapper(calc, self)
if hasattr(calc, 'set_atoms'):
calc.set_atoms(self)
self._calc = calc
def get_calculator(self):
"""Get currently attached calculator object."""
return self._calc
def _del_calculator(self):
self._calc = None
calc = property(get_calculator, set_calculator, _del_calculator,
doc='Calculator object.')
def set_constraint(self, constraint=None):
"""Apply one or more constrains.
The *constraint* argument must be one constraint object or a
list of constraint objects."""
if constraint is None:
self._constraints = []
else:
if isinstance(constraint, (list, tuple)):
self._constraints = constraint
else:
self._constraints = [constraint]
def _get_constraints(self):
return self._constraints
def _del_constraints(self):
self._constraints = []
constraints = property(_get_constraints, set_constraint, _del_constraints,
'Constraints of the atoms.')
def set_cell(self, cell, scale_atoms=False, fix=None):
"""Set unit cell vectors.
Parameters:
cell :
Unit cell. A 3x3 matrix (the three unit cell vectors) or
just three numbers for an orthorhombic cell.
scale_atoms : bool
Fix atomic positions or move atoms with the unit cell?
Default behavior is to *not* move the atoms (scale_atoms=False).
Examples:
Two equivalent ways to define an orthorhombic cell:
>>> a.set_cell([a, b, c])
>>> a.set_cell([(a, 0, 0), (0, b, 0), (0, 0, c)])
FCC unit cell:
>>> a.set_cell([(0, b, b), (b, 0, b), (b, b, 0)])
"""
if fix is not None:
raise TypeError('Please use scale_atoms=%s' % (not fix))
cell = np.array(cell, float)
if cell.shape == (3,):
cell = np.diag(cell)
elif cell.shape != (3, 3):
raise ValueError('Cell must be length 3 sequence or '
'3x3 matrix!')
if scale_atoms:
M = np.linalg.solve(self._cell, cell)
self.arrays['positions'][:] = np.dot(self.arrays['positions'], M)
self._cell = cell
def get_cell(self):
"""Get the three unit cell vectors as a 3x3 ndarray."""
return self._cell.copy()
def get_reciprocal_cell(self):
"""Get the three reciprocal lattice vectors as a 3x3 ndarray.
Note that the commonly used factor of 2 pi for Fourier
transforms is not included here."""
rec_unit_cell = np.linalg.inv(self.get_cell()).transpose()
return rec_unit_cell
def set_pbc(self, pbc):
"""Set periodic boundary condition flags."""
if isinstance(pbc, int):
pbc = (pbc,) * 3
self._pbc = np.array(pbc, bool)
def get_pbc(self):
"""Get periodic boundary condition flags."""
return self._pbc.copy()
def new_array(self, name, a, dtype=None, shape=None):
"""Add new array.
If *shape* is not *None*, the shape of *a* will be checked."""
if dtype is not None:
a = np.array(a, dtype)
else:
a = a.copy()
if name in self.arrays:
raise RuntimeError
for b in self.arrays.values():
if len(a) != len(b):
raise ValueError('Array has wrong length: %d != %d.' %
(len(a), len(b)))
break
if shape is not None and a.shape[1:] != shape:
raise ValueError('Array has wrong shape %s != %s.' %
(a.shape, (a.shape[0:1] + shape)))
self.arrays[name] = a
def get_array(self, name, copy=True):
"""Get an array.
Returns a copy unless the optional argument copy is false.
"""
if copy:
return self.arrays[name].copy()
else:
return self.arrays[name]
def set_array(self, name, a, dtype=None, shape=None):
"""Update array.
If *shape* is not *None*, the shape of *a* will be checked.
If *a* is *None*, then the array is deleted."""
b = self.arrays.get(name)
if b is None:
if a is not None:
self.new_array(name, a, dtype, shape)
else:
if a is None:
del self.arrays[name]
else:
a = np.asarray(a)
if a.shape != b.shape:
raise ValueError('Array has wrong shape %s != %s.' %
(a.shape, b.shape))
b[:] = a
def has(self, name):
"""Check for existence of array.
name must be one of: 'tags', 'momenta', 'masses', 'magmoms',
'charges'."""
return name in self.arrays
def set_atomic_numbers(self, numbers):
"""Set atomic numbers."""
self.set_array('numbers', numbers, int, ())
def get_atomic_numbers(self):
"""Get integer array of atomic numbers."""
return self.arrays['numbers'].copy()
def set_chemical_symbols(self, symbols):
"""Set chemical symbols."""
self.set_array('numbers', symbols2numbers(symbols), int, ())
def get_chemical_symbols(self, reduce=False):
"""Get list of chemical symbol strings.
If reduce is True, a single string is returned, where repeated
elements have been contracted to a single symbol and a number.
E.g. instead of ['C', 'O', 'O', 'H'], the string 'CO2H' is returned.
"""
if not reduce:
# XXX
return [chemical_symbols[Z] for Z in self.arrays['numbers']]
else:
num = self.get_atomic_numbers()
N = len(num)
dis = np.concatenate(([0], np.arange(1, N)[num[1:] != num[:-1]]))
repeat = np.append(dis[1:], N) - dis
symbols = ''.join([chemical_symbols[num[d]] + str(r) * (r != 1)
for r, d in zip(repeat, dis)])
return symbols
def set_tags(self, tags):
"""Set tags for all atoms."""
self.set_array('tags', tags, int, ())
def get_tags(self):
"""Get integer array of tags."""
if 'tags' in self.arrays:
return self.arrays['tags'].copy()
else:
return np.zeros(len(self), int)
def set_momenta(self, momenta):
"""Set momenta."""
if len(self.constraints) > 0 and momenta is not None:
momenta = np.array(momenta) # modify a copy
for constraint in self.constraints:
constraint.adjust_forces(self.arrays['positions'], momenta)
self.set_array('momenta', momenta, float, (3,))
def set_velocities(self, velocities):
"""Set the momenta by specifying the velocities."""
self.set_momenta(self.get_masses()[:, np.newaxis] * velocities)
def get_momenta(self):
"""Get array of momenta."""
if 'momenta' in self.arrays:
return self.arrays['momenta'].copy()
else:
return np.zeros((len(self), 3))
def set_masses(self, masses='defaults'):
"""Set atomic masses.
The array masses should contain a list of masses. In case
the masses argument is not given or for those elements of the
masses list that are None, standard values are set."""
if masses == 'defaults':
masses = atomic_masses[self.arrays['numbers']]
elif isinstance(masses, (list, tuple)):
newmasses = []
for m, Z in zip(masses, self.arrays['numbers']):
if m is None:
newmasses.append(atomic_masses[Z])
else:
newmasses.append(m)
masses = newmasses
self.set_array('masses', masses, float, ())
def get_masses(self):
"""Get array of masses."""
if 'masses' in self.arrays:
return self.arrays['masses'].copy()
else:
return atomic_masses[self.arrays['numbers']]
def set_initial_magnetic_moments(self, magmoms=None):
"""Set the initial magnetic moments.
Use either one or three numbers for every atom (collinear
or non-collinear spins)."""
if magmoms is None:
self.set_array('magmoms', None)
else:
magmoms = np.asarray(magmoms)
self.set_array('magmoms', magmoms, float, magmoms.shape[1:])
def get_initial_magnetic_moments(self):
"""Get array of initial magnetic moments."""
if 'magmoms' in self.arrays:
return self.arrays['magmoms'].copy()
else:
return np.zeros(len(self))
def get_magnetic_moments(self):
"""Get calculated local magnetic moments."""
if self._calc is None:
raise RuntimeError('Atoms object has no calculator.')
if self._calc.get_spin_polarized():
return self._calc.get_magnetic_moments(self)
else:
return np.zeros(len(self))
def get_magnetic_moment(self):
"""Get calculated total magnetic moment."""
if self._calc is None:
raise RuntimeError('Atoms object has no calculator.')
if self._calc.get_spin_polarized():
return self._calc.get_magnetic_moment(self)
else:
return 0.0
def set_charges(self, charges):
"""Set charges."""
self.set_array('charges', charges, float, ())
def get_charges(self):
"""Get array of charges."""
if 'charges' in self.arrays:
return self.arrays['charges'].copy()
else:
return np.zeros(len(self))
def set_positions(self, newpositions):
"""Set positions."""
positions = self.arrays['positions']
if self.constraints:
newpositions = np.asarray(newpositions, float)
for constraint in self.constraints:
constraint.adjust_positions(positions, newpositions)
self.set_array('positions', newpositions, shape=(3,))
def get_positions(self):
"""Get array of positions."""
return self.arrays['positions'].copy()
def get_calculation_done(self):
"""Let the calculator calculate its thing,
using the current input.
"""
if self.calc is None:
raise RuntimeError('Atoms object has no calculator.')
self.calc.initialize(self)
self.calc.calculate(self)
def get_potential_energy(self):
"""Calculate potential energy."""
if self._calc is None:
raise RuntimeError('Atoms object has no calculator.')
return self._calc.get_potential_energy(self)
def get_potential_energies(self):
"""Calculate the potential energies of all the atoms.
Only available with calculators supporting per-atom energies
(e.g. classical potentials).
"""
if self._calc is None:
raise RuntimeError('Atoms object has no calculator.')
return self._calc.get_potential_energies(self)
def get_kinetic_energy(self):
"""Get the kinetic energy."""
momenta = self.arrays.get('momenta')
if momenta is None:
return 0.0
return 0.5 * np.vdot(momenta, self.get_velocities())
def get_velocities(self):
"""Get array of velocities."""
momenta = self.arrays.get('momenta')
if momenta is None:
return None
m = self.arrays.get('masses')
if m is None:
m = atomic_masses[self.arrays['numbers']]
return momenta / m.reshape(-1, 1)
def get_total_energy(self):
"""Get the total energy - potential plus kinetic energy."""
return self.get_potential_energy() + self.get_kinetic_energy()
def get_forces(self, apply_constraint=True):
"""Calculate atomic forces.
Ask the attached calculator to calculate the forces and apply
constraints. Use *apply_constraint=False* to get the raw
forces."""
if self._calc is None:
raise RuntimeError('Atoms object has no calculator.')
forces = self._calc.get_forces(self)
if apply_constraint:
for constraint in self.constraints:
constraint.adjust_forces(self.arrays['positions'], forces)
return forces
def get_stress(self):
"""Calculate stress tensor.
Returns an array of the six independent components of the
symmetric stress tensor, in the traditional order
(s_xx, s_yy, s_zz, s_yz, s_xz, s_xy).
"""
if self._calc is None:
raise RuntimeError('Atoms object has no calculator.')
stress = self._calc.get_stress(self)
shape = getattr(stress, 'shape', None)
if shape == (3, 3):
return np.array([stress[0, 0], stress[1, 1], stress[2, 2],
stress[1, 2], stress[0, 2], stress[0, 1]])
else:
# Hopefully a 6-vector, but don't check in case some weird
# calculator does something else.
return stress
def get_stresses(self):
"""Calculate the stress-tensor of all the atoms.
Only available with calculators supporting per-atom energies and
stresses (e.g. classical potentials). Even for such calculators
there is a certain arbitrariness in defining per-atom stresses.
"""
if self._calc is None:
raise RuntimeError('Atoms object has no calculator.')
return self._calc.get_stresses(self)
def get_dipole_moment(self):
"""Calculate the electric dipole moment for the atoms object.
Only available for calculators which has a get_dipole_moment()
method."""
if self._calc is None:
raise RuntimeError('Atoms object has no calculator.')
try:
dipole = self._calc.get_dipole_moment(self)
except AttributeError:
raise AttributeError(
'Calculator object has no get_dipole_moment method.')
return dipole
def copy(self):
"""Return a copy."""
import copy
atoms = self.__class__(cell=self._cell, pbc=self._pbc, info=self.info)
atoms.arrays = {}
for name, a in self.arrays.items():
atoms.arrays[name] = a.copy()
atoms.constraints = copy.deepcopy(self.constraints)
atoms.adsorbate_info = copy.deepcopy(self.adsorbate_info)
return atoms
def __len__(self):
return len(self.arrays['positions'])
def get_number_of_atoms(self):
"""Returns the number of atoms.
Equivalent to len(atoms) in the standard ASE Atoms class.
"""
return len(self)
def __repr__(self):
num = self.get_atomic_numbers()
N = len(num)
if N == 0:
symbols = ''
elif N <= 60:
symbols = self.get_chemical_symbols(reduce=True)
else:
symbols = ''.join([chemical_symbols[Z] for Z in num[:15]]) + '...'
s = "%s(symbols='%s', " % (self.__class__.__name__, symbols)
for name in self.arrays:
if name == 'numbers':
continue
s += '%s=..., ' % name
if (self._cell - np.diag(self._cell.diagonal())).any():
s += 'cell=%s, ' % self._cell.tolist()
else:
s += 'cell=%s, ' % self._cell.diagonal().tolist()
s += 'pbc=%s, ' % self._pbc.tolist()
if len(self.constraints) == 1:
s += 'constraint=%s, ' % repr(self.constraints[0])
if len(self.constraints) > 1:
s += 'constraint=%s, ' % repr(self.constraints)
if self._calc is not None:
s += 'calculator=%s(...), ' % self._calc.__class__.__name__
return s[:-2] + ')'
def __add__(self, other):
atoms = self.copy()
atoms += other
return atoms
def extend(self, other):
"""Extend atoms object by appending atoms from *other*."""
if isinstance(other, Atom):
other = self.__class__([other])
n1 = len(self)
n2 = len(other)
for name, a1 in self.arrays.items():
a = np.zeros((n1 + n2,) + a1.shape[1:], a1.dtype)
a[:n1] = a1
a2 = other.arrays.get(name)
if a2 is not None:
a[n1:] = a2
self.arrays[name] = a
for name, a2 in other.arrays.items():
if name in self.arrays:
continue
a = np.empty((n1 + n2,) + a2.shape[1:], a2.dtype)
a[n1:] = a2
if name == 'masses':
a[:n1] = self.get_masses()
else:
a[:n1] = 0
self.set_array(name, a)
return self
__iadd__ = extend
def append(self, atom):
"""Append atom to end."""
self.extend(self.__class__([atom]))
def __getitem__(self, i):
"""Return a subset of the atoms.
i -- scalar integer, list of integers, or slice object
describing which atoms to return.
If i is a scalar, return an Atom object. If i is a list or a
slice, return an Atoms object with the same cell, pbc, and
other associated info as the original Atoms object. The
indices of the constraints will be shuffled so that they match
the indexing in the subset returned.
"""
if isinstance(i, int):
natoms = len(self)
if i < -natoms or i >= natoms:
raise IndexError('Index out of range.')
return Atom(atoms=self, index=i)
import copy
from ase.constraints import FixConstraint
atoms = self.__class__(cell=self._cell, pbc=self._pbc, info=self.info)
# TODO: Do we need to shuffle indices in adsorbate_info too?
atoms.adsorbate_info = self.adsorbate_info
atoms.arrays = {}
for name, a in self.arrays.items():
atoms.arrays[name] = a[i].copy()
# Constraints need to be deepcopied, since we need to shuffle
# the indices
atoms.constraints = copy.deepcopy(self.constraints)
condel = []
for con in atoms.constraints:
if isinstance(con, FixConstraint):
try:
con.index_shuffle(i)
except IndexError:
condel.append(con)
for con in condel:
atoms.constraints.remove(con)
return atoms
def __delitem__(self, i):
from ase.constraints import FixAtoms
check_constraint = np.array([isinstance(c, FixAtoms)
for c in self._constraints])
if len(self._constraints) > 0 and not check_constraint.all():
raise RuntimeError('Remove constraint using set_constraint() ' +
'before deleting atoms.')
mask = np.ones(len(self), bool)
mask[i] = False
for name, a in self.arrays.items():
self.arrays[name] = a[mask]
if len(self._constraints) > 0:
for n in range(len(self._constraints)):
self._constraints[n].delete_atom(range(len(mask))[i])
def pop(self, i=-1):
"""Remove and return atom at index *i* (default last)."""
atom = self[i]
atom.cut_reference_to_atoms()
del self[i]
return atom
def __imul__(self, m):
"""In-place repeat of atoms."""
if isinstance(m, int):
m = (m, m, m)
M = np.product(m)
n = len(self)
for name, a in self.arrays.items():
self.arrays[name] = np.tile(a, (M,) + (1,) * (len(a.shape) - 1))
positions = self.arrays['positions']
i0 = 0
for m0 in range(m[0]):
for m1 in range(m[1]):
for m2 in range(m[2]):
i1 = i0 + n
positions[i0:i1] += np.dot((m0, m1, m2), self._cell)
i0 = i1
if self.constraints is not None:
self.constraints = [c.repeat(m, n) for c in self.constraints]
self._cell = np.array([m[c] * self._cell[c] for c in range(3)])
return self
def repeat(self, rep):
"""Create new repeated atoms object.
The *rep* argument should be a sequence of three positive
integers like *(2,3,1)* or a single integer (*r*) equivalent
to *(r,r,r)*."""
atoms = self.copy()
atoms *= rep
return atoms
__mul__ = repeat
def translate(self, displacement):
"""Translate atomic positions.
The displacement argument can be a float an xyz vector or an
nx3 array (where n is the number of atoms)."""
self.arrays['positions'] += np.array(displacement)
def center(self, vacuum=None, axis=None):
"""Center atoms in unit cell.
Centers the atoms in the unit cell, so there is the same
amount of vacuum on all sides.
Parameters:
vacuum (default: None): If specified adjust the amount of
vacuum when centering. If vacuum=10.0 there will thus be 10
Angstrom of vacuum on each side.
axis (default: None): If specified, only act on the specified
axis. Default: Act on all axes.
"""
# Find the orientations of the faces of the unit cell
c = self.get_cell()
dirs = np.zeros_like(c)
for i in range(3):
dirs[i] = np.cross(c[i - 1], c[i - 2])
dirs[i] /= np.sqrt(np.dot(dirs[i], dirs[i])) # normalize
if np.dot(dirs[i], c[i]) < 0.0:
dirs[i] *= -1
# Now, decide how much each basis vector should be made longer
if axis is None:
axes = (0, 1, 2)
else:
axes = (axis,)
p = self.arrays['positions']
longer = np.zeros(3)
shift = np.zeros(3)
for i in axes:
p0 = np.dot(p, dirs[i]).min()
p1 = np.dot(p, dirs[i]).max()
height = np.dot(c[i], dirs[i])
if vacuum is not None:
lng = (p1 - p0 + 2 * vacuum) - height
else:
lng = 0.0 # Do not change unit cell size!
top = lng + height - p1
shf = 0.5 * (top - p0)
cosphi = np.dot(c[i], dirs[i]) / np.sqrt(np.dot(c[i], c[i]))
longer[i] = lng / cosphi
shift[i] = shf / cosphi
# Now, do it!
translation = np.zeros(3)
for i in axes:
nowlen = np.sqrt(np.dot(c[i], c[i]))
self._cell[i] *= 1 + longer[i] / nowlen
translation += shift[i] * c[i] / nowlen
self.arrays['positions'] += translation
def get_center_of_mass(self, scaled=False):
"""Get the center of mass.
If scaled=True the center of mass in scaled coordinates
is returned."""
m = self.arrays.get('masses')
if m is None:
m = atomic_masses[self.arrays['numbers']]
com = np.dot(m, self.arrays['positions']) / m.sum()
if scaled:
return np.linalg.solve(self._cell.T, com)
else:
return com
def get_moments_of_inertia(self, vectors=False):
"""Get the moments of inertia along the principal axes.
The three principal moments of inertia are computed from the
eigenvalues of the symmetric inertial tensor. Periodic boundary
conditions are ignored. Units of the moments of inertia are
amu*angstrom**2.
"""
com = self.get_center_of_mass()
positions = self.get_positions()
positions -= com # translate center of mass to origin
masses = self.get_masses()
#initialize elements of the inertial tensor
I11 = I22 = I33 = I12 = I13 = I23 = 0.0
for i in range(len(self)):
x, y, z = positions[i]
m = masses[i]
I11 += m * (y**2 + z**2)
I22 += m * (x**2 + z**2)
I33 += m * (x**2 + y**2)
I12 += -m * x * y
I13 += -m * x * z
I23 += -m * y * z
I = np.array([[I11, I12, I13],
[I12, I22, I23],
[I13, I23, I33]])
evals, evecs = np.linalg.eigh(I)
if vectors:
return evals, evecs.transpose()
else:
return evals
def get_angular_momentum(self):
"""Get total angular momentum with respect to the center of mass."""
com = self.get_center_of_mass()
positions = self.get_positions()
positions -= com # translate center of mass to origin
return np.cross(positions, self.get_momenta()).sum(0)
def rotate(self, v, a=None, center=(0, 0, 0), rotate_cell=False):
"""Rotate atoms.
Rotate the angle *a* around the vector *v*. If *a* is not
given, the length of *v* is used as the angle. If *a* is a
vector, then *v* is rotated into *a*. The point at *center*
is fixed. Use *center='COM'* to fix the center of mass.
Vectors can also be strings: 'x', '-x', 'y', ... .
Examples:
Rotate 90 degrees around the z-axis, so that the x-axis is
rotated into the y-axis:
>>> a = pi / 2
>>> atoms.rotate('z', a)
>>> atoms.rotate((0, 0, 1), a)
>>> atoms.rotate('-z', -a)
>>> atoms.rotate((0, 0, a))
>>> atoms.rotate('x', 'y')
"""
norm = np.linalg.norm
v = string2vector(v)
if a is None:
a = norm(v)
if isinstance(a, (float, int)):
v /= norm(v)
c = cos(a)
s = sin(a)
else:
v2 = string2vector(a)
v /= norm(v)
v2 /= norm(v2)
c = np.dot(v, v2)
v = np.cross(v, v2)
s = norm(v)
# In case *v* and *a* are parallel, np.cross(v, v2) vanish
# and can't be used as a rotation axis. However, in this
# case any rotation axis perpendicular to v2 will do.
eps = 1e-7
if s < eps:
v = np.cross((0, 0, 1), v2)
if norm(v) < eps:
v = np.cross((1, 0, 0), v2)
assert norm(v) >= eps
if s > 0:
v /= s
if isinstance(center, str) and center.lower() == 'com':
center = self.get_center_of_mass()
p = self.arrays['positions'] - center
self.arrays['positions'][:] = (c * p -
np.cross(p, s * v) +
np.outer(np.dot(p, v), (1.0 - c) * v) +
center)
if rotate_cell:
rotcell = self.get_cell()
rotcell[:] = (c * rotcell -
np.cross(rotcell, s * v) +
np.outer(np.dot(rotcell, v), (1.0 - c) * v))
self.set_cell(rotcell)
def rotate_euler(self, center=(0, 0, 0), phi=0.0, theta=0.0, psi=0.0):
"""Rotate atoms via Euler angles.
See e.g http://mathworld.wolfram.com/EulerAngles.html for explanation.
Parameters:
center :
The point to rotate about. A sequence of length 3 with the
coordinates, or 'COM' to select the center of mass.
phi :
The 1st rotation angle around the z axis.
theta :
Rotation around the x axis.
psi :
2nd rotation around the z axis.
"""
if isinstance(center, str) and center.lower() == 'com':
center = self.get_center_of_mass()
else:
center = np.array(center)
# First move the molecule to the origin In contrast to MATLAB,
# numpy broadcasts the smaller array to the larger row-wise,
# so there is no need to play with the Kronecker product.
rcoords = self.positions - center
# First Euler rotation about z in matrix form
D = np.array(((cos(phi), sin(phi), 0.),
(-sin(phi), cos(phi), 0.),
(0., 0., 1.)))
# Second Euler rotation about x:
C = np.array(((1., 0., 0.),
(0., cos(theta), sin(theta)),
(0., -sin(theta), cos(theta))))
# Third Euler rotation, 2nd rotation about z:
B = np.array(((cos(psi), sin(psi), 0.),
(-sin(psi), cos(psi), 0.),
(0., 0., 1.)))
# Total Euler rotation
A = np.dot(B, np.dot(C, D))
# Do the rotation
rcoords = np.dot(A, np.transpose(rcoords))
# Move back to the rotation point
self.positions = np.transpose(rcoords) + center
def get_dihedral(self, list):
"""Calculate dihedral angle.
Calculate dihedral angle between the vectors list[0]->list[1]
and list[2]->list[3], where list contains the atomic indexes
in question.
"""
# vector 0->1, 1->2, 2->3 and their normalized cross products:
a = self.positions[list[1]] - self.positions[list[0]]
b = self.positions[list[2]] - self.positions[list[1]]
c = self.positions[list[3]] - self.positions[list[2]]
bxa = np.cross(b, a)
bxa /= np.linalg.norm(bxa)
cxb = np.cross(c, b)
cxb /= np.linalg.norm(cxb)
angle = np.vdot(bxa, cxb)
# check for numerical trouble due to finite precision:
if angle < -1:
angle = -1
if angle > 1:
angle = 1
angle = np.arccos(angle)
if np.vdot(bxa, c) > 0:
angle = 2 * np.pi - angle
return angle
def _masked_rotate(self, center, axis, diff, mask):
# do rotation of subgroup by copying it to temporary atoms object
# and then rotating that
#
# recursive object definition might not be the most elegant thing,
# more generally useful might be a rotation function with a mask?
group = self.__class__()
for i in range(len(self)):
if mask[i]:
group += self[i]
group.translate(-center)
group.rotate(axis, diff)
group.translate(center)
# set positions in original atoms object
j = 0
for i in range(len(self)):
if mask[i]:
self.positions[i] = group[j].get_position()
j += 1
def set_dihedral(self, list, angle, mask=None):
"""
set the dihedral angle between vectors list[0]->list[1] and
list[2]->list[3] by changing the atom indexed by list[3]
if mask is not None, all the atoms described in mask
(read: the entire subgroup) are moved
example: the following defines a very crude
ethane-like molecule and twists one half of it by 30 degrees.
>>> atoms = Atoms('HHCCHH', [[-1, 1, 0], [-1, -1, 0], [0, 0, 0],
[1, 0, 0], [2, 1, 0], [2, -1, 0]])
>>> atoms.set_dihedral([1,2,3,4],7*pi/6,mask=[0,0,0,1,1,1])
"""
# if not provided, set mask to the last atom in the
# dihedral description
if mask is None:
mask = np.zeros(len(self))
mask[list[3]] = 1
# compute necessary in dihedral change, from current value
current = self.get_dihedral(list)
diff = angle - current
axis = self.positions[list[2]] - self.positions[list[1]]
center = self.positions[list[2]]
self._masked_rotate(center, axis, diff, mask)
def rotate_dihedral(self, list, angle, mask=None):
"""Rotate dihedral angle.
Complementing the two routines above: rotate a group by a
predefined dihedral angle, starting from its current
configuration
"""
start = self.get_dihedral(list)
self.set_dihedral(list, angle + start, mask)
def get_angle(self, list):
"""Get angle formed by three atoms.
calculate angle between the vectors list[0]->list[1] and
list[1]->list[2], where list contains the atomic indexes in
question."""
# normalized vector 1->0, 1->2:
v10 = self.positions[list[0]] - self.positions[list[1]]
v12 = self.positions[list[2]] - self.positions[list[1]]
v10 /= np.linalg.norm(v10)
v12 /= np.linalg.norm(v12)
angle = np.vdot(v10, v12)
angle = np.arccos(angle)
return angle
def set_angle(self, list, angle, mask=None):
"""Set angle formed by three atoms.
Sets the angle between vectors list[1]->list[0] and
list[1]->list[2].
Same usage as in set_dihedral."""
# If not provided, set mask to the last atom in the angle description
if mask is None:
mask = np.zeros(len(self))
mask[list[2]] = 1
# Compute necessary in angle change, from current value
current = self.get_angle(list)
diff = current - angle
# Do rotation of subgroup by copying it to temporary atoms object and
# then rotating that
v10 = self.positions[list[0]] - self.positions[list[1]]
v12 = self.positions[list[2]] - self.positions[list[1]]
v10 /= np.linalg.norm(v10)
v12 /= np.linalg.norm(v12)
axis = np.cross(v10, v12)
center = self.positions[list[1]]
self._masked_rotate(center, axis, diff, mask)
def rattle(self, stdev=0.001, seed=42):
"""Randomly displace atoms.
This method adds random displacements to the atomic positions,
taking a possible constraint into account. The random numbers are
drawn from a normal distribution of standard deviation stdev.
For a parallel calculation, it is important to use the same
seed on all processors! """
rs = np.random.RandomState(seed)
positions = self.arrays['positions']
self.set_positions(positions +
rs.normal(scale=stdev, size=positions.shape))
def get_distance(self, a0, a1, mic=False):
"""Return distance between two atoms.
Use mic=True to use the Minimum Image Convention.
"""
R = self.arrays['positions']
D = R[a1] - R[a0]
if mic:
Dr = np.linalg.solve(self._cell.T, D)
D = np.dot(Dr - np.round(Dr) * self._pbc, self._cell)
return np.linalg.norm(D)
def set_distance(self, a0, a1, distance, fix=0.5):
"""Set the distance between two atoms.
Set the distance between atoms *a0* and *a1* to *distance*.
By default, the center of the two atoms will be fixed. Use
*fix=0* to fix the first atom, *fix=1* to fix the second
atom and *fix=0.5* (default) to fix the center of the bond."""
R = self.arrays['positions']
D = R[a1] - R[a0]
x = 1.0 - distance / np.linalg.norm(D)
R[a0] += (x * fix) * D
R[a1] -= (x * (1.0 - fix)) * D
def get_scaled_positions(self):
"""Get positions relative to unit cell.
Atoms outside the unit cell will be wrapped into the cell in
those directions with periodic boundary conditions so that the
scaled coordinates are between zero and one."""
scaled = np.linalg.solve(self._cell.T, self.arrays['positions'].T).T
for i in range(3):
if self._pbc[i]:
# Yes, we need to do it twice.
# See the scaled_positions.py test
scaled[:, i] %= 1.0
scaled[:, i] %= 1.0
return scaled
def set_scaled_positions(self, scaled):
"""Set positions relative to unit cell."""
self.arrays['positions'][:] = np.dot(scaled, self._cell)
def get_temperature(self):
"""Get the temperature. in Kelvin"""
ekin = self.get_kinetic_energy() / len(self)
return ekin / (1.5 * units.kB)
def get_isotropic_pressure(self, stress):
"""Get the current calculated pressure, assume isotropic medium.
in Bar
"""
if type(stress) == type(1.0) or type(stress) == type(1):
return -stress * 1e-5 / units.Pascal
elif stress.shape == (3, 3):
return (-(stress[0, 0] + stress[1, 1] + stress[2, 2]) / 3.0) * \
1e-5 / units.Pascal
elif stress.shape == (6,):
return (-(stress[0] + stress[1] + stress[2]) / 3.0) * \
1e-5 / units.Pascal
else:
raise ValueError('The external stress has the wrong shape.')
def __eq__(self, other):
"""Check for identity of two atoms objects.
Identity means: same positions, atomic numbers, unit cell and
periodic boundary conditions."""
try:
a = self.arrays
b = other.arrays
return (len(self) == len(other) and
(a['positions'] == b['positions']).all() and
(a['numbers'] == b['numbers']).all() and
(self._cell == other.cell).all() and
(self._pbc == other.pbc).all())
except AttributeError:
return NotImplemented
def __ne__(self, other):
eq = self.__eq__(other)
if eq is NotImplemented:
return eq
else:
return not eq
__hash__ = None
def get_volume(self):
"""Get volume of unit cell."""
return abs(np.linalg.det(self._cell))
def _get_positions(self):
"""Return reference to positions-array for in-place manipulations."""
return self.arrays['positions']
def _set_positions(self, pos):
"""Set positions directly, bypassing constraints."""
self.arrays['positions'][:] = pos
positions = property(_get_positions, _set_positions,
doc='Attribute for direct ' +
'manipulation of the positions.')
def _get_atomic_numbers(self):
"""Return reference to atomic numbers for in-place
manipulations."""
return self.arrays['numbers']
numbers = property(_get_atomic_numbers, set_atomic_numbers,
doc='Attribute for direct ' +
'manipulation of the atomic numbers.')
def _get_cell(self):
"""Return reference to unit cell for in-place manipulations."""
return self._cell
cell = property(_get_cell, set_cell, doc='Attribute for direct ' +
'manipulation of the unit cell.')
def _get_pbc(self):
"""Return reference to pbc-flags for in-place manipulations."""
return self._pbc
pbc = property(_get_pbc, set_pbc,
doc='Attribute for direct manipulation ' +
'of the periodic boundary condition flags.')
def get_name(self):
"""Return a name extracted from the elements."""
elements = {}
for a in self:
try:
elements[a.symbol] += 1
except:
elements[a.symbol] = 1
name = ''
for element in elements:
name += element
if elements[element] > 1:
name += str(elements[element])
return name
def write(self, filename, format=None, **kwargs):
"""Write yourself to a file."""
from ase.io import write
write(filename, self, format, **kwargs)
def edit(self):
"""Modify atoms interactively through ag viewer.
Conflicts leading to undesirable behaviour might arise
when matplotlib has been pre-imported with certain
incompatible backends and while trying to use the
plot feature inside the interactive ag. To circumvent,
please set matplotlib.use('gtk') before calling this
method.
"""
from ase.gui.images import Images
from ase.gui.gui import GUI
images = Images([self])
gui = GUI(images)
gui.run()
# use atoms returned from gui:
# (1) delete all currently available atoms
self.set_constraint()
for z in range(len(self)):
self.pop()
edited_atoms = gui.images.get_atoms(0)
# (2) extract atoms from edit session
self.extend(edited_atoms)
self.set_constraint(edited_atoms._get_constraints())
self.set_cell(edited_atoms.get_cell())
self.set_initial_magnetic_moments(edited_atoms.get_magnetic_moments())
self.set_tags(edited_atoms.get_tags())
return
def string2symbols(s):
"""Convert string to list of chemical symbols."""
n = len(s)
if n == 0:
return []
c = s[0]
if c.isdigit():
i = 1
while i < n and s[i].isdigit():
i += 1
return int(s[:i]) * string2symbols(s[i:])
if c == '(':
p = 0
for i, c in enumerate(s):
if c == '(':
p += 1
elif c == ')':
p -= 1
if p == 0:
break
j = i + 1
while j < n and s[j].isdigit():
j += 1
if j > i + 1:
m = int(s[i + 1:j])
else:
m = 1
return m * string2symbols(s[1:i]) + string2symbols(s[j:])
if c.isupper():
i = 1
if 1 < n and s[1].islower():
i += 1
j = i
while j < n and s[j].isdigit():
j += 1
if j > i:
m = int(s[i:j])
else:
m = 1
return m * [s[:i]] + string2symbols(s[j:])
else:
raise ValueError
def symbols2numbers(symbols):
if isinstance(symbols, str):
symbols = string2symbols(symbols)
numbers = []
for s in symbols:
if isinstance(s, str):
numbers.append(atomic_numbers[s])
else:
numbers.append(s)
return numbers
def string2vector(v):
if isinstance(v, str):
if v[0] == '-':
return -string2vector(v[1:])
w = np.zeros(3)
w['xyz'.index(v)] = 1.0
return w
return np.array(v, float)
def default(data, dflt):
"""Helper function for setting default values."""
if data is None:
return None
elif isinstance(data, (list, tuple)):
newdata = []
allnone = True
for x in data:
if x is None:
newdata.append(dflt)
else:
newdata.append(x)
allnone = False
if allnone:
return None
return newdata
else:
return data
python-ase-3.6.0.2515/ase/calculators/ 0000755 0001754 0001754 00000000000 11757245036 016276 5 ustar askhl askhl python-ase-3.6.0.2515/ase/calculators/aims.py 0000644 0001754 0001754 00000046340 11666144730 017606 0 ustar askhl askhl """This module defines an ASE interface to FHI-aims.
Felix Hanke hanke@liverpool.ac.uk
Jonas Bjork j.bjork@liverpool.ac.uk
"""
from general import Calculator
import os
import sys
from os.path import join, isfile, islink
import numpy as np
import ase
float_keys = [
'charge',
'charge_mix_param',
'default_initial_moment',
'hartree_convergence_parameter',
'harmonic_length_scale',
'ini_linear_mix_param',
'ini_spin_mix_parma',
'initial_moment',
'MD_MB_init',
'MD_time_step',
'prec_mix_param',
'set_vacuum_level',
'spin_mix_param',
]
exp_keys = [
'sc_accuracy_eev',
'sc_accuracy_etot',
'sc_accuracy_forces',
'sc_accuracy_rho',
]
string_keys = [
'communication_type',
'density_update_method',
'KS_method',
'mixer',
'output_level',
'packed_matrix_format',
'relax_unit_cell',
'restart',
'restart_read_only',
'restart_write_only',
'spin',
'total_energy_method',
'qpe_calc',
'xc',
]
int_keys = [
'empty_states',
'ini_linear_mixing',
'max_relaxation_steps',
'multiplicity',
'n_max_pulay',
'sc_iter_limit',
'walltime',
]
bool_keys = [
'collect_eigenvectors',
'compute_forces',
'compute_kinetic',
'compute_numerical_stress',
'distributed_spline_storage',
'evaluate_work_function',
'final_forces_cleaned',
'hessian_to_restart_geometry',
'load_balancing',
'MD_clean_rotations',
'MD_restart',
'restart_relaxations',
'squeeze_memory',
'use_density_matrix',
'use_dipole_correction',
'use_local_index',
'use_logsbt',
'vdw_correction_hirshfeld',
]
list_keys = [
'init_hess',
'k_grid',
'k_offset',
'MD_run',
'MD_schedule',
'MD_segment',
'mixer_threshold',
'occupation_type',
'output',
'preconditioner',
'relativistic',
'relax_geometry',
]
input_keys = [
'run_command',
'run_dir',
'species_dir',
'cubes',
'output_template',
'track_output',
]
input_parameters_default = {'run_command':None,
'run_dir':None,
'species_dir':None,
'cubes':None,
'output_template':'aims',
'track_output':False}
class Aims(Calculator):
def __init__(self, **kwargs):
self.name = 'Aims'
self.float_params = {}
self.exp_params = {}
self.string_params = {}
self.int_params = {}
self.bool_params = {}
self.list_params = {}
self.input_parameters = {}
for key in float_keys:
self.float_params[key] = None
for key in exp_keys:
self.exp_params[key] = None
for key in string_keys:
self.string_params[key] = None
for key in int_keys:
self.int_params[key] = None
for key in bool_keys:
self.bool_params[key] = None
for key in list_keys:
self.list_params[key] = None
for key in input_keys:
self.input_parameters[key] = input_parameters_default[key]
if os.environ.has_key('AIMS_SPECIES_DIR'):
self.input_parameters['species_dir'] = os.environ['AIMS_SPECIES_DIR']
if os.environ.has_key('AIMS_COMMAND'):
self.input_parameters['run_command'] = os.environ['AIMS_COMMAND']
self.positions = None
self.atoms = None
self.run_counts = 0
self.set(**kwargs)
def set(self, **kwargs):
if 'control' in kwargs:
fname = kwargs['control']
from ase.io.aims import read_aims_calculator
file = open(fname, 'r')
calc_temp = None
while True:
line = file.readline()
if "List of parameters used to initialize the calculator:" in line:
file.readline()
calc_temp = read_aims_calculator(file)
break
if calc_temp is not None:
self.float_params = calc_temp.float_params
self.exp_params = calc_temp.exp_params
self.string_params = calc_temp.string_params
self.int_params = calc_temp.int_params
self.bool_params = calc_temp.bool_params
self.list_params = calc_temp.list_params
self.input_parameters = calc_temp.input_parameters
else:
raise TypeError("Control file to be imported can not be read by ASE = " + fname)
for key in kwargs:
if self.float_params.has_key(key):
self.float_params[key] = kwargs[key]
elif self.exp_params.has_key(key):
self.exp_params[key] = kwargs[key]
elif self.string_params.has_key(key):
self.string_params[key] = kwargs[key]
elif self.int_params.has_key(key):
self.int_params[key] = kwargs[key]
elif self.bool_params.has_key(key):
self.bool_params[key] = kwargs[key]
elif self.list_params.has_key(key):
self.list_params[key] = kwargs[key]
elif self.input_parameters.has_key(key):
self.input_parameters[key] = kwargs[key]
elif key is not 'control':
raise TypeError('Parameter not defined: ' + key)
def update(self, atoms):
if self.calculation_required(atoms,[]):
self.calculate(atoms)
def calculation_required(self, atoms,quantities):
if (self.positions is None or
(self.atoms != atoms) or
(self.atoms != self.old_atoms) or
(self.float_params != self.old_float_params) or
(self.exp_params != self.old_exp_params) or
(self.string_params != self.old_string_params) or
(self.int_params != self.old_int_params) or
(self.bool_params != self.old_bool_params) or
(self.list_params != self.old_list_params) or
(self.input_parameters != self.old_input_parameters)):
return True
else:
return False
def calculate(self, atoms):
"""Generate necessary files in the working directory.
If the directory does not exist it will be created.
"""
positions = atoms.get_positions()
have_lattice_vectors = atoms.get_pbc().any()
have_k_grid = self.list_params['k_grid']
if have_lattice_vectors and not have_k_grid:
raise RuntimeError("Found lattice vectors but no k-grid!")
if not have_lattice_vectors and have_k_grid:
raise RuntimeError("Found k-grid but no lattice vectors!")
from ase.io.aims import write_aims
write_aims('geometry.in', atoms)
self.write_control()
self.write_species()
self.run()
self.converged = self.read_convergence()
if not self.converged:
os.system("tail -20 "+self.out)
raise RuntimeError("FHI-aims did not converge!\n"+
"The last lines of output are printed above "+
"and should give an indication why.")
self.set_results(atoms)
def set_results(self,atoms):
self.read(atoms)
self.old_float_params = self.float_params.copy()
self.old_exp_params = self.exp_params.copy()
self.old_string_params = self.string_params.copy()
self.old_int_params = self.int_params.copy()
self.old_input_parameters = self.input_parameters.copy()
self.old_bool_params = self.bool_params.copy()
self.old_list_params = self.list_params.copy()
self.old_atoms = self.atoms.copy()
def run(self):
if self.input_parameters['track_output']:
self.out = self.input_parameters['output_template']+str(self.run_counts)+'.out'
self.run_counts += 1
else:
self.out = self.input_parameters['output_template']+'.out'
if self.input_parameters['run_command']:
aims_command = self.input_parameters['run_command']
elif os.environ.has_key('AIMS_COMMAND'):
aims_command = os.environ['AIMS_COMMAND']
else:
raise RuntimeError("No specification for running FHI-aims. Aborting!")
aims_command = aims_command + ' >> '
if self.input_parameters['run_dir']:
aims_command = aims_command + self.input_parameters['run_dir'] + '/'
aims_command = aims_command + self.out
self.write_parameters('#',self.out)
exitcode = os.system(aims_command)
if exitcode != 0:
raise RuntimeError('FHI-aims exited with exit code: %d. ' % exitcode)
if self.input_parameters['cubes'] and self.input_parameters['track_output']:
self.input_parameters['cubes'].move_to_base_name(self.input_parameters['output_template']+str(self.run_counts-1))
def write_parameters(self,prefix,filename):
output = open(filename,'w')
output.write(prefix+'=======================================================\n')
output.write(prefix+'FHI-aims file: '+filename+'\n')
output.write(prefix+'Created using the Atomic Simulation Environment (ASE)\n'+prefix+'\n')
output.write(prefix+'List of parameters used to initialize the calculator:\n')
output.write(prefix+'=======================================================\n')
for key, val in self.float_params.items():
if val is not None:
output.write('%-35s%5.6f\n' % (key, val))
for key, val in self.exp_params.items():
if val is not None:
output.write('%-35s%5.2e\n' % (key, val))
for key, val in self.string_params.items():
if val is not None:
output.write('%-35s%s\n' % (key, val))
for key, val in self.int_params.items():
if val is not None:
output.write('%-35s%d\n' % (key, val))
for key, val in self.bool_params.items():
if val is not None:
if key == 'vdw_correction_hirshfeld' and val:
output.write('%-35s\n' % (key))
elif val:
output.write('%-35s.true.\n' % (key))
elif key != 'vdw_correction_hirshfeld':
output.write('%-35s.false.\n' % (key))
for key, val in self.list_params.items():
if val is not None:
if key == 'output':
if not isinstance(val,(list,tuple)):
val = [val]
for output_type in val:
output.write('%-35s%s\n' % (key,str(output_type)))
else:
output.write('%-35s' % (key))
if isinstance(val,str):
output.write(val)
else:
for sub_value in val:
output.write(str(sub_value)+' ')
output.write('\n')
for key, val in self.input_parameters.items():
if key is 'cubes':
if val:
val.write(output)
elif val and val != input_parameters_default[key]:
output.write(prefix+'%-34s%s\n' % (key,val))
output.write(prefix+'=======================================================\n\n')
output.close()
def __repr__(self):
items = self.float_params.items()+self.exp_params.items() \
+self.string_params.items()+self.int_params.items()
rep = 'Aims('
for key, val in items:
if val is not None:
rep += key+' '+str(val)+', '
for key, val in self.bool_params.items():
if val is not None:
if key == 'vdw_correction_hirshfeld' and val:
rep += key + ', '
elif val:
rep += key+' .true., '
elif key != 'vdw_correction_hirshfeld':
rep += key+' .false., '
for key, val in self.list_params.items():
if val is not None:
if key == 'output':
if not isinstance(val,(list,tuple)):
val = [val]
for output_type in val:
rep += key+' '+str(output_type)+', '
else:
rep += key
if isinstance(val,str):
rep += ' '+val
else:
for sub_value in val:
rep += ' '+str(sub_value)
rep += ', '
for key, val in self.input_parameters.items():
if val and val != input_parameters_default[key]:
rep += key+' '+val+', '
return rep[:-2]+')'
def write_control(self, file = 'control.in'):
"""Writes the control.in file."""
self.write_parameters('#',file)
def write_species(self, file = 'control.in'):
from ase.data import atomic_numbers
if not self.input_parameters['species_dir']:
raise RuntimeError('Missing species directory, THIS MUST BE SPECIFIED!')
control = open(file, 'a')
species_path = self.input_parameters['species_dir']
symbols = self.atoms.get_chemical_symbols()
symbols2 = []
for n, symbol in enumerate(symbols):
if symbol not in symbols2:
symbols2.append(symbol)
for symbol in symbols2:
fd = join(species_path, '%02i_%s_default' % (atomic_numbers[symbol], symbol))
for line in open(fd, 'r'):
control.write(line)
control.close()
def get_dipole_moment(self, atoms):
if self.list_params['output'] is None or 'dipole' not in self.list_params['output']:
raise RuntimeError('output=[\'dipole\'] has to be set.')
elif atoms.get_pbc().any():
raise RuntimeError('FHI-aims does not allow this for systems with periodic boundary conditions.')
self.update(atoms)
return self.dipole
def read_dipole(self):
"""Method that reads the electric dipole moment from the output file."""
dipolemoment=np.zeros([1,3])
for line in open(self.out, 'r'):
if line.rfind('Total dipole moment [eAng]') > -1:
dipolemoment=np.array([float(f) for f in line.split()[6:10]])
return dipolemoment
def read_energy(self, all=None):
for line in open(self.out, 'r'):
if line.rfind('Total energy corrected') > -1:
E0 = float(line.split()[5])
elif line.rfind('Total energy uncorrected') > -1:
F = float(line.split()[5])
energy_free, energy_zero = F, E0
return [energy_free, energy_zero]
def read_forces(self, atoms, all=False):
"""Method that reads forces from the output file.
If 'all' is switched on, the forces for all ionic steps
in the output file will be returned, in other case only the
forces for the last ionic configuration are returned."""
lines = open(self.out, 'r').readlines()
forces = np.zeros([len(atoms), 3])
for n, line in enumerate(lines):
if line.rfind('Total atomic forces') > -1:
for iatom in range(len(atoms)):
data = lines[n+iatom+1].split()
for iforce in range(3):
forces[iatom, iforce] = float(data[2+iforce])
return forces
def read_stress(self):
lines = open(self.out, 'r').readlines()
stress = None
for n, line in enumerate(lines):
if line.rfind('Calculation of numerical stress completed') > -1:
stress = []
for i in [n+8,n+9,n+10]:
data = lines[i].split()
stress += [float(data[2]),float(data[3]),float(data[4])]
# rearrange in 6-component form and return
if stress is not None:
return np.array([stress[0], stress[4], stress[8], stress[5], stress[2], stress[1]])
else:
return
def get_stress(self, atoms):
self.update(atoms)
return self.stress
# methods that should be quickly implemented some time, haven't had time yet:
def read_fermi(self):
"""Method that reads Fermi energy from output file"""
return
def read_magnetic_moment(self):
return
def read_convergence(self):
converged = False
lines = open(self.out, 'r').readlines()
for n, line in enumerate(lines):
if line.rfind('Have a nice day') > -1:
converged = True
return converged
def read_eigenvalues(self, kpt=0, spin=0):
return
class AimsCube:
""" object to ensure the output of cube files, can be attached to Aims object"""
def __init__(self,origin=(0,0,0),
edges=[(0.1,0.0,0.0),(0.0,0.1,0.0),(0.0,0.0,0.1)],
points=(50,50,50),plots=None):
""" parameters:
origin, edges, points = same as in the FHI-aims output
plots: what to print, same names as in FHI-aims """
self.name = 'AimsCube'
self.origin = origin
self.edges = edges
self.points = points
self.plots = plots
def ncubes(self):
"""returns the number of cube files to output """
if self.plots:
number = len(self.plots)
else:
number = 0
return number
def set(self,**kwargs):
""" set any of the parameters ... """
# NOT IMPLEMENTED AT THE MOMENT!
def move_to_base_name(self,basename):
""" when output tracking is on or the base namem is not standard,
this routine will rename add the base to the cube file output for
easier tracking """
for plot in self.plots:
found = False
cube = plot.split()
if cube[0] == 'total_density' or cube[0] == 'spin_density' or cube[0] == 'delta_density':
found = True
old_name = cube[0]+'.cube'
new_name = basename+'.'+old_name
if cube[0] == 'eigenstate' or cube[0] == 'eigenstate_density':
found = True
state = int(cube[1])
s_state = cube[1]
for i in [10,100,1000,10000]:
if state < i:
s_state = '0'+s_state
old_name = cube[0]+'_'+s_state+'_spin_1.cube'
new_name = basename+'.'+old_name
if found:
os.system("mv "+old_name+" "+new_name)
def add_plot(self,name):
""" in case you forgot one ... """
plots += [name]
def write(self,file):
""" write the necessary output to the already opened control.in """
file.write('output cube '+self.plots[0]+'\n')
file.write(' cube origin ')
for ival in self.origin:
file.write(str(ival)+' ')
file.write('\n')
for i in range(3):
file.write(' cube edge '+str(self.points[i])+' ')
for ival in self.edges[i]:
file.write(str(ival)+' ')
file.write('\n')
if self.ncubes() > 1:
for i in range(self.ncubes()-1):
file.write('output cube '+self.plots[i+1]+'\n')
python-ase-3.6.0.2515/ase/calculators/__init__.py 0000644 0001754 0001754 00000000100 11721407205 020363 0 ustar askhl askhl """Interfaces to different ASE compatible force-calculators."""
python-ase-3.6.0.2515/ase/calculators/emt.py 0000644 0001754 0001754 00000024347 11633577665 017460 0 ustar askhl askhl """Effective medium theory potential."""
from math import sqrt, exp, log, pi
import numpy as np
import sys
from ase.data import chemical_symbols
from ase.units import Bohr
from ase.calculators.neighborlist import NeighborList
parameters = {
# E0 s0 V0 eta2 kappa lambda n0
# eV bohr eV bohr^-1 bohr^-1 bohr^-1 bohr^-3
'Al': (-3.28, 3.00, 1.493, 1.240, 2.000, 1.169, 0.00700),
'Cu': (-3.51, 2.67, 2.476, 1.652, 2.740, 1.906, 0.00910),
'Ag': (-2.96, 3.01, 2.132, 1.652, 2.790, 1.892, 0.00547),
'Au': (-3.80, 3.00, 2.321, 1.674, 2.873, 2.182, 0.00703),
'Ni': (-4.44, 2.60, 3.673, 1.669, 2.757, 1.948, 0.01030),
'Pd': (-3.90, 2.87, 2.773, 1.818, 3.107, 2.155, 0.00688),
'Pt': (-5.85, 2.90, 4.067, 1.812, 3.145, 2.192, 0.00802),
# extra parameters - just for fun ...
'H': (-3.21, 1.31, 0.132, 2.652, 2.790, 3.892, 0.00547),
'C': (-3.50, 1.81, 0.332, 1.652, 2.790, 1.892, 0.01322),
'N': (-5.10, 1.88, 0.132, 1.652, 2.790, 1.892, 0.01222),
'O': (-4.60, 1.95, 0.332, 1.652, 2.790, 1.892, 0.00850)}
beta = 1.809 # (16 * pi / 3)**(1.0 / 3) / 2**0.5,
# but preserve historical rounding
class EMT:
disabled = False # Set to True to disable (asap does this).
def __init__(self, fakestress=False):
self.energy = None
self.name = 'EMT'
self.version = '1.0'
# fakestress is needed to fake some stress value for the testsuite
# in order to test the filter functionality.
self.fakestress = fakestress
if self.disabled:
print >> sys.stderr, """
ase.EMT has been disabled by Asap. Most likely, you
intended to use Asap's EMT calculator, but accidentally
imported ase's EMT calculator after Asap's. This could
happen if your script contains the lines
from asap3 import *
from ase.calculators.emt import EMT
Swap the two lines to solve the problem.
(or 'from ase import *' in older versions of ASE.) Swap
the two lines to solve the problem.
In the UNLIKELY event that you actually wanted to use
ase.calculators.emt.EMT although asap3 is loaded into memory,
please reactivate it with the command
ase.calculators.emt.EMT.disabled = False
"""
raise RuntimeError('ase.EMT has been disabled. ' +
'See message printed above.')
def get_name(self):
return self.name
def get_version(self):
return self.version
def get_spin_polarized(self):
return False
def initialize(self, atoms):
self.par = {}
self.rc = 0.0
self.numbers = atoms.get_atomic_numbers()
maxseq = max(par[1] for par in parameters.values()) * Bohr
rc = self.rc = beta * maxseq * 0.5 * (sqrt(3) + sqrt(4))
rr = rc * 2 * sqrt(4) / (sqrt(3) + sqrt(4))
self.acut = np.log(9999.0) / (rr - rc)
for Z in self.numbers:
if Z not in self.par:
p = parameters[chemical_symbols[Z]]
s0 = p[1] * Bohr
eta2 = p[3] / Bohr
kappa = p[4] / Bohr
x = eta2 * beta * s0
gamma1 = 0.0
gamma2 = 0.0
for i, n in enumerate([12, 6, 24]):
r = s0 * beta * sqrt(i + 1)
x = n / (12 * (1.0 + exp(self.acut * (r - rc))))
gamma1 += x * exp(-eta2 * (r - beta * s0))
gamma2 += x * exp(-kappa / beta * (r - beta * s0))
self.par[Z] = {'E0': p[0],
's0': s0,
'V0': p[2],
'eta2': eta2,
'kappa': kappa,
'lambda': p[5] / Bohr,
'n0': p[6] / Bohr**3,
'rc': rc,
'gamma1': gamma1,
'gamma2': gamma2}
#if rc + 0.5 > self.rc:
# self.rc = rc + 0.5
self.ksi = {}
for s1, p1 in self.par.items():
self.ksi[s1] = {}
for s2, p2 in self.par.items():
#self.ksi[s1][s2] = (p2['n0'] / p1['n0'] *
# exp(eta1 * (p1['s0'] - p2['s0'])))
self.ksi[s1][s2] = p2['n0'] / p1['n0']
self.forces = np.empty((len(atoms), 3))
self.sigma1 = np.empty(len(atoms))
self.deds = np.empty(len(atoms))
self.nl = NeighborList([0.5 * self.rc + 0.25] * len(atoms),
self_interaction=False)
def update(self, atoms):
if (self.energy is None or
len(self.numbers) != len(atoms) or
(self.numbers != atoms.get_atomic_numbers()).any()):
self.initialize(atoms)
self.calculate(atoms)
elif ((self.positions != atoms.get_positions()).any() or
(self.pbc != atoms.get_pbc()).any() or
(self.cell != atoms.get_cell()).any()):
self.calculate(atoms)
def calculation_required(self, atoms, quantities):
if len(quantities) == 0:
return False
return (self.energy is None or
len(self.numbers) != len(atoms) or
(self.numbers != atoms.get_atomic_numbers()).any() or
(self.positions != atoms.get_positions()).any() or
(self.pbc != atoms.get_pbc()).any() or
(self.cell != atoms.get_cell()).any())
def get_number_of_iterations(self):
return 0
def get_potential_energy(self, atoms):
self.update(atoms)
return self.energy
def get_numeric_forces(self, atoms):
self.update(atoms)
p = atoms.positions
p0 = p.copy()
forces = np.empty_like(p)
eps = 0.0001
for a in range(len(p)):
for c in range(3):
p[a, c] += eps
self.calculate(atoms)
de = self.energy
p[a, c] -= 2 * eps
self.calculate(atoms)
de -= self.energy
p[a, c] += eps
forces[a, c] = -de / (2 * eps)
p[:] = p0
return forces
def get_forces(self, atoms):
self.update(atoms)
return self.forces.copy()
def get_stress(self, atoms):
if self.fakestress:
return np.zeros((6))
else:
raise NotImplementedError
def calculate(self, atoms):
self.positions = atoms.get_positions().copy()
self.cell = atoms.get_cell().copy()
self.pbc = atoms.get_pbc().copy()
self.nl.update(atoms)
self.energy = 0.0
self.sigma1[:] = 0.0
self.forces[:] = 0.0
natoms = len(atoms)
for a1 in range(natoms):
Z1 = self.numbers[a1]
p1 = self.par[Z1]
ksi = self.ksi[Z1]
neighbors, offsets = self.nl.get_neighbors(a1)
offsets = np.dot(offsets, atoms.cell)
for a2, offset in zip(neighbors, offsets):
d = self.positions[a2] + offset - self.positions[a1]
r = sqrt(np.dot(d, d))
if r < self.rc + 0.5:
Z2 = self.numbers[a2]
p2 = self.par[Z2]
self.interact1(a1, a2, d, r, p1, p2, ksi[Z2])
for a in range(natoms):
Z = self.numbers[a]
p = self.par[Z]
try:
ds = -log(self.sigma1[a] / 12) / (beta * p['eta2'])
except (OverflowError, ValueError):
self.deds[a] = 0.0
self.energy -= p['E0']
continue
x = p['lambda'] * ds
y = exp(-x)
z = 6 * p['V0'] * exp(-p['kappa'] * ds)
self.deds[a] = ((x * y * p['E0'] * p['lambda'] + p['kappa'] * z) /
(self.sigma1[a] * beta * p['eta2']))
e = p['E0'] * ((1 + x) * y - 1) + z
self.energy += p['E0'] * ((1 + x) * y - 1) + z
for a1 in range(natoms):
Z1 = self.numbers[a1]
p1 = self.par[Z1]
ksi = self.ksi[Z1]
neighbors, offsets = self.nl.get_neighbors(a1)
offsets = np.dot(offsets, atoms.cell)
for a2, offset in zip(neighbors, offsets):
d = self.positions[a2] + offset - self.positions[a1]
r = sqrt(np.dot(d, d))
if r < self.rc + 0.5:
Z2 = self.numbers[a2]
p2 = self.par[Z2]
self.interact2(a1, a2, d, r, p1, p2, ksi[Z2])
def interact1(self, a1, a2, d, r, p1, p2, ksi):
x = exp(self.acut * (r - self.rc))
theta = 1.0 / (1.0 + x)
y1 = (0.5 * p1['V0'] * exp(-p2['kappa'] * (r / beta - p2['s0'])) *
ksi / p1['gamma2'] * theta)
y2 = (0.5 * p2['V0'] * exp(-p1['kappa'] * (r / beta - p1['s0'])) /
ksi / p2['gamma2'] * theta)
self.energy -= y1 + y2
f = ((y1 * p2['kappa'] + y2 * p1['kappa']) / beta +
(y1 + y2) * self.acut * theta * x) * d / r
self.forces[a1] += f
self.forces[a2] -= f
self.sigma1[a1] += (exp(-p2['eta2'] * (r - beta * p2['s0'])) *
ksi * theta / p1['gamma1'])
self.sigma1[a2] += (exp(-p1['eta2'] * (r - beta * p1['s0'])) /
ksi * theta / p2['gamma1'])
def interact2(self, a1, a2, d, r, p1, p2, ksi):
x = exp(self.acut * (r - self.rc))
theta = 1.0 / (1.0 + x)
y1 = (exp(-p2['eta2'] * (r - beta * p2['s0'])) *
ksi / p1['gamma1'] * theta * self.deds[a1])
y2 = (exp(-p1['eta2'] * (r - beta * p1['s0'])) /
ksi / p2['gamma1'] * theta * self.deds[a2])
f = ((y1 * p2['eta2'] + y2 * p1['eta2']) +
(y1 + y2) * self.acut * theta * x) * d / r
self.forces[a1] -= f
self.forces[a2] += f
def set_atoms(self,*args,**kwargs):
'empty function for compatibility with other calculators and tests'
pass
python-ase-3.6.0.2515/ase/calculators/nwchem.py 0000644 0001754 0001754 00000032017 11721400523 020115 0 ustar askhl askhl """This module defines an ASE interface to NWchem
http://www.nwchem-sw.org/
"""
import os
import sys
import numpy as np
from ase.units import Hartree, Bohr
from ase.io.nwchem import write_nwchem, read_nwchem
from ase.calculators.general import Calculator
class KPoint:
def __init__(self, s):
self.s = s
self.eps_n = []
self.f_n = []
class NWchem(Calculator):
def __init__(self,
label='nwchem',
task='energy',
geometry=None,
xc='LDA',
convergence = {'energy' : None,
'density' : None,
'gradient': None,
'lshift': None, # set to 0.0 for nolevelshifting
},
smear=0.001*Hartree, # smear must be specified to appear in out!
grid=None,
tolerances=None,
cgmin=False,
maxiter = 120,
basis='3-21G',
basispar=None,
ecp=None,
so=None,
charge=None,
multiplicity=None,
spinorbit=False,
kpts=None,
dftcontrol='', # additional dft control string
control='', # additional outside of dft block control string
):
"""Construct NWchem-calculator object.
Parameters
==========
label: str
Prefix to use for filenames (label.nw, label.out, ...).
Default is 'nwchem'.
xc: str
Exchange-correlation functional. LDA and PBE are predefined,
use nchem names instead.
basis: str
Basis set
maxiter: int
Maximal number of iteratations in self-consistent field convergence.
"""
self.label = label
self.task = task
self.geometry = geometry
self.xc = xc
self.convergence = convergence
self.smear = round(smear/Hartree, 4)
self.grid = grid
self.tolerances = tolerances
self.cgmin = cgmin
self.maxiter = maxiter
self.basis = basis
if basispar is not None:
self.basispar = 'basis ' + basispar
else:
self.basispar = 'basis'
self.ecp = ecp
self.so = so
self.charge = charge
self.multiplicity = multiplicity
self.spinorbit = spinorbit
self.kpts = kpts
self.dftcontrol = dftcontrol
self.control = control
# does nwchem have stress ???
self.stress = np.zeros((3, 3))
# atoms must be set
self.atoms = None
self.converged = False
def execute(self, command):
from subprocess import Popen, PIPE
try:
# the sub process gets started here
proc = Popen([command], shell=True, stderr=PIPE)
error = proc.communicate()[1]
if error:
raise OSError(error + '\ncheck ' + self.output)
except OSError, e:
print >> sys.stderr, 'Execution failed:', e
sys.exit(1)
def run(self):
"""Method which explicitely runs Nwchem."""
command = os.environ.get('NWCHEM_COMMAND', 'nwchem')
# The label may contain escapable characters!
self.execute(command + ' "' + \
self.label + '.nw" > "' + self.output + '"')
def get_forces(self, atoms):
self.get_potential_energy(atoms)
return self.forces
def get_ibz_k_points(self):
return np.array([0., 0., 0.])
def get_electronic_temperature(self):
return self.electronic_temperature
def read_smear(self):
smear = None
for line in open(self.label + '.out'): # find last one
if line.find('Smearing applied:') != -1:
smear = float(line.split(':')[1].split()[0].strip().lower().replace('d', 'e'))
return smear
def get_number_of_bands(self):
return self.nvector
def read_number_of_bands(self):
nvector = 0
for line in open(self.label + '.out'):
if line.find('Vector ') != -1: # count all printed vectors
nvector += 1
if not nvector:
nvector = None
return nvector
def get_number_of_electrons(self):
return self.nelect
def read_number_of_electrons(self):
nelect = None
for line in open(self.label + '.out'): # find last one
if line.find('of electrons') != -1:
nelect = float(line.split(':')[1].strip())
return nelect
def get_number_of_iterations(self):
return self.niter
def read_number_of_iterations(self):
niter = 0
for line in open(self.label + '.out'):
if line.find('d= ') != -1: # count all iterations
niter += 1
if not niter:
niter = None
return niter
def get_magnetic_moment(self, atoms):
return self.magnetic_moment
def read_magnetic_moment(self):
magmom = None
for line in open(self.label + '.out'):
if line.find('Spin multiplicity') != -1: # last one
magmom = float(line.split(':')[-1].strip()) - 1
return magmom
def get_magnetic_moments(self, atoms):
# local magnetic moments are not available in nwchem
# so set the total magnetic moment on the atom no. 0 and fill with 0.0
magmoms = [0.0 for a in range(len(atoms))]
magmoms[0] = self.get_magnetic_moment(atoms)
return np.array(magmoms)
def get_dipole_moment(self, atoms=None):
return self.dipole
def read_dipole_moment(self):
dipolemoment=[]
for line in open(self.label + '.out'):
for component in [
'1 1 0 0',
'1 0 1 0',
'1 0 0 1'
]:
if line.find(component) != -1:
value = float(line.split(component)[1].split()[0]) # total dipole component
value = value * Bohr
dipolemoment.append(value)
if len(dipolemoment) == 0:
dipolemoment = None
return dipolemoment
def get_potential_energy(self, atoms):
# update atoms
self.set_atoms(atoms)
# if update of energy is neccessary
if self.energy is None or self.forces is None:
# write input file
f = open(self.label + '.nw', 'w')
if self.charge is not None:
f.write('charge ' + str(self.charge) + '\n')
write_nwchem(f, atoms, self.geometry)
def format_basis_set(string, tag=self.basispar):
formatted = tag + '\n'
lines = string.split('\n')
if len(lines) > 1:
formatted += string
else:
formatted += ' * library ' + string + '\n'
return formatted + 'end\n'
basis = format_basis_set(self.basis)
if self.ecp is not None:
basis += format_basis_set(self.ecp, 'ecp')
if self.so is not None:
basis += format_basis_set(self.so, 'so')
f.write(basis)
if self.xc == 'RHF':
task = 'scf'
else:
if self.spinorbit:
task = 'sodft'
else:
task = 'dft'
nwchem_xc_map = {
'LDA' : 'slater pw91lda',
'PBE' : 'xpbe96 cpbe96',
}
if self.xc in nwchem_xc_map:
xc = nwchem_xc_map[self.xc]
else:
xc = self.xc
f.write('\n' + task + '\n')
f.write(' mult ' + str(self.multiplicity) + '\n')
f.write(' xc ' + xc + '\n')
f.write(' iterations ' + str(self.maxiter) + '\n')
for key in self.convergence:
if key == 'lshift':
if self.convergence[key] is not None:
if not (self.convergence[key] > 0.0):
f.write(' convergence nolevelshifting\n')
else:
f.write(' convergence ' + key + ' ' +
str(self.convergence[key]/Hartree) + '\n')
else:
if self.convergence[key] is not None:
f.write(' convergence ' + key + ' ' +
str(self.convergence[key]) + '\n')
if self.smear is not None:
f.write(' smear ' + str(self.smear) + '\n')
if self.grid is not None:
f.write(' grid ' + str(self.grid) + '\n')
if self.tolerances is not None:
f.write(' tolerances ' + str(self.tolerances) + '\n')
if self.cgmin:
f.write(' cgmin\n')
if self.dftcontrol:
f.write(self.dftcontrol + '\n')
f.write('end\n')
if self.control:
f.write(self.control + '\n')
# f.write('\ntask ' + task + ' gradient\n')
f.write('\ntask ' + task + ' ' + self.task + '\n')
f.close()
# calculate energy
self.output = self.label + '.out'
self.run()
# read output
self.atoms = read_nwchem(self.output)
self.read_energy()
if self.task.find('gradient') > -1:
self.read_forces()
self.niter = self.read_number_of_iterations()
self.nelect = self.read_number_of_electrons()
self.nvector = self.read_number_of_bands()
self.magnetic_moment = self.read_magnetic_moment()
self.electronic_temperature = self.read_smear() * Hartree
self.dipole = self.read_dipole_moment()
else:
print 'taking old values (E)'
return self.energy * Hartree
def read_energy(self):
"""Read Energy from nwchem output file."""
text = open(self.output, 'r').read()
lines = iter(text.split('\n'))
# Energy:
for line in lines:
estring = 'Total '
if self.xc == 'RHF':
estring += 'SCF'
else:
estring += 'DFT'
estring += ' energy'
if line.find(estring) >=0:
energy = float(line.split()[4])
break
self.energy = energy
# Eigenstates
spin = -1
kpts = []
for line in lines:
if line.find('Molecular Orbital Analysis') >= 0:
spin += 1
kpts.append(KPoint(spin))
if spin >= 0:
if line.find('Vector') >= 0:
line = line.lower().replace('d', 'e')
line = line.replace('=', ' ')
word = line.split()
kpts[spin].f_n.append(float(word[3]))
kpts[spin].eps_n.append(float(word[5]))
self.kpts = kpts
def read_forces(self):
"""Read Forces from nwchem output file."""
file = open(self.output, 'r')
lines = file.readlines()
file.close()
for i, line in enumerate(lines):
if line.find('ENERGY GRADIENTS') >=0:
gradients = []
for j in range(i + 4, i + 4 + len(self.atoms)):
word = lines[j].split()
gradients.append([float(word[k]) for k in range(5,8)])
self.forces = - np.array(gradients) * Hartree / Bohr
def get_eigenvalues(self, kpt=0, spin=0):
"""Return eigenvalue array."""
return np.array(self.kpts[spin].eps_n) * Hartree
def get_occupation_numbers(self, kpt=0, spin=0):
"""Return occupation number array."""
return self.kpts[spin].f_n
def get_number_of_spins(self):
"""Return the number of spins in the calculation.
Spin-paired calculations: 1, spin-polarized calculation: 2."""
return len(self.kpts)
def get_spin_polarized(self):
"""Is it a spin-polarized calculation?"""
return len(self.kpts) == 2
def set_atoms(self, atoms):
if self.atoms == atoms:
return
self.atoms = atoms
self.energy = None
self.forces = None
if self.multiplicity is None:
# obtain multiplicity from magnetic momenta
multiplicity = 1 + atoms.get_initial_magnetic_moments().sum()
self.multiplicity = int(multiplicity)
if self.multiplicity != multiplicity:
raise RuntimeError('Noninteger multiplicity not possible.\n' +
'Check initial magnetic moments.')
else:
if self.multiplicity != int(self.multiplicity):
raise RuntimeError('Noninteger multiplicity not possible.')
def update(self, atoms):
self.set_atoms(atoms)
python-ase-3.6.0.2515/ase/calculators/interface.py 0000644 0001754 0001754 00000011567 11542731070 020610 0 ustar askhl askhl import numpy as np
class Calculator:
"""Class for demonstrating the ASE-calculator interface.
A good implementation of a calculator should store a copy of the
atoms object used for the last calculation. When one of the
*get_potential_energy*, *get_forces*, or *get_stress* methods is
called, the calculator should check if anything has changed since
the last calculation and only do the calculation if it's really
needed. The Atoms class implements the methods *__eq__* and
*__ne__* that can be used for checking identity (using *==* and
*!=*): Two sets of atoms are considered identical if they have the
same positions, atomic numbers, unit cell and periodic boundary
conditions."""
def get_potential_energy(self, atoms=None, force_consistent=False):
"""Return total energy.
Both the energy extrapolated to zero Kelvin and the energy
consistent with the forces (the free energy) can be
returned."""
return 0.0
def get_forces(self, atoms):
"""Return the forces."""
return np.zeros((len(atoms), 3))
def get_stress(self, atoms):
"""Return the stress."""
return np.zeros((3, 3))
def calculation_required(self, atoms, quantities):
"""Check if a calculation is required.
Check if the quantities in the *quantities* list have already
been calculated for the atomic configuration *atoms*. The
quantities can be one or more of: 'energy', 'forces', 'stress',
and 'magmoms'."""
return False
def set_atoms(self, atoms):
"""Let the calculator know the atoms.
This method is optional. If it exists, it will be called when
the *Atoms.set_calculator()* method is called.
*Don't* store a reference to *atoms* - that will create a
cyclic reference loop! Store a copy instead."""
self.atoms = atoms.copy()
class DFTCalculator(Calculator):
"""Class for demonstrating the ASE interface to DFT-calculators."""
def get_number_of_bands(self):
"""Return the number of bands."""
return 42
def get_xc_functional(self):
"""Return the XC-functional identifier.
'LDA', 'PBE', ..."""
return 'LDA'
def get_bz_k_points(self):
"""Return all the k-points in the 1. Brillouin zone.
The coordinates are relative to reciprocal latice vectors."""
return np.zeros((1, 3))
def get_number_of_spins(self):
"""Return the number of spins in the calculation.
Spin-paired calculations: 1, spin-polarized calculation: 2."""
return 1
def get_spin_polarized(self):
"""Is it a spin-polarized calculation?"""
return False
def get_ibz_k_points(self):
"""Return k-points in the irreducible part of the Brillouin zone.
The coordinates are relative to reciprocal latice vectors."""
return np.zeros((1, 3))
def get_k_point_weights(self):
"""Weights of the k-points.
The sum of all weights is one."""
return np.ones(1)
def get_pseudo_density(self, spin=None, pad=True):
"""Return pseudo-density array.
If *spin* is not given, then the total density is returned.
Otherwise, the spin up or down density is returned (spin=0 or
1)."""
return np.zeros((40, 40, 40))
def get_effective_potential(self, spin=0, pad=True):
"""Return pseudo-effective-potential array."""
return np.zeros((40, 40, 40))
def get_pseudo_wave_function(self, band=0, kpt=0, spin=0, broadcast=True,
pad=True):
"""Return pseudo-wave-function array."""
return np.zeros((40, 40, 40))
def get_eigenvalues(self, kpt=0, spin=0):
"""Return eigenvalue array."""
return np.arange(42, float)
def get_occupation_numbers(self, kpt=0, spin=0):
"""Return occupation number array."""
return np.ones(42)
def get_fermi_level(self):
"""Return the Fermi level."""
return 0.0
def initial_wannier(self, initialwannier, kpointgrid, fixedstates,
edf, spin, nbands):
"""Initial guess for the shape of wannier functions.
Use initial guess for wannier orbitals to determine rotation
matrices U and C.
"""
raise NotImplementedError
return c, U
def get_wannier_localization_matrix(self, nbands, dirG, kpoint,
nextkpoint, G_I, spin):
"""Calculate integrals for maximally localized Wannier functions."""
def get_magnetic_moment(self, atoms=None):
"""Return the total magnetic moment."""
return self.occupation.magmom
def get_number_of_grid_points(self):
"""Return the shape of arrays."""
return self.gd.N_c
python-ase-3.6.0.2515/ase/calculators/jacapo/ 0000755 0001754 0001754 00000000000 11757245036 017533 5 ustar askhl askhl python-ase-3.6.0.2515/ase/calculators/jacapo/pw91_psp.py 0000644 0001754 0001754 00000006522 11224640334 021561 0 ustar askhl askhl """ Default pseudopotential paths are defined here
"""
__docformat__ = 'reStructuredText'
defaultpseudopotentials = {'H':'ch_e9g4.pseudo', # H
'Li':'Li_us_cc.pseudo', # Li
'Be':'Be_us_cc.pseudo', # Be
'B':'B_us_cc.pseudo', # B
'C':'C_us_gga.pseudo', # C
'N':'N_us.pseudo', # N
'O':'co_gef_e13_gga.pseudo', # O
'F':'F_pw91_us_7.3.4.pseudo', # F
'Na':'Na_tm_lda_cc.pseudo', # Na
'Mg':'mg_us_gga.pseudo', # Mg
'Al':'Al_us_gga_org.pseudo', # Al
'Si':'csi_e8ag4.pseudo', # Si
'P':'P_us.pseudo', # P
'S':'S_tm.pseudo', # S
'Cl':'Cl_us_gga.pseudo', # Cl
'K':'k_us_gga.pseudo', # K
'Ca':'Ca_us_cc_pw91.pseudo', # Ca
'Sc':'Sc_us_cc_pw91.pseudo', # Sc
'Ti':'ti_us_gga.pseudo', # Ti
'V':'V_us_pw91_13elec.pseudo', # V
'Cr':'Cr_us_pw91_14elec.pseudo', # Cr
'Mn':'Mn_us_gga.pseudo', # Mn
'Fe':'Fe_us_gga_d2.1.8.pseudo', # Fe
'Co':'Co_us_gga.pseudo', # Co
'Ni':'Ni_us_gga.pseudo', # Ni
'Cu':'Cu_us_gga.pseudo', # Cu
'Zn':'zn_us_gga.pseudo', # Zn
'Ga':'ga_pw91_us_13elec.pseudo', # Ga
'Ge':'ge_pw91_us_14elec.pseudo', # Ge
'As':'as_pw91_us_15elec.pseudo', # As
'Kr':'Kr_us_gga.pseudo', # Kr
'Sr':'Sr_us_cc_pw91.pseudo', # Sr
'Y':'Y_us_cc_pw91.pseudo', # Y
'Zr':'Zr_us_gga.pseudo', # Zr
'Nb':'Nb_us_pw91_13elec.pseudo', # Nb
'Mo':'Mo_us.pseudo', # Mo
'Ru':'Ru_us_gga.pseudo', # Ru
'Rh':'Rh_us_gga_fl.pseudo', # Rh
'Pd':'pd_us_gga.pseudo', # Pd
'Ag':'ag_us.pseudo', # Ag
'Cd':'Cd_us_gga.pseudo', # Cd
'Sn':'sn_us_f.pseudo', # Sn
'Sb':'sb_us_gga.pseudo', # Sb
'Te':'te_tm.pseudo', # Te
'Xe':'Xe_us_gga.pseudo', # Xe
'Cs':'cs_tm_7el.pseudo', # Cs
'Ba':'Ba_us_cc_pw91.pseudo', # Ba
'La':'La_us_cc_pw91.pseudo', # La
'Ta':'Ta_us_pw91_13elec.pseudo', # Ta
'W':'W_us_pw91_6elec.pseudo', # W
'Re':'re_us_gga_7elec.pseudo', # Re
'Os':'os_us_gga_7elec_7.3.4.pseudo', # Os
'Ir':'ir_us_gga_flocal.pseudo', # Ir
'Pt':'pt_us_gga.pseudo', # Pt
'Au':'Au_us_gga.pseudo', # Au
'Bi':'Bi_us_gga.pseudo'}
python-ase-3.6.0.2515/ase/calculators/jacapo/setup.py 0000644 0001754 0001754 00000001750 11207230242 021227 0 ustar askhl askhl #!/usr/bin/env python
from distutils.core import setup
from glob import glob
from os.path import join
import os
import sys
long_description = """\
Jacapo is a python package providing an interface to Dacapo that
is compatible with the open source Atomic Simulation
Environment in the python scripting language."""
if sys.version_info < (2, 3, 0, 'final', 0):
raise SystemExit, 'Python 2.3 or later is required!'
packages = ['Jacapo']
tools = ['tools/ncsum',
'tools/plotnetcdf',
'tools/pysub',
'tools/qn_relax',
'tools/stripnetcdf']
# Get the current version number:
execfile('version.py')
setup(name = 'python-Jacapo',
version=version,
description='Jacapo - ase + Dacapo',
url='http://www.fysik.dtu.dk/Campos/ase',
maintainer='John Kitchin',
maintainer_email='jkitchin@andrew.cmu.edu',
license='LGPL',
platforms=['linux'],
packages=packages,
scripts=tools,
long_description=long_description)
python-ase-3.6.0.2515/ase/calculators/jacapo/__init__.py 0000644 0001754 0001754 00000001120 11522612425 021624 0 ustar askhl askhl import Scientific
import string
from ase.test import NotAvailable
try:
version = string.split(Scientific.__version__,".")
if map(int,version) < [2,8]:
print 'your ScientifPython version is: ',Scientific.__version__
print 'ScientificPython 2.8 or greater required for numpy support in NetCDF'
raise NotAvailable('ScientificPython version 2.8 or greater is required')
except AttributeError:
print 'It appears your ScientificPython has no version.'
print 'That probably means it is not 2.8, which is required'
raise Exception
from jacapo import *
python-ase-3.6.0.2515/ase/calculators/jacapo/tools/ 0000755 0001754 0001754 00000000000 11757245034 020671 5 ustar askhl askhl python-ase-3.6.0.2515/ase/calculators/jacapo/tools/stripnetcdf 0000755 0001754 0001754 00000001071 11224411772 023134 0 ustar askhl askhl #!/usr/bin/env python
from optparse import OptionParser
from ase.calculators.jacapo import *
from Scientific.IO.NetCDF import NetCDFFile as NetCDF
parser = OptionParser(usage='stripnetcdf',
version='0.1')
options,args = parser.parse_args()
for arg in args:
#check if it is a dacapo file
nc = NetCDF(arg,'r')
if hasattr(nc,'history'):
if nc.history != 'Dacapo':
nc.close()
continue
else:
nc.close()
continue
calc = Jacapo(arg)
calc.strip()
print 'stripped %s' % arg
python-ase-3.6.0.2515/ase/calculators/jacapo/tools/printlocalsetup 0000755 0001754 0001754 00000016714 11521312760 024046 0 ustar askhl askhl #!/usr/bin/env python
import os,string,sys
# tell me about the architecture
print 'Running as user: ', os.environ['USER']
print 'In directory: ',os.getcwd()
try:
import platform
print '------------- system information ---------------'
print 'Hostname = ',os.environ['HOST']
print 'Architecture = ',platform.architecture()
print 'distribution = ',platform.dist()
print 'libc version = ',platform.libc_ver()
print 'Machine type = ',platform.machine()
print 'Platform = ',platform.platform()
print 'processor type = ',platform.processor()
print 'system = ',platform.system()
print 'system version = ',platform.version()
print
print '------------- Python information --------'
print 'python was compiled with: ',platform.python_compiler()
print 'python version = ',platform.python_version()
print 'python was built: ',platform.python_build()
except:
print '*** you have an older version of python'
print '*** you missed some important system information because of that'
print '*** consider upgrading to version 2.3 or greater'
print 'python version = ',sys.version
print 'uname = '
os.system('uname -a')
print '-------------- User ---------------------'
shell = os.environ.get('SHELL')
print 'SHELL = ',shell
print
try:
import Numeric
print 'Numeric version = ',Numeric.__version__
except:
print '*** Numeric is not installed.'
print '*** Get it from http://sourceforge.net/projects/numpy'
try:
import numarray
print 'numarray version = ',numarray.__version__
except:
print '*** numarray is not installed.'
print '*** Get it from http://sourceforge.net/projects/numpy'
try:
import numpy
print 'numpy version = ', numpy.__version__
except:
print '*** numpy is not installed'
try:
import Scientific
print 'Found Scientific'
try:
import Scientific.IO.NetCDF
print 'Found Scientific.IO.NetCDF'
except:
print 'Scientific.IO.NetCDF appears broken.'
print 'Is netcdf installed?'
print 'did you set $NETCDF_PREFIX when you installed Scientific?'
except:
print '*** Scientific not installed'
print '*** Get it at http://starship.python.net/~hinsen/ScientificPython/'
try:
import ASE
print 'Found ASE at ', ASE.__file__
except Exception,error:
print error
print '*** No ASE found. Did you install it?'
try:
import ase
print 'Found an ase version: "%s"' % ase.__version__
print 'at :',ase.__file__
except:
print '*** No ase found. Did you install it?'
try:
import Dacapo
print 'Found Dacapo python modules'
except:
print '*** No Dacapo modules found, did you install them?'
print ' Get them at dcwww.fysik.dtu.dk/campos'
try:
import Gnuplot
print 'Found Gnuplot python module'
except:
print '*** No Gnuplot module found'
try:
import matplotlib
print 'Found matplotlib version: ',matplotlib.__version__
except:
print 'no matplotlib found'
libs = ['cblas',
'lapack',
'f77blas',
'atlas',
'fftw',
'netcdf',
'lamf77mpi']
libpaths = ['/lib',
'/usr/lib',
'/usr/local/lib',
os.path.join(os.environ['HOME'],'lib'),
]
if 'LD_LIBRARY_PATH' in os.environ:
for libpath in os.environ['LD_LIBRARY_PATH'].split(':'):
libpaths.append(libpath)
print
print '------------------ libraries ------------------'
for lib in libs:
found = False
for path in libpaths:
if os.path.exists(os.path.join(path,'lib%s.a' % lib)):
found = True
print 'found %s in %s' % ('lib%s.a' % lib,path)
if not found:
print '*** Could not find lib%s.a' % lib
def IsOnPath(file):
if os.path.isabs(file):
if os.path.exists(file):
return file
else:
return False
else:
path = string.split(os.environ['PATH'],':')
for dir in path:
if os.path.isdir(dir):
if file in os.listdir(dir):
return os.path.join(dir,file)
return False
def FileIsExecutable(file):
if file is not None:
return os.access(file,os.X_OK)
else:
return False
print
print '------------------- compilers -----------------'
c = ['pgf90','pgf77',
'ifort','ifc',
'g95',
'gcc','g77','f77', 'f90',
'mpif77','mpf90',
'xlf_r','xlf90_r','mpxlf_r'
]
for compiler in c:
if IsOnPath(compiler):
print '%s found' % compiler
else:
print '*** %s not found' % compiler
print
print '-------------- Check for ASE and Dacapo tools -------------'
dacapo_tools = ['dacapo.run',
'stripnetcdf'
]
for exe in dacapo_tools:
f = IsOnPath(exe)
if f:
if FileIsExecutable(f):
print '%s found at %s' % (exe,f)
else:
print '%s found, but it is not executable' % exe
else:
print '%s not found' % exe
print 'Dacapo/Tools is not on your executable path'
ase_executables = ['plottrajectory']
for exe in ase_executables:
f = IsOnPath(exe)
if f:
if FileIsExecutable(f):
print '%s found at %s' % (exe,f)
else:
print '%s found, but it is not executable' % exe
else:
print '*** %s not found' % exe
print 'ASE/Tools is not on your executable path'
print
print '-------- Location of dacapo executables ------------'
exe = os.environ.get('DACAPOEXE_SERIAL',None)
f = IsOnPath(exe)
if f:
if FileIsExecutable(f):
print 'default serial executable is: %s' % (exe)
else:
print '%s found, but it is not executable' % exe
else:
print '*** %s not found' % exe
print 'No default serial dacapo executable found'
exe = os.environ.get('DACAPOEXE_PARALLEL',None)
f = IsOnPath(exe)
if f:
if FileIsExecutable(f):
print 'default parallel executable is: %s' % (exe)
else:
print '%s found, but it is not executable' % exe
else:
print '*** %s not found' % exe
print 'No default parallel dacapo executable found'
psp = os.environ.get('DACAPOPATH',None)
if os.path.isdir(psp):
print 'Pseudopotential database = ',psp
else:
print '*** "%s" is not a directory, please check $DACAPOPATH'
print
print '-----------miscellaneous utilities-------------'
for exe in ['rasmol','gnuplot','vmd','vtk',
'rsync','ssh','scp']:
f = IsOnPath(exe)
if f:
if FileIsExecutable(f):
print '%s found at %s' % (exe,f)
else:
print '%s found, but it is not executable' % exe
else:
print '*** %s not found on your path' % exe
print
print '--------------- mpi ------------------'
for exe in ['recon','lamboot','mpirun','lamhalt']:
f = IsOnPath(exe)
if f:
if FileIsExecutable(f):
print '%s found at %s' % (exe,f)
else:
print '%s found, but it is not executable' % exe
else:
print '*** %s not found' % exe
print 'maybe you do not have lam-mpi installed'
print
print '---------- PYTHON environment variables -------------'
print 'PYTHONSTARTUP = ',os.environ.get('PYTHONSTARTUP')
print 'PYTHONOPTIMIZE = ',os.environ.get('PYTHONOPTIMIZE')
print 'PYTHONPATH:'
for x in sys.path:
print '"%s"' % x
print
print '----------- system path --------------------'
path = os.environ.get('PATH')
for x in string.split(path,':'):
print '"%s"' % x
python-ase-3.6.0.2515/ase/calculators/jacapo/tools/ncsum 0000755 0001754 0001754 00000002246 11521312656 021742 0 ustar askhl askhl #!/usr/bin/env python
from optparse import OptionParser
from ase.visualize import view
from ase.calculators.jacapo import *
from Scientific.IO.NetCDF import NetCDFFile as NetCDF
import os
os.environ['DACAPO_READONLY'] = 'On'
parser = OptionParser(usage='ncsum',
version='0.1')
parser.add_option('-e',
nargs=0,
help = 'print only the energy')
parser.add_option('-p',
nargs=0,
help='view atoms')
parser.add_option('-r',
nargs=1,
help='repeat plotted atoms in n1,n2,n3 times')
options,args = parser.parse_args()
for arg in args:
calc = Jacapo(arg)
atoms = calc.get_atoms()
if options.e is not None:
nc = netCDF(arg,'r')
energy = nc.variables.get('TotalEnergy',None)
if energy is not None:
print energy[:][-1]
else:
print None
nc.close()
else:
print calc
if options.p is not None:
if options.r is not None:
n1,n2,n3 = [int(x) for x in options.r.split(',')]
else:
n1,n2,n3 = (1,1,1)
view(atoms.repeat([n1,n2,n3]))
python-ase-3.6.0.2515/ase/calculators/jacapo/tools/plotnetcdf 0000755 0001754 0001754 00000002145 11224411772 022754 0 ustar askhl askhl #!/usr/bin/env python
from optparse import OptionParser
import os, tempfile
from ase.calculators.jacapo import *
from ase.io.pdb import *
parser = OptionParser(usage='%prog [-r R1 R2 R3]] ncfile',
version='%prog 0.1')
parser.add_option('-r', '--repeat', type='int', nargs=3,
help='Repeat R1, R2, R3 times along the three axes',
metavar='R1 R2 R3')
parser.add_option('-t', '--time', type='int', nargs=1,
help='sleep for t seconds',
metavar='t')
options, args = parser.parse_args()
ncfile = args[0]
if options.repeat is None:
options.repeat = (1,1,1)
atoms = Jacapo.read_atoms(ncfile)
handle,tempfilename = tempfile.mkstemp()
write_pdb(tempfilename,atoms.repeat(options.repeat))
script = '''\
zap
load %s
script %s/.rasmolrc
select all
spacefill
#rotate x 180
#rotate z 180
''' % (tempfilename,os.environ['HOME'])
handle,tempscriptname = tempfile.mkstemp()
f = open(tempscriptname,'w')
f.write(script)
f.close()
os.system('rasmol -script %s' % tempscriptname)
os.remove(tempfilename)
os.remove(tempscriptname)
python-ase-3.6.0.2515/ase/calculators/jacapo/tools/qn_relax 0000755 0001754 0001754 00000005122 11521313673 022422 0 ustar askhl askhl #!/usr/bin/env python
from torque import *
from ase import *
from ase.optimize import QuasiNewton
from ase.constraints import FixAtoms
from ase.calculators.jacapo import *
import os, string, sys, tempfile
from optparse import OptionParser
'''
qn_relax -q "-l cput=168:00:00,mem=2000mb -l nodes=3 -j oe"
relax atoms tagged with 5 and 6
qn_relax -t 5,6
'''
parser = OptionParser(usage='qn_relax',
version='0.1')
parser.add_option('-q',
nargs=1,
help = 'submit job to the queue with options to qsub')
parser.add_option('-n',
nargs=1,
help = 'number of nodes to ask for')
parser.add_option('-t',
nargs=1,
help = 'specify which tags to relax, comma-separated list')
options,args = parser.parse_args()
for ncfile in args:
base,ext = os.path.splitext(ncfile)
atoms = Jacapo.read_atoms(ncfile)
if options.t is None:
freetags = [1]
elif options.t == 'all':
freetags = atoms.get_tags()
else:
freetags = [int(x) for x in options.t.split(',')]
#True means fixed
mask = [atom.get_tag() not in freetags for atom in atoms]
#if False not in mask:
# raise Exception, 'No free atoms found!'
atoms.set_constraint(FixAtoms(mask=mask))
if options.q is None:
calc = atoms.get_calculator()
calc.stay_alive = True
qn = QuasiNewton(atoms,trajectory=base+'.traj')
qn.run(fmax=0.05)
else:
h,fname = tempfile.mkstemp()
script = '''\
#!/bin/tcsh
cd $PBS_O_WORKDIR
qn_relax -t %(tags)s %(ncfile)s
#end''' % {'ncfile':ncfile,
'tags':string.join([str(t) for t in freetags],',')}
print script
f = open(fname,'w')
f.write(script)
f.close()
qdict = {'short':'-l cput=24:00:00,mem=500mb -j oe',
'long':'-l cput=168:00:00,mem=500mb -j oe',
'hogs':'-l cput=24:00:00,mem=2500mb -j oe',
'hogl':'-l cput=168:00:00,mem=2800mb -j oe',
}
if options.q in qdict:
qsub_options = qdict[options.q]
else:
qsub_options = options.q
if options.n is not None:
qsub_options += ' -l nodes=%i' % int(options.n)
cmd = 'qsub -N %(name)s %(options)s %(script)s' % {'name':ncfile,
'options':qsub_options,
'script':fname}
print cmd
os.system(cmd)
os.close(h)
os.remove(fname)
python-ase-3.6.0.2515/ase/calculators/jacapo/tools/dacapo.run 0000755 0001754 0001754 00000013632 11437472103 022650 0 ustar askhl askhl #!/usr/bin/env python
'''
This script runs dacapo in either serial or parallel
depending on the existance of an environment variable
from a queue system. Three queue systems are currently
supported:
PBS PBS_NODEFILE
Sun grid engine PE_HOSTFILE
LoadLeveler LOADL_STEP_TYPE
If one of these is found, then the parallel environement
is set up for lam-mpi and the job run
otherwise a serial job is run
dacapo executables are found from one of these environment
variables:
DACAPOEXE_SERIAL default serial executable
DACAPOEXE_PARALLEL default parallel executable
You can trick it into running in parallel at the command line
like this:
env PBS_NODEFILE=pbs.nodes mydacapo.run CO.nc CO.nc -out CO.txt
env PE_HOSTFILE=sge.nodes mydacapo.run CO.nc CO.nc -out CO.txt
where pbs.nodes is a pbs-style nodefile
and sge.nodes is a sun grid engine style nodefile
python scripts as a rule tend to return zero I have found, even if you
tell it to return something else with sys.exit(5) for example. The
only thing I have been able to get to work is to return zero or not
zero. sys.exit('anystring') makes the script return non-zero if an
error occurs. That is why there are so many of these types of commands
here. I use the non-zero status to know if an error has occurred
during the calculation.
John Kitchin
05/22/05
'''
import os,string,sys
from subprocess import *
ARGS = string.join(sys.argv[1:],' ')
def RunSerialDacapo(ARGS):
DACAPOEXE = os.environ.get('DACAPOEXE_SERIAL')
if DACAPOEXE is None:
raise Exception, 'DACAPOEXE_SERIAL was not found in your environment'
cmd = string.join([DACAPOEXE,ARGS],' ')
status = os.system(cmd)
if status != 0:
sys.exit('"%s" failed' % cmd)
### check if LoadLeveler
'''
the loadleveler I am familiar with does not use a nodefile
that the user needs to know aobut. it uses the poe command
which does this stuff for you. according to an old note in
the original dacapo.run shell script the nodelist can be
found in $LOADL_PROCESSOR_LIST
'''
if 'LOADL_STEP_TYPE' in os.environ.keys():
LL_type = os.environ.get('LOADL_STEP_TYPE')
if LL_type == 'PARALLEL':
os.environ['OMP_NUM_THREADS'] = '1'
MPICMD = 'poe'
DACAPOEXE = os.environ.get('DACAPOEXE_PARALLEL')
parcmd = string.join([MPICMD,DACAPOEXE,ARGS],' ')
status = os.system(parcmd)
if status != 0:
sys.exit('"%s" failed' % parcmd)
elif LL_type == 'SERIAL':
RunSerialDacapo(ARGS)
### next check for PBS or SGE
elif ('PBS_NODEFILE' in os.environ.keys() or
'PE_HOSTFILE' in os.environ.keys()):
#print 'PBS_NODEFILE = ',os.environ.get('PBS_NODEFILE')
if 'PBS_NODEFILE' in os.environ.keys():
MACHINEFILE = os.environ.get('PBS_NODEFILE')
NPROCS = len(open(MACHINEFILE,'r').readlines())
JOBID = os.environ.get('PBS_JOBID')
import shutil
nodefile = 'pbs.%s.nodes' % JOBID
# i make a copy here for debugging purposes
# it is deleted after the job if finished
# and the PBS_NODEFILE is temporary somewhere anyway
shutil.copy(MACHINEFILE,nodefile)
# if its not PBS here it must be SGE, but
# I check again anyway
elif 'PE_HOSTFILE' in os.environ.keys():
'''
here is the typical contents of the PE_HOSTFILE
n14.bc.rzg.mpg.de 2 all.q@n14.bc.rzg.mpg.de UNDEFINED
o06.bc.rzg.mpg.de 2 all.q@o06.bc.rzg.mpg.de UNDEFINED
n11.bc.rzg.mpg.de 2 all.q@n11.bc.rzg.mpg.de UNDEFINED
below, I parse the contents of this file to create the nodefile
for lam-mpi:
n14.bc.rzg.mpg.de
n14.bc.rzg.mpg.de
o06.bc.rzg.mpg.de
o06.bc.rzg.mpg.de
n11.bc.rzg.mpg.de
n11.bc.rzg.mpg.de
'''
MACHINEFILE = os.environ.get('PE_HOSTFILE')
JOBID = os.environ.get('JOB_ID')
NPROCS = 0
nodefile = 'sge.%s.nodes' % JOBID
nf = open(nodefile,'w')
for line in open(MACHINEFILE,'r'):
# nodename = fields[0]
# ncpus = fields[1]
# queue = fields[2]
# UNDEFINED = fields[3]
fields = string.split(line)
if __debug__:
print fields
nodename = fields[0]
nprocs = int(fields[1])
if __debug__:
print nodename,nprocs
for n in range(nprocs):
nodeline = '%s\n' % (fields[0])
nf.write(nodeline)
NPROCS += nprocs
nf.close()
if __debug__:
print 'SGE_O_WORKDIR = ',os.environ.get('SGE_O_WORKDIR')
print 'NHOSTS = ',os.environ.get('NHOSTS')
print 'NSLOTS = ',os.environ.get('NSLOTS')
if NPROCS > 1:
# now construct the mpirun command
MPICMD = 'mpirun -np %i' % NPROCS
DACAPOEXE = os.environ.get('DACAPOEXE_PARALLEL')
parcmd = string.join([MPICMD,DACAPOEXE,ARGS],' ')
if __debug__: print parcmd
print 'Running "%s"' % parcmd
p = Popen(parcmd,
shell=True,
stdin=PIPE,
stdout=PIPE,
close_fds=True,
cwd=os.getcwd())
p_pid = p.pid
status = p.wait()
if status != 0:
(sout,serr) = p.communicate()
print 'stdout = ',sout
print 'stderr = ',serr
all_is_ok = False
print '**** the command failed ****'
if not all_is_ok:
sys.exit('"%s" failed' % parcmd)
print
print 'One iteration from parallel run complete'
print '*******************************************************'
print
else:
RunSerialDacapo(ARGS)
else:
# serial job, no parallel environment found.
RunSerialDacapo(ARGS)
#remove the nodefile
try:
if os.path.exists(nodefile):
os.remove(nodefile)
except:
pass
python-ase-3.6.0.2515/ase/calculators/jacapo/tools/pysub 0000755 0001754 0001754 00000002723 11162147213 021753 0 ustar askhl askhl #!/usr/bin/env python
'''
this is pure laziness to submit python scripts to PBS
without the usual cd $PBS_O_WORKDIR stuff
'''
import os,sys, tempfile
from optparse import OptionParser
parser = OptionParser(usage='pysub',
version='0.1')
parser.add_option('-q',
nargs=1,
help = 'submit job to the queue with options to qsub')
parser.add_option('-n',
nargs=1,
help='number of nodes to ask for')
options,args = parser.parse_args()
qdict = {'short':' -l cput=24:00:00,mem=500mb -j oe',
'long':' -l cput=168:00:00,mem=500mb -j oe',
'hogs':' -l cput=24:00:00,mem=2500mb -j oe',
'hogl':' -l cput=168:00:00,mem=2800mb -j oe',}
for pyscript in args:
h,fname = tempfile.mkstemp()
cmd ='''\
#!/bin/tcsh
cd $PBS_O_WORKDIR
python %s
#end''' % pyscript
f = open(fname,'w')
f.write(cmd)
f.close()
if options.q is None:
qsub_options = '-l cput=24:00:00,mem=2500mb -j oe'
elif options.q in qdict:
qsub_options = qdict[options.q]
else:
qsub_options = options.q
if options.n is not None:
qsub_options += ' -l nodes=%i' % int(options.n)
cmd = 'qsub -N %(name)s %(options)s %(script)s' % {'name':pyscript,
'options':qsub_options,
'script':fname}
print cmd
os.system(cmd)
os.close(h)
os.remove(fname)
python-ase-3.6.0.2515/ase/calculators/jacapo/version.py 0000644 0001754 0001754 00000000024 11165127543 021561 0 ustar askhl askhl version = '0.6.7'
python-ase-3.6.0.2515/ase/calculators/jacapo/utils/ 0000755 0001754 0001754 00000000000 11757245036 020673 5 ustar askhl askhl python-ase-3.6.0.2515/ase/calculators/jacapo/utils/symmol.tar.gz 0000644 0001754 0001754 00001140050 11306615121 023325 0 ustar askhl askhl ‹ ÈK ì]ÛnG’õ3¿"|±u#3"¯Ìè…w±¦xöh©ej—ƒ¤=£ùúKFVu7ÙÔØ"¹^w™²Jݧò™yâD^Šëœ]þt±^úðÕ“]ž®#ýø‡ÿ²ò9]€¿
}ÎÁgH_ù >¦¯œº"M×Ï·wg7Î}õßwëÛ»=¸Ë³»Û—ÏQ¢g½]aIpïMó÷ß¹@ÿ9ç—A>õK¤Ý‡‹Ÿ¯o®:__}ºp«Û#÷ÎIrôg)mía™´8>™0ôÐèÜbÙ|hí~L¨%I‚±†\îÁŒ¼¨¡àý˜ÏIgOyÎ<°ôÐ qÁ°¤˜ìaã)3~¼¥šë=·‹q†ù0ÃlåµSž©î°¤!Õ1’α{÷éÝÅõùúgWë?9ww¾vïÎn~¸¾r·ÿ³¾Xß]_ýÉ}¼uôý»»‹Oî
¾ß~æ‡õ»³ËµûéâìŠÆÌ›|îþþñîܽY}ûg¿LTøãëh¤4 ¬ˆž;H/V¿9Zaü²”ÞZ1…6Ç`Ç,ö`¢afyHMÀJ$LÚN‡o û9&o—gs¸b`㎼ٌÁBe„ŽñË[Kü–€oRȉÒK‡z¡'ö㛜àa(åªìé,†2>IyÛXb‹%˜
ñè$Z:°iÃ`u§zEKÇêÅk…º#÷Ë‚òJÛåY&J‚1zÁl—gÂŒtò¶}(S æ˜mû0³äZÌXŽ^š[×Úü?<]øÿÀŸmû’ÿÿ×ñë«®¯ÖÌæGê÷•ò¶nšèFµ€ð }Úÿ6°×ów°×ów°×ów°×ów°×ów°×óŸìÖÈ'©82̨×Ãûg˜]ϯ˜Q¯MÌF^i†™åµÉÛeVu0Ǽt?<\/s
þǧËã1þOvã¿ÿ?Ë–NˆÎíÉ~Ñõ¯Þß]_üÜÙÕû.òIêrÜpûéòr}wó‰ã…žïy üÎoè@J{É?Gß^#'å¢Ù
û…2aàAŒë÷
$^kÛ&v“dŽIÀ˜ç˜´Yìb²a€ô:ð¿(¤‹U?©#aŠ•‡JØJ“¯E/sLa‚øÂ´¶iæå&ø‡òšaÂCy
ÌJ¢Å¤Ü‚æµiÃUÀŽY,K•tÈPifpÆÄ-ÌâLvNä°4¯PÕàÄ ‚ÉaÜ„)£oT©çËF:u`JÑ‘—äØh†i¥3åþ¡tóÒú_¼ÿǧËãþ‡óÿ'<ðÿs\ÇÔ§9:&ïשþ¿°šÿÀ¶>µG'˜ËË€éU ¨ß—WòúŠ<Ý–eÉtËQ: ‡CŽN'Uí—På&&¡#v"9:¯µßøéæèfCá™(¾ÉUç&}õyßã«yî IŸJ1èS™P,N@Ò ãf
cdrê—ž`…‡{ÇÙã¡BîuO
&;î<ÎòS½îœŽÌJ•´÷ñ4ÏªæŠø=Â$ˆ{ë>…ò¸Z5TöG’{ô{s/sÓÕªv&GÑ3˜÷>^ç¹[sÓ㹗˾ÇO6zÅdß[ý¨{³Zäéf
ó´ðÝò9$ÍÒ°ØýÏÛÊz»G}<„¸ÿñy»ÇÐk
Y¢VÂÈTßžÇçíN]4õLÙ™.$÷¶÷ñy»ƒ}€¬ä°ïñ—f½Ãe×ðÿééòxtþÏ—Ãúß]2ŠËúøî6Ç
ÓO7×?]ÝêÖ½_¸¾¹\¿· ñŽCÈ*áåõÅúÝÏk !oç€àwSŒÉ"—m•ne¡¤A‹Ýy‹:z$ÉÚ>¤ä
nCÛY ZHF©X*¡gÄ/ ‹M…gF“7Sx 2¥‚#•¤ÅN*@,•—녮Áÿùéòx„ÿIªÀ.ÿçÿ?Çu|¹¾;g¶þÛ{%õ@¯?G²®Ã?Û«9¡Sa+ise$•q¶êïˆejšKæ]Ìb¬Xe:aä+wÏʈa;˜—¶ìïãã¿<]ŠyvçóÿÏrmùão|›Ýõ»»³óõû›ë+çÞž÷^a‚o|œ Þ&àeF“_ÁÏ×ßÎÖHƒßÅÆàF^}Ý$µßÅÈta˜)ÖÝ*ÆHðèí|4̳ þ¿d”1þëÓåñXü—Ãîú_
‡ñÿ×±û°¾¹¹~·¾Z¿rß-¿_¼Xß¼úå›å›Ÿ¯>ÞýÓ}Z…oÜ_ˆÜêæYëââúÇ›å+÷ë+Jš½IÄ|åe«:©W—²KŒÆ/3ÉðQäÎ]§ùÏÑ_×S ˜’×ù´ÎÉÇ
&üI¨[˜’òlƒ Ïæµ¤ûаÔìu¢¯ÆÙ bQÓAhz“3ÄÙ™ÒÅë©×ˆ°Ì7˜ðTdéè› æ‰RÆê·ÊŒ²±mVæˆY‹èMj±Í%’Î*F'[)åFOÍ$OÐ5Û3Ù†©„Ù$ ÌøI(/1jO0‰}Âë)òf™3°_ïÖìfu_áë]’Ã܆ñõn{‘
ã¼½ÒëÝö¢ä`Ö^'³2G¢”Í2C‘¢¯wíCvƹ}feöÁÖÊÌ>'³2ö";ü½feíEyæY{½Ðøüßž.GøCÜÿëÏs;áîã£ãá÷ùWûÁð<+·JD+¯ÝßÏnÝÍõÝÙÝú½»þà˜ ß¯¼Y¯oÝÙÍõÏWïe
ï—õ»»ë÷áæúÒ}¼»u”ÿÝÍš¸<»åYÁ»k÷×µs_¿Iï¿ù’ûú[
ò¶^•lÝBvÜ3‘8›'WÆwA(Inr*÷>·‘‚mkáÍ)ëâ––{
øxlÓOQ†Rå¦ÕŠšBöåÑlKŒ“2+Cùü2؆÷kËp¦Z098Ù–ã¡[2ÇG-y2,Ib£öEÇ —!x4…aIÞõÁYÓ
)…feˆ¦0,¹Y†ôùe–”24+Cýì2¨·ÞèÕ¼—Uç—¹äÇS€×nê «‰˜‹&§†÷É©%]Yl5ªmsTU¸¿O¾žõê_•B²¤ÐkQýg×âdÓ’Úµ@š•ShrFá‘>i)P(MÔI¨”^†úx¯Æ©-0fíH5ÕÔí {é““(…l)ÄÏOaXr³õskñÒîpí»Lÿ…'[Ü
öÍÿ{;úÏôßs\ÇîüìâÃ4 @ÌùËoŒäåDþó7’ßaÞ“ÎN„9až3’8¼'ω0Çø¹óß±Ä{ö–ÃøŽëXþ~u`%?úÏéBoGl´¤±äàS…H±‘c&L˜Ò¢ E«.!'Þp=Òa›,) Qº.SŒ€„™ÒI1s‘†bˆrκP÷‚#w:•§dà~¬á
+$krÄ’3¥“=ï£,B(z^;Ùp:8Ê“ku¼Q‚¤IvTæÓqÈ`IµÊòU&îº Ñ5‹)¬3ñ†Aٴɲ¬…YtˆËÒq±ó¥[Ì
%]FmIêåk˜Ex”NŒØQ:£>õå)†£,JmT/ºñ¹’ôæãm>—J˜~èÏ!PfzP-#6ÞB˜2ê^kIÒÜÁPæ‘Ô‘µEÔ#p-QÝ9Ú‰¼3sŠ‘íœ$ÁBt&ÇŽVg1òñŒ&5¾¢ì›¥NÒ°Í¢ºHy¡Ú‹ˆ
ùœÅm ÚZš